STM32学习23--I2C-1
一、简介1、I2C(Inter-Integraed Circuit集成电路间总线飞利浦1982年推出的一种通用数据总线同步半双工、串行、多主从总线只用2根信号线即可挂载多个设备一主多从、多主多从广泛用于传感器、OLED、EEPROM、RTC、AD/DA等低速外设。2、两根核心信号线所有I2C设备的SCL连在一起SDA连一起1SDASerial Data数据线双向传输数据2SCLSerial Clock时钟线由主机产生同步时钟3、硬件关键上拉电阻SDA、SCL都是开漏输出只能拉低电平无法主动输出高电平必须外接4.7~10kΩ的上拉电阻到电源3.3V/5V总线空闲时SDA、SCL都是高电平。必须开漏原因I2C的SDA、SCL都是共享双向总线多个设备并联在同一根线上不能强行输出高电平只能拉低只有开漏能实现只拉低、不主动拉高的电气特性。推挽输出VS开漏输出推挽内部两个MOS管上管接VCC下管接GND。输出高电平上管导通→强行把信号线拉到VCC输出低电平下管导通→强行拉到GND致命问题总线上两个设备同时控制一根线时会打架设备A输出高强制VCC设备B输出低强制GND电源直接对地短路→大电流烧坏芯片IO口。开漏输出内部只有下拉MOS管没有上拉管输出低下拉管导通→信号线拉到GND输出高下拉管断开→IO浮空高阻不控制这条线。所以总线电平完全靠外部上拉电阻维持芯片不能主动强行拉高。4、电气电平兼容标准5V I2C现在主流3.3V。可通过电平转换模块实现5V→3.3V。5、时钟频率标准模式100KHz通用低速外设快速模式400KHz大多数传感器、屏幕等外设一句话本质SCL提供节拍SDA在时钟高/低电平的时候改变数据一问一答通信。I2C铁律数据只有SCL低的时候才能变SCL高的时候SDA变化只能用来做起始和停止不能传输数据。二、寻址机制1、地址格式与寻址原理I2C总线通过唯一的地址来区分挂载在同一总线上的不同从设备。每个从设备在出厂时都会被分配一个固定的7位或10位地址主机在发起通信时首先发送目标从机的地址只有地址匹配的从机才会响应后续的数据传输。这种机制允许多个设备共享同一对信号线SDA和SCL实现了简洁的总线拓扑。一条I2C总线理论上最多可挂载的设备数量由地址位数决定7位地址模式这是最常用的模式。7位地址范围是0x00到0x7F二进制0000000到1111111共128个地址。但其中0x00 (0000000)被保留为广播地址0x01到0x07 (0000001到0000111)以及0x78到0x7F (1111000到1111111)被保留用于特殊用途如10位地址扩展、CBUS兼容等。因此实际可用的普通从机地址约为112个。在完整的I2C数据帧中地址字节由7位地址和1位读写方向位R/W组成共8位1字节。10位地址模式为满足更多设备的需求I2C协议扩展了10位地址模式。其地址范围是0x000到0x3FF共1024个地址。10位地址的传输需要两个字节第一个字节的高5位是固定的11110后两位是10位地址的最高两位A9, A8加上读写位第二个字节是地址的低8位A7-A0。由于寻址过程更复杂且大多数应用场景112个地址已足够因此10位地址在实际项目中较少使用。2、7位地址帧结构详解一个完整的7位地址数据帧结构如下| 7位从机地址 (A6-A0) | 读写位 (R/W) | |---------------------|-------------| | MSB First | 0写, 1读 |读写位 (R/W Bit)这是地址字节的第8位最低位LSB。0 (写模式)表示主机将要向从机写入数据。1 (读模式)表示主机将要从从机读取数据。示例从机地址0x48的读写指令假设一个从设备如某个温度传感器的7位硬件地址是0x48二进制0100 1000。主机写指令主机需要向该传感器写入配置寄存器。计算地址0x48左移1位0x48 1 0x90然后与写位0进行或操作0x90 | 0 0x90。因此主机发送的地址字节是0x90二进制1001 0000其中高7位0100100是地址最低位0表示写操作。主机读指令主机需要从该传感器读取数据。计算地址0x48左移1位0x90然后与读位1进行或操作0x90 | 1 0x91。因此主机发送的地址字节是0x91二进制1001 0001最低位1表示读操作。在代码中我们通常使用宏定义或移位操作来组合地址和读写位#define DEVICE_ADDR 0x48 #define WRITE_CMD ((DEVICE_ADDR 1) | 0) // 0x90 #define READ_CMD ((DEVICE_ADDR 1) | 1) // 0x913、ACK/NACK应答机制详解ACKAcknowledge应答是I2C协议保证数据可靠传输的核心机制。其规则如下时机在每成功传输一个字节8位数据后的第9个时钟周期由数据的接收方发出应答信号。ACK信号应答接收方无论是主机还是从机在SCL的第9个高电平期间将SDA线拉低输出低电平表示“已成功收到上一个字节请继续发送”。NACK信号非应答接收方在第9个时钟周期保持SDA线为高电平不拉低表示“未成功接收或不再需要数据”。物理过程在第9个时钟周期SCL由主机拉高。在此期间发送方会释放SDA线变为高阻态而接收方则控制SDA线电平。若接收方拉低SDA则总线呈现低电平即ACK若接收方不拉低则上拉电阻将SDA维持在高电平即NACK。主机在SCL高电平期间采样SDA线状态以判断应答结果。NACK出现的常见原因从机设备不存在主机发送的地址在总线上无对应设备。地址错误主机发送的地址与从机硬件地址不匹配。从机忙从机正在处理其他任务无法及时响应。通信结束主机在读取多个字节后发送NACK告知从机停止发送数据。从机故障从机硬件损坏或电源异常。4、广播地址与特殊地址如前所述部分地址被协议保留用于特殊功能广播地址 (0x00)主机可以向地址0x00发送数据总线上所有从机都会接收。这用于同时配置多个同型号设备或发送系统复位命令等场景但使用较少。CBUS地址 (0x01, 0x02)用于与旧的CBUS兼容设备通信。保留地址 (0x03-0x07, 0x78-0x7F)为未来协议扩展或其他用途保留不应分配给普通从机。在实际选型和电路设计时需要查阅器件数据手册确认其使用的具体I2C地址并注意避免地址冲突。三、标准通讯时序1、起始信号StartSCL高电平期间SDA由高→低总线启动告诉从设备准备通信。规则SCL高SDA跳变起始/停止SCL低时才能切换SDA传输数据2、停止信号StopSCL高电平期间SDA由低→高通信结束3、数据传输1发送一个字节SCL拉低→主机改变SDA电平0/1高位先行SCL拉高→从机读取SDA电平所以SCL高电平期间SDA不允许有数据变化依次循环上述8次即可发送一个字节。即低电平主机放数据高电平从机读数据。2接收一个字节SCL低电平从机将数据位依次放SDA线高位先行释放SCL主机在SCL高电平期间读取数据位SCL高电平期间SDA不允许有数据变化依次循环上述8次即可接收一个字节但主机在接收之前需要释放SDA。即低电平从机放数据高电平主机读数据3发送和接收应答发送应答主机接收完一个字节之后在下一个时钟发送一位数据数据0表示应答数据1表示非应答接收应答主机在发送完一个字节之后在下一个时钟接收一位数据判断从机是否应答数据0表示应答数据1表示非应答主机在接收之前数据释放SDA。注发送和接收应答都是相对主机而言4、完整写时序主机写1字节到从机寄存器1发送Start起始2发送从机7位地址写位R/W03等待从机ACK应答4发送寄存器地址5等待ACK6发送要写入的数据字节7等待ACK8发送Stop停止5、完整读时序读取从机寄存器数据I2C读分为2步先指定寄存器再切换读模式1start2从机地址写位发送寄存器地址ACK3重复起始信号4从机地址读位R/W1;5主机释放SDA等待从机输出数据6读取数据继续读主机返回ACK读完最后一个字节主机返回NACK告知从机停止输出7Stop停止四、两种实现方式1、硬件I2CSTM32内置外设优点硬件自动生成SCL时序CPU占用低速度稳定支持DMA缺点引脚固定资源有限配置较复杂适用大量、高频I2C读写屏幕、多传感器2、软件模拟优点任意2个GPIO口都能当SDA/SCL灵活跨芯片通用缺点占用CPU速度慢中断会打断时序导致通讯异常适用低速、简答外设、I2C引脚被占用时替代五、代码部分采用软件模拟的方式根据I2C时序写I2C函数起始MyI2C_Start()结束MyI2C_Stopt();主机发送一个字节MyI2C_SendByte(uint8_t Byte);主机接收一个字节uint8_t MyI2C_ReceiveByte()主机发送应答MyI2C_SendAck(uint8_t AckBit);主机接收应答MyI2C_ReceiveAck();1、MyI2C.c文件#include stm32f10x.h // Device header #include Delay.h #define SCL_PORT GPIOB #define SCL_PIN GPIO_Pin_10 #define SDA_PIN GPIO_Pin_11 /** brief BitValue设1或0就可以释放或者拉低SCL也可在函数里加入延时函数延时操作 param retval */ void MyI2C_W_SCL(uint8_t BitValue)//w表示写 { GPIO_WriteBit(GPIOB,GPIO_Pin_10,(BitAction)BitValue); Delay_us(5); } void MyI2C_W_SDA(uint8_t BitValue)//w表示写 { GPIO_WriteBit(GPIOB,GPIO_Pin_11,(BitAction)BitValue); Delay_us(5); } /** brief 读取SDA的电平 param retval */ uint8_t MyI2C_R_SDA() { uint8_t BitValue; BitValue GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11); Delay_us(5); return BitValue; } void MyI2C_Init() { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); GPIO_InitTypeDef GPIO_InitStructrue; GPIO_InitStructrue.GPIO_Mode GPIO_Mode_Out_OD;//配置成开漏输出同时也可以输入 GPIO_InitStructrue.GPIO_Pin GPIO_Pin_10 |GPIO_Pin_11; GPIO_InitStructrue.GPIO_Speed GPIO_Speed_50MHz ; GPIO_Init(GPIOB,GPIO_InitStructrue); GPIO_SetBits(GPIOB,GPIO_Pin_10 |GPIO_Pin_11); } //先拉低SDA再拉低SCL void MyI2C_Start() { MyI2C_W_SDA(1); MyI2C_W_SCL(1); MyI2C_W_SDA(0); MyI2C_W_SCL(0); } //除了终止条件其他都会保证SCL以低电平结束方便各个单元拼接 /停止/ void MyI2C_Stop() { MyI2C_W_SCL(0); MyI2C_W_SDA(0); MyI2C_W_SCL(1); MyI2C_W_SDA(1); } //主机发送 void MyI2C_SendByte(uint8_t Byte) { // MyI2C_W_SDA(Byte0x80);//取出数据的最高位 uint8_t i; for(i0;i8;i) { MyI2C_W_SDA(Byte(0x80i));//数据从高到低位加载到SDA上 MyI2C_W_SCL(1); MyI2C_W_SCL(0); } } uint8_t MyI2C_ReceiveByte() { uint8_t i,Byte 0x00; MyI2C_W_SDA(1); for(i0;ilt;8;i) { MyI2C_W_SCL(1); if(MyI2C_R_SDA()1) { Byte |(0x80gt;gt;i); } MyI2C_W_SCL(0); } return Byte; } //发送应答 void MyI2C_SendAck(uint8_t AckBit) { MyI2C_W_SDA(AckBit); MyI2C_W_SCL(1); MyI2C_W_SCL(0); } uint8_t MyI2C_ReceiveAck() { uint8_t AckBit ; MyI2C_W_SDA(1);//主机释放SDA MyI2C_W_SCL(1); AckBit MyI2C_R_SDA(); MyI2C_W_SCL(0); return AckBit; }2、MyI2C.h文件#ifndef __MYI2C_H #define __MYI2C_H void MyI2C_Init(); void MyI2C_Start(); void MyI2C_Stop(); void MyI2C_SendByte(uint8_t Byte); uint8_t MyI2C_ReceiveByte(); void MyI2C_SendAck(uint8_t AckBit); uint8_t MyI2C_ReceiveAck(); #endif3、main函数测试以MPU6050发送地址看是否应答0应答代码正确1非应答代码不正确#include stm32f10x.h #include Delay.h #include OLED.h #include I2C.h int main() { OLED_Init(); MyI2C_Init(); MyI2C_Start(); MyI2C_SendByte(0xD0); uint8_t ACK MyI2C_ReveiveACK(); MyI2C_Stop(); OLED_ShowNum(1,1,ACK,2); while(1) { } }经实测变量ACK为0代码正确。六、适配I2C三大核心机制1、多设备总线共享一条I2C总线挂主机个哥从机所有SDA/SCL并联。任何设备想发0自己开漏拉低信号线任何设备想发1自己高阻放手由上拉电阻统一拉为高不存在一方强制拉高、另一方强制拉低短路冲突。2、双向SDA数据SDA是双向主机发数据、从机回ACK/读取数据主机发送数据是主机控制SDA电平从机应答ACK时主机释放SDA高阻从机单独拉低SDA如果是推挽主机一直强制拉高从机根本拉不低ACK信号根本无法发出通信失效。3、多主机仲裁I2C支持多个主机仲裁逻辑主机发出1但总线被另一台主机拉成0本机检测到电平不一致主动放弃总线。只有开漏架构才能做到多个主机可以独立拉低总线但不能强制拉高”仲裁才能正常工作。本文完

相关新闻

5.鸿蒙OS7 30痛——分布式软总线:中心化调度在设备蜂鸣下的“雪崩”风险

5.鸿蒙OS7 30痛——分布式软总线:中心化调度在设备蜂鸣下的“雪崩”风险

5.0 分布式软总线:中心化调度在设备蜂鸣下的“雪崩”风险 ——鸿蒙OS7 30痛:星形拓扑中心节点过载与组网规模天花板 鸿蒙OS7 30大核心痛点:逻辑拓扑与因果链索引图兼目录 ↑↑↑——本系列总纲,建议优先阅读。所有痛点的前因后果、依赖关系、推荐阅读路径均在该文中定义…

2026/10/16 6:39:23 阅读更多 →
不装 Steam 客户端也能下创意工坊模组?免费开源 WorkshopDL 三步上手全攻略

不装 Steam 客户端也能下创意工坊模组?免费开源 WorkshopDL 三步上手全攻略

不装 Steam 客户端也能下创意工坊模组?免费开源 WorkshopDL 三步上手全攻略 【免费下载链接】WorkshopDL WorkshopDL - The Best Steam Workshop Downloader 项目地址: https://gitcode.com/gh_mirrors/wo/WorkshopDL 游戏是在 GOG 或 Epic 上买的&#xff0…

2026/10/15 12:35:41 阅读更多 →
特斯拉V9.0 OTA深度解析:从架构重塑到自动驾驶与娱乐体验的全面进化

特斯拉V9.0 OTA深度解析:从架构重塑到自动驾驶与娱乐体验的全面进化

1. 从一次深夜的OTA推送说起:V9.0的“软着陆” 那天晚上,我的手机屏幕突然亮了一下,不是消息,而是特斯拉App的一条推送:“您的车辆软件更新已就绪”。点开一看,版本号赫然写着“2024.8.x”——这正是V9.0版…

2026/10/15 12:58:15 阅读更多 →

最新新闻

通风机振动信号小波阈值去噪:从原理到Python实战的特征提取指南

通风机振动信号小波阈值去噪:从原理到Python实战的特征提取指南

简介:这份资源是发表于《能源与环保》的期刊论文《基于小波阈值的通风机故障特征提取应用研究》,面向煤矿机电、通风安全及信号处理方向的工程技术人员与研究人员,用于解决主通风机振动信号噪声干扰大、故障特征难以准确提取的问题。资源包为…

2026/10/17 14:49:31 阅读更多 →
基于SpringBoot+Vue的山区农产品供销系统毕设全解析

基于SpringBoot+Vue的山区农产品供销系统毕设全解析

每年到这个节点,总有一批做Java毕设的同学拿到类似的题目:基于SpringBootvue的某某系统设计与实现。尤其是这种带“山区农产品供销”方向的项目,本身业务场景足够清晰,又贴近实际民生需求,是很多高校计科、电商、农林信…

2026/10/17 14:49:31 阅读更多 →
锂电池制造SAP解决方案:165页PPT的模块映射与分期实施拆解

锂电池制造SAP解决方案:165页PPT的模块映射与分期实施拆解

简介:这份165页PPT聚焦锂电池制造行业的SAP解决方案,面向新能源制造企业的信息化负责人、SAP实施顾问及智能制造从业者,围绕凯致电子的业务流程、项目背景、项目计划与实施、案例分享等模块展开,帮助读者理解如何以SAP为载体构建平…

2026/10/17 14:49:31 阅读更多 →
48G魔改4090跑开源MoE模型:从60到150 token/s的推理优化实战

48G魔改4090跑开源MoE模型:从60到150 token/s的推理优化实战

前两天我刷到一条标题——某个开源推理框架配魔改显存的4090,把一款3.8B激活参数的MoE模型跑到了150 token/s的解码速度。第一反应是标题党,毕竟我自己手里就有一张改过显存的4090,日常跑同级别模型也就是七八十的水平。但当天晚上我把模型和…

2026/10/17 14:49:31 阅读更多 →
挑战Claude Code和Cursor:阿里Qoder的Agentic上下文工程,TaoToken统一Key接入实测

挑战Claude Code和Cursor:阿里Qoder的Agentic上下文工程,TaoToken统一Key接入实测

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 14:49:31 阅读更多 →
Unity原生Text渐显状态机:告别协程混乱,清晰控制UI过渡

Unity原生Text渐显状态机:告别协程混乱,清晰控制UI过渡

最近在做一个剧情驱动的小游戏,里面有大段的对话文本需要逐句渐显。最初图省事,直接用协程在Update里拖进度条,写着写着发现状态一多,代码就开始乱成一团——对话要渐显、选项要延迟出现、跳过要瞬间完成、切场景要立刻清空。各个…

2026/10/17 14:48:31 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/16 21:35:51 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/17 1:44:59 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 21:54:38 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →