这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » STM32 » STM32F103VET6 ADC采集64点做FFT变换

共2条 1/1 1 跳转至

STM32F103VET6 ADC采集64点做FFT变换

菜鸟
2017-06-14 13:22:07     打赏

 最近在做一个采集卡的东西,需要采集电压电流,用STM32做主控芯片,考虑到还得驱动其他器件,所以就不能用中断的方式采集,于是有了下面的方法: TIM输出PWM触发ADC, 进行周期性采集,采集数据通过DMA传输至内存,保存64点后,产生一个中断表示采集完成,进行一次FFT变换,得到基波幅值。这样只在采集开始设置一下,然后采集结束后处理,处理过程中又可以进行下一次采集,效率很高。

  1. /******************** (C) COPYRIGHT 2012 WildFire Team **************************
  2. 2015.1.1
  3. 1.TIM2 PWM触发ADC1采集,3200hz,采集完成后数据DMA存到内存,一次64点,采集64点完成产生DMA中断

  4. 2.用ST公司自带库进行64点FFT运算,测试OK


  5. **********************************************************************************/
  6. #include "stm32f10x.h"
  7. #include "led.h"
  8. #include "sys.h"
  9. #include "SysTickDelay.h"
  10. #include <math.h>
  11. #include <stdio.h>
  12. #include "stm32_dsp.h"
  13. #include "table_fft.h"


  14. //#define    MI_ERR    (-2)

  15. #define PI2  6.28318530717959
  16. #define NPT 64            /* NPT = No of FFT point*/
  17. #define Fs 3200


  18. #define ADC1_DR_Address ((u32)0x40012400+0x4c)

  19. void led_init(void);
  20. void Adc_GPIO_Init(void);
  21. void Adc_single_Init(void);
  22. void ADC1_DMA_Init(void);
  23. void TIM2_NVIC_Config_1s(void);
  24. void TIM2_Config_1s(void);
  25. void TIM2_Configration(void);

  26. void dsp_asm_init(void);
  27. void dsp_test(void);
  28. void dsp_asm_powerMag(void);



  29. long lBUFIN[NPT];         /* Complex input vector */
  30. long lBUFOUT[NPT];        /* Complex output vector */
  31. long lBUFMAG[NPT + NPT/2];/* Magnitude vector */
  32. long lBUFMAG_base;
  33. float average = 0.0;

  34. float voltage = 0.0;
  35. extern uint16_t TableFFT[];


  36. __IO uint16_t ADCConvertedValue[64];

  37. uint8_t DMA_FLAG = 0;
  38. uint8_t led_flag = 0;
  39. int main(void)
  40. {
  41.         led_init();//pc 3 4 5 
  42.         
  43.         SysTick_Initaize();
  44.         
  45.         Adc_GPIO_Init();//pc2
  46.         Adc_single_Init();
  47.         ADC1_DMA_Init();
  48.         
  49.         TIM2_Configration();

  50.         
  51.         while(1)
  52.         {        
  53.                 led0 = 0;
  54.                 led0 = 1;
  55.                 while(1)
  56.                 {
  57.                   while(DMA_FLAG == 0);
  58.                         dsp_asm_init();
  59.                         dsp_test();
  60.                 }
  61.                 
  62.         }
  63. }











  64. void led_init(void)
  65. {                
  66.         /*定义一个GPIO_InitTypeDef类型的结构体*/
  67.           GPIO_InitTypeDef GPIO_InitStructure;

  68.         /*开启GPIOC的外设时钟*/
  69.           RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE); 

  70.         /*选择要控制的GPIOC引脚*/                                                                                                                           
  71.           GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;        

  72.         /*设置引脚模式为通用推挽输出*/
  73.           GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   

  74.         /*设置引脚速率为50MHz */   
  75.           GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 

  76.         /*调用库函数,初始化GPIOC*/
  77.           GPIO_Init(GPIOC, &GPIO_InitStructure);                  

  78.         /* 关闭所有led灯        */
  79.         GPIO_SetBits(GPIOC, GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5);         
  80. }

  81. void Adc_GPIO_Init(void)
  82. {
  83.         GPIO_InitTypeDef GPIO_InitStructure;
  84.         
  85.         RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE); 
  86.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;        
  87.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  88.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
  89.         GPIO_Init(GPIOC, &GPIO_InitStructure);
  90. }

  91. void Adc_single_Init(void)
  92. {
  93.         ADC_InitTypeDef ADC_InitStructure;
  94.         
  95.         ADC_DeInit(ADC1);
  96.         
  97.         RCC_APB2PeriphClockCmd( RCC_APB2Periph_ADC1, ENABLE); 
  98.         RCC_ADCCLKConfig(RCC_PCLK2_Div6);//设置ADC时钟(ADCCLK) 72MHZ/6 = 12MHZ
  99.         
  100.         ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//独立模式
  101.         ADC_InitStructure.ADC_ScanConvMode = DISABLE;//单次模式(单通道)
  102.         ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//连续模式
  103.         ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2;//转换由TIM2 CC2 trig
  104.         ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//ADC数据右对齐
  105.         ADC_InitStructure.ADC_NbrOfChannel = 1;//规则转换的ADC的通道数目,取值范围为1-16
  106.         ADC_Init(ADC1,&ADC_InitStructure);//初始化配置
  107.    
  108.         
  109.         
  110.         ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 1, ADC_SampleTime_7Cycles5);
  111.         
  112.         
  113.         ADC_DMACmd(ADC1, ENABLE);//enable DMA

  114.         ADC_Cmd(ADC1,ENABLE);// enable adc
  115.         
  116.         ADC_ResetCalibration(ADC1);
  117.         while( ADC_GetResetCalibrationStatus(ADC1));//获取ADC重置校准寄存器的状态 等待复位结束
  118.         ADC_StartCalibration(ADC1);//开始指定ADC的校准状态
  119.         while( ADC_GetCalibrationStatus(ADC1) );
  120.         
  121.         ADC_ExternalTrigConvCmd(ADC1,ENABLE);
  122.         
  123.         
  124.         
  125. }

  126. void ADC1_DMA_Init(void)
  127. {
  128.          DMA_InitTypeDef DMA_InitStructure;
  129.          NVIC_InitTypeDef NVIC_InitStructure;
  130.         
  131.    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

  132.    //ADC1 DMA channel 1
  133.    DMA_DeInit(DMA1_Channel1);
  134.    DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
  135.    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADCConvertedValue;
  136.    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
  137.    DMA_InitStructure.DMA_BufferSize = 64;
  138.    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  139.    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//  内存自增
  140.    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//16位
  141.    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//16位
  142.    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//DMA normal
  143.    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  144.    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  145.    DMA_Init(DMA1_Channel1, &DMA_InitStructure);
  146.    
  147.                 NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
  148.                 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;     // 主优先级为0
  149.                 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;            // 次优先级为0
  150.                 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  151.                 NVIC_Init(&NVIC_InitStructure);

  152.    DMA_ITConfig(DMA1_Channel1,DMA_IT_TC, ENABLE);//使能或者失能指定的通道x中断(DMA1 通道1)


  153.    /* Enable DMA1 channel1 */
  154.    DMA_Cmd(DMA1_Channel1, ENABLE);

  155. }

  156. void TIM2_NVIC_Config_1s(void)
  157. {
  158.     NVIC_InitTypeDef NVIC_InitStructure; 
  159.     
  160.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);                                                                                                          
  161.     NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;          
  162.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  163.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;        
  164.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  165.     NVIC_Init(&NVIC_InitStructure);
  166. }

  167. void TIM2_Config_1s(void)
  168. {
  169.     TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  170.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , ENABLE);
  171.     TIM_DeInit(TIM2);
  172.     TIM_TimeBaseStructure.TIM_Period=10000;                                                                                 /* 自动重装载寄存器周期的值(计数值) */
  173.     /* 累计 TIM_Period个频率后产生一个更新或者中断 */
  174.     TIM_TimeBaseStructure.TIM_Prescaler= (7200 - 1);                                    /* 时钟预分频数 72M/72 */
  175.     TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;                 /* 采样分频 */
  176.     TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; /* 向上计数模式 */
  177.     TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
  178.         
  179.     TIM_ClearFlag(TIM2, TIM_FLAG_Update);                                                                            /* 清除溢出中断标志 */
  180.     TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
  181.     TIM_Cmd(TIM2, ENABLE);                                                                                                                                                /* 开启时钟 */
  182.     
  183.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , ENABLE);                /*先关闭等待使用*/    
  184. }

  185. void TIM2_Configration(void)
  186. {
  187.         TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  188.         TIM_OCInitTypeDef TIM_OCInitStructure;
  189.         //TIM_DeInit(TIM2);
  190.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , ENABLE);
  191.         
  192.         TIM_TimeBaseStructure.TIM_Period=100;                                                                                 /* 自动重装载寄存器周期的值(计数值) */
  193.         /* 累计 TIM_Period个频率后产生一个更新或者中断 */
  194.   TIM_TimeBaseStructure.TIM_Prescaler= (225 - 1);                                    // 时钟预分频数 72000000/3200 = 22500 = 225 * 100
  195.         TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;                 /* 采样分频 */
  196.         TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; /* 向上计数模式 */
  197.         TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
  198.         TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
  199.         
  200.         TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//PWM模式1
  201.         TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//使能

  202.         TIM_OCInitStructure.TIM_Pulse = 50;//脉冲宽度,由这个设置占空比
  203.         TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;//LOW电平有效

  204.         TIM_OC2Init(TIM2,&TIM_OCInitStructure);//初始化
  205.                 
  206.         TIM_Cmd(TIM2,ENABLE);
  207.         
  208.         TIM_InternalClockConfig(TIM2);
  209.         TIM_OC2PreloadConfig(TIM2,TIM_OCPreload_Enable);
  210.         TIM_UpdateDisableConfig(TIM2,DISABLE);
  211.         
  212.         
  213. }

  214. void dsp_asm_init(void)
  215. {
  216.         uint16_t i = 0;
  217.         //float fx;
  218.         for( i = 0;i<NPT;i++ )
  219.         {
  220.                 //fx = 4000 * sin(PI2*i*50.0/Fs ) + 4000*sin(PI2*i*2500.0/Fs) + 4000*sin(PI2*i*2550.0/Fs);
  221.                 average = average + ADCConvertedValue[i];
  222.         }
  223.         average = average / NPT;
  224.         
  225.         for( i = 0;i<NPT;i++ )
  226.         {
  227.                 lBUFIN[i] = ((int16_t)(ADCConvertedValue[i] - average)) << 16;
  228.         }
  229.         
  230. }

  231. void dsp_test(void)
  232. {
  233.         cr4_fft_64_stm32(lBUFOUT, lBUFIN, NPT);
  234.         dsp_asm_powerMag();
  235. }


  236. // int main(void)
  237. // {        
  238. //         dsp_asm_init();
  239. //         dsp_test();
  240. //         dsp_test();
  241. // }



  242. void dsp_asm_powerMag(void)
  243. {
  244.         int16_t lX,lY;
  245.         uint32_t i;
  246.         float X =0.0;
  247.         float Y =0.0;
  248.         float Mag = 0.0;
  249.         for(i=0;i<NPT/2;i++)
  250.         {
  251.                 lX = ( lBUFOUT[i] << 16 ) >> 16;
  252.                 lY = ( lBUFOUT[i] >> 16 );
  253.                 {
  254.                          X = NPT * ((float)lX) / 32768;
  255.                          Y = NPT * ((float)lY) / 32768;
  256.                          Mag = sqrt ( X*X + Y*Y)/NPT;
  257.                         lBUFMAG[i] = (uint32_t)(Mag*65536);
  258.                 }
  259.         }
  260.         voltage = (float)(lBUFMAG[1]) / 4096.0 * 3.3;
  261.         
  262. //         lX = ( lBUFOUT[1] << 16 ) >> 16;
  263. //         lY = ( lBUFOUT[1] >> 16 );
  264. //   X = NPT * ((float)lX) / 32768;
  265. //         Y = NPT * ((float)lY) / 32768;
  266. //   Mag = sqrt ( X*X + Y*Y)/NPT;
  267. //   lBUFMAG_base = (uint32_t)(Mag*65536);        
  268.         
  269. }




关键词: STM32F103VET6     采集    

管理员
2017-06-14 21:40:34     打赏
2楼
谢谢分享

共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]