STM32单片机I2C通信详解

文章目录

1. I2C通信概述

2. 硬件电路

3. I2C时序基本单元

4. I2C时序

4.1 指定地址写

4.2 当前地址读

4.3 指定地址读

5. I2C外设

6. I2C框图

7. I2C基本结构

8. 主机发送

9. 主机接收

10. 软件和硬件波形对比

11. 代码示例


1. I2C通信概述

I2C(Inter-Integrated Circuit)和和SPI一样,都是实现主控芯片和外挂芯片之间的数据交流。

通信线

  • SCL(Serial Clock):串行时钟线。
  • SDA(Serial Data):串行数据线。

特性

  • 同步:I2C总线是同步通信。
  • 半双工:数据可以在两个方向传输,但不能同时进行。

数据应答:I2C总线支持数据应答机制。

支持多设备

  • 一主多从:一个主设备可以连接多个从设备。
  • 多主多从:多个主设备可以连接多个从设备。

起始条件:在SCL高电平期间,SDA从高电平切换到低电平,表示通信的开始。

终止条件:在SCL高电平期间,SDA从低电平切换到高电平,表示通信的结束。

时序单元:每个时序单元从SCL的低电平开始,并以低电平结束。

从设备限制:从设备不允许产生起始和终止条件。

2. 硬件电路

所有I2C设备的SCL连在一起,SDA连在一起,并且设备的SCL和SDA均要配置成开漏输出模式

SCL和SDA各添加一个上拉电阻,阻值一般为4.7KΩ左右

3. I2C时序基本单元

起始条件:SCL高电平期间,SDA从高电平切换到低电平

终止条件:SCL高电平期间,SDA从低电平切换到高电平

发送一个字节:SCL低电平期间,主机将数据位依次放到SDA线上(高位先行),然后释放SCL,从机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可发送一个字节

接收一个字节:SCL低电平期间,从机将数据位依次放到SDA线上(高位先行),然后释放SCL,主机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可接收一个字节(主机在接收之前,需要释放SDA)

主机发送应答:主机在接收完一个字节之后,在下一个时钟发送一位数据,数据0表示应答,数据1表示非应答。

  1. 准备数据
    • 主机拉低SCL,将数据放在SDA线上。
  2. 发送数据位
    • SCL低电平期间
      • 若要发送0,主机将SDA拉低到低电平。
      • 若要发送1,主机释放SDA,SDA回弹到高电平。
      • SCL低电平期间允许改变SDA的电平。
    • SCL高电平期间
      • 主机松开SCL,SCL回弹到高电平。
      • 从机在SCL高电平期间读取SDA上的数据位。
      • SCL高电平期间,SDA电平不允许变化。
  3. 完成数据位传输
    • 主机在松开SCL一段时间后,继续拉低SCL,准备传输下一位。
    • 该过程在SCL同步下循环8次,传输完成一个字节(8位数据)。

从机接收数据

接收应答:主机在发送完一个字节之后,在下一个时钟接收一位数据,判断从机是否应答,数据0表示应答,数据1表示非应答(主机在接收之前,需要释放SDA)

  1. 准备接收
    • 主机拉低SCL,将数据位依次放到SDA线上。
  2. 读取数据位
    • SCL高电平期间
      • 主机在SCL高电平期间读取SDA上的数据位。
      • SCL高电平期间,SDA电平不允许变化。
  3. 完成数据位接收
    • 从机在SCL低电平期间,将下一位数据放到SDA线上。
    • 该过程在SCL同步下循环8次,从机接收一个字节(8位数据)。

应答机制

在I2C通信中,主机发送一个数据后会立即接收一个位作为应答位,用来判断从机是否正确接收到数据。

从机地址

  1. 发送从机地址
    • 主机在起始条件之后,先发送一个字节(从机地址)。
    • 所有从机会接收该字节,并与自己的地址进行比较。
    • 如果地址匹配,相应的从机会响应主机的读写操作。
  2. 唯一地址
    • 同一条I2C总线上的每个设备地址必须唯一,以防止主机发送一个地址时有多个设备响应。

I2C地址类型

  • 7位地址:常用的I2C地址格式。
  • 10位地址:用于一些特殊情况下的I2C地址格式。

设备地址分配

  • 每个I2C设备在出厂时由厂商分配一个7位地址。例如,MPU6050的地址是1101 000。
  • 不同型号的设备地址不同,相同型号的设备地址相同。

地址可变部分

  • 对于挂在同一条总线上的相同型号设备,可以利用设备地址的可变部分来区分。
  • MPU6050
    • 地址的最后一位由板上的AD0引脚确定。
    • AD0引脚接低电平,地址为1101 000。
    • AD0引脚接高电平,地址为1101 001。

通过这种方式,可以在同一条I2C总线上挂载多个相同型号的设备,并通过改变引脚电平来分配不同的地址,避免地址冲突。

4. I2C时序

4.1 指定地址写

对于指定设备(Slave Address),在指定地址(Reg Address)下,写入指定数据(Data)

对于指定设备(从机地址),在指定地址(寄存器地址)下写入数据。

空闲状态

  • 两条总线(SCL和SDA)都是高电平。

产生起始条件

  1. 主机在SCL高电平期间拉低SDA,产生起始条件。

  2. 在起始条件之后,主机发送一个字节,该字节内容为从机地址和读写位(从机地址是7位,读写位是1位,总共8位)。

发送从机地址和读写位

  1. 发送从机地址:确定通信的对象。

  2. 发送读写位:确认接下来是写入还是读出(0表示写入,1表示读出)。

接收应答位

  1. 主机发送从机地址和读写位后,释放SDA。

  2. 从机响应后会拉低SDA,产生应答位。

  3. 应答位产生后,从机释放SDA的控制权。

发送数据

  1. 主机再次发送第二个字节,通常为寄存器地址或控制字。

  2. 接着发送第三个字节,表示要写入寄存器地址中的数据值。

产生停止条件

  1. 主机拉低SDA,为后续的上升沿做准备。

  2. 然后依次释放SCL和SDA,产生SCL高电平期间的SDA上升沿,表示停止条件。

示例

对于从机地址为1101000的设备,在其内部0x19地址的寄存器中写入0xAA这个数据,数据帧的过程如下:

  1. 起始条件:SCL高电平期间,SDA从高电平拉低。
  2. 发送从机地址和读写位(1101000+0)。
  3. 接收从机应答位。
  4. 发送寄存器地址(0x19)。
  5. 接收从机应答位。
  6. 发送数据值(0xAA)。
  7. 接收从机应答位。
  8. 停止条件:SCL高电平期间,SDA从低电平释放至高电平。

通过这些步骤,主机可以可靠地在从机的指定寄存器地址中写入数据。

4.2 当前地址读

对于指定设备(Slave Address),在当前地址指针指示的地址下,读取从机数据(Data)

产生起始条件

  1. 主机在SCL高电平期间拉低SDA,产生起始条件。

寻址和读写操作

  1. 主机首先发送一个字节,用于从机的寻址和设置读写标志位。

  2. 在本次通信中,主机发送的目标地址是1101000,读写标志位为1,表示主机接下来要读取数据。

接收从机应答位

  1. 主机发送完寻址字节后,接收从机的应答位。

  2. 从机收到第一个字节后,拉低SDA,表示应答,并将SDA的控制权交回主机。

接收数据

  1. 主机调用接收数据的时序,准备接收从机发送的数据。

  2. 从机得到允许后,在SCL低电平期间将数据写入SDA。

  3. 主机在SCL高电平期间读取SDA上的数据。

  4. 主机在SCL高电平期间依次读取8位数据,从而接收到从机发送的一个字节数据(例如:0000 1111,即0x0F)。

指针自动递增

  1. I2C通信中没有指定寄存器地址的环节,默认情况下,从机中的所有寄存器被分配到一个线性区域中。

  2. 从机内部有一个指针变量,指向某个寄存器。上电时,这个指针通常默认指向0地址。

  3. 每次写入或读出一个字节后,这个指针会自动递增,指向下一个寄存器位置。

  4. 主机读取到的数据是当前指针指向的寄存器的值。

4.3 指定地址读

对于指定设备(Slave Address),在指定地址(Reg Address)下,读取从机数据(Data)

写入操作

  1. 指定从机地址和读写标志位
    • 从机地址为1101000,读写标志位为0,表示要进行写操作。
  2. 从机应答
    • 从机应答后,主机发送第二个字节(0001 1001),用于指定寄存器地址。
    • 这个数据写入到从机的地址指针中,从机的寄存器指针指向0x19位置。

重新开始读操作

  1. 产生新的起始条件
    • 主机再次产生一个起始条件。
  2. 重新寻址并指定读写标志位
    • 主机重新发送从机地址(1101000)和读写标志位(此时读写标志位为1,表示读操作)。
  3. 主机接收数据
    • 从机应答后,主机开始接收一个字节的数据。
    • 这个字节的数据是从机0x19地址下的内容。

5. I2C外设

硬件资源

  • I2C外设:STM32内部集成的I2C外设,通过通信协议在时序上,驱动根据协议的规范去翻转通信引脚的高低电平。

  • I2C控制器:STM32的I2C外设包括I2C1和I2C2控制器,能够自动进行时钟生成、起始条件生成、应答位发送和接收,减轻了CPU负担。

特性

  • 多主机模式:支持多个主机设备,可变多主机模式。

  • 地址模式:支持7位和10位地址模式。

  • 通信速度:支持不同的通信速率,标准模式最高100kHz,快速模式最高400kHz。

  • DMA支持:支持DMA,在多字节传输时提高传输效率。

  • 兼容SMBus协议:SMBus协议用于电源管理系统(System Management Bus)。

10位地址模式

  • 标志位:10位地址模式下,起始后的前两个字节都用于寻址,前5位为标志位,表示这是一个10位地址模式。

  • 数据格式

    • 第一个字节:前5位标志位为11110,第6位到第8位为高3位地址。

    • 第二个字节:包含剩下的7位地址位。

  • 寻址过程

    • 第一个字节发送特定数据作为10位寻址模式的标志,即11110。

    • 如果第二个字节也是寻址,则第一个字节的前5位必须是11110。

示例说明

  • I2C地址转换

    • 二进制地址1101000转换为十六进制为0x68。

    • I2C通信时,需要发送7位地址和1位读写位。

    • 从机地址0x68左移1位再加上读写位:

      • 0x68左移1位为11010000(0xD0),加上读写位为0xD1。

    • 读写操作

      • 写操作:从机地址为0xD0。

      • 读操作:从机地址为0xD1。

I2C在STM32中的实现

  • STM32F103C8T6集成了I2C1和I2C2两个I2C外设,支持多种功能和特性,适用于各种嵌入式应用。
  • 通过配置I2C寄存器,可以实现从机地址设置、通信速度调整、DMA传输等功能,满足不同应用需求。

6. I2C框图

数据发送

  1. 写入数据寄存器:当需要发送数据时,将一个字节数据写入数据寄存器(DR)。
  2. 移位寄存器:如果移位寄存器(SR)没有数据在移位,数据寄存器中的值会转移到移位寄存器中。
  3. 连续发送:在移位过程中,可以将下一个数据字节放入数据寄存器,准备发送。一旦前一个数据移位完成,下一个数据就可以无缝衔接继续发送。
  4. 状态标志:当数据从数据寄存器转移到移位寄存器时,状态标志寄存器的TXE位会置1,表示发送寄存器为空,可以继续写入新的数据。

数据接收

  1. 接收数据:输入的数据一位一位从引脚移入移位寄存器。
  2. 移入数据寄存器:当一个字节的数据接收完整后,数据整体从移位寄存器转移到数据寄存器(DR)。
  3. 状态标志:同时,状态标志寄存器的RXNE位会置1,表示接收寄存器非空,此时可以从数据寄存器读取数据。

7. I2C基本结构

数据发送

  1. 移位寄存器与DR配合:I2C协议规定数据高位先行,因此移位寄存器的数据是向左移位的。

  2. 移位过程

    • 在发送时,最高位首先移出,接着是次高位,依次类推。

    • 每个SCL时钟周期,移位寄存器移位一次。

    • 经过8次移位后,一个字节的数据由高位到低位依次放到SDA线上。

数据接收

  1. 移位过程

    • 接收时,数据通过GPIO口从右边依次移入移位寄存器。

    • 经过8次移位后,一个字节的数据接收完成。

GPIO配置

  1. 复用开漏输出模式

    • 使用硬件I2C时,GPIO口需配置为复用开漏输出模式。
    • 复用:将GPIO的控制权交给片上硬件外设。
    • 开漏输出:I2C协议要求的端口配置,即便是开漏输出模式,GPIO也能进行输入操作。
  2. 时钟与数据传输

    • 时钟控制器通过GPIO控制时钟线(SCL)。
    • 数据通过GPIO输出到SDA端口。
    • 接收数据时,数据通过GPIO输入移位寄存器。

8. 主机发送

初始化与起始条件

  1. 总线空闲状态:在初始化后,总线默认处于空闲状态,STM32默认设置为从模式。

  2. 产生起始条件:为了开始通信,STM32需要在控制寄存器中写入相应的值以产生起始条件。

    • 查看手册中的I2C接口寄存器描述,确定起始条件的写入方法。

  3. 切换到主模式:产生起始条件后,STM32从从模式切换到主模式。在多主机模型下,STM32有数据要发送时会主动跳出来。

控制与检查标志位

  1. 控制硬件电路:在控制完硬件电路后,需要检查标志位,以确认硬件是否达到了预期状态。

  2. 发送从机地址:将从机地址写入数据寄存器(DR)。硬件电路会自动将这个字节转移到移位寄存器,并将其放到I2C总线上。

应答与事件处理

  1. 应答判断:硬件自动接收应答并进行判断。如果没有应答,硬件会置应答失败标志位,并可能触发中断来提醒。

  2. 事件EV6:寻址完成后,会触发EV6事件。

  3. 事件EV8_1:TXE标志位=1,表示数据寄存器和移位寄存器均为空,此时需要向数据寄存器写入数据以进行发送。

数据发送

  1. 写入数据寄存器:将数据写入数据寄存器(DR)。如果移位寄存器为空,数据会立即转移到移位寄存器并开始发送。

  2. 事件EV8:检测到EV8事件,表示数据寄存器为空,可以写入下一个数据。

数据发送完成

  1. 事件EV8_2:当移位寄存器和数据寄存器都为空(TXE=1),会触发EV8_2事件。

  2. 字节发送结束标志位(BTF):EV8_2后,BTF标志位表示字节传输完成。

终止条件

  1. 产生终止条件:在控制寄存器中写入相应的值以产生终止条件,结束数据传输。

9. 主机接收

 10位地址读操作流程

  1. 起始条件:产生起始条件
  2. 发送帧头:发送帧头,帧头中的读写位应为写(0),因为后面还需要发送第二个字节的地址。
  3. 发送第二个字节地址:继续发送第二个字节的8位地址,这样才能完成寻址。
  4. 重复起始条件:为了转入读的时序,必须再发送一个重复起始条件。
  5. 再次发送帧头:这次帧头中的读写位应为读(1),发送读的指令后,直接转入接收数据的程序,不再发送第二个字节的地址。

7位地址读操作流程

  1. 起始条件:在控制寄存器中写入START位,产生起始条件。
  2. 等待EV5事件:EV5事件表示起始条件已发送。
  3. 寻址与应答:发送从机地址,接收应答,结束后产生EV6事件,表示寻址完成。
  4. 数据输入:数据通过移位寄存器输入,产生EV6_1事件,表示数据正在移位。
  5. 发送应答位:根据配置,硬件自动发送应答位。
  6. 移入数据寄存器:当移位寄存器成功移入一个字节数据后,这个字节整体转移到数据寄存器,同时置RXNE标志位,表示数据寄存器非空。
  7. EV7事件:RXNE=1,表示数据寄存器非空,读取数据寄存器(DR)清除EV7事件,表示已收到数据。
  8. 持续接收数据:当数据1还未读走时,数据2可以直接移入移位寄存器,产生EV7事件,读走数据2后EV7事件消失。按照此流程,继续接收数据。
  9. 结束接收
    • 当不再需要继续接收数据时,在最后一个时序单元发生时,提前将ACK位置0,并设置终止条件请求,这就是EV7_1事件。
    • 在最后一个时序单元完成后,因ACK=0,发送非应答位。
    • 设置STOP位,产生终止条件,完成接收一个字节的时序。

10. 软件和硬件波形对比

软件I2C实现

  1. 波形特点:软件I2C的波形较为不规整,每个时钟周期和空闲时间都不一致。
  2. 操作特点:软件I2C时的引脚操作会有一定的延时,因此各个时钟周期的间隔和占空比都不均匀。

硬件I2C实现

  1. 波形特点:硬件I2C的波形更加规整,时钟周期和占空比非常一致。
  2. 操作特点:每个时钟周期后都有严格的延时,保证每个周期的时间相同。

11. 代码示例

STM32通过I2C软件读写MPU6050

STM32通过I2C软件读写MPU6050-CSDN博客

STM32通过I2C硬件读写MPU6050

STM32通过I2C硬件读写MPU6050-CSDN博客

 

  • 21
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
STM32F103是一款32位ARM Cortex-M3内核的微控制器,支持硬件I2C通信。在使用硬件I2C进行通信时,可以参考ST官方提供的例程和参考手册。 官方例程中的代码并没有像网上大多数代码在I2C中断里面调用库函数来发,而是采用判断寄存器的值来处理数据的收发等。在阅读官方的代码前,最好准备STM32参考手册,主要关注SR1和SR2这两个寄存器。\[1\] 如果你想自己编写I2C通信的代码,可以参考引用\[2\]中的MyI2C.h文件,其中定义了一些常用的I2C操作函数。 在使用I2C总线连接多个单片机时,需要注意从机的地址设置。根据引用\[3\]的描述,如果主机接收的数据不正确,可以尝试更改从机的地址。建议多个从机地址之间最好不要连续,最好隔几个地址。在实验中,从机地址可以设置为0x30、0x40或其他值,只要保证不重复即可。 如果你尝试使用HAL库的I2C功能,但无法读取数据,请确保你正确配置了I2C的参数,并检查硬件连接是否正确。如果问题仍然存在,建议查阅相关文档或向有经验的朋友寻求帮助。\[3\] #### 引用[.reference_title] - *1* *3* [STM32F103 硬件I2C主从机通信](https://blog.csdn.net/changshengxiao/article/details/88069376)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [STM32——I2C通信](https://blog.csdn.net/NRWHF/article/details/128599644)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TENET-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值