模拟 IIC 逻辑的深度解构

IIC说明

  • 介绍:串行、半双工总线 (可收可发不能同时收发)
  • 总线:一根SDA数据线,一根SCL时钟线

模拟IIC本质

  • 主控芯片 (STM32/GD32):使用模拟IIC协议:主控的引脚为通用引脚,需要模拟IIC协议的信号收发流程
  • 通信芯片 (M24C02):使用硬件IIC
  • 主控芯片通过通用引脚模拟SCL和SDA发送高低电平,而通信芯片通过硬件IIC直接解析并回应主控
  • 首先先通过这两根模拟引脚寻址通信芯片的地址,并确定收发方向,使用read还是send,确定SDA的控制权限
  • 其次收发数据:8bit数据 + 1bit ACK应答

引脚 & 芯片地址

  • 引脚:主控芯片通过两根引脚模拟 SCL 和 SDA
  • 芯片地址:芯片厂家预设开头 + 预留引脚 (接地为0,接电源为1)
  • 预留引脚:预留几位,代表同样前缀的芯片可以挂载 2n2^n2n 颗
  • 预留引脚不能悬空,否则会造成读取地址错误

常见 IIC 芯片预设前缀

芯片类型 典型型号 基因前缀 (7位中的高位) 可变位 (A2/A1/A0) 默认 7位地址 (若全接地) 8位点名地址 (写/读)
存储器 (EEPROM) AT24C02 / M24C02 1010 3位 (A2,A1,A0) 0x50 0xA0 / 0xA1
实时时钟 (RTC) DS1307 / PCF8563 1101000 无 (固定) 0x68 0xD0 / 0xD1
惯性传感器 MPU6050 / MPU9250 110100 1位 (AD0引脚) 0x68 0xD0 / 0xD1
大气压/气温 BMP280 111011 1位 (SDO引脚) 0x76 0xEC / 0xED
温湿度传感器 AHT10 / AHT20 0111000 无 (固定) 0x38 0x70 / 0x71
OLED 显示屏 SSD1306 011110 1位 (SA0引脚) 0x3C 0x78 / 0x79

如果你在同一组 SCL/SDA 总线上挂了 8 片 M24C02,你只需要把它们的 A0, A1, A2 按照二进制编排好:

  • 第一片:全接地(地址 0x50
  • 第二片:A0 接高,其余接地(地址 0x51
  • ...
  • 第八片:全接高(地址 0x57

很多手册里写地址是 0x50(7位),但你写代码发字节时必须左移一位变成 0xA0

  • (0x50 << 1) | 0 →\rightarrow→ 发送 0xA0
  • (0x50 << 1) | 1 →\rightarrow→ 发送 0xA1

数据格式

  • 主机读写:8bit数据位 + 1bit确认位
  • 主机在发送或者读取每一位都以 SCL 拉低为结束,为了下一次 SDA 操作的安全性

主机控制SCL & SDA控制权

  • 不论是写还是读,SCL(时钟线)的 9 个脉冲永远由主机掌控
  • 区别只在于 SDA 这根线上,谁在控制
主机动作 前 8 位(数据位)脉冲 第 9 位(应答位)脉冲 逻辑精髓
主机发送 (Write) 主机控线: 根据数据 0/1 控制 SDA 的高低点评 主机放手 (SDA=High): 看从机拉不拉低 SDA。 发完 8 位听响声 (Wait_Ack)
主机接收 (Read) 主机放手 (SDA=High): 看从机在 SDA 发过来的高低电平 主机控线: 根据还要不要,把 SDA 拽低(0)或抬高(1)。 收完 8 位给表态 (Send_Ack/Nack)

主机发送起始和终止信号

  • 主机主动发送起始停止信号
  • 起始和终止信号,SCL都为高
  • 起始:SCL高,SDA从高 → 低
  • 终止:SCL高,SDA从低 → 高

主机写入 / 从机写入

  • 当 SCL 从高 → 低,主机/从机才能往 SDA 上写入数据
  • 写1bit,然后SCL拉高等待对方读,然后SCL再拉低,再写
  • 主机在发送或者读取每一位都以 SCL 拉低为结束,为了下一次 SDA 操作的安全性

IIC 1-Bit 传输标准时序流 (主机视角)

阶段 动作 物理意义 专家级注脚
1. 申请准入 SCL 从高 →\rightarrow→ 低 打开"变动窗口" 只有在低电平,动 SDA 才不会被误判为 Start/Stop。
2. 摆放数据 主机/从机 更新 SDA 写入 1 bit 发送方根据要发的 0 或 1,拉低或释放 SDA 线。
3. 信号建立 Delay_us(2) 稳定电平 给电信号一点时间,让它在长长的 PCB 走线上稳下来。
4. 发令采样 SCL 从低 →\rightarrow→ 高 锁定"采样窗口" 接收方看到上升沿,立刻读取此时 SDA 的电平状态。
5. 保持稳定 Delay_us(2) 确保读取完成 此时 SDA 绝不能动,它是接收方眼里的"真理"。
6. 安全收尾 SCL 从高 →\rightarrow→ 低 关闭窗口 / 释放路权 这步最关键! 结束这一位,并为下一位的 SDA 变动提供安全环境。

主机读取

  • 只有当 SCL 从低电平变到高电平时,接收方 (主机/从机) 才会去读 SDA
  • 也就是说,想要主机主动读取数据,或者从机被动读取数据。SCL必须进行一次从低到高的跳变
  • 主机在发送或者读取每一位都以 SCL 拉低为结束,为了下一次 SDA 操作的安全性

从机

  • 时钟拉伸:如果从机处理不过来(比如 EEPROM 正在写数据),可以把 SCL 拉低不放,强迫主机等它一会儿
  • 主机处理时钟拉伸:主机在拉高SCL之后,加一个 while(READ_SCL == 0);处理从机的"时钟拉伸"。

IIC通信流程

  • 先发1byte的通信信息:7bit地址信息 + 1bit收发方向 (主机还是从机控制SDA)
  • 收发数据

IIC具体通信流程

通信芯片 (M24C02/EEPROM) 【SCL线 / SDA线】 主控 (STM32/GD32) 通信芯片 (M24C02/EEPROM) 【SCL线 / SDA线】 主控 (STM32/GD32) #mermaid-svg-77nZEaxja4gZlIjg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-77nZEaxja4gZlIjg .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-77nZEaxja4gZlIjg .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-77nZEaxja4gZlIjg .error-icon{fill:#552222;}#mermaid-svg-77nZEaxja4gZlIjg .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-77nZEaxja4gZlIjg .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-77nZEaxja4gZlIjg .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-77nZEaxja4gZlIjg .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-77nZEaxja4gZlIjg .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-77nZEaxja4gZlIjg .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-77nZEaxja4gZlIjg .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-77nZEaxja4gZlIjg .marker{fill:#333333;stroke:#333333;}#mermaid-svg-77nZEaxja4gZlIjg .marker.cross{stroke:#333333;}#mermaid-svg-77nZEaxja4gZlIjg svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-77nZEaxja4gZlIjg p{margin:0;}#mermaid-svg-77nZEaxja4gZlIjg .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-77nZEaxja4gZlIjg text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-77nZEaxja4gZlIjg .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-77nZEaxja4gZlIjg .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-77nZEaxja4gZlIjg .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-77nZEaxja4gZlIjg .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-77nZEaxja4gZlIjg #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-77nZEaxja4gZlIjg .sequenceNumber{fill:white;}#mermaid-svg-77nZEaxja4gZlIjg #sequencenumber{fill:#333;}#mermaid-svg-77nZEaxja4gZlIjg #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-77nZEaxja4gZlIjg .messageText{fill:#333;stroke:none;}#mermaid-svg-77nZEaxja4gZlIjg .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-77nZEaxja4gZlIjg .labelText,#mermaid-svg-77nZEaxja4gZlIjg .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-77nZEaxja4gZlIjg .loopText,#mermaid-svg-77nZEaxja4gZlIjg .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-77nZEaxja4gZlIjg .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-77nZEaxja4gZlIjg .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-77nZEaxja4gZlIjg .noteText,#mermaid-svg-77nZEaxja4gZlIjg .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-77nZEaxja4gZlIjg .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-77nZEaxja4gZlIjg .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-77nZEaxja4gZlIjg .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-77nZEaxja4gZlIjg .actorPopupMenu{position:absolute;}#mermaid-svg-77nZEaxja4gZlIjg .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-77nZEaxja4gZlIjg .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-77nZEaxja4gZlIjg .actor-man circle,#mermaid-svg-77nZEaxja4gZlIjg line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-77nZEaxja4gZlIjg :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 物理连接:SCL(PB6) <--->> SDA(PB7) 【起始信号】 【寻址阶段】MSB高位在前 【数据传输】写操作示例 【停止信号】 SCL保持高,SDA由高变低硬件电路触发中断/状态机7位地址 (1010000) + 写(0)逻辑门匹配【ACK】从机硬件强行拉低SDA主控读取到低电平,点名成功发送 8bit 数据 (SCL每跳一次读1bit)【ACK】从机完成接收,拉低SDA主控确认,准备下一包或停止SCL保持高,SDA由低变高释放总线,进入待机/写入周期

  • 主机发送起始信号启用总线
  • 主机发送一个字节数据指明从机地址和后续字节的传送方向
    • 7bit地址
    • 1bit方向 (0表示主机发送给从机,1表示从机发送给主机)
  • 被寻址的从机发送应答信号回应主机
  • 发送器发送一个字节数据
  • 接收器发送应答信号回应发送器
  • ... ... (循环步骤4、5)
  • 通信完成后主机发送停止信号释放总线
相关推荐
苹果嘉尔121381 小时前
imx6ull芯片——设置流程
单片机·嵌入式硬件
深圳市恒锐丰科技杨生2 小时前
EG2032 220V 单路半桥栅极驱动芯片|中压外置 MOS/IGBT 驱动方案
嵌入式硬件·硬件工程
小雪崩2 小时前
嵌入式学习 day44:51单片机入门
嵌入式硬件·学习·51单片机
zcmodeltech2 小时前
冷链物流沙盘模型控制系统设计——基于STM32与Modbus RTU的冷藏车、冷库全流程动态展示方案
数据结构·stm32·单片机·嵌入式硬件·物联网·能源
智闲电子设计2 小时前
RS485 总线实战:终端电阻、差分信号、半双工方向控制,工程里最容易翻车的几处
c语言·stm32·单片机·嵌入式硬件
不悔哥5 小时前
开源 Zephyr:现代嵌入式 RTOS 长什么样
单片机·开源·嵌入式
广州灵眸科技有限公司5 小时前
瑞芯微(EASY EAI)RV1126B display
开发语言·数据库·人工智能·科技·嵌入式硬件
the sun345 小时前
CMSIS标准与各种库的发展历史+哈弗架构+CPU统一编址
stm32·架构·嵌入式
国产化创客6 小时前
创客开发入门(三)Arduino IDE 开发环境
ide·单片机·嵌入式硬件·课程设计·智能硬件