DSP TMS320C5509A 控制DDS AD9854芯片驱动

15 篇文章 1 订阅

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左右。

下次再写如何调制。

 

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值