这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界» 论坛首页» 嵌入式开发» 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
  11. #include
  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. SysTick_Initaize();

  43. Adc_GPIO_Init();//pc2
  44. Adc_single_Init();
  45. ADC1_DMA_Init();

  46. TIM2_Configration();


  47. while(1)
  48. {
  49. led0 = 0;
  50. led0 = 1;
  51. while(1)
  52. {
  53. while(DMA_FLAG == 0);
  54. dsp_asm_init();
  55. dsp_test();
  56. }

  57. }
  58. }











  59. void led_init(void)
  60. {
  61. /*定义一个GPIO_InitTypeDef类型的结构体*/
  62. GPIO_InitTypeDef GPIO_InitStructure;

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

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

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

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

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

  73. /* 关闭所有led灯 */
  74. GPIO_SetBits(GPIOC, GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5);
  75. }

  76. void Adc_GPIO_Init(void)
  77. {
  78. GPIO_InitTypeDef GPIO_InitStructure;

  79. RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE);
  80. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  81. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  82. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  83. GPIO_Init(GPIOC, &GPIO_InitStructure);
  84. }

  85. void Adc_single_Init(void)
  86. {
  87. ADC_InitTypeDef ADC_InitStructure;

  88. ADC_DeInit(ADC1);

  89. RCC_APB2PeriphClockCmd( RCC_APB2Periph_ADC1, ENABLE);
  90. RCC_ADCCLKConfig(RCC_PCLK2_Div6);//设置ADC时钟(ADCCLK) 72MHZ/6 = 12MHZ

  91. ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//独立模式
  92. ADC_InitStructure.ADC_ScanConvMode = DISABLE;//单次模式(单通道)
  93. ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//连续模式
  94. ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2;//转换由TIM2 CC2 trig
  95. ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//ADC数据右对齐
  96. ADC_InitStructure.ADC_NbrOfChannel = 1;//规则转换的ADC的通道数目,取值范围为1-16
  97. ADC_Init(ADC1,&ADC_InitStructure);//初始化配置



  98. ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 1, ADC_SampleTime_7Cycles5);


  99. ADC_DMACmd(ADC1, ENABLE);//enable DMA

  100. ADC_Cmd(ADC1,ENABLE);// enable adc

  101. ADC_ResetCalibration(ADC1);
  102. while( ADC_GetResetCalibrationStatus(ADC1));//获取ADC重置校准寄存器的状态 等待复位结束
  103. ADC_StartCalibration(ADC1);//开始指定ADC的校准状态
  104. while( ADC_GetCalibrationStatus(ADC1) );

  105. ADC_ExternalTrigConvCmd(ADC1,ENABLE);



  106. }

  107. void ADC1_DMA_Init(void)
  108. {
  109. DMA_InitTypeDef DMA_InitStructure;
  110. NVIC_InitTypeDef NVIC_InitStructure;

  111. RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

  112. //ADC1 DMA channel 1
  113. DMA_DeInit(DMA1_Channel1);
  114. DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
  115. DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADCConvertedValue;
  116. DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
  117. DMA_InitStructure.DMA_BufferSize = 64;
  118. DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  119. DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;// 内存自增
  120. DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//16位
  121. DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//16位
  122. DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//DMA normal
  123. DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  124. DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  125. DMA_Init(DMA1_Channel1, &DMA_InitStructure);

  126. NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
  127. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 主优先级为0
  128. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 次优先级为0
  129. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  130. NVIC_Init(&NVIC_InitStructure);

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


  132. /* Enable DMA1 channel1 */
  133. DMA_Cmd(DMA1_Channel1, ENABLE);

  134. }

  135. void TIM2_NVIC_Config_1s(void)
  136. {
  137. NVIC_InitTypeDef NVIC_InitStructure;

  138. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
  139. NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
  140. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  141. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
  142. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  143. NVIC_Init(&NVIC_InitStructure);
  144. }

  145. void TIM2_Config_1s(void)
  146. {
  147. TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
  148. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , ENABLE);
  149. TIM_DeInit(TIM2);
  150. TIM_TimeBaseStructure.TIM_Period=10000; /* 自动重装载寄存器周期的值(计数值) */
  151. /* 累计 TIM_Period个频率后产生一个更新或者中断 */
  152. TIM_TimeBaseStructure.TIM_Prescaler= (7200 - 1); /* 时钟预分频数 72M/72 */
  153. TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; /* 采样分频 */
  154. TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; /* 向上计数模式 */
  155. TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

  156. TIM_ClearFlag(TIM2, TIM_FLAG_Update); /* 清除溢出中断标志 */
  157. TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
  158. TIM_Cmd(TIM2, ENABLE); /* 开启时钟 */

  159. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , ENABLE); /*先关闭等待使用*/
  160. }

  161. void TIM2_Configration(void)
  162. {
  163. TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
  164. TIM_OCInitTypeDef TIM_OCInitStructure;
  165. //TIM_DeInit(TIM2);
  166. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , ENABLE);

  167. TIM_TimeBaseStructure.TIM_Period=100; /* 自动重装载寄存器周期的值(计数值) */
  168. /* 累计 TIM_Period个频率后产生一个更新或者中断 */
  169. TIM_TimeBaseStructure.TIM_Prescaler= (225 - 1); // 时钟预分频数 72000000/3200 = 22500 = 225 * 100
  170. TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; /* 采样分频 */
  171. TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; /* 向上计数模式 */
  172. TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
  173. TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

  174. TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//PWM模式1
  175. TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//使能

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

  178. TIM_OC2Init(TIM2,&TIM_OCInitStructure);//初始化

  179. TIM_Cmd(TIM2,ENABLE);

  180. TIM_InternalClockConfig(TIM2);
  181. TIM_OC2PreloadConfig(TIM2,TIM_OCPreload_Enable);
  182. TIM_UpdateDisableConfig(TIM2,DISABLE);


  183. }

  184. void dsp_asm_init(void)
  185. {
  186. uint16_t i = 0;
  187. //float fx;
  188. for( i = 0;i
  189. {
  190. //fx = 4000 * sin(PI2*i*50.0/Fs ) + 4000*sin(PI2*i*2500.0/Fs) + 4000*sin(PI2*i*2550.0/Fs);
  191. average = average + ADCConvertedValue[i];
  192. }
  193. average = average / NPT;

  194. for( i = 0;i
  195. {
  196. lBUFIN[i] = ((int16_t)(ADCConvertedValue[i] - average)) << 16;
  197. }

  198. }

  199. void dsp_test(void)
  200. {
  201. cr4_fft_64_stm32(lBUFOUT, lBUFIN, NPT);
  202. dsp_asm_powerMag();
  203. }


  204. // int main(void)
  205. // {
  206. // dsp_asm_init();
  207. // dsp_test();
  208. // dsp_test();
  209. // }



  210. void dsp_asm_powerMag(void)
  211. {
  212. int16_t lX,lY;
  213. uint32_t i;
  214. float X =0.0;
  215. float Y =0.0;
  216. float Mag = 0.0;
  217. for(i=0;i
  218. {
  219. lX = ( lBUFOUT[i] << 16 ) >> 16;
  220. lY = ( lBUFOUT[i] >> 16 );
  221. {
  222. X = NPT * ((float)lX) / 32768;
  223. Y = NPT * ((float)lY) / 32768;
  224. Mag = sqrt ( X*X + Y*Y)/NPT;
  225. lBUFMAG[i] = (uint32_t)(Mag*65536);
  226. }
  227. }
  228. voltage = (float)(lBUFMAG[1]) / 4096.0 * 3.3;

  229. // lX = ( lBUFOUT[1] << 16 ) >> 16;
  230. // lY = ( lBUFOUT[1] >> 16 );
  231. // X = NPT * ((float)lX) / 32768;
  232. // Y = NPT * ((float)lY) / 32768;
  233. // Mag = sqrt ( X*X + Y*Y)/NPT;
  234. // lBUFMAG_base = (uint32_t)(Mag*65536);

  235. }




关键词: STM32F103VET6 采集

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

共2条 1/1 1 跳转至

回复

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