通讯协议之路主要分为两部分,第一部分从理论上面讲解各类协议的通讯原理以及通讯格式,第二部分从具体运用上讲解各类通讯协议的具体应用方法。
后续文章会同时发表在个人博客(jason1016.club)、CSDN;视频会发布在bilibili(UID:399951374)
序:简述个人理解:
读数据帧操作:
START+设备地址+(7)+写数据位(0)+应答信号(0)+寄存器地址(8)+应答信号(0)+START+接收的数据(8)+应答信号(1)+STOP
写数据帧操作:
START+设备地址+(7)+写数据位(0)+应答信号(0)+寄存器地址(8)+应答信号(0)+写入的数据(8)+应答信号(0)+STOP
【4分钟看懂!I2C通讯协议 最简单的总线通讯!】 4分钟看懂!I2C通讯协议 最简单的总线通讯!_哔哩哔哩_bilibili
IIC(Inter-Integrated Circuit)是一种具有两线传输的串行通信总线,使用多主从架构,由飞利浦公司在1980年为了让主板、嵌入式系统或手机连接低速周边设备而提出,适用于数据量不大且传输距离短的场合。
IIC串行总线由两根信号线组成,一根是双向的数据线SDA,另一根是单向的时钟线SCL,在空闲状态时,SDA和SCL线都置’1‘,为高电平。
IIC为同步的半双工通信方式
常见的传输速率有:100kb/s、300kb/s、3.4Mkb/s
IIC由两根通信信号线组成,SCL是由主模块输入的时钟信号,是单向的信号,而SDA是由主机或从机控制的数据信号,是双向信号。
传输时序
在空闲状态下,SCL及SDA都是置高的状态,当需要进行一次IIC传输时,由START信号指示当前数据传输开始,由STOP信号指示当前的数据传输结束,START信号的标识是在SCL高电平情况下,SDA信号由高变低 ,即视为START开始,STOP信号标识是在SCL高电平情况下,SDA信号由低变高,即视为STOP结束,START信号与STOP信号之间的信号流即为所传输信号。
IIC传输格式每一次传输都是以8bit为一个基本传输单位,所含数据流一般包含地址、片选、读写、数据信号。其基本时序如图1所示,SCL为输入的时钟信号,SDA既可作为数据的输入信号,也可作为数据的输出信号
tHIGH 和 tLOW分别为高电平和低电平持续时间;
tsu,sta 和 thd,sta分别为开始信号start的建立和保持时间;
tsu,dat 和 thd,dat分别为数据信号data的建立和保持时间;
tsu,sto 和 thd,sto分别为结束信号stop的建立和保持时间;
图1、IIC传输时序图
写操作时序
在进行写操作时,SCL一直保持时钟的信号,SDA线的传输以8位为一个单位,在进行第一个8bit的传输后,若从设备接收到传输信号,则会返回一个应答信号ack,然后拉低SDA线,进行下一步的数据写入,写周期时序图如下图所示 ,twr 为进行数据写入的时钟周期
图2、IIC写操作时序图
数据有效性
IIC进行传输时,数据data的改变必须在SCL信号为低电平时进行,在SCL为高电平时保持稳定,此时认为在SCL为高电平时的数据有效,其时序如下图所示
图3、信号变换时序图
开始&结束信号
IIC传输的开始及结束如下图4所示,在SCL为高电平期间,SDA由高变低,即为start信号;在SCL为高电平期间,SDA信号由低变高,即为stop信号.
图4、start & stop 信号时序图
从机应答信号
传输过程中的应答信号时序如下图5所示,当检测到start信号后,在随后的8个时钟周期,SDA线进行一次8bit的数据传输,若接收到相应的8bit信号,则在第9个时钟周期拉低SDA信号,并视为一次ack应答信号
图5、ack应答信号时序图
进行一次IIC传输时,由START信号指示当前数据传输开始,由STOP信号指示当前的数据传输结束,IIC传输格式每一次传输都是以8bit为一个基本传输单位,一次完整的IIC传输包含
Trans_data = Start + n * Bytes+ n * ack + Stop
基本数据格式如下图所示:
当检测到Start信号时,主机输出8bit的信号,其中前7bit表示从机的地址,为选中的从机信息,第8bit表示当前进行的读写操作,为’1’表示读操作,为’0’表示写操作,然后第9位为从机的应答ack信号,表示指定从机已接收到地址信号,以进行后续的传输;后续的传输以 8 bit + ack 的重复,即 n * Bytes + n * ack 信号来进行数据的传输,最后主机发出Stop信号,即当前的一次IIC传输结束。
前面提到IIC一般适用于吞吐量较低的场景,其常见的传输速率(SCL线上时钟)有:100kb/s、300kb/s、3.4Mkb/s,而数字处理逻辑动辄几十百兆速率的系统时钟,因而对于IIC必须要做一个低频的时钟。一个完整的IIC传输过程中会用到三个时钟:1、系统频率时钟;2、IIC传输驱动时钟;3、SCL线上时钟(伪时钟)
时钟信号 | 定义 |
System_clk | 系统时钟 |
IIC_dri_clk | IIC驱动时钟 |
SCL_clk | SCL线上时钟(伪时钟) |
SDA信号数据的改变必须是在SCL为低电平时改变,在SCL为高电平时保持稳定,因而可以得出IIC_dri_clk和SCL_clk的关系,IIC_dri_clk频率应至少为SCL_clk的两倍以上(通常选用四倍频,若选用两倍频则只能在下降沿或在当前数据获取的clk上升沿进行改变,易出现毛刺),SDA才能实现在SCL低电平改变数据。时钟频率关系如下,其中 Freq_div 为 分频系数
FIIC_dri_clk=4 * FSCL_clk
Freq_div=FSystem_clk /FIIC_dri_clk
时钟分频具体实现如下:
assign Freq_div= (System_clk/SCL_clk) >> 2'd2; always @(posedge System_clk or negedge rst_n) begin if(!rst_n) begin IIC_clk <= 1'b0; clk_cnt <= 10'd0; end else if(clk_cnt == Freq_div/2 - 1'd1) begin clk_cnt <= 10'd0; IIC_dri_clk <= ~IIC_dri_clk; end else clk_cnt <= clk_cnt + 1'b1; end
整个IIC传输过程中,先传器件地址,再传读/写地址,然后再传读/写数据,因而整个传输过程可以用状态机来控制,状态定义及跳转如下图
状态 | 定义 |
IDLE | 起始状态 |
SLAVE_ADDR | 发送器件地址 |
WR_ADDR_16 | 发送16位字地址 |
WR_DATA | 写数据 |
RD_ADDR | 读地址 |
RD_DATA | 读数据 |
DONE | 传输结束 |
整个状态机具体实现如下:
- always @(posedge IIC_dri_clk or negedge rst_n) begin
- if(!rst_n)
- state_c <= IDLE;
- else
- state_c <= state_n;
- end
-
-
- always @(*) begin
- state_n = IDLE;
- case(state_c)
- IDLE: begin
- if(iic_flag) begin
- state_n = Slave_ADDR;
- end
- else
- state_n = IDLE;
- end
- Slave_ADDR: begin
- if(iic_done) begin
- if(bit_ctrl)
- state_n = WR_ADDR_16;
- else
- state_n = WR_ADDR_8 ;
- end
- else
- state_n = Slave_ADDR;
- end
- WR_ADDR_16: begin
- if(iic_done) begin
- state_n = WR_ADDR_8;
- end
- else begin
- state_n = WR_ADDR_16;
- end
- end
- WR_ADDR_8: begin
- if(iic_done) begin
- if(wr_flag==1'b0)
- state_n = WR_DATA;
- else
- state_n = RD_ADDR;
- end
- else begin
- state_n = WR_ADDR_8;
- end
- end
- WR_DATA: begin
- if(iic_done)
- state_n = DONE;
- else
- state_n = WR_DATA;
- end
- RD_ADDR: begin
- if(iic_done) begin
- state_n = RD_DATA;
- end
- else begin
- state_n = RD_ADDR;
- end
- end
- RD_DATA: begin
- if(iic_done)
- state_n = DONE;
- else
- state_n = RD_DATA;
- end
- DONE: begin
- if(iic_done)
- state_n = IDLE;
- else
- state_n = DONE ;
- end
- default: state_n= IDLE;
- endcase
- end
在整个IIC传输过程中,SCL信号是由主模块传输给从模块的时钟信号,SDA既可以主机发送从机接收,也可以是主机接收从机发送的信号,因而SDA线是双向的信号,在RTL中用inout接口类型来表示该双向信号,在这里即涉及到一个三态门的实现
即当IIC进行主机发送从机接收传输时,IIC_flag信号置高,sda线上信号即为主机发送信号,当从机发送主机接收时,IIC_flag信号拉低,此时sda与sda_out信号间为高阻状态,视为断开,此时通过sda_in信号来获取sda信号线上的输入数据
三态门具体实现如下:
assign sda = IIC_flag ? sda_out : 1'bz; assign sda_in = sda ;
参考文章:通信协议详解(二):IIC总线协议(传输时序+数据格式+设计实现)_iic时序_俩个圆的博客-CSDN博客
在I2C(Inter-Integrated Circuit)通信中,不发送停止位是可以实现持续通信的。I2C是一种串行通信协议,用于在芯片之间进行短距离的数据传输。
在I2C通信中,每个数据传输都由起始位和停止位来标识。起始位表示数据传输的开始,停止位表示数据传输的结束。在每个数据传输之后,需要发送一个停止位来结束当前传输。
然而,在某些特定的应用场景下,可以通过不发送停止位来实现持续通信。这种持续通信的方式被称为"连续传输模式"或"无停止位模式"。
在连续传输模式下,数据传输不会以停止位结束,而是直接开始下一个数据传输。这样可以在不中断通信的情况下连续传输多个数据。
要使用连续传输模式,需要满足以下条件:
1. I2C设备支持连续传输模式:不是所有的I2C设备都支持连续传输模式。需要查看设备的规格书或文档,确认设备是否支持连续传输模式。
2. 主设备和从设备的支持:主设备和从设备都需要支持连续传输模式,才能在通信中实现持续传输。
3. 适当的时序和延时:在连续传输模式下,需要适当的时序和延时来确保数据的正确传输。这需要根据具体的设备和通信速率进行配置。
需要注意的是,连续传输模式可能会增加通信的复杂性和错误处理的难度。因此,在使用连续传输模式时,需要仔细考虑应用需求和设备支持,并进行适当的测试和验证。
在I2C通信中,读数据帧模式通常需要在读取寄存器地址后再次读取从机设备地址。这是因为在I2C通信中,读操作需要先发送从机设备地址和寄存器地址,然后再进行数据的读取。
下面是读数据帧模式的一般步骤:
1. 发送起始位和从机设备地址:主设备发送起始位后,紧接着发送从机设备地址和读/写位。从机设备地址用于选择要进行通信的从机设备,读/写位用于指示是读操作还是写操作。
2. 发送寄存器地址:主设备发送要读取的寄存器地址,用于指示从机设备要读取的数据的位置。
3. 重新发送起始位和从机设备地址:在读数据帧模式中,通常需要重新发送起始位和从机设备地址,以切换到读模式。
4. 读取数据:主设备发送从机设备地址和读位后,从机设备将发送请求的数据。
需要注意的是,具体的通信流程和协议可能会因设备和应用而有所不同。因此,在使用I2C通信时,需要参考设备的规格书或文档,了解具体的通信协议和要求。