G2--FPGA_IIC通信-2021.10.31

FPGA IIC接口通信

本文介绍IIC通信协议以及代码开发的注意事项,跑通了IIC协议,那么后续将会根据此代码的基础上进行IIC的读写应用,例如读写EEPROM。到时将会上传代码。

1.IIC简介

1.1 IIC特性

IIC即 Inter-Integrated Circuit(集成电路总线),是由 Philips 半导体公司在八十年代初设计出来的一种简单、双向、二线制总线标准。多用于主机和从机在数据量不大且传输距离短的场合下的主从通信。主机启动总线,并产生时钟用于传送数据,此时任何接收数据的器件均被认为是从机。

每个连接在总线上的 IIC 器件都有一个唯一的器件地址,在通信的时候就是靠这个地址来通信的。传输速率标准模式下可以达到100kb/s,快速模式下可以达到 400kb/s,高速模式下可达 3.4Mbit/s。IIC接口只需要两条总线线路,即 SCL(串行时钟线)、SDA(串行数据线),IIC 总线是半双工通信。
与UART不同的是,IIC总线上可以挂载若干个从机(一对多)通过主机下发的器件地址选择从机进行通信,并且需要有双向IO的支持,抗干扰能力较弱。而UART为异步串行通信,可称为点对点通信,较为复杂,需要有波特率,即数据传输的间隔要相等,以及接收和发送两根线可实现全双工。

IIC传输时,按照从高到低的位序进行传输,即采用大端模式。大端模式:就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。小端模式:是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

1.2 总线结构

总线(Bus),是指计算机设备和设备之间传输信息的公共数据通道。总线是连接计算机硬件系统内多种设备的通信线路,它的一个重要特征是由总线上的所有设备共享,可以将计算机系统内的多种设备连接到总线上。如果是某两个设备或设备之间专用的信号连线,就不能称之为总线。

总线的性能直接影响到整机系统的性能,而且任何系统的研制和外围模块的开发都必须依从所采用的总线规范。总线技术随着微机结构的改进而不断发展与完善。常见的总线有好多,例如IIC总线、SPI总线、USB总线、JTAG接口、PCI-E总线等。
IIC总线,结构如图所示。
G2--FPGA_IIC通信-2021.10.31

因此,每个 IIC 器件都应该有一个器件地址,有的器件地址在出厂时地址就设置好了,用户不可以更改,有的确定了几位,剩下几位由硬件确定(比如常见的IIC接口的EEPROM存储器,留有3个控地址的引脚,由用户自己在硬件设计时确定)。

严格讲,主机不是直接向从机发送地址,而是主机往总线上发送地址,所有的从机都能接收到主机发出的地址,然后每个从机都将主机发出的地址与自己的地址比较,如果匹配上了,这个从机就会向总线发出一个响应信号。主机收到响应信号后,开始向总线上发送数据,与这个从机的通讯就建立起来了。如果主机没有收到响应信号,则表示寻址失败。

通常情况下,主从器件的角色是确定的,也就是说从机一直工作在从机模式。不同器件定义地址的方式是不同的,有的是软件定义,有的是硬件定义。例如某些单片机的 IIC接口作为从机时,其器件地址是可以通过软件修改从机地址寄存器确定的。而对于一些其他器件,如 CMOS 图像传感器、EEPROM 存储器,其器件地址在出厂时就已经完全或部分设定好了,具体情况可以在对应器件的数据手册中查到。

2.IIC通信协议

2.1信息种类

G2--FPGA_IIC通信-2021.10.31

如上图所示,IIC 协议规定,在时钟(SCL)为高电平的时候,数据总线(SDA)必须保持稳定,所以数据总线(SDA)在时钟(SCL)为低电平的时候才能改变。因此,当SCL为高电平时,改变SDA的值,这些情况被赋予了特殊的含义,主机向从机发送的信息种类有启动信号、停止信号、7位地址码、读/写控制位、10位地址码(地址扩展)、数据字节、重启动信号、应答信号、时钟脉冲。而从机向主机发送的信息种类有应答信号、数据字节、时钟低电平(时钟拉伸)。
空闲状态:在空闲状态下SDA与SCL均为高电平;
G2--FPGA_IIC通信-2021.10.31
起始信号:在时钟(SCL)为高电平的时候,数据总线(SDA)由高到低的跳变;
停止信号:在时钟(SCL)为高电平的时候,数据总线(SDA)由低到高的跳变;
G2--FPGA_IIC通信-2021.10.31
重新开始信号:在IIC总线上,由主机发送一个开始信号启动一次通信后,在首次发送停止信号之前,主机通过发送重新开始信号,可以转换与当前从机的通信模式,或是切换到与另一个从机通信。当SCL为高电平时,SDA由高电平向低电平跳变,产生重新开始信号,它的本质就是一个开始信号。

G2--FPGA_IIC通信-2021.10.31
应答位:IIC总线上的所有数据都是以8位字节传送的,发送器每发送一个字节,就在第9个时钟脉冲期间释放数据线,由接收器反馈一个应答信号。应答信号为低电平时,规定为有效应答位(ACK简称应答位),表示接收器已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。因此一个完整的字节数据传输需要9个时钟脉冲。如果从机作为接收方向主机发送非应答信号,主机方就认为此次数据传输失败;如果是主机作为接收方,在从机发送器发送完一个字节数据后,向从机发送了非应答信号,从机就认为数据传输结束,并释放SDA线。不论是以上哪种情况都会终止数据传输,这时主机或是产生停止信号释放总线或是产生重新开始信号,开始一次新的通信。

插入等待时间:如果被控器需要延迟下一个数据字节开始传送的时间,则可以通过把时钟线SCL电平拉低并且保持,使主控器进入等待状态。一旦被控器释放时钟线,数据传输就得以继续下去,这样就使得被控器得到足够时间转移已经收到的数据字节,或者准备好即将发送的数据字节。
器件地址:任何IIC设备都有一个7位地址,理论上,现实中只能有127种不同的IIC设备。实际上,已有IIC的设备种类远远多于这个限制,在一条总线上出现相同的地址的IIC设备的概率相当高。为了突破这个限制,很多设备使用了双重地址——7位地址加引脚地址(external configuration pins)。IIC 标准也预知了这种限制,提出10位的地址方案。10位的地址方案对 IIC协议的影响有两点:地址帧为两个字节长,原来的是一个字节;第一个字节前五位最高有效位用作10位地址标识,约定是“11110”。

2.2通信过程

写过程
G2--FPGA_IIC通信-2021.10.31
(1)主机设置SDA为输出;
(2)主机发起起始信号;
(3)主机传输器件地址字节,其中最低位为 0,表明为写操作;
(4)主机设置 SDA 为三态门输入,读取从机应答信号;
(5)读取应答信号成功,主机设置 SDA 为输出,传输待写入的数据;
(6)设置 SDA 为三态门输入,读取从机应答信号;
(7)读取应答信号成功,主机产生 STOP 位,终止传输。
读过程
G2--FPGA_IIC通信-2021.10.31

① 主机设置 SDA 为输出;
② 主机发起起始信号;
③ 主机传输器件地址字节,其中最低位为 1,表明为读操作;
④ 设置 SDA 为三态门输入,读取从机应答信号;
⑤ 读取应答信号成功,主机设置SDA为三态门输入,读取SDA总线上的一个字节的数据;
⑥ 主机收到数据后向从机反馈一个应答信号;
⑦ 从机收到应答信号后再向主机发送下一个数据;
⑧ 当主机完成接收数据后,向从机发送一个“非应答信号(ACK=1)”,从机收到ACK=1 的非应答信号后便停止发送;
⑨ 主机发送非应答信号后,再发送一个停止信号,释放总线结束通信。

3.开发过程注意事项

3.1用户时钟的选择

用户时钟选择四倍于scl的时钟频率,因为协议规定sda改变时需要在scl为低电平时,所以iic_dri_clk可以很好的处理sda与scl的改变均为其上升沿,因此使用较为方便,当然高于这个时钟频率也可以。
G2--FPGA_IIC通信-2021.10.31

3.2典型时钟分频电路产生SCL信号

always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        iic_dri_clk <=  1'b0;
        clk_cnt <= 10'd0;
    end
    else if(clk_cnt == clk_div[8:1] - 1'd1) begin
        clk_cnt <= 10'd0;
        iic_dri_clk <= ~iic_dri_clk;
    end
    else
        clk_cnt <= clk_cnt + 1'b1;
end

3.3流控制计数器的使用

此程序IIC每一个状态的时序由一个流控制计数器完成,以计数器的值来判定改变scl、sda的电平状态模拟IIC时序,代码示例以及示意图如下:

sladdr: begin          //写地址
case(flow_cnt)     //示意图 ,后面都是按照这个思路来写的 
7'd1 : sda_out <= 1'b0; //开始I2C
7'd3 : iic_scl <= 1'b0;              
7'd4 : sda_out <= SLAVE_ADDR[6]; //传送器件地址
7'd5 : iic_scl <= 1'b1;              
7'd7 : iic_scl <= 1'b0;              
7'd8 : sda_out <= SLAVE_ADDR[5]; 
……

这样又同时保证了sda在scl低电平时的中点改变。
G2--FPGA_IIC通信-2021.10.31

4.仿真结果展示
写仿真
G2--FPGA_IIC通信-2021.10.31
读仿真
G2--FPGA_IIC通信-2021.10.31

上一篇:TMS320F280049C I2C IIC 相对于库函数操作CAT24C02 中文


下一篇:Docker构建私有registry