c51单片机驱动AD9954的程序及调试
一开始调试,先要正确控制SYNC_CLK,因为这个输出引脚就是内部DDS时钟的4分频(假设DDS时钟最高为400MHz,那么SYNC_CLK此时应当输出100MHz;反之,通常用SYNC_CLK来推测DDS系统时钟)。前提是必须复位Control Function Register No.1(CFR1:0x00)中的bit1(SYNC_CLK Disable)。
然后根据输入时钟的频率正确设置CFR2中的倍频系数REFCLK Multiplier和VCO Range(0:100~250MHz;1:250~400MHz)。只要外部电路没什么错的地方,SYNC_CLK一般都OK了。
用了才发现,AD9954真的还不错,400MHz的系统时钟就先不说了,居然可以用控制字Amplitude Scale Factor (ASF:0x02)调节输出信号的幅度,前提是打开CFR1中的OSK Enable。并且14bit的长度也能够达到足够高的幅度控制精度了。当时作信号源的时候,还用外接AD835+TLV5638控制幅度,现在想来真是憨啊。
还有就是,输出信号的相位可调。控制字Phase Offset Word(POW0 0x05)中含有14bit的相位偏移控制字,因此相位调节的精度也是相当高的,可达360°/16384 = 0.022°,在大多数情况下肯定够用,比AD9851的5bit控制字(360°/32 = 11.25°)强多了。具体见程序1。
然后想尝试一下线性扫频功能(Linear-sweeping Mode),调了一整天都没出来,然后就放假回家了。
最近在搞毕业设计(频率特性测试仪Frequency Response Analyzer)的同时,又把原来的AD9954测试板拿出来调试,Single-Tone Mode当然是没问题的,这次主要是再一次研究Linear-Sweeping Mode。于是打开原来写的程序,看了一会儿,调了一会儿,突然发现一个极其简单的错误——控制字的一个字节位置写错了,改过来再测试,一切OK。具体见程序2。去年居然花了一整天去查都没查出来,Wordless。
好了,现在该最后一关了——RAM模式。Datasheet有关章节再看了一遍,然后大概写了一个程序试了一下,出来的波形一团糟。于是参考了AD官网的AD9954示例代码(ASM的,具体见程序3),并和自己写的一步一步对比,最后终于搞定了。是因为向RAM写数据的时候,只需要在第一次送数据前送一次RAM指令字节(RAM:0x0b),具体见程序4。但是我没注意到这一点,每次数据前都送一遍0x0b,结果就悲剧了。不过最后还是发现原因了,嘿嘿!
下图是RAM Segment Address Ramp Rate设置为0x0400(1024)时的切换时间测量波形。两个光标之间的时间大概是10.24us,因为10.24us = 1024×10ns,说明更新速率是10ns,即SYNC_CLK,和线性扫频时的最快频率更新速度一样。
利用AD9954的RAM Mode可以很方便的实现对数扫频,只需要计算出相应的对数频率点并存储进RAM即可。
除此之外,AD9954还可以实现高速调频波。如果固定波表1000个点,那么调制波的频率可以是100kHz,50kHz,33.33kHz……,即100/n kHz(n正整数)。如果采用不定波表500~999个点,则可以实现200kHz以内的,调制波的频率步进不大于0.4%的调频波。但实现起来有些麻烦,所以一般不用AD9954作调制波频率连续可调的调频波信号源。
现在AD9954的程序部分了解得差不多了,等毕业设计结束之后,有时间了就升级一下以前做的信号源。AD835,TLV5638直接去掉,再加入比较基础的调频/调幅功能,还有就是加入一个EEPROM用于幅度校准存储。另外,硬件电路方面做一板PCB降降噪声,同时功放输出的功率也要提升到10Vpp@50欧负载。
下面是部分程序,与有兴趣的朋友们一起分享(才起步,拙劣之处还请多多包涵):
公共程序段:
#include reg51.h>#include absacc.h>#include intrins.h>#define uchar unsigned charsbit ioupdate = P1^0;sbit sdio = P1^1;sbit clk = P1^2;sbit adcs = P1^3;sbit adreset = P1^4;sbit tlvcs = P1^5;sbit ps0 = P1^6;void send(uchar dat){uchar i;for(i=0;i 8;i++){clk = 0;dat = _crol_(dat,1);sdio = dat0x01;clk = 1;}}程序1:(Single-Tone Mode)void main(){P1 = 0xff;adreset = 0;adcs = 0;send(0x00); //CFR1send(0x02); //bit1 OSK Enable,bit0 Auto OSK Enable;send(0x00);send(0x00);send(0x42); //bit6 comp PD,bit1 SYNC_clk Disable;SYNC_clk = DDSclk/4;ioupdate = 0;ioupdate = 1;send(0x01); //CFR2send(0x00); //not used;send(0x08); //bit3 High Speed SYNC Enable;send(0xa4); //bit7-bit3 REF clk Multiplier factor;bit2 VCO Range //(0:100-250;1:250-400);bit1-bit0 Charge Pump;send(0x02); //ASF,when OSK Enabled(CFR1 bit25);send(0x3f);send(0xff);send(0x04); //FTW0 0x 00 a3 d7 0a=1MHz (0x ff ff ff ff ==> 400MHz)send(0x00);send(0xa3);send(0xd7);send(0x0a);send(0x05); //POW0,Phase Initialsend(0x00);send(0x00);ioupdate = 0;ioupdate = 1;adcs = 1;adcs = 0; //POW0.Phase shift 180 (0x 3f ff ==> 360)send(0x05);send(0x20);send(0x00);adcs = 1;ioupdate = 0;ioupdate = 1;}程序2:(Linear-Sweeping Mode)void main(){P1 = 0xff;adreset = 0;adcs = 0;send(0x00); //CFR1send(0x00);send(0x20); //bit5 Linear Sweeping Enablesend(0x00);send(0x46); //bit2 Linear Sweeping No-Dwellioupdate = 0;ioupdate = 1;send(0x07); //NLSCWsend(0x10);send(0x00);send(0x00);send(0x00);send(0x10);send(0x08); //PLSCWsend(0x10);send(0x00);send(0x00);send(0x00);send(0x10);send(0x04); //FTW0 0x 00 a3 d7 0a ==1MHz (0x ff ff ff ff ==> 400MHz)send(0x00);send(0xa3);send(0xd7);send(0x0a);send(0x06); //FTW1 0x 01 68 72 b0 ==2.2MHz (0x ff ff ff ff ==> 400MHz))send(0x01);send(0x68);send(0x72);send(0xb0);adcs = 1;ioupdate = 0;ioupdate = 1;ps0 = ~ps0; //Toggle ps0 to sweep;ps0 = ~ps0;}程序3:(AD9954_ADIcode)程序4:(RAM Mode) void main(){P1 = 0xff;ps0 = 0;adreset = 0;adcs = 0;send(0x01); //CFR2send(0x00); //not used;send(0x00); //bit3 High Speed SYNC Enable;send(0xa4); //bit7-bit3 REF clk Multiplier factor; bit1-bit0 Charge Pump;send(0x04); //FTW0;send(0x12);send(0xf6);send(0x84);send(0xbe);ioupdate = 0;ioupdate = 1;send(0x00); //CFR1send(0x80); // bit7 RAM Enable;bit5-3 Internal Profile Controlsend(0x00);send(0x02); //bit1 SDIO Only;send(0x00); //bit6 comp PD,bit1 SYNC_clk Disable;SYNC_clk = DDSclk/4;send(0x02); //ASF,when OSK Enabled(CFR1 bit25);send(0x3f);send(0xff);ioupdate = 0;ioupdate = 1;send(0x07); //RSCW0;ps0 = 0; ps1 = 0;send(0xff); //RAM Segment Address Ramp Rate 7:0>send(0xff); //RAM Segment Address Ramp Rate 15:8>send(0x07);send(0x00); //Segment0 Address:0x00000-0x00007send(0x00); //RSCW0send(0x08); //RSCW1;ps0 = 1; ps1 = 0;send(0xff); //RAM Segment Address Ramp Rate 7:0>send(0xff); //RAM Segment Address Ramp Rate 15:8>send(0x00);send(0x01); //Segment1 Address:0x00000-0x00001send(0x04);adcs = 1;ioupdate = 0;ioupdate = 1;adcs = 0;send(0x0b); //RAMsend(0x00); //stall freq into RAM from the final address to beginning address;send(0xa3);send(0xd7);send(0x0a); //RAM0 1MHzsend(0x00);send(0xf5);send(0xc2);send(0x8f); //RAM1 1.5MHzsend(0x01);send(0x47);send(0xae);send(0x14); //RAM2 2MHzsend(0x01);send(0x99);send(0x99);send(0x99); //RAM3 2.5MHzsend(0x01);send(0xeb);send(0x85);send(0x1e); //RAM4 3MHzsend(0x02);send(0x3d);send(0x70);send(0xa3); //RAM5 3.5MHzsend(0x02);send(0x8f);send(0x5c);send(0x28); //RAM6 4MHzsend(0x02);send(0xe1);send(0x47);send(0xae); //RAM7 4.5MHzps0 = 1;send(0x0b); //RAM Instruction Againsend(0x03);send(0x33);send(0x33);send(0x33); //RAM0 5MHzioupdate = 0;ioupdate = 1;send(0x07); //RSCW0;ps0 = 0; ps1 = 0;send(0x00); //RAM Segment Address Ramp Rate 7:0>send(0x04); //RAM Segment Address Ramp Rate 15:8>send(0x07);send(0x00);send(0x60); //RAM Mode of Operation: Continuous Bidirectional Rampadcs = 1; //RSCW0ioupdate = 0;ioupdate = 1;}
- 基于单片机的智能计步器设计(09-20)
- C51单片机微调SH-20504程序(12-02)
- C51单片机运用定时器T0中断实现电子时钟(12-02)
- T6963C的51单片机驱动程序(12-02)
- 89C51单片机I/O口模拟串行通信的实现方法(11-30)
- 基于stc51单片机的光立方c语言源代码(11-30)