使用STM32 DAC DMA和AD9850构建的高性能波形发生器
基于STM32+DAC+DMA和AD9850的波形发生器
试验目的
一、通过STM32单片机DAC+DMA产生频率可调正弦波、三角波、锯齿波、方波。
二、使用STM32驱动AD9850波形发生模块产生正弦波和方波。
一、AD9850/AD9851的简介
AD9850/AD9851 模块是采用 ADI 应用最广泛的 DDS(AD9850 和 AD9851)制作的模块。
主要功能特点:
模块能够输出正弦波和方波,2 个正弦波和 2 个方波输出。
AD9850: 0-40MHz
AD9851: 0-70MHz
频率在 20-30MHz 后谐波越来越大,波形会越来越不干净。
方波: 0-1MHz
采用 70MHz 的低通滤波器,使波形的 SN 比更好
比较器的基准输入端电压由可变电阻产生,调节该电阻可以得到不同的占空比方波
AD9850 模块采用 125MHz 的有源晶振,AD9851 模块采用 30MHZ 的有源晶振
二、AD9850驱动程序
1、模块初始化
/********************************************
函数名称:Init_AD9834(主要是初始化GPIO)
功 能:初始化AD9834
参 数:无
返回值 :无
*********************************************/
void Init_AD9850(void)
{
#ifdef MODE_SEIAL //串行模式
GPIO_InitTypeDef GPIO_InitStructure ;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);
GPIO_InitStructure.GPIO_Pin = AD9850_WCLK | AD9850_FQUD | AD9850_RST | AD9850_DATA ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(AD9850_CONTROL_PORT ,&GPIO_InitStructure) ;
AD9850_Reset_Sreial() ;
#endif
#ifdef MODE_PARALLEL //并行模式
GPIO_InitTypeDef GPIO_InitStructure ;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO , ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);//?
GPIO_InitStructure.GPIO_Pin = AD9850_WCLK | AD9850_FQUD | AD9850_RST ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
GPIO_Init(AD9850_CONTROL_PORT ,&GPIO_InitStructure) ;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All ;//可以
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(AD9850_DATA_PORT ,&GPIO_InitStructure);
AD9850_Reset_Parallel() ;//并行模式下复位AD9850
#endif
}
/********************************************
函数名称:AD9850_Reset_Sreial
功 能:在串行模式下复位AD9850
参 数:无
返回值 :无
*********************************************/
void AD9850_Reset_Sreial(void)
{
AD9850_WCLK_CLR ;
AD9850_FQUD_CLR ;
//RST信号
AD9850_RST_CLR ;
AD9850_RST_SET ;
// AD9850_Delay(0xFFFF) ;
delay_ms(3);
AD9850_RST_CLR ;
//WCLK信号
AD9850_WCLK_CLR ;
AD9850_WCLK_SET ;
// AD9850_Delay(0xFFFF) ;
delay_ms(3);
AD9850_WCLK_CLR ;
//FQUD信号
AD9850_FQUD_CLR ;
AD9850_FQUD_SET ;
// AD9850_Delay(0xFFFF) ;
delay_ms(3);
AD9850_FQUD_CLR ;
}
2、串行模式数据写入
/********************************************
函数名称:AD9850_Write_Serial
功 能:在串行模式下写AD9850寄存器
参 数:W0 - W0寄存器的值
freq - 频率值
返回值 :无
*********************************************/
void AD9850_Write_Serial(unsigned char W0,unsigned long freq)
{
unsigned char i,wdata ;
unsigned long y ;
y=4294967296.0/125;
y*=(((float)freq)/1000000);
wdata = y>>0 ; //写w4
for(i=0 ;i<8 ;i++)
{
if(wdata & 0x01)
AD9850_DATA_Write_1 ;
else
AD9850_DATA_Write_0 ;
AD9850_WCLK_SET ;
wdata >>= 1 ;
AD9850_WCLK_CLR ;
}
wdata = y>>8 ; //写w3
for(i=0 ;i<8 ;i++)
{
if(wdata & 0x01)
AD9850_DATA_Write_1 ;
else
AD9850_DATA_Write_0 ;
AD9850_WCLK_SET ;
wdata >>= 1 ;
AD9850_WCLK_CLR ;
}
wdata = y>>16 ; //写w2
for(i=0 ;i<8 ;i++)
{
if(wdata & 0x01)
AD9850_DATA_Write_1 ;
else
AD9850_DATA_Write_0 ;
AD9850_WCLK_SET ;
wdata >>= 1 ;
AD9850_WCLK_CLR ;
}
wdata = y>>24 ; //写w1
for(i=0 ;i<8 ;i++)
{
if(wdata & 0x01)
AD9850_DATA_Write_1 ;
else
AD9850_DATA_Write_0 ;
AD9850_WCLK_SET ;
wdata >>= 1 ;
AD9850_WCLK_CLR ;
}
wdata = W0 ; //写w0
for(i=0 ;i<8 ;i++)
{
if(wdata & 0x01)
AD9850_DATA_Write_1 ;
else
AD9850_DATA_Write_0 ;
AD9850_WCLK_SET ;
wdata >>= 1 ;
AD9850_WCLK_CLR ;
}
AD9850_FQUD_SET ; //移入使能
// AD9850_Delay(0xFFFF) ;
AD9850_FQUD_CLR ;
}
三、基于STM32+DAC+DMA 的波形发生器
1、DAC DMA 初始化
void Wave_Init(u16 Wave1_Fre,float Um_H,float Um_l)
{
u32 Freq;
Freq=(u32)(72000000/sizeof(SineWave_Value)*2/Wave1_Fre);//计算频率
// SquareWave_Data(256,SineWave_Value,Um_H,Um_l);//产生方波
// SineWave_Data(256,SineWave_Value,Um_H);//产生正弦波
TriangleWave_Data(256,SineWave_Value,Um_H);//产生三角波
// SawTooth_Data(256,SineWave_Value,Um_H);//产生锯齿波
SineWave_GPIO_Config(); //初始化io
SineWave_TIM_Config(Freq); //初始化定时器
SineWave_DAC_Config(); //配置DAC
SineWave_DMA_Config(); //配置DMA
TIM_Cmd(TIM2, ENABLE);
}
2、生成波形数据表
/********生成正弦波输出表***********/
//cycle :波形表的位数 (0~256)
//Um :输出电压的峰值(0~1.5)
/*******************************/
void SineWave_Data( u16 cycle ,u16 *D,float Um)
{
u16 i;
for( i=0;i<cycle;i++)
{
D[i]=(u16)((Um*sin(( 1.0*i/(cycle-1))*2*PI)+Um)*4095/3.3);
}
}
/********生成方波输出表***********/
//cycle :波形表的位数 (0~256)
//Um :输出电压
/*******************************/
void SquareWave_Data( u16 cycle ,u16 *D,float Um_H,float Um_L)
{
u16 i;
float daH=0,daL=0;
daH=4095*Um_H/3.3f;
daL=4095*Um_L/3.3f;
for(i=0;i<256/2;i++)
{
D[i]= (u16)(daL);
}
for( i=256/2;i<256;i++)
{
D[i]=(u16)(daH);
}
}
/********生成三角波输出表***********/
//cycle :波形表的位数 (0~256)
//Um :输出电压的峰值(0~1.5)
/*******************************/
void TriangleWave_Data( u16 cycle ,u16 *D,float Um)
{
u16 i;
int n=1;
for( i=0;i<cycle;i++)
{
if(i<cycle/2)
{
D[i]= (u16)(1.0*i/255*4095);
}
else
{
D[i]= (u16)(1.0*(i-2*n)/255*4095);
n++;
}
}
}
/********生成锯齿波形输出表***********/
//cycle :波形表的位数 (0~256)
//Um :输出电压
/*******************************/
void SawTooth_Data( u16 cycle ,u16 *D,float Um)
{
u16 i;
for( i=0;i<cycle;i++)
{
D[i]= (u16)(1.0*i/255*4095);
}
}
3、主函数
int main(void)
{
uint32_t FREQ=10000;
u8 p[250];
delay_init();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
uart_init(115200);
Init_AD9850();
LED_Init();
LCD_Init();
LCD_Clear(BLACK);
BACK_COLOR = BLACK;
POINT_COLOR = WHITE;
LCD_ShowString(50,40,200,24,24,(u8*)"AD9850 TEST");
AD9850_Write_Serial(0x00,FREQ);
sprintf((char*)p,"Freq : %d KHz",FREQ/1000);
if(FREQ>=1000000) sprintf((char*)p,"Freq : %d MHz",FREQ/1000000);
LCD_ShowString(30,100,200,24,24,p);
Wave_Init(SquareFreq,SquareV_H,SquareV_L);
while(1)
{
LED0=!LED0;
delay_ms(250);
}
}
四、调试波形