微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 实现stm32在FSK调制解调器的综合设计

实现stm32在FSK调制解调器的综合设计

时间:11-13 来源:互联网 点击:

缓存大小为64

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

DMA_InitStructure.DMA_Priority = DMA_Priority_High;

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

DMA_Init(DMA2_Channel4,&DMA_InitStructure);

DMA_Cmd(DMA2_Channel4, ENABLE);

}

TIM2和DAC的配置如下:

void TIM2_DAC_Init(u16 arr,u16 psc)

{

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

DAC_InitTypeDef DAC_InitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);

TIM_TimeBaseStructure.TIM_Period = arr;

TIM_TimeBaseStructure.TIM_Prescaler = psc;

TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Down; //设为向下计数

TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);

DAC_InitStructure.DAC_Trigger = DAC_Trigger_T2_TRGO;

DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;

DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable; //使能输出缓存

DAC_Init(DAC_Channel_2, &DAC_InitStructure);

DAC_Cmd(DAC_Channel_2, ENABLE);

DAC_DMACmd(DAC_Channel_2, ENABLE);

TIM_Cmd(TIM2, ENABLE);

}

这里笔者把两个模块的配置同时放在一个初始化函数里面,只是图个方便,在官方例程里是将DAC和DMA的配置放在一起。这段代码有两个地方需要注意:一是TIM2计数模式设为向下计数,二是使能了DAC的输出缓存。设为向下计数是为了在两个正弦波频率切换时不会因为计数溢出而出现问题,在FSK产生环节里还会详细说到这一点;使能输出缓存是因为stm32的DAC在输出缓存关闭时输出阻抗太大,带负载能力弱,在输入捕获时正弦波严重失真,故需要开启输出缓存,但同时也存在一个问题:使能输出缓存后,DAC没办法使输出达到0,这就使得原始正弦波的峰值数据丢失,导致底部失真。于是我们需要用上面的代码对原始正弦波数据做一个处理——先乘上8除以10防止峰值超过12位精度的最大值4096(不能直接乘上0.8,因为数组存储的数据必须是整形),然后再加上500,将正弦波数据整体抬高。
生成正弦波后自然是要把两个正弦波组合在一起形成FSK信号,这个组合当然不是随意组合,是要在基带信号的控制下进行。代码在主函数执行,如下:

int main(void)

{

... //初始化代码

while(1)

{

if(Base_Signal == 1)

{

TIM2->ARR = 140;;

}

if(Base_Signal == 0)

{

TIM2->ARR = 280;

}

}

}

while(1)循环里if语句判断基带信号的码元序列,“1”对应8khz载波,“0”对应4khz载波。通过改变TIM2的自动重装载寄存器(ARR)的值实现两个载波的频率切换。解释一下这里为什么选择140和280:采样64个点,8khz对应的DAC转换速率为8000*64hz,那么TIM2就要每隔8000/64/72 000 000 = 1/140s触发一次DAC,故TIM2的ARR值为140;同样的,4khz对应的ARR值为280。在这里还要注意:TIM2的计数模式应配置为向下计数。一般例程都会把定时器配置为向上计数,但用在这里会出现一个问题:在基带信号由0变为1时,FSK信号也要相应的从4khz正弦波跳变到8khz正弦波。我们知道向上计数模式是TIM2->CNT寄存器从0开始计数,一直计到ARR的值,进入中断,然后重新清零,继续计数直到又达到ARR设定的值。。。假设FSK信号在4khz正弦波时TIM2->CNT一度计数到140以上(此时ARR的值为280),突然基带信号变为1,FSK信号由4khz正弦波变为8khz,ARR值被设定为140,这时候CNT寄存器将一直往上计数,永远不会停止,直到溢出(ARR寄存器为16位)。实际上笔者在调试时,当基带信号为“1“,输出的FSK信号为一条直线。把计数模式改为向下计数,问题解决。
经过上述一番折腾,调制总算是搞定了。

接下来就是解调。笔者用了两次解调才把基带信号完整复现出来。先来看看初步解调代码,用的是TIM1

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top