你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32F103VET6 ADC采集64点做FFT变换  

[复制链接]
mengyu139 发布时间:2015-1-5 20:00
        最近在做一个采集卡的东西,需要采集电压电流,用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. }
复制代码





评分

参与人数 1 ST金币 +1 收起 理由
mochen32 + 1 值得收藏,待我测试以后来评价.

查看全部评分

收藏 10 评论35 发布时间:2015-1-5 20:00

举报

35个回答
gdgn526345 回答时间:2018-5-16 14:12:30
谢谢楼主分享! 另外,在楼主贴出来的代码 ,没有看到 FFT 调用的那部分的?                                        比如说 :cr4_fft_64_stm32(Pout, Poin, 64);
xmshao 回答时间:2017-1-13 11:07:00
zhangxu56726 发表于 2017-1-12 20:32
请问下 ,这样设置后ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2;//转换由TIM2 ...

是这个意思,即通过TIM2的通道2的比较事件来触发ADC。
zhangxu56726 回答时间:2017-1-12 20:32:23
请问下 ,这样设置后ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2;//转换由TIM2 CC2 trig,
   是不是 STM32 内部已经与TIM2的CC2 连接起来,触发ADC转换。

是这样的吗?
mengyu139 回答时间:2015-1-5 20:01:41
使用STM32 的DSP库进行FFT变换说明及例程.rar (51.34 KB, 下载次数: 1417)
vilsenma 回答时间:2015-8-9 15:00:11
学习学习,今天正好搞搞这块!3q
Only_Time 回答时间:2015-8-9 15:14:52
学习了
心中月古 回答时间:2015-9-1 08:54:26

谢谢,不知道效果怎么样!?
Jason96 回答时间:2016-11-28 14:47:50
谢谢,好好学习
andypanfan 回答时间:2016-11-29 08:54:18
原来学习了  一段时间   后来忙其他的  又给忘了!!!!
5265325 回答时间:2016-11-29 09:22:35
gl542400 回答时间:2017-1-12 19:56:21

谢谢,好好学习
小小超 回答时间:2017-1-13 08:56:24
谢谢分享!!!!
zbber 回答时间:2017-1-13 13:17:38
纯友情支持 帮顶
shuolang126 回答时间:2017-1-24 09:03:25
学习了!
shuolang126 回答时间:2017-1-24 09:03:57
还没有用过DSP的库
123下一页

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版