通讯协议学习之路:IIC协议理论

news2025/1/19 2:54:01

通讯协议之路主要分为两部分,第一部分从理论上面讲解各类协议的通讯原理以及通讯格式,第二部分从具体运用上讲解各类通讯协议的具体应用方法。

后续文章会同时发表在个人博客(jason1016.club)、CSDN;视频会发布在bilibili(UID:399951374)

序:简述个人理解:

  1. IIC协议支持一主多从的连接方式,可以主机可以与多下属设备通信,但是一次通信中依然只能选其中一从机单对单通信
  2. IIC协议是同步半双工通信,拥有数据线SDA与时钟线SCL,通讯空闲状态SDA与SCL均为高电平态(1)
  3. 在IIC处于工作态后SCL将不断上下翻转形成时钟脉搏
  4. IIC协议起始位为在SCL为高电平时将SDA的高电平翻转为低电平,停止位为当SCL为高电平时将SDA的低电平转换为高电平
  5. IIC协议开启工作状态后只在SCL为高电平读取数据,这是SDA的高低电频则对应着逻辑1和逻辑0
  • 常态:SCL==1;SDA==1
  • 工作态:SCL电频周期翻转;SDA电频由数据而定
  • 起始位:SCL==1时:SDA==1-->0
  • 停止位:SCL==1时:SDA==0-->1
  • 逻辑1:SCL==1时:SDA==1
  • 逻辑0:SCL==0时:SDA==0

  1. IIC数据格式分为读取数据以及写入数据格式,二者格式并不一致。
  2. IIC协议支持连续通信,即起始位并且握手后在数据帧以八位数据信号加应答信号不断发送或接收数据,最后再挂在停止位。但是连续通信需要满足几个条件才能执行,具体条件在下文提及。

读数据帧操作:

START+设备地址+(7)+写数据位(0)+应答信号(0)+寄存器地址(8)+应答信号(0)+START+接收的数据(8)+应答信号(1)+STOP

写数据帧操作:

START+设备地址+(7)+写数据位(0)+应答信号(0)+寄存器地址(8)+应答信号(0)+写入的数据(8)+应答信号(0)+STOP

一、IIC(Inter-Integrated Circuit)介绍

【4分钟看懂!I2C通讯协议 最简单的总线通讯!】 4分钟看懂!I2C通讯协议 最简单的总线通讯!_哔哩哔哩_bilibili

    IIC(Inter-Integrated Circuit)是一种具有两线传输的串行通信总线,使用多主从架构,由飞利浦公司在1980年为了让主板、嵌入式系统或手机连接低速周边设备而提出,适用于数据量不大且传输距离短的场合。

    IIC串行总线由两根信号线组成,一根是双向的数据线SDA,另一根是单向的时钟线SCL,在空闲状态时,SDA和SCL线都置’1‘,为高电平。

IIC为同步的半双工通信方式

常见的传输速率有:100kb/s、300kb/s、3.4Mkb/s

二、传输协议

1.时序

    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应答信号时序图

2.数据格式

    进行一次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传输结束。

三、设计实现

1、时钟

    前面提到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

2、传输过程

   整个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

3、 三态门

在整个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博客

四、疑难问题

1、IIC通讯中不发送停止位可以持续通信吗

在I2C(Inter-Integrated Circuit)通信中,不发送停止位是可以实现持续通信的。I2C是一种串行通信协议,用于在芯片之间进行短距离的数据传输。

在I2C通信中,每个数据传输都由起始位和停止位来标识。起始位表示数据传输的开始,停止位表示数据传输的结束。在每个数据传输之后,需要发送一个停止位来结束当前传输。

然而,在某些特定的应用场景下,可以通过不发送停止位来实现持续通信。这种持续通信的方式被称为"连续传输模式"或"无停止位模式"。

在连续传输模式下,数据传输不会以停止位结束,而是直接开始下一个数据传输。这样可以在不中断通信的情况下连续传输多个数据。

要使用连续传输模式,需要满足以下条件:

1. I2C设备支持连续传输模式:不是所有的I2C设备都支持连续传输模式。需要查看设备的规格书或文档,确认设备是否支持连续传输模式。

2. 主设备和从设备的支持:主设备和从设备都需要支持连续传输模式,才能在通信中实现持续传输。

3. 适当的时序和延时:在连续传输模式下,需要适当的时序和延时来确保数据的正确传输。这需要根据具体的设备和通信速率进行配置。

需要注意的是,连续传输模式可能会增加通信的复杂性和错误处理的难度。因此,在使用连续传输模式时,需要仔细考虑应用需求和设备支持,并进行适当的测试和验证。

2、IIC通讯在读数据帧模式中,在读取寄存器地址后还需要再次读取从机设备地址吗

在I2C通信中,读数据帧模式通常需要在读取寄存器地址后再次读取从机设备地址。这是因为在I2C通信中,读操作需要先发送从机设备地址和寄存器地址,然后再进行数据的读取。

下面是读数据帧模式的一般步骤:

1. 发送起始位和从机设备地址:主设备发送起始位后,紧接着发送从机设备地址和读/写位。从机设备地址用于选择要进行通信的从机设备,读/写位用于指示是读操作还是写操作。

2. 发送寄存器地址:主设备发送要读取的寄存器地址,用于指示从机设备要读取的数据的位置。

3. 重新发送起始位和从机设备地址:在读数据帧模式中,通常需要重新发送起始位和从机设备地址,以切换到读模式。

4. 读取数据:主设备发送从机设备地址和读位后,从机设备将发送请求的数据。

需要注意的是,具体的通信流程和协议可能会因设备和应用而有所不同。因此,在使用I2C通信时,需要参考设备的规格书或文档,了解具体的通信协议和要求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1107387.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PyCharm运行python测试,报错“没有发现测试”/“空套件”

问题描述&#xff1a;没有发现测试/空套件 当时没截图&#xff0c;可惜了&#xff01; 解决办法 把python测试文件的文件名改为非test开头的&#xff01; &#xff08;虽然pytest的官方说要以test开头&#xff0c;但是他这样会有错误&#xff0c;就很…

节流防抖

节流&#xff1a;wait时间内只能执行一次func 防抖&#xff1a;触发后延迟wait秒调用func 代码对比&#xff1a;&#xff08;建议自己手敲一遍&#xff0c;不要养成直接cv的坏习惯&#xff09; 节流&#xff1a; 其中的apply函数是 apply() 是 JavaScript 函数的一个方法…

Python 编程基础 | 第六章-包与模块管理 | 1、包与模块简介

一、模块 在程序开发过程中&#xff0c;文件代码越来越长&#xff0c;维护越来越不容易。可以把很多不同的功能编写成函数&#xff0c;放到不同的文件里&#xff0c;方便管理和调用。在Python中&#xff0c;一个.py文件就称之为一个模块&#xff08;Module&#xff09;。 1、简…

Acwing 3306.装珠饰(十一届蓝桥java/py组J题)

分析&#xff1a; 6件装备作为一个整体去看待&#xff01;&#xff01;&#xff01;加的效果是看总的装备数目 分组背包的一个特点&#xff1a;每一个组里面只能取出一个物品&#xff0c;这里是把抽象成不同的方案数(有点多重背包的二进制处理方法的感觉。) 代码实现&#xff1…

vue-cli脚手架创建项目时报错Error: command failed: npm install --loglevel error

项目背景 环境&#xff1a;vue-cli 5.x 在工程文件中&#xff0c;后端模块wms已经创建完成&#xff0c;现在想新建一个名为vue-web的前端模块 执行命令vue create vue-web时&#xff0c; 报错Error: command failed: npm install --loglevel error 问题分析及解决 排查过程…

2023各版本JDK下载链接

Java Archive | Oracle Java Archive | Oraclehttps://www.oracle.com/java/technologies/downloads/archive/

音乐播放器蜂鸣器AX301开发板verilog,视频/代码

名称&#xff1a;音乐播放器蜂鸣器播放音乐按键切歌 软件&#xff1a;Quartus 语言&#xff1a;Verilog 代码功能&#xff1a; 设计一个音乐播放器&#xff0c;使用板子上的蜂鸣器播放歌曲&#xff0c;可以播放三首歌&#xff08;歌曲任选&#xff09;&#xff0c;通过按键控…

ESP RainMaker 客户案例 #2|PitPat

PitPat 是美国领先的健身品牌&#xff0c;致力于通过游戏化的方式改变人们的锻炼习惯&#xff0c;增强健康。该品牌通过智能设备和相关的移动应用程序为从事家庭锻炼的个人提供虚拟跑步体验。目前&#xff0c;PitPat 针对不同受众群体&#xff0c;开发了Superun&#xff0c;Dee…

JMM-多线程先行发生原则happens-before

5.6 JMM规范下多线程先行发生原则之happens-before 在JVM中&#xff0c;如果一个操作执行的结果需要对另一个操作可见或者代码重排序&#xff0c;那么这两个操作之间 必须存在happens-before&#xff08;先行发生&#xff09;原则&#xff0c;逻辑上的先后关系。 5.6.2 先行并…

9章【同余】

蒙特卡罗算法【和一个模型联系起来】 舍伍德算法【】 拉斯维加斯算法【最不靠谱&#xff0c;思路&#xff1a;把该算法和固有算法相结合】 随机数 学习目标&#xff1a; 利用数据序列的随机性和概率 分布等点&#xff0c;设计解决问题的算法或提高 已有算法的效率。 随机性…

swagger报错Illegal DefaultValue null for parameter type integer

文章目录 报错:作者说这只是一个警告并不是个错误,并且有点烦躁的说已经是提的1000个issues了解决给Integer类型或者long类型的example设置值,不设置也不行(不建议)有时候参数很多,很麻烦.或者不用处理方法一:修改AbstractSerializableParameter类的日志级别为Error方法二:修改…

【数据结构】线性表(二)单链表及其基本操作(创建、插入、删除、修改、遍历打印)

目录 前文、线性表的定义及其基本操作&#xff08;顺序表插入、删除、查找、修改&#xff09; 四、线性表的链接存储结构 1. 单链表&#xff08;C语言&#xff09; a. 链表节点结构 b. 创建新节点 c. 在链表末尾插入新节点 d. 删除指定节点 e. 修改指定节点的数据 f. …

循环日程安排问题(分治法)

函数接口定义&#xff1a; void Plan(int a[][N],int k); 裁判测试程序样例&#xff1a; #include #include <math.h> #include using namespace std; #define N 100 void Plan(int a[][N],int k); int main() { int i,j,a[N][N],k,size; cin>>k; sizepow(2,k)…

“滑动窗口”算法专项训练

目录 题目链接&#xff1a;长度最小的子数组 题目描述 思路分析&#xff1a;滑动窗口(利用单调性&#xff0c;使用"同向双指针来优化) 细节处理 画图解析 代码 题目链接&#xff1a;最大连续1的个数 III 题目描述 思路分析&#xff1a;滑动窗口(同向双指针) 细节…

面对纷繁复杂的低代码和无代码产品,开发者该如何选择?

凭借着革命性的生产力优势&#xff0c;低代码技术火爆了整个IT圈。面对纷繁复杂的低代码和无代码产品&#xff0c;开发者该如何选择&#xff1f; 在研究低代码平台的年数上&#xff0c;本人已有3年&#xff0c;也算是个低代码资深用户了&#xff0c;很多企业面临低代码选型上的…

TCP/IP(二十)TCP 实战抓包分析(四)TCP 第二次握手 SYN、ACK 丢包

一 实验二&#xff1a;TCP 第二次握手 SYN、ACK 丢包 重点&#xff1a; 通过设置 tcp_synack_retries 和 tcp_syn_retries内核参数,观察丢包的现象 ① 实验环境 iptables -t filter -I INPUT -s 172.25.2.100 -j DROPtcpdump -nni ens3 tcp and host 172.25.2.100 and por…

【算法 | 位运算No.1】leetcode268. 丢失的数字

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【Leetcode】 &#x1f354;本专栏旨在提高自己算法能力的同时&#xff0c;记录一下自己的学习过程&#xff0c;希望…

打造一个开箱即用的超级丝滑的漂亮hexo博客网站

打造一个开箱即用的超级丝滑的漂亮hexo博客网站 目录 文章目录 打造一个开箱即用的超级丝滑的漂亮hexo博客网站目录文章持续更新地址鸣谢hexo简介hexo优缺点优点缺点&#x1f44e; 没有后台管理 博客效果主题特性版本迭代1.原版版本迭代2.自己版本迭代 贡献者主题下载&#x1f…

Python中if __name__ == ‘__main__‘

1. 在Python中&#xff0c;凡是以两个下划线开头&#xff0c;两个下划线结尾的变量叫做“魔法变量”。瓦特&#xff1f;魔法变量&#xff1f;对&#xff0c;你没有听错&#xff0c;就是魔法变量。所谓魔法变量就是Python对象内置天生就有的属性变量&#xff0c;你使用这些变量前…

开关电源测试方案介绍:如何进行电源耐压测试?

耐压测试是检验电源模块、电器设备等承受过压能力的测试方法&#xff0c;同时电源模块耐压测试还可以检测出设备的绝缘性能。在电气设备的使用过程中会出现电压突然上升的情况&#xff0c;有时也会因为天气原因出现高压&#xff0c;如果耐压性能弱&#xff0c;设备绝缘能力差&a…