IIC协议

news/2024/12/4 17:31:29/

1.认识IIC

1、IIC协议概述:

  • IIC(Inter-Integrated Circuit,集成电路总线)是一种串行通信协议,也被称为I2C协议。它是由荷兰的PHILIPS公司(现在philips公司将其半导体部门拆分出来并更名为NXP半导体公司)在1982年开发的一种简单、高效的通信协议。
  • IIC协议主要用与连接电路之间进行短距离的数字通信,比如连接微控制器及其外围设备。
  • IIC协议使用两线式串行总线。
  • IIC有点像串口,但是串口是全双工,但是IIC属于半双工同步通信方式,数据传输线只有一根,传输和接收要去占用SDA线。

2、IIC协议特点:

  1. 简单性:IIC协议只使用了两根信号线,并且由于接口直接在组件之上,因此IIC总线占用的空间非常小,减少了电路板的空间和芯片管脚的数量,降低了互联成本。能够支持40个组件。
  2. IIC协议的通信速率:在一些特定的应用或特定的环境下(比如用于学习),为了提供高通信的稳定确定性和可靠性,某些设备或系统选择将IIC协议的传输速率限制在较低的速率,例如10 Kbps。但它并不代表IIC协议的最大通信速率就是10 Kbps。根据协议版本不同IIC协议的通信速率会有不同,标准模式的IIC协议支持最大传输速率为100 Kbps,快速模式则为 400 Kbps,高速模式则为 3.4 Mbps。
  3. 多主控(multimastering):其中任何能够进行发送和接收的设备都可以成为主控设备,这些主控设备可以是MCU、OLED、手持传感器、陀螺仪等其他I2C接口器件(如下图),这些I2C接口器件都共用这两根串行总线。当然,在任何时间点上只能有一个主控。主控设备负有责任发起和控制通信,它可以向其他设备发送命令、读取数据,并负责协调总线上的通信活动。其他设备被称为从属设备(Slave Device),它们被主控设备控制并响应主控设备的命令。从属设备不能主动发起通信,而正在主控设备的指示下进行相应的操作。因此,虽然任何设备都可以作为IIC协议中的主控设备,但在实际应用中,根据设备的功能和设计,选择合适的设备作为主控设备,其他设备则作为从属设备,以满足通信需求和数据交换的要求
  4. 硬件地址查找:每个从设备在总线上都有唯一一个硬件地址,主设备通过这个地址来选择与之通信的从设备。

3、IIC协议构成:IIC协议是两线式串行总线,两根信号线分别是数据线SDA和时钟线SCL。所有用IIC通讯的设备都需要遵循相同的通讯时序。

  1. SDA(Serial Data Line,数据线):用于传输数据。
  2. SCL(Serial Clock Line)时钟线:用于传输时间信息,时钟信号是由主控器件产生的。

  • 在时间信息的控制下,主设备(如微控制器)可以与多个从设备(如传感器、存储器、显示器等)进行双向通信。
  • 所有接到IIC总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上。对于并联在一条总线上的每个IC都有唯一的地址。

4、单片机使用IIC协议的注意点:

  1. 由于51单片机开发板上刚好有硬件串口,也就是有与串口对应的寄存器支持,所以,51单片机的串口通信协议(波特率、数据位、起始位、停止位)是通过配置寄存器来完成的。
  2. 但是51单片机上没有IIC这种硬件设备,所以无法通过配置寄存器来驱动串行通信协议,需要分析I2C接口器件时序后转化为代码,通过I/O口来模拟IIC协议(类似于LCD模块、DHT11模块这些非标协议)。
  3. 接下来,我们以51单片机作为主设备,以OLED屏幕作为从设备,连接方式是直连。当然如果有多个从设备,那么就需要用到面包板,实现如上图中并联的效果。
  4. C语言在调用函数时有一个压栈和弹栈的过程,所以即使你调用的函数什么也没有做,在晶振为11.0592MHz的情况下,也需要耗费5微秒的时间。而单片机中_nop()_就是一个空函数,一个nop的耗时为5微秒。

5、IIC总线的信号类型:IIC总线在传输数据的过程中一共有三种类型信号,分别为:开始信号、结束信号和应答信号。

  • 类似于串口,多机通讯无非要关注:起始位,停止位,数据位,波特率。
  • 那么在IIC协议中,开始信号就相当于设置起始位,结束信号就相当于设置停止位,程序中根据时序图通过延时等方法去控制时间点相当于设置波特率。

6、分析时序图的正确逻辑:回顾DHT11模块的时序分析,我们做的还不好,正确的分析逻辑应该如下。

  1. 对总线上的信号进行分类:因为不同信号的表达方式是不一样的,比如启动信号是置高低电平,响应信号是被拉成高低电平。分类完成后的每部分信号都是总体通讯时序图中的一部分。
  2. 在每种信号时序上标注字母:每种信号时序图上可能有多个数据线,所以标注的点最好划分的细致一点
  3. 三步骤读时序图:读时序图关注开始、转折、结尾。读的时候进行记录,可以使用“置高/低电平”、“电平被拉高/低”、“从低/高电平转折为高/低电平”、“维持高/低电平”、“延时”、“卡x点,直到数据线变成高/低电平”等字眼帮助判断。
  4. 编写代码:将时序逻辑复制到代码编辑器中,照着时序分析写代码(一个时序分析完之后就进行一次函数封装)。
  • 注意:当时序图中总线多的时候(比如LCD1602的读写时序图中有4根总线),那么就需要先查看引脚说明。

2.IIC协议通讯时序分析1:起始、终止、应答

1、起始信号:

  1. o点:
    1. SCL置高电平
    2. SDA置低电平
  2. a点:
    1. SCL维持高电平
    2. SDA从低电平转折为高电平,时间未知
  3. a—>b:
    1. SCL维持高电平
    2. SDA延时4.7微秒
  4. b—>c:
    1. SCL维持高电平
    2. SDA从高电平转折为低电平,时间未知
  5. c—>d:
    1. SCL延时4微秒
    2. SDA维持低电平
  6. d点:
    1. SCL从高电平转折为低电平,时间未知
    2. SDA维持低电平
  7. void IIC_Start()
    {// a点:scl = 1;    // SCL置高电平sda = 1;    // SDA从低电平转折为高电平,时间未知// a—>b:// SCL维持高电平_nop_();    // SDA延时4.7微秒// b—>c:// SCL维持高电平sda = 0;    // SDA从高电平转折为低电平,时间未知// c—>d:_nop();    // SCL延时4微秒// SDA维持低电平// d点:scl = 0;    // SCL从高电平转折为低电平,时间未知// SDA维持低电平
    }

2、终止信号:

  1. o点:
    1. SCL置低电平
    2. SDA置低电平
  2. a点:
    1. SCL从低电平转折为高电平,时间未知
    2. SDA维持低电平
  3. a—>b:
    1. SCL维持高电平
    2. SDA延时4微秒
  4. b—>c:
    1. SCL维持高电平
    2. SDA从低电平转折为高电平,时间未知
  5. c—>d:
    1. SCL维持低高电平
    2. SDA延时4.7微秒
  6. d点:
    1. SCL维持高电平
    2. SDA从高电平转折为低电平,时间未知
  7. void IIC_Stop()
    {// a点:scl = 1;    // SCL从低电平转折为高电平,时间未知sda = 0;    // SDA置低电平// a—>b:// SCL维持高电平_nop_();    // SDA延时4微秒// b—>c:// SCL维持高电平sda = 1;    // SDA从低电平折为高电平,时间未知// c—>d:// SCL维持低高电平_nop_();    // SDA延时4.7微秒// d点:// SCL维持高电平sda = 0;    // SDA从高电平转折为低电平,时间未知
    }

3、应答信号ACK:应答信号的时序图如下图所示,由于SDA是被读量,所以只在SCL数据线上划分点。

  • 目的:IIC的设计是当SDA和SCL总线上连接有上拉电阻(电平被拉高)时,实际上是不走数据的,也就是释放数据线。在从设备收到完整的一个字节(8位)之后,就主动去拉低SDA总线上的电平,代表接收器成功地接收了该字节。
  • 响应形式:
    • 应答信号为低电平时,规定为有效应答位(ACK,Acknowledgement Character,简称应答位),表示接收器已经成功地接收了该字节;
    • 应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。
  1. o点:
    1. SCL置低电平
    2. SDA:在主控设备发送完成一个字节数据后,就立马发送一个高电平,代表释放SDA数据线
  2. o—>a:
    1. SCL延时
  3. a点:
    1. SCL从低电平转折为高电平,代表释放SCL数据线
  4. a—>b:
    1. SCL延时4微秒,因为读取SDA的时候一定要保证SCL处于高电平的状态
    2. SDA被读
    3. SCL延时4微秒,因为读取SDA的时候一定要保证SCL处于高电平的状态
  5. b点:
    1. SCL从高电平转折为低电平
  6. b—>c:
    1. SCL延时
  • 实际上我们不是很关心ACK函数,只有在后面显示出问题了,比如说显示乱码了才会去调用这个函数进行判断。
    void IIC_ACK()
    {char flag;// o点:// SCL置低电平sda = 1;    // SDA:在主控设备发送完成一个字节数据后,就立马发送一个高电平,代表释放SDA数据线// o—>a:_nop_();    // SCL延时// a点:scl = 1;    // SCL从低电平转折为高电平,代表释放SCL数据线// a—>b:_nop_();    // SCL延时4微秒,因为读取SDA的时候一定要保证SCL处于高电平的状态flag = sda; // SDA被读_nop_();    // SCL延时4微秒,因为读取SDA的时候一定要保证SCL处于高电平的状态// b点:scl = 0;    // SCL从高电平转折为低电平// b—>c:_nop_();    // SCL延时return flag;
    }

3.IIC协议通讯时序分析2:数据发送

1、回顾串口和LCD的数据发送:

  • 在学习串口的时候,我们不去关心数据的发送需要根据数据发送时序图写什么代码,只需要往SBUF里面传输数据就可以了,这是因为单片机上有对应的寄存器硬件;
  • 在学习LCD1602的时候,我们也不去关心数据的发送需要根据写操作时序图写什么代码,只需要往单片机的P0这个I/O口组(和LCD的DB0~DB7相连)里面传输数据就可以了,这也是因为有硬件。
  • 二者相同点:数据传输伴随着一个脉冲信号。
    • 串口发送数据时,脉冲信号由串行移位寄存器SHIFT提供:
      • SHIFT为低电平时进行一位数据的发送;
      • SHIFT由低变高(上升沿)代表发送结束;
      • SHIFT为高电平时允许数据翻转;
      • SHIFT由高变低(下降沿)代表开始发送下一位数据。
    • LCD发送数据时,脉冲信号由使能引脚E提供:
      • 在E由低变高(上升沿)之前就开始发送一字节数据;
      • 一字节数据发送完毕之后E由高变低(下降沿)。

 

 

2、IIC数据发送的时序:

  1. 与起始/终止信号的区别:IIC在进行数据发送的时候,需要注意:
    1. 在SCL为高电平时,允许SDA上进行一位数据的传输,期间不允许数据的翻转;
    2. 在SCL为低电平时,允许数据的翻转。
    3. 如果在SCL为高电平时出现了SDA上数据的翻转,那么IIC接收器会误以为这是起始信号或终止信号。所以每次SDA上进行数据翻转前都要保证SCL处于低电平。
  2. 时序逻辑
    1. o点:
      1. SCL置低电平:允许数据翻转
      2. SDA发送1bit数据
    2. o—>a:
      1. SCL延时5微秒
      2. SDA正在发送数据
    3. a点:
      1. SCL从低电平转折为高电平
    4. a—>b:
      1. SCL延时5微秒
      2. SDA正在发送数据
    5. b点:
      1. SCL从高电平转折为低电平:为下一次数据翻转做准备
    6. b—>c:
      1. SCL延时5微秒

 

3、IIC协议发送一个字节数据:

  1. 编程逻辑:我们用字符型变量cdata来保存8bit的待发数据。
    1. cdata从哪里来?答:函数传递。
    2. 怎么往SDA线上发1个字节?答:将cdata的每一bit依次传输给sda,共传输8次。
  2. 前提:基于SDA总线数据传输时高位先出的原则。不同的数据传输方法对应不同的读取方式。
  3. 方法:不同于串口的数据位是低位在先,IIC的数据位是高位在先。根据高位先出的原则,每次从SDA发送出去的都是字符型变量cdata的最高位。
    1. 让cdata位与上二进制数1000 0000,即十六进制的0x80(按位运算):这是取位技巧,将取到的最高位结果发送给SDA。
    2. 传输完1bit后让cdata进行左移1位(移位运算):剔除cdata的最高位。

     

  4. void IIC_Send_Byte(char cdata)
    {int i;for(i=0; i<8; i++){// o点:scl = 0;            // SCL置低电平:允许数据翻转sda = cdata & 0x80; // SDA发送1bit数据// o—>a:_nop_();            // SCL延时5微秒// SDA正在发送数据// a点:scl = 1;            // SCL从低电平转折为高电平// a—>b:_nop_();            // SCL延时5微秒// SDA正在发送数据// b点:scl = 0;            // SCL从高电平转折为低电平:为下一次数据翻转做准备// b—>c:_nop_();            // SCL延时5微秒cdata = cdata << 1;}
    }


http://www.ppmy.cn/news/100041.html

相关文章

2023年江苏省中职网络安全Web渗透测试解析(超详细)

一、竞赛时间 180分钟 共计3小时 二、竞赛阶段 1.访问地址http://靶机IP/web1,分析页面内容,获取flag值,Flag格式为flag{xxx}; 2.访问地址http://靶机IP/web2,访问登录页面。用户user01的密码为1-1000以内的数,获取用户user01的密码,将密码作为Flag进行提交,Flag格式为…

golang jwt

目录 一、jwt基础 二、jwt签名与验签的算法 三、定义MyCustomClaims 与jwt各个字段的含义 四、golang的HS256签名与验签 五、golang的RS256签名与验签 六、登录与中间件 一、jwt基础 jwt由三部分构成&#xff0c;headerpayloadsignature,由两个"."进行分割。 …

如何在华为OD机试中获得满分?Java实现【水仙花数】一文详解!

✅创作者:陈书予 🎉个人主页:陈书予的个人主页 🍁陈书予的个人社区,欢迎你的加入: 陈书予的社区 🌟专栏地址: Java华为OD机试真题(2022&2023) 文章目录 1. 题目描述2. 输入描述3. 输出描述4. Java算法源码5. 测试6.解题思路1. 题目描述 所谓水仙花数,是指一个…

前端切图仔跑路真经

一、闭包 谈到闭包&#xff0c;我们首先要讨论的就是作用域。 1、作用域&#xff1a; 是指程序源代码中代码定义的范围。规定了如何设置变量&#xff0c;也就是确定了当前执行代码对变量的访问权限。 JavaScript采用词法作用域&#xff0c;也就是静态作用域&#xff0c;就是在…

驱动LSM6DS3TR-C实现高效运动检测与数据采集(1)----获取ID

概述 本文将介绍如何驱动和利用LSM6DS3TR-C传感器&#xff0c;实现精确的运动感应功能。LSM6DS3TR-C是一款先进的6轴惯性测量单元&#xff08;IMU&#xff09;&#xff0c;集成了三轴加速度计和三轴陀螺仪&#xff0c;可用于测量和检测设备的加速度、姿态和运动。 本文将提供L…

计算机的大小端存储模式(计算机小白必看!)

目录 1.什么是大端小端 2.为什么会有大小端模式之分呢&#xff1f; 3.如何判断当前机器为大端字节序还是小端字节序 本文将介绍计算机存储数据时的大小端问题 1.什么是大端小端 大端&#xff08;存储&#xff09;模式&#xff0c;是指数据的低位保存在内存的高地址中&…

位图布隆过滤器

位图 概念&#xff1a;就是用每一位来存放某种状态&#xff0c;适用于海量数据&#xff0c;数据无重复的场景。通常是用来判断某个数据存不存在的。 比如&#xff0c;需要在40亿个整数中&#xff0c;查看某个数是否存在&#xff1f; 1G1024M*1024KB*1024B~10亿字节~80亿比特。…

如何使用ChatGPT提升自己的“码”力?

如何使用chatGPT提升自己的"码"力? 代码评审(CodeReview)代码优化代码释义提供解决方案代码生成设计模式和架构建议学习新知识总结 ChatGPT是什么&#xff0c;我就不用再多介绍了吧&#xff01;相信大家已经看到了它在文本领域所展现出来的实力&#xff0c;虽然目前…