双路低频信号发生分析仪(部分)
程序员文章站
2022-07-12 10:28:39
...
花两天时间做了一下,主要也是想了解一下DFT及FFT的使用,这里写个备忘录以防忘记。
本题要求是程控产生范围为1000hz到2000hz的正弦波矩形波三角波和锯齿波,且步进值为10hz,这里使用stm32的两路DAC来产生波形,大概想法为调用DMA,DAC来构建交互,用TIM来控制频率,从数据手册来看的话DAC上升时间暨相邻两个点的上升时间为1us,用示波器看也确实如此,其他不赘述
一,基础部分
void DAC_Channel1Init(void)
{
DAC_InitTypeDef DAC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
DAC_InitStructure.DAC_Trigger = DAC_Trigger_T2_TRGO;
DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;
DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
DAC_Init(DAC_Channel_1, &DAC_InitStructure);
DAC_SetChannel1Data( DAC_Align_12b_R , 0 );
DAC_Cmd( DAC_Channel_1 , ENABLE );
DAC_DMACmd( DAC_Channel_1 , ENABLE );
}
/******************************************
DAC通道2使能
PA.5输出
*******************************************/
void DAC_Channel2Init(void)
{
DAC_InitTypeDef DAC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
DAC_InitStructure.DAC_Trigger = DAC_Trigger_T4_TRGO;
DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;
DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
DAC_Init(DAC_Channel_2, &DAC_InitStructure);
DAC_SetChannel2Data( DAC_Align_12b_R , 0x00 );
DAC_Cmd( DAC_Channel_2 , ENABLE );
//DAC_DMACmd( DAC_Channel_2 , ENABLE );
}
再配置完DMA
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2|RCC_APB1Periph_TIM4, ENABLE);
TIM_TimeBaseStructure.TIM_Period = 0;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);
配置时钟,改变频率仅需通过改变重装载值即可
正弦波产生
矩形波产生
锯齿波产生
/************************
锯齿波产生
vpp: 赋值
***************************/
void Saw_wave(float vpp)
{
u16 i=0;
u16 Temp=0;
float k=0.0;
Temp = (u16)( (vpp/3.3)*4096);
//printf("%d\r\n",Temp);
k=Temp/1024.0;
//printf("%f\r\n",k);
for(i=0;i<1023;i++)
{
DAC_outData[i]=k*i+80;
//printf("%d\r\n",DAC_outData[i]);
}
DAC_outData[1023]=0;
}
接下来只需要初始化即可自动产生波形,步进值通过按键改变封装函数的值即可。
移相只需要在两个dac准备产生波形的时间之中延时你所需的相位时间即可
两路DAC所产生的相移波形
二 、 FFT变换
两路正弦信号使用加法电路进行叠加,这里使用官方dsp库进行分析
这里用的是DFT采集1024个点的方式,根据采样定律,需要大于最大频率两倍的采样频率才可以正确采样,因此这里调用定时器使用5KHz的频率采样。即每点4.8hz的速率采集
void GetPowerMag(void)
{
signed short lX,lY;
float X,Y,Mag;
unsigned short i;
for(i=0; i<NPT/2; i++)
{
lX = (lBufOutArray[i] << 16) >> 16;
lY = (lBufOutArray[i] >> 16);
X = NPT * ((float)lX) / 32768;
Y = NPT * ((float)lY) / 32768;
Mag = sqrt(X * X + Y * Y) / NPT;
if(i == 0)
lBufMagArray[i] = (unsigned long)(Mag * 32768);
else
lBufMagArray[i] = (unsigned long)(Mag * 65536);
}
}
下一篇: Java进阶总结——异常
推荐阅读