ad9851程序
- 格式:doc
- 大小:148.50 KB
- 文档页数:21
AD9851内部有5个输入寄存器,储存来自外部数据线(Do~D7)的32位频率控制字、5个相位控制字、1位6倍参考时钟倍乘器使能控制、1位电源休眠功能(powerdown)控制及一位逻辑0.寄存器接受数的方式有并行输入和串行输入两种方式.并行输入方式是通过Do~D78位数据线来完成40位控制数据的输入.复位信号RESET 有效,会使输入数据地址指针指向第一个输入寄存器,W—CLK信号上升沿写入第一组8位数据,并把指针指向下一个输入寄存器,连续5个W—CLK上升沿,即可完成40位控制数据的输入,FQ—UD信
号上升沿后40位数据,从输入寄存器被写入频率和相位控制寄存器,更新DDS 的信号输出频率和相位.
AD9851内部的控制字寄存器首先寄存来自外部的频率、相位控制字,相位累加器接收来自控制字寄存器的数据后,决定最终输出信号频率和相位的范围及精度.然后再经过内部D /A 转换器,得到最终的数字合成信号.如果相位累加器的位数为N ,相位控制字的值为F ,频率控制字的位数为M ,频率控制字的值为FM ,参考时钟乘法器使能为系统外部参考时钟,频率为30 MHz ,6倍频,经过内部6倍参考时钟乘法器后,可得到AD9851内部工作时钟F 。
为180 MHz ,此时最终合成信号的频率可由公式(1)来决定,合成信号的相位由公式(2)来决定.
/2C F F F M
M =
(1) 2/2F θπN
N =
(2)。
电赛总结(四)——波形发⽣芯⽚总结之AD9851⼀、特性参数1、180 MHz时钟速率参考时钟具有6倍倍乘器。
芯⽚具有⾼性能10位DAC和⾼速滞后⽐较器2、+2.7 V⾄+5.25 V单电源⼯作3、正常输出⼯作频率范围为 0~72MHz ;4、具有6倍频,所以只要30MHz的时钟供给即可。
⼆、功能管脚图三、管脚说明管脚名称功能D0–D78位数据输⼊. 数据端⼝,⽤于装载32位的频率控制字和8位相位控制字。
D7为最⾼位,D0=最低位D7, 25引脚, 也作为40位控制字串⾏输⼊引脚PGND6倍参考时钟倍乘器地PVcc6倍参考时钟倍乘器电源W-CLK字装⼊信号,上升沿有效FQ-UD频率更新控制信号,时钟上升沿确认输⼊数据有效FREFCLOCK外部参考时钟输⼊,脉冲序列可直接或间接地加到6倍参考时钟倍乘器上。
在直接⽅式中,输⼊频率即是系统时钟;在6倍参考时钟倍乘器⽅式,系统时钟为倍乘器输出AGND模拟地AVDD模拟电源(+5V)DGND数字地DVDD数字电源(+5V)RSET DAC外部参考电阻连接端VOUTN内部⽐较器负向输出端VOUTP内部⽐较器正向输出端VINN内部⽐较器的负向输⼊端VINP内部⽐较器的正向输⼊端DACBP DAC旁路连接端IOUTB“互补”DAC输出IOUT内部DAC输出端RESET复位端。
低电平清除DDS累加器和相位延迟器为0Hz和0 相位,同时置数据输⼊为串⾏模式以及禁⽌6倍参考时钟倍乘器⼯作四、外围电路PCB原理图五、STM32F103驱动程序#ifndef __AD9851_H#define __AD9851_H#include "stm32f10x.h"#include "gpio.h"#define ad9851_Clk Pin10#define ad9851_FQ_UD Pin11#define ad9851_Rst Pin12#define ad9851_D0 Pin2#define ad9851_D1 Pin3#define ad9851_D2 Pin4#define ad9851_D3 Pin5#define ad9851_D4 Pin6#define ad9851_D5 Pin7#define ad9851_D6 Pin8#define ad9851_D7 Pin9void ad9851_write_dds(unsigned long dds);void ad9851_init(void);void ad9851_writefrq(unsigned long freq);#endif /* __DAC_H */#include "ad9851.h"#include "pbdata.h"#include "math.h"unsigned char phase_word = 0x00; //相位控制字,使⽤低五位unsigned char power_down = 0x00; //低功耗模式unsigned char mult = 0x01; //六倍频开关unsigned char ww[5] = {0x09,0x0E,0x38,0xE3,0xBE};unsigned long freq,set_value;void ad9851_init(void){set_out(GPIOG,ad9851_Clk | ad9851_FQ_UD | ad9851_Rst | ad9851_D0 | ad9851_D1 | ad9851_D2 | ad9851_D3 | ad9851_D4 | ad9851_D5 |ad9851_D6 | ad9851_D7 ); set_outH(GPIOG,ad9851_Rst);delay_ms(10);set_outL(GPIOG,ad9851_Rst);delay_ms(10);}void ad9851_write_dds(unsigned long dds){unsigned char i;ww[0] = (phase_word << 3) | power_down << 2 | mult;ww[1] = (dds >> 24) & 0xff;ww[2] = (dds >> 16) & 0xff;ww[3] = (dds >> 8) & 0xff;ww[4] = dds & 0xff;set_outL(GPIOG,ad9851_FQ_UD);for(i=0;i<5;i++){set_outL(GPIOG,ad9851_Clk);set_outH(GPIOG,ww[i] << 2);set_outL(GPIOG,((~ww[i]) << 2) & 0x3fc);delay_us(10);set_outH(GPIOG,ad9851_Clk);delay_us(10);}set_outH(GPIOG,ad9851_FQ_UD);delay_us(10);set_outL(GPIOG,ad9851_FQ_UD);}void ad9851_writefrq(unsigned long freq){unsigned long dds;dds = freq;ad9851_write_dds(dds);}。
--------------------------------------------------------------------------------直接数字频率合成AD9851的原理AD9851可以产生一个频谱纯净、频率和相位都可编程控制且稳定性很好的模拟正弦波,这个正弦波能够直接作为基准信号源,或通过其内部高速比较器转换成标准方波输出,作为灵敏时钟发生器来使用。
AD9851的各引脚功能如下,引脚排列,如图5:D0~D7:8位数据输入口,可给内部寄存器装入40位控制数据。
PGND:6倍参考时钟倍乘器地。
PVCC:6倍参考时钟倍乘器电源。
W-CLK:字装入信号,上升沿有效。
FQ-UD:频率更新控制信号,时钟上升沿确认输入数据有效。
FREFCLOCK:外部参考时钟输入。
CMOS/TTL脉冲序列可直接或间接地加到6倍参考时钟倍乘器上。
在直接方式中,输入频率即是系统时钟;在6倍参考时钟倍乘器方式,系统时钟为倍乘器输出。
AGND:模拟地。
A VDD:模拟电源(+5V)。
DGND:数字地。
图5DVDD:数字电源(+5V)。
RSET、DAC:外部复位连接端。
VOUTN:内部比较器负向输出端。
VOUTP:内部比较器正向输出端。
VINN:内部比较器的负向输入端。
VINP:内部比较器的正向输入端。
DACBP:DAC旁路连接端。
IOUTB:“互补”DAC输出。
IOUT:内部DAC输出端。
RESET:复位端。
低电平清除DDS累加器和相位延迟器为0Hz和0 相位,同时置数据输入为串行模式以及禁止6倍参考时钟倍乘器工作。
AD9851在信号源中的应用为了能够完成调频、调幅、调相的各种功能,要向AD9851输入频率/相位控制字,这是通过AD9851和微处理器相连接来实现。
可以和AD9851的数据线直接相连接的单片机类型很多,本文中选用的是Atmel公司生产的单片机AT89S51,如图6所示,为AT89S51和AD9851的硬件串行接口框图。
基于STM32的AD9851并行源代码#include"stm32f10x.h"#define ad9851_rest_l GPIO_ResetBits(GPIOC,GPIO_Pin_0)#define ad9851_rest_h GPIO_SetBits(GPIOC,GPIO_Pin_0)#define ad9851_fq_up_l GPIO_ResetBits(GPIOC,GPIO_Pin_1) #define ad9851_fq_up_h GPIO_SetBits(GPIOC,GPIO_Pin_1)#define ad9851_w_clk_l GPIO_ResetBits(GPIOC,GPIO_Pin_2)#define ad9851_w_clk_h GPIO_SetBits(GPIOC,GPIO_Pin_2)/*void RCC_HSE_Configuration(void){RCC_DeInit();//将外设RCC寄存器重设为缺省值RCC_HSEConfig(RCC_HSE_ON);//设置外部高速晶振(HSE),HSE晶振打开(ON)if(RCC_WaitForHSEStartUp()==SUCCESS)//等待HSE起振,SUCCESS:HSE 晶振稳定且就绪{RCC_HCLKConfig(RCC_SYSCLK_Div1);//设置AHB时钟(HCLK)RCC_SYSCLK_Div1--AHB时钟=系统时钟RCC_PCLK2Config(RCC_HCLK_Div1);//设置高速AHB时钟(PCLK2)RCC_HCLK_Div1--APB2时钟=HCLKRCC_PCLK1Config(RCC_HCLK_Div2);//设置低速AHB时钟(PCLK1)RCC_HCLK_Div2--APB1时钟=HCLK/2FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);//选择FLASH预取指缓存的模,预取指缓存使能FLASH_SetLatency(FLASH_Latency_2);//设置FLASH存储器延时时钟周期数FLASH_LATENCY_2 2延时周期RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_2);//设置PLL时钟源及倍频系数RCC_PLLCmd(ENABLE);//PLL使能while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET);//检查指定的RCC标志位(PLL准备好标志)设置与否RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//设置系统时钟SYSCLKwhile(RCC_GetSYSCLKSource()!= 0x08);//0x08:PLL作为系统时钟}}*/void AD9851_GPIOC_Configuration(void){GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE );GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_ Pin_2;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOC,&GPIO_InitStructure);}void AD9851_GPIOD_Configuration(void){GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE );GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_ Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOD,&GPIO_InitStructure);}void ad9851_reset_parrel(){ad9851_w_clk_l;ad9851_fq_up_l;//rest信号ad9851_rest_l;ad9851_rest_h;ad9851_rest_l;}void ad9851_wr_parrel(u8 w0,u32 frequence) {u8 w;frequence=frequence*4294967296/180000000; //写w0数据w=w0;GPIO_Write(GPIOD,w); //w0ad9851_w_clk_h;ad9851_w_clk_l;//写w1数据w=(frequence>>24);GPIO_Write(GPIOD,w); //w1ad9851_w_clk_h;ad9851_w_clk_l;//写w2数据w=(frequence>>16);GPIO_Write(GPIOD,w); //w2ad9851_w_clk_h;ad9851_w_clk_l;//写w3数据w=(frequence>>8);GPIO_Write(GPIOD,w); //w3ad9851_w_clk_h;ad9851_w_clk_l;//写w4数据w=(frequence>>=0);GPIO_Write(GPIOD,w); //w4ad9851_w_clk_h;ad9851_w_clk_l;//移入始能ad9851_fq_up_h;ad9851_fq_up_l;}int main(){// RCC_HSE_Configuration();AD9851_GPIOC_Configuration(); AD9851_GPIOD_Configuration(); GPIO_Write(GPIOC,0x0000); GPIO_Write(GPIOD,0x0000);//串行写1000Hz程序ad9851_reset_parrel();ad9851_wr_parrel(0x01,10000000); while(1);}。
淘宝上搞了个AD9851的DDS模块,回来测试了一下,把程序发上来,给大家参考,也给自己留个备份。
说不准过几天还真的要用呢。
#include "reg52.h"/****************51串行驱动****************/sbit clk =P3^1;sbit fq_ud =P3^2;sbit rst =P3^3;sbit dat =P3^0;sbit key1 =P1^4;sbit key2 =P1^5;sbit key3 =P1^6;sbit key4 =P1^7;unsigned char phase_word=0x00; //相位控制字,使用低5位unsigned char power_down=0x00; //低功耗模式unsigned char mult=0x01; //6倍频是否打开unsigned char ww[5]={0x09,0x0E,0x38,0xE3,0x8E};unsigned long freq,set_value;void delay_us(unsigned int i) //delay{while(i--);}//AD9851初始化,在此之前请确认D0,D1和D2的电平状态void init_dds(void){rst=1; //高电平复位delay_us(10000); //延时10mSrst=0;delay_us(10000); //延时10mSclk=0;fq_ud=0;delay_us(2);clk=1; //送入W0delay_us(2);clk=0;delay_us(2);fq_ud=1; //使能delay_us(2);fq_ud=0;delay_us(2);delay_us(10000);}//往AD9851写数据void write_dds(unsigned long dds){unsigned char i,j,temp;ww[0]=dds&0xFF; //频率字最低字节ww[1]=(dds>>8)&0xFF;ww[2]=(dds>>16)&0xFF;ww[3]=dds>>24; //频率字最高字节ww[4]= (phase_word<<3)|| power_down<<2 || mult; //控制字fq_ud=0; //FQ_UD置低clk=0; //CLK置低for(i=0;i<5;i++) //送入5个字节的控制字{temp=ww[i];for(j=0;j<8;j++){clk=0;if(temp&0x01)dat=1;else dat=0;delay_us(2);clk=1;delay_us(2);temp>>=1;}}clk=0;fq_ud=1; //使能信号delay_us(3);fq_ud=0;}//写入频率void write_freq(unsigned long freq){unsigned long dds;dds=24.250929422*freq; //频率字计算,可进行微调write_dds(dds);}main(){P0=0xff; P1=0xff;delay_us(10000);init_dds();while(1){if(key1==0) {delay_us(10000);while(!key1);write_freq(1000);} if(key2==0) {delay_us(10000);while(!key2);write_freq(5000);} if(key3==0) {delay_us(10000);while(!key3);write_freq(12000);} if(key4==0) {delay_us(10000);while(!key4);write_freq(19000);} };}亲测ok,也欢迎大家指正,谢谢!应网友要求,补上电路图脚一律悬空,Good luck!。
4V峰峰值的正弦波程序作者:佚名文章来源:百度点击数:606 更新时间:2010/8/6 11:54:19 热★★★要求是做个4V峰峰值的正弦波频率必须可调1HZ~10KHZ硬件电路能满足还是尽量用硬件电路上的设施不能外加任何东西这个要求是采用最小系统单片机来完成的程序:#include"at89x51.h"#define uchar unsigned char#define uint unsigned int#define ulong unsigned long/************************* 全局变量定义部分**************************///硬件设计接口不同,要修改下一行uchar code acLEDCS[]={0x7f,0xbf,0xdf,0xef};uchar codeacLedSegCode[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7 c,0x58,0x5e};/* 段码*/uchar acLED[4]; /* 显示缓冲区*/char cScanIndex; /* 位选指针0~3 */uchar cKey;sbit cKey1=P2^2;sbit cKey2=P2^1;sbit cKey3=P2^0;uchar cKeyCode;uchar cLongDelay;uchar Out[32];bit bStill; /* 是否松键标志*/uint nDelayKey=0; /* 键盘延时变量,为定时中断间隔时间的整数倍*/ uchar cMode=0;uchar Num;uchar cF=100;uchar code tosin[32]={0x80,0x99,0xb1,0xc7,0xda,0xea,0xf6,0xfd,0xff,0xfd,0xf5,0xe9,0xd8,0xc5,0xae,0x96,0x80,0x66,0x4e,0x38,0x25,0x15,0x09,0x02,0x00,0x02,0x0a,0x16,0x27,0x3a,0x51,0x69};union UniT{uint m_nT;uchar m_ucT[2];}idata uT;/*************************** 函数声明部分***************************/void Display1(void);void Display2(void);void Scankey(void);void DisposeKEY(void);/******************** 按键处理程序******************/void DisposeKEY(void){if (cKey1==0) { if(cF<134)cF++;else cF = 1;nDelayKey = 2000;}else if (cKey2==0){if(cF>1)cF--;else cF = 135;nDelayKey = 2000;}else if (cKey3==0){if(bStill==0) { cMode++;cMode &= 3; bStill = 1;}}//switch(cKey)//{//case 0x30: /* 例如:KeyADD */// if(cF<134)cF++;// else cF = 1;// nDelayKey = 2000; /* 按住键不动,可连续产生键值,相当于连续按键*/ // break;// case 0x28: /* 例如:KeySUB */// if(cF>1)cF--;// else cF = 135;// nDelayKey = 2000;// break;// case 0x18:// if(bStill==0)// {// cMode++; /* 假设有4种显示状态*/// cMode &= 3;// bStill = 1; /* 如果没松键就不会再改变显示方式*/// }// break;// default:break;// }Display2();cKey = 0;}void Display2(void){uchar i;acLED[0]=acLedSegCode[cMode+10]; /* LED显示第1位*/ acLED[1]=acLedSegCode[cF/100]; /* LED显示第2位*/acLED[2]=acLedSegCode[cF/10%10]; /* LED显示第3位*/acLED[3]=acLedSegCode[cF%10]; /* LED显示第4位*/ uT.m_nT=38-5760/cF;switch(cMode){case 0:for(i=0;i<16;i++)Out[i] = 255; //方波for(i=16;i<32;i++)Out[i] = 0;break;case 1:for(i=0;i<32;i++)Out[i] = tosin[i]; //正弦波break;case 2:for(i=0;i<16;i++)Out[i] = i << 4; //三角波for(i=16;i<32;i++)Out[i] = 255-i<<4;break;case 3:for(i=0;i<32;i++)Out[i] = i<<3; //锯齿波break;}}/************************** 主函数*****************************/void main(void){P3_7=0;/**************** 定时器初始化*******************/TMOD= 0x12; /* 定义定时器0工作于方式2(8位自动重装),定时器1工作于方式1(16位定时器)*/uT.m_nT=18-2880/cF;TH1 =uT.m_ucT[0];TL1 =uT.m_ucT[1];TR1 = 1;ET1 = 1;IP = 0x04; /* T1中断优先*/TH0 = -200; /* 8位自动重装定时器约每100uS中断1次,9216次为1秒*/TL0 = -200;TR0 = 1;ET0 = 1;EA = 1; /* 开总中断*/while(1){if(cKey){DisposeKEY(); /* 响应按键操作*/}}}/****************** 多任务时序控制时钟中断*********************/void IntT0(void) interrupt 1 /* 定时器0中断,完成1秒定时和LED延时*/ {P0 = 0; /* 先清显示再换位选*/P2 = acLEDCS[cScanIndex]; /* 送位选数据*/P0 = acLED[cScanIndex++]; /* 送显示数据,位选指针移位*/cScanIndex &= 3; /* 位选指针回位*//************************* 扫描按键程序******************/if(nDelayKey==0){cKey = P2 & 0x0e; // 取键值P2.3、P2.2、P2.1if(cKey != 0x0e)nDelayKey=100;// 设置延迟时间削颤else{bStill = 0;} // 松键}else // 有按键利用DelayKey按键消颤{nDelayKey--;if(nDelayKey==0){cKeyCode = P2 &0x0e;if(cKey != cKeyCode){cKeyCode = 0;}}}}/****************** 可控制定时时间间隔的时钟中断*********************/void IntT1(void) interrupt 3 /* 定时器1中断,记录T1计时溢出次数*/ {TL1 =uT.m_ucT[1];TH1 =uT.m_ucT[0];P1 = Out[Num++];Num &= 31;}。
标签:DDS,AD9851,信号发生器基于ad9851的信号发生器本人有一块个人闲置的ad9852芯片转让;需要者点击本链接,进入本人淘宝店;最近几年的电子设计大赛,差不多每年都考了DDS的设计。
本人曾经也调试过DDS,但走了一些弯路,在这里写下一些心得,希望能对初调者有点帮助。
下面将有电路图,以及详细的代码。
学过FPGA的同仁们,应该对DDS的原理就会有很好的理解了。
用FPGA是很容易把一个简单型的ad8952烧出来的!其实原理相当的简单,无非就是由相位累加器,相位调制器,正弦查找ROM,DAC构成。
通过改变相位累加的增量就很容易的改变的输出的频率了。
如果相位累加器(频率控制子)的位宽为N位(ad9851的N=32位)这就意味着把一个周期的正弦波形离散成了2的N次方个点,把这些点的幅值存在一个ROM中就构成了正弦查找ROM。
如果系统时钟为Fclk,即把Fclk分成了2的N 次方份。
如果此时的相位累加增量为(频率控制字)为B,那么此时的输出频率应为Fout=(B*Fclk)/。
显然B=1时其最小值为Fclk/。
B的值也不能太大,否则会输出失真波形。
Fout的最大值理论上应该至少小于Fclk/4。
所以要想提高输出频率的最大值,就得靠提高系统的外部时钟Fclk。
下面结合本人的代码来具体讲讲AD9851的应用。
AD9851的一些具体介绍这里就不说了。
其DATASHEET上都说的很清楚。
若看不懂E文,可以发E_M给我,我有中文资料。
AD9851要写40位的控制子。
其中前面32位就是频率控制子了。
后面是有1个6倍频使能位,1个logic0位,1个POWER_DOWN位,还有5位相位模式字。
这里我们只解决频率控制问题。
也就是说在代码中本人只写了,32位的频率控制子,还有一个6倍频使能。
其余的剩下几位由于没用到也就默认写为0了。
AD9851可以用并和串俩中方式写入控制子。
其串行发送方式的控制子表如下:本人主要将用串写控制子的时序与代码。
其并的方式的代码也会给出。
硬件电路图网上有很多资源,自己去找找!主要看看代码吧:/*************************************************************ad9851串口驱动程序2007-8-28-------------water************************************************************/#include <reg52.h>#include <intrins.h>#include <ABSACC.H>//-----------------------定义管脚--------------------------------------------------------sbit D7=P3^3; //控制子串传送位sbit DDS_FQUD=P3^4; //更新发送频率sbit DDS_CLK=P3^5; //接外部晶振时钟这里为30Munsigned long control_word(float freq);void send_control( unsigned long bytedata);void AD9851Init(void) //DDS初始化函数,包括DDS复位和初始化为串行发送{DDS_CLK=0;DDS_FQUD=0;DDS_CLK=1;DDS_CLK=0;DDS_FQUD=1;DDS_FQUD=0;}main(){unsigned long x;DDS_FQUD=0;AD9851Init();x=control_word(500000);while(1)send_control(x);}//计算9851控制字,freq为你要输出的频率unsigned long control_word(float freq){unsigned long water;water=23.86115*freq;//外部晶振为30M,6倍频后180M,其关系由公式算出。
//water=143.456*freq; //若不用6倍频,则其关系return(water);}//发送控制字void send_control( unsigned long bytedata){int i;unsigned char model="0x01";//模式选择为六倍频DDS_FQUD=0;_nop_();_nop_();_nop_();_nop_();_nop_();for(i=0;i<32;i++)//先写32位的频率控制子(现低位后高位){D7=(bit)(bytedata&(0x00000001)); //按时序写入DDS_CLK=1;_nop_();_nop_();_nop_();_nop_();_nop_(); //必要的时序延时DDS_CLK=0;_nop_();_nop_();_nop_();_nop_();_nop_();bytedata>>=1;}for(i=0;i<8;i++)//再写其他8位控制字,这里只写了6倍频使能{D7=(bit)(model&(0x01));DDS_CLK=1;_nop_();_nop_();_nop_();_nop_();_nop_();DDS_CLK=0;_nop_();_nop_();_nop_();_nop_();_nop_();model>>=1;}DDS_FQUD=1;DDS_FQUD=0;}上面的代码中已经有详细的注解。
其参考DATASHEET中的时序如下:并行方式的驱动代码如下:AD9851.H文件//======IO Define=======//sbit DDSRST="P2"^0;sbit FQ_UD_AD9851=P3^3;sbit W_CLK_AD9851=P3^4;//======================unsigned long int freq = 0;//unsigned char Control_AD9851 = 0x09; // Phase0 ,power down mode and 6 REFCLK Multiplier enable//unsigned char Control_AD9851 = 0x00; // Phase0 ,power on mode and 6 REFCLK Multiplier disableunsigned char Control_AD9851 = 0x01; // Phase0 ,power on mode and 6 REFCLK Multiplier enableunsigned char W1=0X0e;//附初值为1MHZunsigned char W2=0X38;unsigned char W3=0Xe3;unsigned char W4=0X8e;void Parallel2Serial_AD9851(void){ FQ_UD_AD9851=0;W_CLK_AD9851=0;P2=Control_AD9851;_nop_();_nop_();_nop_();_nop_();//延时很重要,对时序W_CLK_AD9851=1;//字装入信号,上升沿有效W_CLK_AD9851=0;P2=W1;_nop_();_nop_();_nop_();_nop_();_nop_();W_CLK_AD9851=1;W_CLK_AD9851=0;P2=W2;_nop_();_nop_();_nop_();_nop_();_nop_();W_CLK_AD9851=1;W_CLK_AD9851=0;P2=W3;_nop_();_nop_();_nop_();_nop_();_nop_();W_CLK_AD9851=1;W_CLK_AD9851=0;P2=W4;_nop_();_nop_();_nop_();_nop_();_nop_();W_CLK_AD9851=1;W_CLK_AD9851=0;FQ_UD_AD9851=1;FQ_UD_AD9851=0;}void Set_Freq(float Freqency){//freq= (unsigned long int)(23.86092942*Freqency); // SYSCLK = 180 MHzfreq= (unsigned long int)(23.86115*Freqency); // SYSCLK = 180 MHzW4=(unsigned char)freq&0xff;freq=freq>>8;W3=(unsigned char)freq&0xff;freq=freq>>8;W2=(unsigned char)freq&0xff;freq=freq>>8;W1=(unsigned char)freq&0xff;Parallel2Serial_AD9851();}AD9851.C文件/*******************************************************ad9851并口驱动程序外部提供30MHZ晶振,6倍频率模式2007-8-28-----------------water*********************************************************/#include<reg52.h>#include <intrins.h>#include <AD9851.h>sbit RST_AD9851= P3^2;//长延时void Delay80Ms(unsigned int k){unsigned int j;while(k--){j=7269;while(j--);}}void main(void){RST_AD9851=1;RST_AD9851=1;RST_AD9851=0;//Set_Freq(23000000);//发送的频率while(1){Set_Freq(22000000);//发送的频率}}以上就是AD9851的驱动程序。
下面是本人用KS0108控制器的LCD做的任意频率信号发生器(当然为简单只写了正弦波和方波)AD9851是可以直接产生方波的(里面有比较器)。
全部代码如下(有兴趣的可以参考):// body.h文件void delay(unsigned int t);void write_com(unsigned char cmdcode);void write_data(unsigned char Dispdata);unsigned char read_data();void Clr_Scr();void Disp_Img(unsigned char code *img);void hz_disp16(unsigned char pag,unsigned char col, unsigned char code *hzk);void hz_disp32(unsigned char pag,unsigned char col, unsigned char code *hzk);void hz_disp48(unsigned char pag,unsigned char col, unsigned char code *hzk);void hz_disp64(unsigned char pag,unsigned char col, unsigned char code *hzk);void init_lcd();void Putedot(unsigned char Order);void Putstr( unsigned char *str , unsigned char i , unsigned char lie, unsigned char hang);void Msg(int flg) ;bit judge_hitkey() ;void mdelay(unsigned int N) ;unsigned char kbscan(void);unsigned long int covert_decimal_to_hex(unsigned long int r) ;#define Disp_On 0x3f#define Disp_Off 0x3e#define Col_Add 0x40#define Page_Add 0xb8#define Start_Line 0xc0#define Lcd_Bus P0 //MCU P1<------> LCMsbit Mcs="P1"^5; //Master chip enablesbit Scs="P1"^6; //Slave chip enablesbit Enable="P1"^2; //6800 mode Enable singlesbit Di="P1"^0; //Data or Instrument Selectsbit RW="P1"^1; //Write or Readsbit Lcd_Rst=P1^7; //Lcm reset// body.c文件#include <reg52.h>#include <ctype.h>#include <string.h>#include <stdlib.h>#include <stdio.h>//#include <math.h>#include "data.h"//-----------液晶定义引脚-----------------------#define Disp_On 0x3f#define Disp_Off 0x3e#define Col_Add 0x40#define Page_Add 0xb8#define Start_Line 0xc0#define Lcd_Bus P0 //MCU P1<------> LCMsbit Mcs="P1"^5; //Master chip enablesbit Scs="P1"^6; //Slave chip enablesbit Enable="P1"^2; //6800 mode Enable singlesbit Di="P1"^0; //Data or Instrument Selectsbit RW="P1"^1; //Write or Readsbit Lcd_Rst=P1^7; //Lcm reset//-----------------------ad9851定义管脚--------------------------------------------------------sbit D7=P3^3;sbit DDS_FQUD=P3^4; //更新发送频率sbit DDS_CLK=P3^5;//--------------------ad9851函数声明-------------unsigned long control_word(float freq);void send_control( unsigned long bytedata);//-----------全局变量---------------------------unsigned char row;unsigned char col;extern unsigned char j_j; //一级菜单标志j_j为全局变量extern float beauty;/****************************液晶程序部分************************************//*------------------延时子程序-----------------------------*/void delay(unsigned int t){unsigned int i,j;for(i=0;i<t;i++)for(j=0;j<10;j++);}/*------------------写命令到LCD------------------------------*/void write_com(unsigned char cmdcode){Di=0;RW=0;Lcd_Bus=cmdcode;delay(0);Enable=1;delay(0);Enable=0;}/*-------------------写数据到LCD----------------------------*/ void write_data(unsigned char Dispdata){Di=1;RW=0;Lcd_Bus=Dispdata;delay(0);Enable=1;delay(0);Enable=0;}/*-------------------读LCD数据----------------------------*/ unsigned char read_data(){unsigned char tmpin;Di=1;RW=1;delay(0);Enable=1;delay(0);Enable=0;tmpin=Lcd_Bus;return tmpin;}/*------------------清除内存---------------*/void Clr_Scr(){unsigned char j,k;Mcs=1;Scs=1;write_com(Page_Add+0);write_com(Col_Add+0);for(k=0;k<8;k++){write_com(Page_Add+k);for(j=0;j<64;j++)write_data(0x00);}}/*---------------------指定位置显示汉字8*16-----------------------*/void hz_disp8(unsigned char pag,unsigned char col, unsigned char code *hzk) {unsigned char j="0",i=0;for(j=0;j<2;j++){write_com(Page_Add+pag+j);write_com(Col_Add+col);for(i=0;i<8;i++) write_data(hzk[8*j+i]);}}/*---------------------指定位置显示汉字16*16-----------------------*/void hz_disp16(unsigned char pag,unsigned char col, unsigned char code *hzk) {unsigned char j="0",i=0;for(j=0;j<2;j++){write_com(Page_Add+pag+j);write_com(Col_Add+col);for(i=0;i<16;i++) write_data(hzk[16*j+i]);}}/*---------------------显示32*16的汉字字窜-----------------------*/void hz_disp32(unsigned char pag,unsigned char col, unsigned char code *hzk) {unsigned char j="0",i=0;for(j=0;j<2;j++){write_com(Page_Add+pag+j);write_com(Col_Add+col);for(i=0;i<32;i++) write_data(hzk[32*j+i]);}}/*---------------------显示48*16的字窜----------------------*/void hz_disp48(unsigned char pag,unsigned char col, unsigned char code *hzk) {unsigned char j="0",i=0;for(j=0;j<2;j++){write_com(Page_Add+pag+j);write_com(Col_Add+col);for(i=0;i<48;i++) write_data(hzk[48*j+i]);}}/*--------------------显示64*16的字窜---------------------*/void hz_disp64(unsigned char pag,unsigned char col, unsigned char code *hzk) {unsigned char j="0",i=0;for(j=0;j<2;j++){write_com(Page_Add+pag+j);write_com(Col_Add+col);for(i=0;i<64;i++) write_data(hzk[64*j+i]);}}/*------------------初始化LCD屏--------------------------*/void init_lcd(){Lcd_Rst=0;delay(100);Lcd_Rst=1;delay(100);Mcs=1;Scs=1;delay(100);write_com(Disp_Off);write_com(Page_Add+0);write_com(Start_Line+0);write_com(Col_Add+0);write_com(Disp_On);}//-----------------半角字符点阵码数据输出----------------------void Putedot(unsigned char Order){unsigned char cbyte, j="0",i=0;int x;x=Order * 0x10;for(j=0;j<2;j++){write_com(Page_Add+row+j);write_com(Col_Add+col);for(i=0;i<8;i++){cbyte = Ezk[x];write_data(cbyte); //写输出一字节x++;}}}//------------------------一个字串的输出----------------------------------------void Putstr( unsigned char *str , unsigned char i , unsigned char lie, unsigned char hang){unsigned char j,X;for (j=0;j<i;j++){col=lie+8*j; //换列。