IIc通信协议之(二)——PCF8591控制

 

本章继上节iic通信协议,在理论学习之后,找到一块iic接口的片子——PCF8591,它是一款AD-DA集成芯片。所以本节对iic通信协议不做过多的介绍,重心放在iic的rtl建模,本次通过iic控制PCF8591实现DAC输出功能。

 

PART1:建模前的准备

包括两部分,一是芯片手册阅读,二是建模思路;

阅读PCF8591芯片手册,获得以下信息:

>PCF8591的指令控制顺序:主机先向其发送地址指令(包括sda方向选择指令);然后是控制字指令;最后是数据指令(dac对应8bit的dac二进制数据,adc对应为sda方向操作控制指令)

>PCF8591具有adc和dac两种功能,选择哪一种功能需要通过指令(2、3指令功能决定)进行确定。

>模块硬件地址应确定,为000(A2A1A0)。

>具体的寄存器配置(指令)就不详细介绍,总结如下:

adc功能配置,先后发送0x90、0x40+channel(取值0、1、2、3,总共有四个通道)、0x91即可;

dac功能配置,先后发送0x90、0x40、user_data(8bit)即可;

>要注意iic通信速率及相关时间的限制,总结如下:

DAC模式输出频率Fmax=11.1KHz;

Fsclk_max=100kHz;(这就对sclk的高低电平持续时间有要求);

开始、结束、数据的建立保持时间(如下表);

【相关参数表格】

IIc通信协议之(二)——PCF8591控制

【iic时序示意图】

IIc通信协议之(二)——PCF8591控制

总结一下:

建立时间和保持时间大都与4.7us有关,且Fsclk_max=100K,即Tmin=10us,取5us作为标准,保持时间和建立时间都为5us;

输出信号频率有全范围输出的时间间隔决定(1111_1111à0000_0000),由数据手册知,Tscale=90us,则fout_max=11.1KHz。

IIc通信协议之(二)——PCF8591控制

以上,就是建模前的准备工作。

PART2:第一次建模(失败)

如下,是第一次建模的仿真波形,整体上sclk和sda的时序都是满足起始和停止条件的,但下载到FPGA中并没有正确的结果。

仿真波形(第一次):

IIc通信协议之(二)——PCF8591控制

所以究竟是什么原因呢?于是我用signaltap对板子上的信号进行波形抓取,确实,在signaltap中确实抓到了波形,且与仿真的波形基本一致。这时,我一度认为是芯片坏了(寻求一下自我安慰,实际上这个模块是新买的移植没有使用过)。还是不甘心,于是我下老本了,找到一台示波器,我要亲自看看这个数据波形到底是不是真的有(提醒一下大家,signaltap上抓取的波形基本上就是实际用示波器探测到的波形,所以大家不用怀疑signaltap欺骗了你,大家也不用向我这样真的去用示波器看波形)。以下给出示波器波形:

>sda波形:

IIc通信协议之(二)——PCF8591控制

>sclk波形:

IIc通信协议之(二)——PCF8591控制

就在这万般无奈之际,闹钟突然闪过一条信息——iic的速度不会非常快。这才意识到,我最开始sclk的频率取得是clk(50MHz)的4分频,也就是接近12.5MHz,而从手册上看到Fsclk_max=100KHz。于是,欣喜地修改了分频系数,本以为可以成功输出目标电压值,然后事实是并没有。不幸,Round1失败。

PART3:建模修改

第二天,并没有花时间去修改代码,而是在思考原因何在?在没有对策之后,我决定重新阅读英文版芯片手册,主要看其通信协议及其注意事项,这才有了本文最开始的图和表,也就引出一个很重要的概念——信号的建立时间和保持时间。

所以,我是走了弯路的,这里希望大家引以为戒。我犯了一个错误,一开始值看了中文版的芯片手册,而里面并没有给出相关的通信协议的注意事项(因为中文版的资料是出自他人之手的加工品,它不可能像原版手册那么全面地介绍了芯片使用的方方面面),所以,大家以后还是尽量阅读英文原版手册(或者至少出问题时请及时去参看原文手册)。

以上是建议,此外,就是建立时间和保持时间,这个概念真的非常重要,是任何一个数字设计者必须熟悉的概念。所以,在进行通信协议建模或者数字设计时,心中时刻要有这两个的概念。此后,我也将继续学习相关知识,可能的话建立相关专题,为大家分享的我的学习经历。

 

回归主题,意识到问题所在,对照最开始的建模代码,不满足时序要求的最主要的两点:一是start的相关时序;二是stop的相关时序。主要就是时间过短,最终的解决方法是折中取5us左右作为相关时序的持续时间。对症下药之后,一遍出电压,成功驱动。以下给出dac=1100_1111时的电压输出值,V_the=4.0V左右(基准4.95V),实际输出V_act=3.95V。这样的误差在正常范围内。

仿真波形如下:(dac_reg=1111_1111)

IIc通信协议之(二)——PCF8591控制

SignalTap_ii中的波形:

其中sda线上在第8bit数据输出后悔出现一个小的脉冲,这是与仿真波形不一致的地方,但这并没有影响最终的输出。(因为sclk为1时数据时有效的)

IIc通信协议之(二)——PCF8591控制

以上波形对照iic时序示意图,起始和停止的建立时间和保持时间均满足极限要求。

最后,给出整个工程的RTL视图:

IIc通信协议之(二)——PCF8591控制

总结一下:

<1>iic协议是一种半双工通信协议,sda是双向接口。用verilog设计,可以采用以下方式:定义reg变量表示sda的输出方向,若是输入则定义为高组态,输入由外部连接所决定;正常时zuuuooo输出即可。

reg sda_out; 	 	//sda输出寄存器
reg io_link; 	 	//sda方向寄存器,1表示输出(dac),0表示输入(adc)
assign sda = io_link ? sda_out : 1'bz; 	 	//sda作输入时,将其设置为高阻状态,则sda的实际状态由实际线上的状态决定

<2>使用状态机实现,考虑好是单个状态机实现还是使用嵌套,不是说越多就越高大上,功能稳定是关键;

<3>数字设计特别是涉及到时序相关的,心中一定时刻要有建立时间和保持时间的概念。

以上就是运用PCF8951学习iic通信协议的相关总结。

本设计的相关代码链接:

 

 

上一篇:虚机安装vyOS使用Xshell连接


下一篇:Kali Linux虚拟机的安装