8通道模拟信号输出,8Bit分辨率,数字转模拟芯片DAC5578芯片的使用(I2C通讯协议)

个人的学习记录,方便大家学习交流以及日后个人复习,因为我只是边学边做,如果存在错误,请在评论区留下你的意见。
大部分资料来自于TI官网的DAC5578芯片数据手册,吃生肉很难受。
这个芯片输出的最低电压是0.2V,最高电压也比VCC稍低
DAC5578芯片数据手册下载地址:http://www.ti.com/cn/lit/ds/symlink/dac5578.pdf
DAC5578电源电压范围:2.7V 到5.5V
此次学习使用的电压是3.3V。
驱动芯片 : STM32F103C8 (感觉51单片机也行,但没有实际使用过)
目标:使用 DAC5578 输出模拟信号
代码链接:https://pan.baidu.com/s/1_y0r4LiE4hXPTwtAZUIUjg 提取码 : fb1m
主要内容在 User \ main.c 里
DAC5578引脚分布:

引脚说明:
AVDD : 电源正极
GND : 电源负极
VREFIN : 基准电压,接电源正极
LDAC : 使缓存区数据更新到DAC输出端,低电平触发
ADDR0 : 芯片地址设置,
置0时(接GND),芯片地址为 1001 000,
置1时(接VCC),芯片地址为 1001 010,
浮空时(什么都不接),芯片地址为 1001 100 。
CLR : 芯片重启端,下降沿触发
SCL : I2C串行通讯时钟端 (时钟端)
SDA : I2C串行通讯数据端 (数据端)
VOUTA到VOUTH : 模拟信号输出端
我是在面包板上用贴片转直插的PCB进行试验,最好刮一刮导线的接触面,保证接触良好,电源电压够高,不然会导致数据写入失败。


数据传输使用的引脚需要上拉电阻,手册上阻值范围为1K到10K,个人使用的是5K电阻,然后接到单片机上,这里 SCL 我接到 PB0 ,SDA 接到 PB1。
单片机引脚需设为开漏输出(写 0 输出低电平,写 1 浮空),初始化时置为 1 。
浮空:对地电阻非常大,且电压值几乎为零
接下面的说明里,主机 代表单片机,从机 代表DAC5578,时钟端代表SCL, 数据端代表SDA
单片机引脚定义:

最下面的两个定义用来操纵引脚,例如
DAC5578_SCL(LOW) 会使时钟端变为0,DAC5578_SCL(HIGH) 会使时钟端变为1
DAC5578_SDA(LOW) 会使数据端变为0,DAC5578_SDA(HIGH) 会使数据端变为1
初始化函数:

通讯启动:
主机发出启动信号: 时钟端为1时,数据端出现下降沿(由1变0),等待。

延时函数 和 通讯启动函数:

写入数据:
每次改变DAC5578的输出都需要写入4次数据,每次写入1字节(8Bit)
写入 1Bit 数据的方法如下:
拉低时钟端 , 数据端送入数据,等待,
拉高时钟端 , 等待(数据起效);
写入1个字节(8Bit)需要将上面的流程执行8次。

时钟端 为0时,数据端送入数据,
时钟端为 1 时,数据起效。
数据先写高位,再写低位,每次写入 1字节,
例如 1011 0100 (0xb4) ,它的最高位是 1 ,接着是 0、1、 1、 0、 1、 0、 0。
每次写完 1个字节 ,就需要接收一次来自从机的响应(ACK),确认写入成功。
主机将时钟端拉低,数据端拉高(释放引脚),等待,
时钟端拉高,等待,
检查数据端的电平,若为 0 ,写入成功,不然,写入失败。


注意:数据端必须要有合适的上拉电阻,过大过小都不能用,且单片机的引脚必须是开漏模式(写 0 输出低电平, 写 1 浮空),不然会干扰到从机的响应信号!
数据写入函数:

因为设为开漏输出,这时主机的 数据端 是浮空的,从机若发出响应,便会将自己的 数据端 拉低,主机就会读取到 0 ,不然,受上拉电阻的影响,主机将会读取到 1 。
使用 LED 展示写入结果,LED的相关程序在我提供的文件里有,在这不作详解。
当主机收到从机的第四个响应后,主机应发出通讯结束的信号。
通讯结束:
数据端和时钟端都置为 0 ,拉高时钟端,等待,拉高数据端。

通讯结束函数:

写入的数据里,每个字节的作用如下:
第1个字节的前7位时芯片的地址位,ADDR0引脚接VCC时,该芯片的地址为 1001 010 。
最后一位写 0 (Write)表示主机要写入数据,写 1 (Read)表示主机要读取数据,
简称(R/W)位。
所以这个字节的数据为 1001 0100 (0x94)。
第二个字节的前四位是指令,写 0010 (选择DAC端口,并即刻输出DAC信号,需要LDAC一直为0),后四位选择输出端口(通道),数据与端口的对应关系如下

写 0000 选中VOUTA ,写 0001 选中VOUTB,......,写 1111 选中全部端口。
如果要改变 VOUTA 的输出信号,则这个字节的数据为 0010 0000 (0x20)。
如果要改变 VOUTC的输出信号,则这个字节的数据为 0010 0010 (0x22)。
芯片的其他指令请参考数据手册第 31 页。
第三和第四字节的数据大小可以调节输出的电压的大小,DAC5578的分辨率只有 8Bit,所以只有第三字节有效,第四字节写什么都行。
第三字节可选择的数值范围是 0 到 255,理想状况下,写入0时,输出电压为 0V,写入255时,输出电压与VREFIN的电压相同。
实际上,该芯片写入 0 时,输出的电压值为 0.2V,最大值也比VREFIN的电压略低,但对于我现在的应用场景,这些都在允许的范围内。
第四字节是预留给 DAC6578 (10Bit分辨率) 和 DAC7578 (12Bit分辨率) 的,在DAC5578里,这个字节没有用,但必须写。
设置输出电压的函数:

主函数:

最后的运行结果应为,LED2稳定闪烁,LED1微弱的发出亮光后灭掉,万用表测量VoutA的电压是1.65V左右。
一定要保证电源电压足够大,之前我有时同样的程序,时不时写入失败就因为导线接触不好,供电电压只有2.6V左右,真是坑爹呢。
请务必确认电路连接的正确,一开始VREFIN我什么都没接,浪费了一个早上,差点就放弃了
程序里所有的延时函数都可以不要,依然能稳定驱动芯片,我一开始看数据手册上写什么,就做什么了。手册上给出了这个芯片的其他功能,但我还不会用,也没什么兴趣就不看了。
STM32自身也带有I2C通讯协议的外设,但我第一次解读这些全英文的数据手册,为了稳一点还是自己模拟I2C通讯好了,这也是我第一次接触I2C协议,大家自己尝试一下,可能比这么写还快哦。
第一次干这种事一开始感觉就是摸黑走路呢,非常感谢翻译软件的存在,过去的一周时间里也有过几次放弃的念头,用其他芯片代替好了,但那很浪费单片机引脚和钱,也怀疑过芯片质量,但最后算一切顺利了呢。
觉得这个专栏对你有所帮助的请点个赞,投个币,还有收藏,当然,关注就是对我的最大支持啦。虽然我也不知道下一次更新是什么时候,会更新什么就是了。
感觉有些地方没看懂的请留下你的评论。当然,去Bing搜索更快些。
最后附上使用DAC5578输出不断变化的电压的GIF。
