1. 为什么值得花一周把I2C彻底啃下来I2C这两根线SCL和SDA看起来简单得不像话——一根时钟一根数据挂上拉电阻就能通信。但我见过太多人在这上面翻车有人调GT911触摸屏调了三天最后发现是上拉电阻选错了有人在多主系统里遇到总线锁死复位都不管用还有人用逻辑分析仪抓波形看到数据全是FF以为是芯片坏了结果是时序配置差了一个数量级。I2C的坑几乎全部集中在两个地方开漏物理层的电气特性和多主仲裁的状态机逻辑。这两块内容数据手册上往往一笔带过但实际调试中出问题的概率极高。我自己的经验是把这两块彻底搞明白后面不管遇到什么I2C设备——EEPROM、OLED、传感器、触摸屏——都能快速定位问题。这篇内容适合谁看如果你正在调I2C设备但总是时好时坏如果你要设计多主系统但不确定仲裁机制怎么工作如果你用逻辑分析仪抓了波形但看不懂那些毛刺和异常那这一周的时间花得值。我会从最底层的物理层开始一路讲到多主仲裁的状态机把每个环节的“为什么”都讲清楚。2. 开漏物理层两根线背后的电气逻辑2.1 开漏输出到底是什么开漏Open-Drain这个词拆开看就是“漏极开路”。在MOS管里漏极是输出端开漏意味着这个输出端没有内部上拉只有一个NMOS管把线拉到地。PMOS管没有。所以开漏输出只有两种状态拉低或者高阻态。高阻态是什么概念就是输出端相当于断开既不输出高电平也不输出低电平线的电平完全由外部决定。这就引出了I2C最核心的电气设计所有设备只能拉低总线不能主动拉高。总线的高电平靠什么靠上拉电阻。这个设计的好处太明显了。假设有两个设备同时想拉低SDA线一个拉低另一个也拉低线就是低电平没有任何冲突。如果换成推挽输出一个输出高一个输出低那就是电源直接对地短路芯片当场冒烟。开漏输出天然支持“线与”逻辑——只要有一个设备拉低总线就是低所有设备都释放总线才被上拉电阻拉高。注意开漏输出必须配合上拉电阻使用。没有上拉电阻总线永远无法回到高电平通信直接失效。这是新手最容易忽略的一点。2.2 上拉电阻怎么选不是随便放一个就行上拉电阻的选型是I2C硬件设计里最需要计算的地方。选大了上升沿太慢高速通信时数据还没到高电平就被采样了选小了低电平时的灌电流太大可能超过芯片的驱动能力。先看上升时间的约束。I2C总线的上升时间由RC充电决定R是上拉电阻C是总线电容。标准模式100kHz要求上升时间小于1000ns快速模式400kHz要求小于300ns快速模式1MHz要求小于120ns。总线电容C来自哪里PCB走线电容、引脚电容、器件电容。经验值大概是每根线10pF到20pF如果走线长或者挂的设备多可能到50pF甚至100pF。假设C100pF快速模式要求上升时间小于300ns那么RC300nsR3kΩ。这是上限。再看低电平灌电流的约束。I2C标准规定低电平时的灌电流不能超过3mA标准模式和快速模式快速模式不能超过20mA。灌电流等于VDD除以R忽略MOS管的导通电阻。假设VDD3.3VR1kΩ灌电流就是3.3mA已经超过3mA了。所以R不能太小。综合下来3.3V系统、快速模式、总线电容100pF的情况下上拉电阻选2.2kΩ到4.7kΩ比较合适。如果总线电容更大比如挂了8个设备电容可能到200pF那R要降到1.5kΩ左右才能满足上升时间。但这时候灌电流又上去了需要确认所有设备的灌电流能力。模式最高速率上升时间要求典型上拉电阻3.3VC100pF灌电流标准模式100kHz1000ns4.7kΩ-10kΩ0.7mA快速模式400kHz300ns2.2kΩ-4.7kΩ1.5mA快速模式1MHz120ns1kΩ-2.2kΩ3.3mA实际选型时我一般先用4.7kΩ试用示波器看上升沿。如果上升沿太缓降到2.2kΩ如果低电平太高超过0.4V说明灌电流不够再适当加大电阻。这个调试过程比纯计算更靠谱因为实际电容很难精确估算。2.3 总线电容的隐藏陷阱总线电容是I2C设计里最容易被低估的参数。数据手册上写的引脚电容通常是5pF到10pF但实际PCB上还有走线电容、过孔电容、连接器电容。如果走线长度超过10cm电容可能增加20pF到30pF。更隐蔽的是有些器件的引脚在断电时呈现低阻抗相当于给总线加了一个大电容。我遇到过一块板子I2C总线上挂了一个未供电的传感器结果整个总线通信不稳定。后来查出来是那个传感器的SDA引脚在断电时有保护二极管把总线电压钳位了。实操心得调试I2C时先用万用表量SCL和SDA对地的电容。如果超过200pF就要考虑降低上拉电阻或者加总线缓冲器。总线缓冲器如PCA9515可以隔离电容但会引入额外的传播延迟需要重新评估时序。2.4 开漏输出的边沿特性与信号完整性开漏输出的上升沿是指数上升的不是理想的方波。因为上拉电阻和总线电容构成RC充电电路电压按V(t)VDD*(1-e^(-t/RC))变化。这意味着上升沿在接近高电平时变得很缓如果采样点太靠近上升沿的尾部可能读到不确定的值。下降沿则完全不同。开漏输出拉低时NMOS管导通总线电容通过MOS管的导通电阻放电。这个电阻通常只有几十欧姆所以下降沿非常陡峭几乎是瞬间的。这就造成了I2C波形的不对称下降沿快上升沿慢。这种不对称在高速通信时特别明显。400kHz的时钟周期是2.5μs高电平时间只有1.25μs左右。如果上升时间占了300ns那高电平的有效窗口就只有950ns。如果上升时间到了500ns有效窗口只剩750ns采样裕量就很小了。我见过一个案例客户用1MHz快速模式上拉电阻选了10kΩ结果波形上升沿超过1μs数据完全错乱。换成1.5kΩ后问题解决。所以高速模式下上拉电阻的选型必须用示波器验证不能凭经验拍脑袋。3. I2C时序从起始条件到数据帧的完整拆解3.1 起始条件和停止条件的精确时序I2C的起始条件Start定义为SCL为高电平时SDA从高变低。停止条件Stop定义为SCL为高电平时SDA从低变高。这两个条件的核心在于SDA的变化发生在SCL高电平期间而数据位的变化必须发生在SCL低电平期间。为什么这么设计因为SCL高电平是数据有效的窗口。如果SDA在SCL高电平期间变化那就不是数据位而是起始或停止条件。这个规则保证了接收方可以在SCL高电平时稳定采样SDA。起始条件的时序参数很关键。标准模式要求起始条件的建立时间SDA下降沿到SCL下降沿大于4.7μs保持时间SCL下降沿到SDA上升沿大于4μs。快速模式下这些参数缩小到0.6μs和0.6μs。如果建立时间不够从机可能还没检测到起始条件SCL就拉低了导致通信失败。我遇到过一种情况主机用软件模拟I2C起始条件里SDA拉低后立刻拉低SCL建立时间只有100ns。从机是标准模式的EEPROM需要4.7μs的建立时间结果完全没反应。后来在SDA拉低后加了5μs延时通信正常。这就是典型的时序参数不匹配。3.2 数据位的建立与保持时间数据位的传输规则是SCL低电平期间发送方改变SDASCL高电平期间接收方采样SDA。所以数据位的建立时间是指SDA变化到SCL上升沿的时间保持时间是指SCL下降沿到SDA下次变化的时间。标准模式下数据建立时间要求大于250ns保持时间要求大于0ns实际上要大于300ns才能稳定。快速模式下建立时间大于100ns保持时间大于0ns。这些参数看起来宽松但在软件模拟I2C时很容易违反。比如用GPIO模拟I2C代码里先拉低SCL然后设置SDA再拉高SCL。如果GPIO操作之间没有延时SDA变化到SCL上升沿可能只有几十纳秒不满足建立时间。从机采样时可能读到旧数据。解决方法是在SDA设置后加一个短延时确保建立时间足够。注意保持时间为0ns意味着SCL下降沿后SDA可以立刻变化。但实际设计中建议保留至少100ns的保持时间给从机内部电路足够的响应时间。3.3 时钟同步与时钟拉伸I2C是多主总线但SCL线是共享的。多个主机同时发送时钟时怎么保证时钟信号不冲突答案是时钟同步。每个主机在拉低SCL后会检测SCL的实际电平。如果另一个主机还在拉低SCL当前主机就会等待直到SCL真正变高才开始自己的高电平周期。这个机制的结果是SCL的低电平周期由所有主机中最长的那个决定高电平周期由最短的那个决定。最终SCL的频率由最慢的主机决定。这就像几个人一起抬一根杆子谁都不松手杆子就抬不起来只要有一个人松手杆子就能抬起来。时钟拉伸Clock Stretching是另一种机制。从机如果来不及处理数据可以在SCL高电平期间拉低SCL强制主机等待。主机检测到SCL没有按预期变高就知道从机在拉伸时钟于是暂停计时直到SCL真正变高。时钟拉伸在实际中很常见。EEPROM在写入周期需要5ms左右期间会拉伸时钟。如果主机不支持时钟拉伸就会在EEPROM还没写完时发送下一个字节导致数据丢失。我见过一个案例客户用硬件I2C控制器但控制器不支持时钟拉伸写EEPROM时总是失败。后来改用软件模拟I2C支持时钟拉伸问题解决。3.4 完整数据帧格式与ACK/NACK机制一个完整的I2C数据帧包括起始条件、7位从机地址、1位读写位、ACK/NACK、数据字节、ACK/NACK、...、停止条件。每个字节传输后接收方必须发送ACK拉低SDA或NACK释放SDA。ACK/NACK的时序很特殊。发送方在第8个时钟周期后释放SDA接收方在第9个时钟周期拉低SDA表示ACK。如果接收方不拉低SDA就是NACK。主机在发送完最后一个字节后会发送NACK然后发送停止条件。这里有个容易混淆的地方ACK是由接收方发送的不是发送方。主机发送地址后从机发送ACK主机发送数据后从机发送ACK从机发送数据后主机发送ACK。很多人第一次看时序图时会搞混这个方向。帧阶段发送方接收方ACK发送方地址帧主机从机从机写数据帧主机从机从机读数据帧从机主机主机最后一个读数据帧从机主机主机发送NACK3.5 自由数据模式与重复起始条件I2C有一种特殊模式叫“自由数据模式”Free Data Format这时候没有地址帧数据直接传输。这种模式很少用但在某些专用场景下会出现。比如两个固定设备之间的通信不需要寻址直接用自由数据模式简化协议。更常用的是重复起始条件Repeated Start。有时候主机需要在不断开总线的情况下切换读写方向比如先写寄存器地址然后读数据。这时候不能用停止条件因为停止条件会释放总线其他主机可能抢占总线。重复起始条件就是在不发送停止条件的情况下再发送一个起始条件。重复起始条件的时序和普通起始条件一样只是前面没有停止条件。从机检测到重复起始条件后知道主机要继续通信不会释放总线。这个机制在读写EEPROM时特别常用先写地址重复起始再读数据。4. 多主仲裁当两个主机同时开口说话4.1 仲裁的基本原理线与逻辑的天然优势多主仲裁是I2C最精妙的设计之一。两个主机同时发送数据时怎么决定谁赢答案是线与逻辑。前面说过开漏输出只能拉低不能拉高。所以当两个主机同时发送时只要有一个拉低总线就是低只有两个都释放总线才是高。仲裁规则很简单每个主机在发送每一位时都会检测SDA的实际电平。如果自己发送的是高电平但检测到SDA是低电平说明另一个主机在拉低SDA自己就失去了仲裁立刻停止发送转为从机模式。如果自己发送的是低电平检测到SDA也是低电平那就继续发送。这个过程是逐位进行的不需要额外的仲裁线。仲裁的赢家是发送数据中“低电平更多”的那个主机。比如主机A发送0x5001010000主机B发送0x4801001000逐位比较第1位都是0第2位都是1第3位A是0B是0第4位A是1B是0——B拉低了SDAA检测到SDA是低但自己发的是高A失去仲裁B继续发送。实操心得仲裁失败的主机不会损坏也不会丢失数据。它会自动切换到从机模式等待下一次总线空闲。这个机制非常优雅但前提是所有主机都支持多主模式。有些低端MCU的硬件I2C不支持多主仲裁只能做单主。4.2 仲裁的时序窗口与采样点仲裁的采样点在哪里在SCL高电平期间。每个主机在SCL高电平时检测SDA与自己发送的值比较。如果SCL是低电平SDA的变化不参与仲裁因为那是数据准备阶段。这个采样点的选择很关键。如果采样点太早SDA还没稳定如果太晚可能错过仲裁窗口。I2C标准规定仲裁在SCL高电平期间进行具体采样点由各主机的内部电路决定。一般来说采样点靠近SCL高电平的中间位置这样SDA已经稳定。我遇到过一种情况两个主机同时启动但其中一个主机的SCL上升沿比较慢导致采样点偏移。结果仲裁过程中慢速主机在SCL还没完全变高时就采样了SDA读到了错误的值仲裁失败但没正确切换到从机模式导致总线冲突。后来调整了上拉电阻SCL上升沿变快问题解决。4.3 仲裁失败后的处理与总线恢复仲裁失败的主机需要立刻停止发送释放SDA和SCL转为从机模式。但这里有个问题如果仲裁失败的主机已经发送了一部分数据从机可能已经接收了这些数据。这时候从机怎么处理答案是从机会继续接收直到收到停止条件或重复起始条件。仲裁失败的主机虽然停止了发送但总线上的通信还在继续。从机不知道哪个主机赢了它只关心总线上的数据。所以仲裁失败的主机必须确保自己释放总线后不会干扰赢家的通信。总线恢复是另一个重要话题。如果总线被意外拉低比如某个设备死机怎么恢复标准做法是发送9个时钟脉冲让所有设备完成当前字节的传输然后发送停止条件。如果还不行就需要硬件复位。我见过一个案例一个从机在通信过程中断电SDA线被拉低总线锁死。主机发送任何数据都没反应。后来用GPIO模拟时钟发送9个脉冲总线恢复。这个技巧在调试时非常有用。4.4 多主系统的时钟同步细节多主系统中时钟同步是仲裁的基础。每个主机在拉低SCL后会等待SCL实际变高才开始自己的高电平周期。如果另一个主机还在拉低SCL当前主机就继续等待。这个过程是自动的不需要软件干预。时钟同步的结果是SCL的低电平周期由所有主机中最长的那个决定。比如主机A的低电平周期是1μs主机B是2μs那么实际SCL低电平就是2μs。高电平周期由最短的那个决定。最终SCL频率由最慢的主机决定。这个机制保证了即使多个主机同时发送SCL也不会冲突。但有个前提所有主机的SCL引脚都是开漏输出。如果某个主机的SCL是推挽输出就会破坏时钟同步导致总线冲突。场景主机A SCL主机B SCL实际SCL结果都拉低低低低正常A拉低B释放低高阻低A控制A释放B拉低高阻低低B控制都释放高阻高阻高上拉电阻拉高4.5 多主仲裁的边界情况与异常处理多主仲裁有几个边界情况需要特别注意。第一种是同时发送相同数据。如果两个主机发送完全相同的数据仲裁不会失败两个主机会一直发送到最后。这时候总线上的数据是正确的但两个主机都以为自己在控制总线。这种情况通常不会出问题因为数据相同从机接收到的数据也是正确的。但停止条件时两个主机同时发送停止条件可能会产生竞争。第二种是仲裁过程中出现起始条件。如果一个主机在仲裁过程中发送了起始条件而另一个主机还在发送数据就会产生冲突。I2C标准规定起始条件只能在总线空闲时发送。如果仲裁过程中出现起始条件说明有主机违反了协议总线可能锁死。第三种是时钟拉伸与仲裁的交互。从机拉伸时钟时主机暂停计时。如果此时另一个主机也在发送仲裁会怎么处理答案是时钟拉伸会暂停所有主机的计时仲裁也暂停。直到SCL真正变高仲裁才继续。这个机制保证了时钟拉伸不会影响仲裁的公平性。5. 实战调试逻辑分析仪与常见问题排查5.1 逻辑分析仪抓I2C波形的正确姿势逻辑分析仪是调试I2C的利器但很多人用不对。首先采样率要足够高。I2C快速模式是400kHz快速模式是1MHz。根据奈奎斯特采样定理采样率至少是信号频率的2倍但实际调试中建议10倍以上。所以400kHz的I2C采样率至少4MHz1MHz的I2C采样率至少10MHz。其次触发条件要设对。调试I2C时通常用起始条件触发。逻辑分析仪的触发设置里选择SCL高电平时SDA下降沿作为触发条件。这样每次通信开始时逻辑分析仪都会抓取波形。第三解码设置要正确。逻辑分析仪通常有I2C解码器需要设置SCL和SDA的通道、地址位数7位或10位、读写位位置。如果解码结果全是FF或00说明解码设置不对或者信号质量有问题。注意逻辑分析仪的探头电容会影响I2C信号。如果探头电容太大上升沿会变缓导致通信失败。调试时尽量用低电容探头或者缩短探头地线。5.2 常见问题速查表现象可能原因排查方法解决方法通信完全无反应上拉电阻缺失或太大量SCL/SDA空闲电平加4.7kΩ上拉电阻数据偶尔错误上升沿太慢示波器看上升时间减小上拉电阻从机不ACK地址错误或从机未供电逻辑分析仪看地址帧检查地址和供电总线锁死从机死机拉低SDA量SDA电平发送9个时钟脉冲读写EEPROM失败不支持时钟拉伸看SCL是否被拉伸改用软件I2C多主系统冲突某个主机不支持仲裁逐个主机测试更换支持多主的MCUGT911触摸失败上拉电阻或时序问题看起始条件建立时间调整上拉和延时数据全是FF解码设置错误检查逻辑分析仪设置重新配置解码器5.3 GT911触摸屏I2C通信失败案例GT911是一款常见的电容触摸屏控制器I2C接口。我遇到过很多次GT911通信失败的情况总结下来主要有几个原因。第一个是上拉电阻。GT911的I2C接口要求上拉电阻在2.2kΩ到4.7kΩ之间。如果用了10kΩ上升沿太慢GT911可能检测不到起始条件。我见过一个客户用10kΩ上拉通信成功率只有50%换成2.2kΩ后100%成功。第二个是复位时序。GT911上电后需要复位复位时序不对会导致I2C地址错误。GT911的I2C地址由复位时的INT引脚电平决定INT高电平是0x5DINT低电平是0x14。如果复位时INT引脚状态不对地址就错了主机发送的地址从机不响应。第三个是时钟拉伸。GT911在某些操作时会拉伸时钟如果主机不支持时钟拉伸就会通信失败。解决方法是用支持时钟拉伸的I2C控制器或者用软件模拟I2C。5.4 I2C读写EEPROM的Verilog实现要点用Verilog实现I2C读写EEPROM核心是状态机设计。状态机需要包括空闲、起始、发送地址、等待ACK、发送数据、等待ACK、停止等状态。每个状态的转移条件要严格按时序参数设计。时钟分频是关键。假设系统时钟是50MHzI2C时钟是100kHz分频系数是500。但I2C的时钟不是50%占空比而是低电平时间大于高电平时间。标准模式下低电平至少4.7μs高电平至少4μs。所以分频系数要分别计算低电平和高电平的计数值。// I2C时钟分频示例 parameter CLK_DIV 500; // 50MHz / 100kHz reg [15:0] clk_cnt; reg scl_reg; always (posedge clk) begin if (clk_cnt CLK_DIV - 1) begin clk_cnt 0; scl_reg ~scl_reg; end else begin clk_cnt clk_cnt 1; end end这个简单的分频产生50%占空比的SCL但I2C要求低电平时间更长。所以实际实现时低电平计数值要大于高电平计数值。比如低电平计数值300高电平计数值200总周期500。ACK检测是另一个关键点。发送完8位数据后主机释放SDA在第9个时钟周期检测SDA电平。如果SDA是低说明从机ACK如果是高说明NACK。Verilog里需要在第9个时钟周期的特定时刻采样SDA。5.5 软件模拟I2C的延时技巧软件模拟I2C时延时是核心。延时不够时序不满足延时太长通信速度慢。我的经验是用示波器测量实际波形调整延时直到满足时序参数。对于100kHz的标准模式半周期是5μs。如果系统时钟是72MHz一个NOP是13.9ns5μs需要360个NOP。但实际代码里还有GPIO操作的开销所以延时循环要实测调整。// 软件I2C延时示例 void i2c_delay(void) { for (volatile int i 0; i 10; i); } void i2c_start(void) { SDA_HIGH(); SCL_HIGH(); i2c_delay(); SDA_LOW(); i2c_delay(); SCL_LOW(); i2c_delay(); }这个延时循环的计数值需要根据实际系统时钟调整。我一般先用一个保守的值然后用逻辑分析仪看波形逐步减小直到时序刚好满足。这样既能保证可靠性又能提高通信速度。6. 从PMBus到I2C扩展协议变体与系统设计6.1 PMBus与I2C的区别PMBus是建立在I2C基础上的电源管理协议。物理层和I2C完全一样但协议层有区别。PMBus定义了标准的命令集比如读电压、读电流、设置输出电压等。I2C只定义了物理层和数据链路层应用层由设备自己定义。PMBus的时钟频率通常是100kHz或400kHz和I2C一样。但PMBus有块传输模式可以一次传输多个字节提高效率。PMBus还定义了PECPacket Error Checking用CRC校验数据完整性。I2C没有这个机制。实际应用中PMBus设备通常也支持I2C通信。如果不需要PMBus的高级功能可以当普通I2C设备用。但要注意PMBus设备可能对时序有更严格的要求比如某些命令需要特定的延时。6.2 I2C多路复用与总线扩展当系统需要挂很多I2C设备时地址冲突是常见问题。7位地址只有128个去掉保留地址实际可用的更少。如果两个设备地址相同就需要多路复用。I2C多路复用器如PCA9548可以把一条总线分成多条每条挂不同的设备。主机通过多路复用器选择要通信的通道这样地址相同的设备可以挂在不同通道上。另一种扩展方式是I2C到SPI桥接或者I2C到UART桥接。这些桥接芯片可以把I2C设备扩展到其他总线上。比如用SC16IS752把I2C转成UART可以挂多个串口设备。实操心得多路复用器的通道切换需要时间切换后要加延时再通信。我见过一个案例客户切换通道后立刻发送数据结果数据发到了错误的通道。后来在切换后加了100μs延时问题解决。6.3 I2C在Linux系统中的使用Linux系统里I2C设备通过/dev/i2c-X设备节点访问。用户空间可以用i2c-tools工具集包括i2cdetect、i2cget、i2cset等。i2cdetect可以扫描总线上的设备地址i2cget和i2cset可以读写寄存器。内核空间里I2C设备通过i2c_driver注册。驱动里实现probe、remove、read、write等函数。设备树里配置I2C控制器的地址、时钟频率、上拉电阻等参数。Linux的I2C子系统支持SMBus协议SMBus是I2C的子集增加了超时和PEC。如果设备支持SMBus可以用SMBus接口访问。但要注意SMBus的时序要求比I2C严格某些I2C设备可能不兼容SMBus。6.4 I2C HID设备资源问题排查I2C HID是触摸屏、触摸板等设备常用的协议。Windows系统里I2C HID设备需要足够的资源才能正常工作。如果资源不足设备管理器会报“该设备找不到足够资源可以使用代码12”。这个问题通常是因为I2C控制器的资源被其他设备占用或者GPIO中断资源不足。解决方法是检查设备管理器里的资源分配释放不必要的资源或者更换I2C控制器。另一个常见问题是I2C HID设备的描述符错误。描述符里定义了报告长度、中断间隔等参数。如果描述符不符合HID规范系统可能无法正确识别设备。这时候需要用USBlyzer或类似工具抓取描述符检查是否符合规范。7. 一周学习路径与实操建议7.1 第一到第二天物理层与硬件设计前两天重点搞明白开漏输出、上拉电阻、总线电容。找一块现成的I2C开发板用示波器看SCL和SDA的波形。改变上拉电阻观察上升时间的变化。用万用表量总线电容验证RC充电的计算。实操项目用4.7kΩ和10kΩ上拉电阻分别测试100kHz和400kHz通信记录波形和误码率。这个实验能让你直观理解上拉电阻对信号完整性的影响。7.2 第三到第四天时序与协议层这两天重点研究起始条件、数据位、ACK/NACK、重复起始条件。用逻辑分析仪抓取完整的通信过程逐帧分析。找一个EEPROM用软件模拟I2C读写调整延时参数观察时序变化。实操项目用GPIO模拟I2C读写AT24C02 EEPROM。先写一个字节再读回来验证数据正确。然后故意违反时序参数观察从机的反应。这个实验能让你深刻理解时序参数的重要性。7.3 第五到第六天多主仲裁与异常处理这两天重点研究多主仲裁。找两个支持多主模式的MCU同时发送数据用逻辑分析仪观察仲裁过程。故意让两个主机发送不同数据看哪个赢。然后模拟总线锁死用9个时钟脉冲恢复。实操项目两个MCU同时读写同一个EEPROM观察仲裁和时钟同步。记录仲裁失败的主机如何切换到从机模式。这个实验能让你理解多主系统的实际行为。7.4 第七天综合调试与问题排查最后一天综合运用前面学的知识调试一个实际的I2C设备。可以是OLED、传感器、触摸屏。遇到问题按速查表排查记录解决过程。实操项目调试SSD1306 OLED显示一段文字。如果通信失败用逻辑分析仪抓波形检查地址、时序、上拉电阻。这个项目涵盖了I2C的大部分知识点是很好的综合练习。我个人在实际操作中的体会是I2C的坑大多不在协议本身而在物理层和时序细节。把开漏物理层和多主仲裁这两块搞透后面遇到任何I2C问题都能快速定位。另外逻辑分析仪是必备工具没有它调试I2C就像盲人摸象。最后再分享一个小技巧调试I2C时先用最低速比如10kHz通信成功后再逐步提高速度。这样能快速区分是协议问题还是信号完整性问题。
