当前位置:   article > 正文

STM32-三重ADC同步采样-FFT测信号相位差_stm32三重采样

stm32三重采样

STM32---adc-fft-信号相位差

目录

STM32---adc-fft-信号相位差

前言:

基础知识:

正文:

时钟配置:

基础配置:

串口配置:

TIM定时器:

ADC配置:

 DMA配置:

代码示例:

结语:


前言:

        在信号处理领域,测量两个信号之间的相位差在许多应用中至关重要,如电力系统的同步、振动分析、以及通信系统中的相位调制。STM32系列微控制器,特别是STM32F407,具有强大的ADC模块,可以实现多路同步采样。通过使用三重ADC同步采样,并结合快速傅里叶变换(FFT),我们可以精确地测量信号之间的相位差。本次将分享如何使用STM32,利用三重ADC同步采样模式,配合FFT测信号相位差。本教程使用stm32f4,基于cubemx、keil5开发。(相位差这一概念,存在于频率相同,相位不同的信号中)


基础知识:

有关FFT的使用方法,大家可以先看看这篇博客

——《stm32-HAL库-fft-测频率幅度

        STM32系列微控制器(如STM32F407)提供了多个ADC模块,允许用户配置它们以同步方式采样多个通道。STM32的多ADC模块可以通过一个公共触发源(例如一个定时器)来实现同步启动,从而保证多ADC通道的采样在同一时间点进行。

正文:

关于时钟,串口,定时器这些比较常规的配置,我就不多做解释了,在下面这篇文章中我有过详细的介绍,如果需要的话,大家可以先看看这篇文章了解一下。下面ADC的配置比较重要!!!

——《stm32-HAL 电赛信号教程

时钟配置:

基础配置:

串口配置:

TIM定时器:

这里我开的是2M采样率。128M/64=2M

ADC配置:

 DMA配置:

到此,配置完成。

代码示例:

这里就以ADC1和ADC2两个ADC采集为例,获得信号的相位差。但实际这个程序也采集了ADC3的数据,处理方法跟这两一样的哈。

(1)宏定义

  1. /* Private define ------------------------------------------------------------*/
  2. /* USER CODE BEGIN PD */
  3. #define FFT_LENGTH 1024
  4. #define ADC1_DMA_Size 3072
  5. #define ADC2_DMA_Size 1024

(2)定义数组变量

  1. int freq1=0; //获得ADC1采集信号的频率
  2. int freq2=0; //获得ADC2采集信号的频率
  3. float phase_1=0; //获得ADC1采集信号的相位
  4. float phase_2=0; //获得ADC2采集信号的相位
  5. float phase_differ=0; //相位差
  6. int SAM_FRE=2000000; //采样率-与cubemx配置的数据一致
  7. float fft_inputbuf1 [FFT_LENGTH*2];
  8. float fft_inputbuf2 [FFT_LENGTH*2];
  9. float fft_outputbuf1[FFT_LENGTH];
  10. float fft_outputbuf2[FFT_LENGTH];
  11. uint32_t ADC1_ConvertedValue[1024][3];//存放各ADC采集到的数据

(3)数据处理

打开ADC-DMA开启数据采集和传输。

  1. HAL_ADC_Start(&hadc1);
  2. HAL_ADC_Start(&hadc2);
  3. HAL_ADC_Start(&hadc3);
  4. HAL_ADCEx_MultiModeStart_DMA(&hadc1,(uint32_t*)ADC1_ConvertedValue,3072);
  5. HAL_TIM_Base_Start(&htim8);
  6. /* USER CODE END 2 */
  7. /* Infinite loop */
  8. /* USER CODE BEGIN WHILE */
  9. while (1)
  10. {

 主函数main中

  1. /* USER CODE BEGIN WHILE */
  2. while (1)
  3. {
  4. if(DMA_FLAG==1)
  5. {
  6. DMA_FLAG=0;
  7. HAL_TIM_Base_Stop(&htim8); //关闭ADC-tim,防止数据处理时数据变化
  8. HAL_ADCEx_MultiModeStop_DMA(&hadc1);
  9. HAL_ADC_Stop(&hadc1);
  10. HAL_ADC_Stop(&hadc2);
  11. HAL_ADC_Stop(&hadc3);
  12. for(int i=0;i<1024;i++)
  13. {
  14. //printf("%d,%d,%d\r\n",ADC1_ConvertedValue[i][0],ADC1_ConvertedValue[i][1],ADC1_ConvertedValue[i][2]);
  15. fft_inputbuf1[i*2]= (ADC1_ConvertedValue[i][0])*3.3/4095;//将ADC1采集的数据放到FFT待处理数组中
  16. fft_inputbuf1[2*i+1]=0;
  17. fft_inputbuf2[i*2]= (ADC1_ConvertedValue[i][1])*3.3/4095;//将ADC2采集的数据放到FFT待处理数组中
  18. fft_inputbuf2[2*i+1]=0;
  19. }
  20. arm_cfft_f32(&arm_cfft_sR_f32_len1024,fft_inputbuf1,0,1); //ADC1采集的数据FFT运算
  21. arm_cmplx_mag_f32(fft_inputbuf1, fft_outputbuf1, FFT_LENGTH);
  22. arm_cfft_f32(&arm_cfft_sR_f32_len1024,fft_inputbuf2,0,1); //ADC2采集的数据FFT运算
  23. arm_cmplx_mag_f32(fft_inputbuf2, fft_outputbuf2, FFT_LENGTH);
  24. freq1= findmax((float*)fft_outputbuf1,1024,2); //获得ADC1采集信号的频率
  25. freq2= findmax((float*)fft_outputbuf2,1024,2); //获得ADC2采集信号的频率
  26. phase_1=Phase_atan(fft_inputbuf1,freq1); //获得ADC1采集信号的相位
  27. phase_2=Phase_atan(fft_inputbuf2,freq2); //获得ADC2采集信号的相位
  28. phase_differ=phase_1-phase_2; //计算相位差
  29. if(phase_differ>180) //相位调整
  30. {
  31. phase_differ=phase_differ-360;
  32. }
  33. if(phase_differ<-180)
  34. {
  35. phase_differ=phase_differ+360;
  36. }
  37. printf("phase_differ = %f\r\n",phase_differ);
  38. HAL_Delay(1000);
  39. HAL_ADC_Start(&hadc1);
  40. HAL_ADC_Start(&hadc2);
  41. HAL_ADC_Start(&hadc3);
  42. HAL_ADCEx_MultiModeStart_DMA(&hadc1,(uint32_t*)ADC1_ConvertedValue,3072);
  43. HAL_TIM_Base_Start(&htim8);
  44. }
  45. /* USER CODE END WHILE */
  46. /* USER CODE BEGIN 3 */
  47. }

信号频率计算函数

  1. int findmax(float*arry,uint16_t len,uint16_t s) //s表示从第几个数开始找
  2. {
  3. int i;
  4. int j=s;
  5. for(i=s;i<len/2;i++)
  6. {
  7. if(arry[i]>arry[j])
  8. {
  9. j=i;
  10. }
  11. }
  12. return j;
  13. }

相位计算函数:FFT计算后的fft_inputbuf数组中,虚部除实部就是相位。

  1. //相位计算函数
  2. float Phase_atan(float32_t *inputSignal,uint32_t index)
  3. {
  4. return atan(inputSignal[2*index+1] / inputSignal[2*index]) / PI * 180;
  5. }

OKOK,代码编写完成,大家可以打ADC1与ADC2采集的数据使用vofa+打印出来,用函数信号发生器产生两个频率相同,相位差为0的信号,可以发现两图案是重叠的,证明确实是同步采样。

结语:

        测量相位的内容较多且较为复杂,可以有点难理解,希望我的分享对大家能有帮助。如果需要完整代码,可以私信我或者留言,有疑问或建议欢迎留言!(这些代码都是在实验室验证过的哟)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/1018164
推荐阅读
相关标签
  

闽ICP备14008679号