STM32单片机学习(21) —— I2C通信

文章目录

串口通信回顾

在前面我们已经了解UART串口通信了,它是一种简单易用的通信方式。

但在嵌入式编程中光学习一个串口通信,显然无法满足我们的需求,现在我们再来回顾一下串口通信的特点,分析一下串口通信的局限性

串口通信的特点

串口(USART)通信是一种点对点的、全双工的、异步串行通信方式,它只需要两根线(Tx 和 Rx)就可以实现数据的发送和接收。

在通信过程中,发送方和接收方需要事先约定好相同的波特率,以此来保证数据能够被正确解析。

除此之外,串口通信还需要约定数据帧格式,比如起始位、数据位以及停止位等。

由于串口通信结构简单、实现成本低,因此在 PC 与单片机通信、传感器数据采集、蓝牙 / Wi-Fi 模块通信 等场景中被广泛使用。

串口通信的局限性

在串口通信中,通信双方通常是一对一、点对点的关系。

虽然在实践中,确实也可以通过增加多组 TX / RX 引脚,勉强实现一对多通信,但这种方式存在明显的问题:

  1. 硬件接线会很复杂,复杂性高,可维护性差。
  2. 单片机的引脚资源有限,这导致可连接的串口设备数量受限。
    1. 以我们使用的STM32F103C8T6单片机为例
    2. 该款单片机一共有三个USART外设,分别是:USART1、USART2以及USART3
    3. 实际可用的Tx和Rx引脚只有四对,其中有两对都属于USART1外设
    4. 所以,即便不考虑引脚使用过多、接线复杂、软件实现繁琐等问题,使用串口通信在多设备通信数量上,也存在显著瓶颈。
  3. 串口通用无法真正做到一对多通信。在同一时刻,一个串口只能做到与一台设备进行通信。

在嵌入式系统中,一对多通信的需求并不少见。

尤其是在资源紧张、引脚数量有限的情况下,实现一对多通信是嵌入式开发者必然面临的场景。

为了解决这个问题,我们需要学习一种新的通信方式,也就是I2C通信。

I2C通信 VS 串口通信

虽然我们还没有学习I2C通信,但不妨碍我们先来比较一下I2C通信和串口通信的差异,大家权当先了解一下。

待到学完I2C通信后,相信大家会对下列表格的内容有更加深入的理解。

特性 USART(串口通信) I2C(I²C通信)
连接方式 点对点 多设备总线连接
所需引脚 每一台设备都需要 2 个引脚(TX、RX) 即便连接多台设备,也仅需 2 个引脚(SCL、SDA)
可连接设备数量 受 USART 引脚数量限制(通常 2~3 个) 理论支持多达 100+个设备
通信模式 一对一(点对点) 一对多(支持主从模式
数据传输方式 异步串行传输 同步串行传输
数据传输速率 波特率9600 - 115200 bps 标准模式 100 Kbps,高速模式 400 Kbps
设备寻址 无设备寻址,发送端和接收端点对点通信 支持设备寻址(7-bit 或 10-bit 地址)
全双工/半双工 全双工(可以同时发送和接收数据) 半双工(同一时刻通信时只能单向传输)
适用场景 单片机与PC调试通信、GPS、蓝牙Wi-Fi通信 传感器网络、EEPROM 存储、嵌入式设备之间通信

串口通信虽然简单易用,但由于 需要独立的 TX/RX 线、端口数量受限、缺乏寻址能力,在多设备通信场景下并不适用。

因此,在嵌入式开发中,我们更倾向于使用 I2C 或者其它通信方式来进行一对多的通信。

I2C 仅需 两根信号线(SCL 和 SDA),即可实现一对多个设备的通信,同时实现简单易用性强、灵活和扩展性也非常不错。

总的来讲,I2C是嵌入式环境下,多设备通信中的性价比之选

下面我们正式开始学习I2C通信!

I2C是什么?

按照老规矩,我们在学习一个新的技术模块时,还是先来了解一下与这个技术模块相关的一些概念。

比如一个很简单的问题:I2C是什么东西?

I2C通信最早由飞利浦(现恩智浦半导体)公司,在1982年左右开发提出。

I2C是英文词组Inter-Integrated Circuit的缩写,更准确的缩写是"I2C",其中的2表示"I"字母的平方,即两个I。

在中文语境下,不要把它读成"I 二 C",而是要读成"I 方 C",其中方表示平方的意思。

如何理解Inter-Integrated Circuit这个词组呢?

  1. Inter-:意为 "相互、互相",表示设备之间的交互通信。
  2. Integrated Circuit(IC):指 "集成电路",也就是各种芯片。

所以I2C通信就可以理解成:集成电路间的通信、芯片之间的通信。

I2C 正是为了解决 不同芯片、不同集成电路之间进行数据通信 这一需求而设计的一种通信协议。

直到今天,I2C 依然是嵌入式系统中最常见的通信协议之一

I2C通信被广泛应用于 单片机与各类外设芯片(如OLED、传感器、EEPROM 等)之间的通信

  1. I2C通信是芯片之间的通信,通信双方芯片按照各自的程序,基于I2C通信协议完成通信
  2. 不要把I2C通信理解成谁控制谁,双方都是芯片,都有烧录好的程序,双方基于同样的I2C通信协议
  3. 只要双方在约定好的时间,做约定好的事情,通信就完成
  4. 对于我们而言,单片机有我们控制,单片机的I2C通信程序也由程序员完成
  5. 而与单片机进行I2C通信的设备,它有烧录好的I2C通信程序,我们不需要关心它的程序实现

总线

经过上面的描述,再加上对串口通信的了解,你一定已经对 I2C 有了一个基本认识:

I2C 是一种引脚资源占用少,但却能够实现多台设备通信的通信方式。

那么问题就来了:

多台设备,是如何在只使用极少引脚的情况下,实现通信的呢?

最起码的,接线是如何接的呢?

要回答这个问题,就不得不先引入一个非常重要的概念------总线

什么是总线呢?

其实前面讲单片机系统架构时,也提过这个概念。

总线(Bus)是计算机系统中,多个设备之间共享的,数据传输通道。

通过总线结构:

  1. 多台设备不再需要一对一单独连线实现通信,而是统一将自身"挂在"总线上。这样就大幅度减少了引脚数量的使用,降低了接线复杂度。
  2. 相同总线上连接的设备,可以共用同一套通信协议进行通信,进一步降低了系统的复杂性。

结合上面的描述,通俗一点,可以把总线理解成"高速公路":

一条公共道路,多辆车都能上路,拥有统一的交通规则,这样大家都能顺利抵达目的地。

I2C总线

I2C通信,正是一种典型的总线式通信手段,所以很多地方也会直接把I2C通信,叫做I2C总线。

I2C通信对引脚资源的占用很少,使用的接线也很少,只需要两条信号线就可以了。这是I2C通信的优势!

在I2C通信中:

  1. 所有设备,都将自身挂载在同一条I2C总线上。
  2. I2C总线,仅包含两条线,即SDA总线与SCL总线。
  3. 通信设备自身,也仅占用两个引脚,即SDA引脚和SCL引脚。

其总线结构,如下图所示:

这两条总线分别是:

  1. SCL,Serial Clock Line,串行时钟信号线:I2C是同步串行通信方式,由SCL时钟信号线控制产生统一的时钟信号。
  2. SDA,Serial Data Line,串行数据传输线:用于双向传输数据,总线上所有设备的数据通信,都通过这一条数据总线完成。

关于这两条总线的详细作用以及工作原理,这些内容比较复杂,且都涉及I2C通信协议,我们留到后续小节再讲。

现在,仅看I2C总线结构,以及这两条总线的大体作用,你能得出什么结论呢?

这里,希望大家能够记住以下结论:

  1. I2C仍然是一种串行通信,I2C总线就是"串行总线"。
  2. 数据以 bit 为单位进行传输,通信时是 1 bit、1 bit 地依次传输。
  3. 数字电平含义与串口通信一致:高电平代表1,低电平代表0。
  4. 这种总线设计使得,即便单片机需要与多台设备通信,也仅需要占用两个引脚,大大减少了通信引脚资源的占用。
  5. 这种总线设计使得,即便单片机需要与多台设备通信,其余设备也只需要将自身挂在总线上,大大降低电路设计复杂性。
  6. 通信双方,只能通过一条SDA总线进行传输数据,显然,I2C肯定不是一种全双工通信协议。
  7. I2C是典型的半双工通信协议,在同一时刻,I2C通信中,数据都只能单向传输。
    1. 比如单片机给设备1发数据时,设备1就只能接收,而不能发送。
    2. 当然数据通信是双向的,在下一个时刻,设备1可以给单片机发数据,单片机此时只能接收。
    3. 半双工,意味着数据不能同时双向传输,但仍然支持双向数据传输。

至此,我们已经对 I2C 的总线式通信结构有了一个整体认识。

那么就会产生这样的疑问:

总线式设计将所有的设备,都挂载在总线上。

这么多设备都在总线上,如果随便发数据,随意互相通信,势必乱了套。

所以,I2C通信中,通信的过程是怎么控制的呢?由谁来控制呢?

为了回答这个问题,我们就需要了解I2C通信中,最重要的、最核心的概念------主从模式。

主从模式(重点!)

在I2C通信中,最核心且最重要的特点就是:主从模式。

通过 I2C 总线连接的多台设备,具有 "主-从"(Master-Slave) 关系。

整个I2C总线上的设备,可以分为两大类:

  1. 主机(Master):负责控制时钟信号总线(SCL),生成时钟信号,控制通信时序,掌控整个通信的过程。
  2. 从机(Slave):响应主设备的请求,执行数据发送或接收,本身不参与任何通信过程的控制。

严格来说,I2C 通信协议支持的主从模式是:一主多从,并且支持主设备切换。

在学习阶段,为了便于理解和实现,在后续我们固定把单片机作为主机,其它通过 I2C 总线与单片机相连的设备,一律视为从机。

在实际工程应用中,为了避免多设备竞争总线控制权而引发冲突,主设备切换这一功能也并不常用。

绝大多数实际场景中,I2C都是采用固定主机,一主多从式的通信方式。

该如何理解主从模式呢?

其实上面已经写得非常清楚了------I2C通信过程中,任何通信的操作都是由主机发起并控制的。

比如:

  1. 主机可以主动将数据发给从机,从机被动接收数据。
    1. 这种操作,称之为**"I2C的写模式**"。
    2. 站在主机的视角,将数据输出传递,这就是写!
  2. 从机不可以主动擅自将数据发给主机!
  3. 从机只能在主机的要求下,被动地将数据发给主机。
    1. 这种操作,称之为"I2C的读模式"。
    2. 站在主机的视角,从机输入数据,这就是读。

或者我们举一个通俗的例子:

所谓主从模式,就是皇帝和太监。

皇上想做什么,就跟太监说,太监必须配合去做。

太监想做什么,那是不可能的,太监不能主动做事情。必须是皇上让他做,他才可以做。

总之:

在I2C通信中,任何数据交互都必须由主机发起,任何通信过程都由主机控制,从机只能被动配合!这是I2C通信协议最重要且最核心的概念!!

主从模式容易产生的误解

在理解了 I2C 的主从通信模式之后,有些同学可能会产生这样一种疑惑与误解:

既然主机完全控制通信过程,那么是不是意味着:

如果没有主机的控制,从机就什么也做不了?什么都不会做?

主机完全控制从机,如果没有主机控制,从机啥也做不了,啥也不会干。

是不是这样呢?

这显然是一种误解,主机虽然有"控制欲",但肯定不会这么强。

从机需要配合主机完成通信,基于I2C通信协议,在这个过程中,从机有自身应当完成的工作,不是所有事情都由主机控制。

当然主机完全控制从机,这种事情也不可能做得到。

还是举例皇帝和太监。

皇上饿了,跟太监说"我饿了,弄点吃的来。"

太监于是去准备吃的,并且端过来。

这个过程,太监必然具有一定主观能动性,根据自身对皇帝喜好的了解,准备一些吃的,端上来。

但这个过程肯定不会是:"我饿了,你去菜园子搞点西红柿,再去鸡窝里捡几颗鸡蛋,然后把西红柿洗好了,切好了,先炒好鸡蛋..."

总之:

在I2C通信的过程中,主机具有绝对控制权,但主机只负责控制通信的重要节点,比如通信的开始,结束等。

从机需要按照通信协议,自主完成一些工作,比如数据接收和发送。

实际上,I2C本身就是两颗芯片之间的通信。

既然双方都是芯片,那么芯片内部必然都存储了符合I2C通信协议的程序。

作为单片机开发者,我们负责开发单片机的内部程序,而与单片机通信的从机设备,它们芯片上的程序已经在生产制造时烧录完成了。

只要你编写的,单片机上的程序,完全符合I2C通信协议,那么通信就会成功实现。

从机地址

I²C 通信是一种 "一对多" 的主从式通信方式

在一条 I2C 总线上,主机可以连接多个从机设备。那么主机如何在多个从机中,找到目标从机设备呢?

这时就需要了解一个"从机地址"的概念。

在 I²C 通信中,从机地址(Slave Address) 是 主机 用来选择通信对象的唯一标识。

整条I2C总线上挂载的多台从机设备,每一台都需要拥有一个唯一的从机地址。

主机在控制通信开始时,会在总线上发送目标从机地址,只有匹配该地址的从机才会响应,从而建立通信关系。

在I2C通信中,这个过程被指为"寻址"。寻址对于I2C的任何通信过程而言,总是第一步需要完成的行为。

从机地址的确定

如何确定一台从机的从机地址呢?

首先从机地址,从格式上来说,通常就是一个7位的二进制数。

而具体到设备,大多数I2C从机设备,其从机地址在设备生产制造时就已经设定好了。

所以,获取从机地址,最准确的做法是:查阅厂商提供的官方数据手册

除此之外,还可以:

  1. 咨询设备的销售商。
  2. 向有经验的同学 / 同事 / 工程师请教。
  3. 借助 AI 工具,根据设备型号查询相关资料

当然无论你从什么渠道获取了从机地址,最终都需要验证一下再相信。

从机数量的限制

在上面的表格中,我们提到:I2C通信,理论支持的最大设备数量是100+。

这个数据并不是胡编乱造的,而是根据从机地址计算得出。

既然 I2C 从机地址是一个 7 位的二进制数,那么理论上可表示的从机地址数量就是:27 = 128

I2C 通信协议中自保留了一部分特殊地址,不能分配给普通从设备,例如:

  1. 0000 000(7位0):通用呼叫地址,广播地址,即主机广播式的向每一台从机发数据。
  2. 1 1 1 1 1 1 1(7位1):无特殊含义用途,但协议自保留,从机不能使用
  3. ...等等

因此,在实际 I2C 系统中,可用的从机地址数量并不是 128,而是大约 100+ 个

当然这个数量已经非常多了,在绝大多数嵌入式场景中,已经非常够用了。

从机地址冲突的问题

从机设备那么多,生产的厂商也很多,不可能都事先商量好。

如果两家生产的从机设备,出现了从机地址冲突,该怎么办?

这个问题非常好,有时候确实也会碰到。

而且这还涉及到一个非常重要的问题:

如果I2C总线上,挂载着两台相同从机地址的从设备,会出现什么情况呢?

答:

  1. I2C 总线上,不能同时存在两台地址完全相同的从机。
  2. 一旦寻址出现了多从机响应,后续通信一定会失败!
  3. 任何一个时刻,主机都只能与一台从机设备,进行正常的双向数据通信。

原因也很简单,I2C通信过程中,主机发送从机接收,从机发送主机接收。这个数据通信是双向,可切换的,只是不允许同时发生。

一旦通信过程允许超过1台从机参与,那么多台从机就会争抢同一条总线的使用权,就会出现总线冲突问题。

I2C通信是无法解决这种问题的,这在物理线路上就不可能实现。

所以切记,I2C通信,同一条总线上只允许挂载从机地址不同的,多台从机设备。

从机地址的出厂特殊设计

为了避免从机地址冲突,设备的生产厂商在设置从机地址时,都会进行一些特殊的设计。

大多数厂商生产的从机设备,其从机地址都不是绝对固定的7位二进制数。

最常见的情况是:7位从机地址的高几位固定不变,但低几位设置为可配置。

举一个例子:

厂商生产了一种支持I2C通信的从机设备A,其从机地址的高6位固定为:011 110

而最低的1位可以在使用时,自由配置:可以配置为0,也可以配置为1。

那么,该设备在实际使用时,就可以切换两种不同的从机地址:

  1. 011 1100
  2. 011 1101

这种设计就增强了从机地址的灵活性,降低了从机地址冲突的可能性。

除此之外,这种设计还有一个明显的好处:

如果我想在嵌入式系统中,接入两台A设备作为从机,可以实现吗?

答:当然是可以实现的。只需要在接入总线时,将A1设备的从机地址设置为011 1100,A2设备的从机地址设置为011 1101。

当然,如果你还是想问,两台从机地址一样的设备,就真的没有办法接入同一条I2C总线了吗?

答:确实是这样,这是 I2C 通信本身的局限性,或者说特性。

扩展:关于广播模式

部分同学在了解了从机地址冲突的问题之后,可能还会产生这样一个新的疑问:

I2C通信不是支持广播模式吗?

广播模式下,不就是一台主机与多台从机,同时进行通信吗?

这又是什么情况呢?

其实这个问题回答起来非常简单。

首先,我们要知道,I2C之所以不允许多台从机参与通信:

是因为在一般通信情况下,多台从机如果同时向主机发数据,会产生总线竞争,出现无法解决的冲突问题。

而广播模式,显然是没有这种烦恼的!

大家上中学的时候,教室里都有广播大喇叭。

这个大喇叭就是主机,所有学生都是从机。

这个过程中,大喇叭发声,学生只需要听着就行。

学生需要回复大喇叭吗?大喇叭关心学生的回复吗?

显然是不需要的。

在I2C的广播模式下,虽然允许多台从机同时参与通信。但这些从机只负责接收主机数据,而不会向主机发送数据。

这些从机不需要竞争总线,不会产生冲突,自然就没有问题了

相关推荐
qq_333120973 小时前
深入探讨8051单片机C351语言及编译器应用
单片机·嵌入式硬件·51单片机
时光の尘3 小时前
【STM32实战】ESP8266 通过 MQTT 协议对接 OneNET 云平台实现数据上传与下发(源码可直接移植)
stm32·mqtt·嵌入式·iot·esp8266
searchforAI3 小时前
B站视频转笔记用哪个工具?2026年四款AI笔记工具对比实测
人工智能·经验分享·笔记·gpt·学习·视频总结·ai笔记
十年编程老舅3 小时前
读懂 MCU 启动:从上电到程序运行全链路
单片机·嵌入式硬件·mcu·嵌入式·cpu·嵌入式开发·ram
爱上好庆祝4 小时前
学习JS第十一天(JS的进阶)
前端·javascript·学习
yeiweilan4 小时前
AI应用学习
学习
吃好睡好便好4 小时前
矩阵的加减运算
开发语言·人工智能·学习·线性代数·算法·matlab·矩阵
北京盟通科技官方账号5 小时前
Windows如何实现硬实时?LxWin双系统隔离架构深度解析
stm32·嵌入式硬件·具身智能·ethercat·人形机器人·实时系统·windows实时扩展
Mister西泽5 小时前
C++ Primer Plus 第六版 编程练习题及详细答案
开发语言·c++·学习·visual studio