AD5429/AD5439/AD5449分别是CMOS、8/10/12位、双通道、电流输出的数模(DAC)。这些芯片均采用2.5 V至5.5 V电源供电,因此适合电池等低功耗的场合.芯片采用CMOS亚微米工艺制造,能够提供出色的四象限乘法特性,大信号乘法带宽达10 MHz。
这些DAC采用双缓冲三线式串行,并且与SPI、QSPI™、MICROWIRE™及大多数DSP接口标准兼容。采用多个封装时,还可以通过串行数据输出(SDO)引脚,将这些DAC以菊花链形式相连。利用数据回读功能,用户可以通过SDO引脚读取DAC寄存器的内容。上电时,内部和锁存以0填充,DAC输出处于零电平。
满量程输出电流由所施加的外部基准输入电压(VREF)决定。与外部电流至电压精密放大器配合使用时,集成的反馈(RFB)可提供温度跟踪和满量程电压输出。
AD5449 AD5429AD5439引脚图 芯片的优势和特点:
pdf英文资料下载:http://www.51hei.com/f/AD5429_5439_5449.pdf
中文资料下载:http://www.51hei.com/f/AD5439中文资料.docx
AD5439是双路10bit电流输出型DAC,由于没有搞过SPI接口的DAC,所以先在网上下载了一个该DAC的底层函数,程序代码如下:
#include"macros.h" #include"math.h" #include"dac.h"
//向AD5439写命令字以及待转换的数据 voidWriteAD5439(unsignedintControlBits,unsignedintdata) { unsignedchari; data=(data<<2); data=(ControlBits|data); SCLK_SET; SYNC_CLR; for(i=0;i<16;i++) { SCLK_SET; if((data&0x8000)!=0) { SDIN_SET; } else { SDIN_CLR; } SCLK_CLR; data=(data<<1); } SYNC_SET; LDAC_CLR; SCLK_CLR; LDAC_SET; delay_ms(1); }
//初始化AD5439, voidInitAD5439(void) { ACL_CLR;//AD5439.CLR=LOW,清零 delay_ms(5); ADCCL_SET;//AD5439.CLR=High,准备工作 WriteAD5439_CMD(0x9000); }
//读出SDO的值 unsignedintreadSDO(unsignedintchannal) { unsignedchari=0; unsignedintreadData=0; //写入控制字,选择读回的通道 if(channal==ReadBack_I) { WriteAD5439_CMD(ReadBack_I); } if(channal==ReadBack_V) { WriteAD5439_CMD(ReadBack_V); } //准备接收数据 SYNC_CLR; SCLK_CLR; //读数据,并处理 for(i=0;i<16;i++) { SCLK_SET;//上升沿,读一位 readData|=(PINB&0x01)<<(15-i); SCLK_CLR;//准备下一回读出数据 //delay_ms(1); } SYNC_SET; readData=((readData>>2)&0x3ff);//根据5439的命令字格式进行调整 //返回数据 returnreadData; }
//针对Init5439(),readSDO(),只写命令字,不写数据 voidWriteAD5439_CMD(unsignedintControlBits) { unsignedchari; unsignedintdata=ControlBits; SCLK_SET; SYNC_CLR; for(i=0;i<16;i++) { SCLK_SET; if((data&0x8000)!=0) { SDIN_SET; } else { SDIN_CLR; } SCLK_CLR; data=(data<<1); } SYNC_SET; LDAC_CLR; SCLK_CLR; LDAC_SET; delay_ms(20); }
voidWriteVoltage(unsignedintControlBits,unsignedintdata) { unsignedintchannal,i;//选择通道 unsignedintdataInUse=data;//用以重新调用write5439(),防止data受到破坏 unsignedintdataReadBack=0;
if(ControlBits==Load_I) { channal=ReadBack_I; } if(ControlBits==Load_V) { channal=ReadBack_V; }
i=0; for(;;) { WriteAD5439(ControlBits,dataInUse); dataReadBack=readSDO(channal); if(dataInUse==dataReadBack) { WriteAD5439(Updata_AB,dataInUse); break; } else { i++; } if(i>10)//连续10次写不正确,则关机退出 { SoftStartOff; } }
}
voidmain(void) { init_();//初始化MCU
WriteVoltage(Load_V,1024);
while(1) { process(); }
}
我首先看的是中文的pdf,我结合着这个程序去看该DAC的读写时序图,没发现程序有什么问题!那就开工吧,我用的是STC89C52RC作为主控,用io口模拟SPI,没多久程序一个简单的测试程序就出来啦,编译没错误没警告。下载,调试,上显示出一个-5v的电压,哦,忘了说我用的是哪个电路啦,上图
我是用的双极性输出电路,我采用5v的基准,那么输出电压范围为-5到+5v。
下面需要解决的问题就是,为何DAC一直输出-5v
我所采用解决方法如下:
第一:采用看我程序输出的时序是否正确,经观察时序和pdf上的时序一样。找不到问题,我没办法只好硬着头皮去看英文pdf,勉强可以看懂,看一遍后没发现问题所在。。。。。。这消耗了两天多的时间,最后确实没辙啦,好吧找技术支持,第二天技术支持给我回复啦,他提出了两个问题(1)SCLK占空比不是50%(2)独立模式下,数据建立时间是否足够长
独立模式时序图
时序图上对应的各个时间
我解决SCLK占空比不是50%的问题,方法如下

通过给时钟加延时来实现占空比为50%,如红线示
通过时序图我们可以知道数据建立时间为t5,5ns,使用52作为主控,数据建立时间肯定大于5ns,程序改好,上电,观察示波器还是-5v,崩溃。。。。。。再次拿起英文pdf从头到尾看了一篇,还是没思路,先放放吧,去焊接个板子去吧,让大家看看板子的图,嘻嘻

同样的板子焊接了两块
焊接结束我接着调试我的DAC,一样的没有进展,一样的办法我接着看英文pdf,然后接着迷茫。。。。。。
最后在一个阳光明媚的下午,突然间我想起啦上次调试AD7799出现的问题就是因为CS的信号有问题,我看了看AD5439的时序图,发现SYNC貌似和CS有同样的功能,我直接把SYNC拉低,输出电压时0v,貌似不是这里的问题,我又把SYNC接回单片机引脚,这时候竟然奇迹的电压变化啦,我试了好几个数据电压输出却是变啦,但是没试几次就不管用啦,又回到了-5v。这时候我隐约觉得是不是SYNC的时序真的有问题呢?重看时序,发现问题啦!!!

红框框里标记的我理解的是16个脉冲结束后,SYNC置高,拉低都可以,我当时按参考程序上来的,直接给SYNC置高!
voidWriteAD5439(uintContralBits,uintDAdata) { unsignedchari; uintbuf; uintwave_data; buf=DAdata; buf=(buf<<2); wave_data=(ContralBits|buf); SYNC_SET(); delay(1); SCLK_SET(); SYNC_CLR(); for(i=0;i<16;i++) { SCLK_SET(); if((wave_data&0x8000)!=0) {SDIN_SET();} else {SDIN_CLR();} delay(1); SCLK_CLR(); delay(1); wave_data=(wave_data<<1); } SYNC_SET(); LDAC_CLR(); delay(1); SCLK_SET(); LDAC_SET(); delay(1); }
我就想改下试试吧,然后我就把写数据的函数改为下面的
voidWriteAD5439(uintContralBits,uintDAdata) { unsignedchari; uintbuf; uintwave_data; buf=DAdata; buf=(buf<<2); wave_data=(ContralBits|buf); SYNC_SET(); delay(1); SCLK_SET(); SYNC_CLR(); for(i=0;i<16;i++) { SCLK_SET(); if((wave_data&0x8000)!=0) {SDIN_SET();} else {SDIN_CLR();} delay(1); SCLK_CLR(); delay(1); wave_data=(wave_data<<1); } SYNC_CLR(); SCLK_SET(); delay(1); }
重新上电,示波器上的数据终于会变化啦!!!搞定!收尾附上我的测试程序,以方便别人学习!!!
#include<at89x51.h>
#defineucharunsignedchar #defineuintunsignedint
#defineSDIN_SET()P0_0=1; #defineSDIN_CLR()P0_0=0;
#defineSCLK_SET()P0_1=1; #defineSCLK_CLR()P0_1=0;
#defineSYNC_SET()P0_2=1; #defineSYNC_CLR()P0_2=0;
#defineLDAC_SET()P0_3=1; #defineLDAC_CLR()P0_3=0;
#defineDACLR_SET()P0_4=1; #defineDACLR_CLR()P0_4=0;
uintnum;
voiddelay(uintt) { uinti; while(t--) { for(i=0;i<125;i++); } }
voidWriteAD5439_CMD(uintCMits) { unsignedchari; unsignedintdata1=CMDBits; SYNC_SET(); delay(1); SCLK_SET(); SYNC_CLR(); for(i=0;i<16;i++) { SCLK_SET(); if((data1&0x8000)!=0) { SDIN_SET(); } else { SDIN_CLR(); } delay(1); SCLK_CLR(); delay(1); data1=(data1<<1); } SYNC_CLR(); //LDAC_CLR(); //delay(1); SCLK_SET(); //LDAC_SET(); delay(20); }
voidWriteAD5439(uintContralBits,uintDAdata) { unsignedchari; uintbuf; uintwave_data; buf=DAdata; buf=(buf<<2); wave_data=(ContralBits|buf); SYNC_SET(); delay(1); SCLK_SET(); SYNC_CLR(); for(i=0;i<16;i++) { SCLK_SET(); if((wave_data&0x8000)!=0) {SDIN_SET();} else {SDIN_CLR();} delay(1); SCLK_CLR(); delay(1); wave_data=(wave_data<<1); } SYNC_CLR(); //LDAC_CLR(); //delay(1); SCLK_SET(); //LDAC_SET(); delay(1); }
unsignedintreadSDO(void) { unsignedchari=0; unsignedintreadData=0; bititemp; WriteA