> 技术文档 > STM32-三重ADC同步采样-FFT测信号相位差_stm32 fft 相位

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


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)宏定义

/* Private define ------------------------------------------------------------*//* USER CODE BEGIN PD */#define FFT_LENGTH 1024#define ADC1_DMA_Size 3072#define ADC2_DMA_Size 1024

(2)定义数组变量

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

(3)数据处理

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

 HAL_ADC_Start(&hadc1); HAL_ADC_Start(&hadc2); HAL_ADC_Start(&hadc3); HAL_ADCEx_MultiModeStart_DMA(&hadc1,(uint32_t*)ADC1_ConvertedValue,3072); HAL_TIM_Base_Start(&htim8); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) {

 主函数main中

 /* USER CODE BEGIN WHILE */ while (1) { if(DMA_FLAG==1) { DMA_FLAG=0; HAL_TIM_Base_Stop(&htim8); //关闭ADC-tim,防止数据处理时数据变化 HAL_ADCEx_MultiModeStop_DMA(&hadc1); HAL_ADC_Stop(&hadc1); HAL_ADC_Stop(&hadc2); HAL_ADC_Stop(&hadc3); for(int i=0;i180) //相位调整 { phase_differ=phase_differ-360; } if(phase_differ<-180) { phase_differ=phase_differ+360; } printf(\"phase_differ = %f\\r\\n\",phase_differ); HAL_Delay(1000); HAL_ADC_Start(&hadc1);HAL_ADC_Start(&hadc2); HAL_ADC_Start(&hadc3); HAL_ADCEx_MultiModeStart_DMA(&hadc1,(uint32_t*)ADC1_ConvertedValue,3072); HAL_TIM_Base_Start(&htim8); } /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ }

信号频率计算函数

int findmax(float*arry,uint16_t len,uint16_t s) //s表示从第几个数开始找 { int i; int j=s; for(i=s;iarry[j]) { j=i; } } return j; }

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

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

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

结语:

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