DSP

DSP TMS320C5509A 控制DDS AD9854芯片驱动

2019-07-13 12:47发布

AD9854是一款200MHz主频的DDS,支持AM.FSK,PSK调制的方式, 可以用串行和并行两种方式进行控制,推荐用并行控制, 由于DSP管脚驱动能力较弱,如果PCB布线时两个芯片距离较远,最好加入驱动芯片。 AD9854的驱动基本上三步走, 第一步,确定时钟; 第二步,确定频率控制字FTW; 第三步,初始化寄存器。 首先是时钟配置 #define CLK_Set 12 #define CRYSTAL 12800000 12.8MHz的晶振 12倍频 然后根据芯片手册中FTW的计算公式,由于是48位累加器,设置如下 const unsigned long Freq_mult_ulong = 1832519; const double Freq_mult_doulle = 1832519.379626667; 然后是寄存器配置 //DDS寄存器设置 uint8 AD9854_Addr_PHA1_config[AD9854_Length_PHA1+1] = {AD9854_Addr_PHA1,0x00,0x00}; uint8 AD9854_Addr_PHA2_config[AD9854_Length_PHA2+1] = {AD9854_Addr_PHA2,0x00,0x00}; uint8 AD9854_Addr_FRE1_config[AD9854_Length_FRE1+1] = {AD9854_Addr_FRE1,0x0,0x5,0x1F,0x0,0x0,0x0}; uint8 AD9854_Addr_FRE2_config[AD9854_Length_FRE2+1] = {AD9854_Addr_FRE2,0x0,0x0,0x0,0x0,0x0,0x0}; uint8 AD9854_Addr_DELTA_config[AD9854_Length_DELTA+1] = {AD9854_Addr_DELTA,0x00,0x00,0x00,0x00,0x00,0x00}; uint8 AD9854_Addr_UPDATA_config[AD9854_Length_UPDATA+1] = {AD9854_Addr_UPDATA,0x00,0x00,0x00,0x00}; uint8 AD9854_Addr_RAMP_CLK_config[AD9854_Length_RAMP_CLK+1] = {AD9854_Addr_RAMP_CLK,0x00,0x00,0x00}; uint8 AD9854_Addr_CTR_REG_config[AD9854_Length_CTR_REG+1] = {AD9854_Addr_CTR_REG,0x00,CLK_Set,0x00,0x60}; uint8 AD9854_Addr_I_MUL_config[AD9854_Length_I_MUL+1] = {AD9854_Addr_I_MUL,0xff,0xff}; uint8 AD9854_Addr_Q_MUL_config[ AD9854_Length_Q_MUL+1] = {AD9854_Addr_Q_MUL,0xff,0xff}; uint8 AD9854_Addr_SHAPED_config[AD9854_Length_SHAPED+1] = {AD9854_Addr_SHAPED,0x00}; uint8 AD9854_Addr_Q_DAC_config[AD9854_Length_Q_DAC+1] = {AD9854_Addr_Q_DAC,0x00,0x00}; 下面看配置函数 void ad9854_update(void) { UNCLOCK_HIGH; GPIO_ALL.GPIO_SUM = GPIO_ALL.GPIO_SUM & 0x00ff; GPIO_RSET(IODATA,(unsigned char)GPIO_ALL.GPIO_SUM); //更新AD9854输出 //delay(15); asm(" nop "); UNCLOCK_LOW; GPIO_ALL.GPIO_SUM = GPIO_ALL.GPIO_SUM & 0x00ff; GPIO_RSET(IODATA,(unsigned char)GPIO_ALL.GPIO_SUM); } //==================================================================================== //函数名称:void AD9854_WR_Byte(uchar addr,uchar dat) //函数功能:AD9854并行口写入数据 //入口参数:addr 6位地址 // dat 写入的数据 //出口参数:无 //==================================================================================== void AD9854_WR_Byte(uint8 addr,uint8 dat) { unsigned int aport_data; unsigned int addr_real,data_real; GPIO_RSET(AGPIODIR,0xFFFF); addr_real = addr; data_real = dat; /* 0<<13 1<<12 2<<11 3<<10*/ aport_data = 0x3FFF&(((addr_real & 0x1)<<13)|((addr_real & 0x2)<<11)|((addr_real & 0x4)<<9)|((addr_real & 0x8)<<7)| /* 4<<9 5<<8 0<<7 1<<6*/ ((addr_real & 0x10)<<5)|((addr_real & 0x20)<<3)|((data_real & 0x1)<<7)|((data_real & 0x02)<<5)| /* 2<<5 3<<4 4>>3 5>>2*/ ((data_real & 0x04)<<3)|((data_real & 0x8)<<1)|((data_real & 0x10)>>1)|((data_real & 0x20)>>3) /* 6>>1 7>>0*/ |((data_real & 0x40)>>5)|((data_real & 0x80)>>7)); GPIO_RSET(AGPIODATA,aport_data); asm(" nop "); WR_EN; GPIO_ALL.GPIO_SUM = GPIO_ALL.GPIO_SUM & 0x00ff; GPIO_RSET(IODATA,(unsigned char)GPIO_ALL.GPIO_SUM); asm(" nop "); WR_DIS; GPIO_ALL.GPIO_SUM = GPIO_ALL.GPIO_SUM & 0x00ff; GPIO_RSET(IODATA,(unsigned char)GPIO_ALL.GPIO_SUM); // delay(100); } //==================================================================================== //函数名称:uint8 AD9854_WR_Byte(uchar addr) //函数功能:AD9854并行口读取数据 //入口参数:addr 6位地址 // //出口参数:读到的数据 8位数据 //==================================================================================== uint8 AD9854_RD_Byte(uint8 addr) { unsigned int aport_data; unsigned int realdata = 0; unsigned int realaddr = 0; GPIO_RSET(AGPIODIR,0x3F00); /* 0<<13 1<<12 2<<11 3<<10*/ realaddr = ((addr & 0x1)<<13)|((addr & 0x2)<<11)|((addr & 0x4)<<9)|((addr & 0x8)<<7)| /* 4<<9 5<<8*/ ((addr & 0x10)<<5)|((addr & 0x20)<<3); GPIO_RSET(AGPIODATA,realaddr); RD_EN; // GPIO_RSET(IODATA,GPIO_ALL.GPIO_SUM); delay(100); aport_data=GPIO_RGET(AGPIODATA) & 0xff; /* 0<<7 1<<6 2<<5 3<<4*/ realdata = ((aport_data & 0x01)<<7) | ((aport_data & 0x02)<<5) | ((aport_data & 0x04)<<3) | ((aport_data & 0x08)<<1)| /* 4>>3 5>>2 6>>1 7>>0*/ ((aport_data & 0x10)>>1) | ((aport_data & 0x20)>>3) | ((aport_data & 0x40)>>5) | ((aport_data & 0x80)>>7); RD_DIS; // GPIO_RSET(IODATA,GPIO_ALL.GPIO_SUM); return((uint8)realdata); } //==================================================================================== //函数名称:void Freq_doublt_convert(double Freq) //函数功能:正弦信号频率数据转换 //入口参数:Freq 需要转换的频率,取值从0~SYSCLK/2 //出口参数:无 但是影响全局变量FreqWord[6]的值 //说明: 有公式FTW = (Desired Output Frequency × 2N)/SYSCLK得到该函数, // 其中N=48,Desired Output Frequency 为所需要的频率,即Freq,SYSCLK // 为可编程的系统时钟,FTW为48Bit的频率控制字,即FreqWord[6] //注意: 该函数与上面函数的区别为该函数的入口参数为double,可使信号的频率更精确 // 建议在100HZ以下用本函数,在高于100HZ的情况下用函数void Freq_convert(long Freq) //==================================================================================== void Freq_double_convert(double Freq) { unsigned long Low32; unsigned int High16; double Temp=Freq_mult_doulle; //2的48次方除以当前CLK频率(参考晶振乘以倍频) Freq*=(double)(Temp); // 1 0000 0000 0000 0000 0000 0000 0000 0000 = 4294967295 High16 =(int)(Freq/4294967295); //2^32 = 4294967295 Freq -= (double)High16*4294967295; Low32 = (unsigned long)Freq; AD9854_Addr_FRE1_config[1]=Low32; AD9854_Addr_FRE1_config[2]=Low32>>8; AD9854_Addr_FRE1_config[3]=Low32>>16; AD9854_Addr_FRE1_config[4]=Low32>>24; AD9854_Addr_FRE1_config[5]=High16; AD9854_Addr_FRE1_config[6]=High16>>8; } 采用的是DSP的GPIO口组控制命令信号,A组引脚控制地址和数据,以后有机会会放原理图,请留意后续文章。 之后是初始化和生成波形的程序 //==================================================================================== //函数名称:void Freq_doublt_convert(double Freq) //函数功能:正弦信号频率数据转换 //入口参数:Freq 需要转换的频率,取值从0~SYSCLK/2 //出口参数:无 但是影响全局变量FreqWord[6]的值 //说明: 有公式FTW = (Desired Output Frequency × 2N)/SYSCLK得到该函数, // 其中N=48,Desired Output Frequency 为所需要的频率,即Freq,SYSCLK // 为可编程的系统时钟,FTW为48Bit的频率控制字,即FreqWord[6] //注意: 该函数与上面函数的区别为该函数的入口参数为double,可使信号的频率更精确 // 建议在100HZ以下用本函数,在高于100HZ的情况下用函数void Freq_convert(long Freq) //==================================================================================== void Freq_double_convert(double Freq) { unsigned long Low32; unsigned int High16; double Temp=Freq_mult_doulle; //2的48次方除以当前CLK频率(参考晶振乘以倍频) Freq*=(double)(Temp); // 1 0000 0000 0000 0000 0000 0000 0000 0000 = 4294967295 High16 =(int)(Freq/4294967295); //2^32 = 4294967295 Freq -= (double)High16*4294967295; Low32 = (unsigned long)Freq; AD9854_Addr_FRE1_config[1]=Low32; AD9854_Addr_FRE1_config[2]=Low32>>8; AD9854_Addr_FRE1_config[3]=Low32>>16; AD9854_Addr_FRE1_config[4]=Low32>>24; AD9854_Addr_FRE1_config[5]=High16; AD9854_Addr_FRE1_config[6]=High16>>8; } void ad9854_int(void) { GPIO_RSET(AGPIOEN,0xFFFF); //A端口设置为GPIO GPIO_RSET(AGPIODIR,0xFFFF); //全部输出 GPIO_RSET(IODIR,0xFF); //GPIO端口全部输出 RESET_LOW; WR_DIS; RD_DIS; // CRYSTAL_ON; UNCLOCK_LOW; GPIO_ALL.GPIO_SUM = GPIO_ALL.GPIO_SUM & 0x00ff; GPIO_RSET(IODATA,(unsigned char)GPIO_ALL.GPIO_SUM); //初始化 RESET_HIGH; GPIO_ALL.GPIO_SUM = GPIO_ALL.GPIO_SUM & 0x00ff; GPIO_RSET(IODATA,(unsigned char)GPIO_ALL.GPIO_SUM); //主复位 delay(15); RESET_LOW; GPIO_ALL.GPIO_SUM = GPIO_ALL.GPIO_SUM & 0x00ff; GPIO_RSET(IODATA,(unsigned char)GPIO_ALL.GPIO_SUM); // CRYSTAL_OFF; // GPIO_RSET(IODATA,GPIO_ALL.GPIO_SUM); //关晶振 // delay(100); // AD9854_WR_Byte(0x16,0xff); // AD9854_WR_Byte(0x17,0xff); // AD9854_WR_Byte(0x18,0xff); AD9854_WR_Byte(0x19,0x40); AD9854_WR_Byte(CTRL1_ADDRESS,0x14); //关闭比较器 AD9854_WR_Byte(CTRL2_ADDRESS,CLK_Set); //设置系统时钟倍频 AD9854_WR_Byte(CTRL3_ADDRESS,0x00); //设置系统为模式0,由外部更新 AD9854_WR_Byte(CTRL4_ADDRESS,0x60); //设置为可调节幅度,取消插值补偿 // AD9854_WR_Byte(OSK_RAMP_DATE_ADDRESS,0x00); // CRYSTAL_ON; // GPIO_RSET(IODATA,GPIO_ALL.GPIO_SUM); delay(100); ad9854_update(); //更新AD9854输出 } //==================================================================================== //函数名称:void AD9854_SetSine_double(double Freq,uint Shape) //函数功能:AD9854正弦波产生程序 //入口参数:Freq 频率设置,取值范围为0~1/2*SYSCLK // Amp 幅度设置. 为12 Bit,取值范围为(0~4095) //出口参数:无 //==================================================================================== void AD9854_SetSine_double(double Freq,uint16 Amp) { uint8 count=0; uint8 Adress=FTW1_ADDRESS; Freq_double_convert(Freq); //频率转换 for(count=0;count<6;count++) //写入6字节的频率控制字 { AD9854_WR_Byte(Adress++,AD9854_Addr_FRE1_config[6-count]); } AD9854_WR_Byte(OSK_I1_ADDRESS,Amp>>8); //设置I通道幅度 AD9854_WR_Byte(OSK_I2_ADDRESS,(uint8)(Amp&0xff)); AD9854_WR_Byte(OSK_Q1_ADDRESS,Amp>>8); //设置Q通道幅度 AD9854_WR_Byte(OSK_Q2_ADDRESS,(uint8)(Amp&0xff)); ad9854_update(); } 然后调用如下两个函数即可 ad9854_int(); AD9854_SetSine_double(455000,4095); 头文件如下: #ifndef DDS_H #define DDS_H #include "csl_gpio.h" #define AD9854_Addr_PHA1 0 // 2 Bytes #define AD9854_Addr_PHA2 1 // 2 Bytes #define AD9854_Addr_FRE1 2 // 6 Bytes #define AD9854_Addr_FRE2 3 // 6 Bytes #define AD9854_Addr_DELTA 4 // 6 Bytes #define AD9854_Addr_UPDATA 5 // 4 Bytes #define AD9854_Addr_RAMP_CLK 6 // 3 Bytes #define AD9854_Addr_CTR_REG 7 // 4 Bytes #define AD9854_Addr_I_MUL 8 // 2 Bytes #define AD9854_Addr_Q_MUL 9 // 2 Bytes #define AD9854_Addr_SHAPED 10 // 1 Bytes #define AD9854_Addr_Q_DAC 11 // 2 Bytes #define AD9854_Length_PHA1 2 // 2 Bytes #define AD9854_Length_PHA2 2 // 2 Bytes #define AD9854_Length_FRE1 6 // 6 Bytes #define AD9854_Length_FRE2 6 // 6 Bytes #define AD9854_Length_DELTA 6 // 6 Bytes #define AD9854_Length_UPDATA 4 // 4 Bytes #define AD9854_Length_RAMP_CLK 3 // 3 Bytes #define AD9854_Length_CTR_REG 4 // 4 Bytes #define AD9854_Length_I_MUL 2 // 2 Bytes #define AD9854_Length_Q_MUL 2 // 2 Bytes #define AD9854_Length_SHAPED 1 // 1 Bytes #define AD9854_Length_Q_DAC 2 // 2 Bytes typedef unsigned char uint8; typedef unsigned int uint16; union { unsigned char GPIO_SUM; struct { unsigned int RES2:8; unsigned int GOIO_7:1; unsigned int GOIO_6:1; unsigned int RES1:1; unsigned int GOIO_4:1; unsigned int GOIO_3:1; unsigned int GOIO_2:1; unsigned int GOIO_1:1; unsigned int GOIO_0:1; }GPIO_8; }GPIO_ALL; //parallel define #define RESET_HIGH (GPIO_ALL.GPIO_8.GOIO_4=1) #define RESET_LOW (GPIO_ALL.GPIO_8.GOIO_4=0) #define WR_DIS (GPIO_ALL.GPIO_8.GOIO_6=1) #define WR_EN (GPIO_ALL.GPIO_8.GOIO_6=0) #define RD_DIS asm(" SSBX XF ") //XF置1 RD_DIS #define RD_EN asm(" RSBX XF ") //XF置0 RD_EN //#define CRYSTAL_ON (GPIO_ALL.GPIO_8.GOIO_4=1) //#define CRYSTAL_OFF (GPIO_ALL.GPIO_8.GOIO_4=0) #define UNCLOCK_HIGH (GPIO_ALL.GPIO_8.GOIO_7=1) #define UNCLOCK_LOW (GPIO_ALL.GPIO_8.GOIO_7=0) //serial define #define IO_RESET_HIGH_SER (GPIO_ALL.GPIO_8.GOIO_0=1) #define IO_RESET_LOW_SER (GPIO_ALL.GPIO_8.GOIO_0=0) #define RESET_HIGH_SER (GPIO_ALL.GPIO_8.GOIO_1=1) #define RESET_LOW_SER (GPIO_ALL.GPIO_8.GOIO_1=0) #define CRYSTAL_ON_SER (GPIO_ALL.GPIO_8.GOIO_2=1) #define CRYSTAL_OFF_SER (GPIO_ALL.GPIO_8.GOIO_2=0) #define UNCLOCK_HIGH_SER (GPIO_ALL.GPIO_8.GOIO_7=1) #define UNCLOCK_LOW_SER (GPIO_ALL.GPIO_8.GOIO_7=0) //parallel address #define FTW1_ADDRESS 0x04 #define FTW2_ADDRESS 0x05 #define FTW3_ADDRESS 0x06 #define FTW4_ADDRESS 0x07 #define FTW5_ADDRESS 0x08 #define FTW6_ADDRESS 0x09 #define UNCLOCK1_ADDRESS 0x16 #define UNCLOCK2_ADDRESS 0x17 #define UNCLOCK3_ADDRESS 0x18 #define UNCLOCK4_ADDRESS 0x19 #define CTRL1_ADDRESS 0x1D #define CTRL2_ADDRESS 0x1E #define CTRL3_ADDRESS 0x1F #define CTRL4_ADDRESS 0x20 #define OSK_I1_ADDRESS 0x21 #define OSK_I2_ADDRESS 0x22 #define OSK_Q1_ADDRESS 0x23 #define OSK_Q2_ADDRESS 0x24 #define OSK_RAMP_DATE_ADDRESS 0x25 extern char dds_flag; #endif 这样会输出一个满幅值的455KHz的正弦波形,幅度大约为-7dBm左右。 下次再写如何调制。