ADI公司的ad5544一个四通道、16bit 精度的DAC芯片。本身硬件原理不复杂,所以软件控制也不复杂,但是优点就精度非常高,用于数字量转模拟量电流,比如用于信号仿真。假设输出是正弦波,因为有16bit 相当于有0xFFFF个档位变化,已经是非常高精度存在了。

芯片的管脚fb是什么意思(数模转换芯片AD5544详细解读)(1)

因此我们在这个芯片上研究不少时间,文档和开发板都很简单,但是自写软件总是控制不了,走了很大的弯路,直到后面实测发现才发现这个文档有留了一个坑。

这款芯片一大特点就是用一个4线的SPI总线来输入一个特殊指令来控制输出电流的变化,相对于用IO脚来控制方法,大大节约了硬件管脚数量。

它的原理就是在有一个稳定的输入参考电压(VREFX),通过软件发送SPI指定参数可以动态在在输出端输出 模拟电压,跨度在0-7.5V 电压. 这个特性常用于硬件乘法器,信号发器等设计.

   其中输入电压与输出电压的换算关系满足如下公式​

芯片的管脚fb是什么意思(数模转换芯片AD5544详细解读)(2)

这个公式中,-Vref 是输入电压,一般是桓定的5V, Vout为输出电压, 65536是一个常量,这个D就SPI输入换算系数. 65536即2的16次方,可以限定D的最大值不能超过16bit ,这就是由芯片硬件精度限制.

在这个公式里,开头-号表示输入和输出电压极性正好相反.即输入一个正电压,出来是负电压.

这里顺便是提一下ADI另一颗DAC芯片AD5554是14bit精度,这样公式就换算成

芯片的管脚fb是什么意思(数模转换芯片AD5544详细解读)(3)

这里16384就是 2的14次方.

硬件解读

这是硬件框图,

在面向上位机 ,有7个管脚,其中CS/SCLK/SCIN/SDO 这是SPI四个标准脚,但这里只需要软件输出即可,SCIN用于多块AD5544串连使用.因此ADI把这个又称为3 wire spi.

芯片的管脚fb是什么意思(数模转换芯片AD5544详细解读)(4)

另外一个3个功能脚是 MSB 用于设定输出量程, 零代码状态(MSB = 0) 接地

或半量程状态(MSB = 1), MSB脚为0表示全量程,为1表示输出半量程,即参考电压一半(比如即5V输入, -2.5v输出​)。这是输出是硬件执行,不需要软件干预,所以可以用于测试芯片硬件是否正常工作。在实际运行直接设为MSB=0

芯片的管脚fb是什么意思(数模转换芯片AD5544详细解读)(5)

对RS复位管脚,低电平有效置0表示软件复位​​,相当于软件重启

LDAC管脚,低电平有效,功能加载DAC寄存器选通​.相当于spi数据生效.

也就是说最低需要 ldac,cs,sclk,sdo 四个管脚就可以工作了。

为了验证这一过程,ADI提供发板 EVAL-AD5544为例来介绍如何控制AD5544,

芯片的管脚fb是什么意思(数模转换芯片AD5544详细解读)(6)

按文档介绍,专门介绍两个实例

芯片的管脚fb是什么意思(数模转换芯片AD5544详细解读)(7)

翻译过来就是

当输入电压为10v,输入数据为0x4000时,输入地址为0,即产生1/4量程电压,即在 VoutA上产生 -2.5v电压输出

当输入电压为10v,输入数据为0xC000时,输入地址为0,即在 VoutA上产生 -7.5v电压输出

​测试下来,的确如此。

软件控制接口

参考基功能框图,在其SDO端,软件要发来18bit的SPI控制数据

芯片的管脚fb是什么意思(数模转换芯片AD5544详细解读)(8)

其中 18bit 的数据中,高2位是地址,低16bit 控制数据D

芯片的管脚fb是什么意思(数模转换芯片AD5544详细解读)(9)

地址对应关系如下​,用来指明向哪个通道输出电压

芯片的管脚fb是什么意思(数模转换芯片AD5544详细解读)(10)

但是我们知道,无论单片机还是x86,arm 软件用下传输数据都是基于8对齐,也就是说我们通过spi发送18bit数据,必须要补齐至少24bit,也就是3个byte数据,软件才能操作。

  那这多出来6bit补哪里呢?这里文档写明是按msb优先。我们理解成在SPI MSB模式下,​首先传输bit17,bit16,自然多出位要补数字低位.但是测试下来芯片如终不为所动.

  最后突然反应过来是否补错了?ADI公布很多芯片的驱动代码,但偏偏就少这款芯片的,后面反应过来,实际上补在数字高位也就是第一个byte低两位就是地址,高位没用。

然后再传输16bit的控制数据,正好2byte,至此所有代码一通百通。希望后来的兄弟少走弯路

void US_SPI_Write2Byte(u8 addr_TD, u16 ad5544_data) { u8 tempdata = 0; AD5544_CS_HIGH(); if(addr_TD == 0) //通道0 { AD5544_CS_LOW(); AD5544_ReadWriteByte(0); } else if(addr_TD == 1) //通道1 { AD5544_CS_LOW(); AD5544_ReadWriteByte(1); } else if(addr_TD == 2) //通道2 { AD5544_CS_LOW(); AD5544_ReadWriteByte(2); } else//通道3 { AD5544_CS_LOW(); AD5544_ReadWriteByte(3); } tempdata = (ad5544_data >> 8); //发送高8位 AD5544_ReadWriteByte(tempdata); tempdata = ad5544_data; //发送低8位 AD5544_ReadWriteByte(tempdata); AD5544_CS_HIGH(); }

,