1. I2C总线:嵌入式世界的“电话会议”系统
在嵌入式系统开发中,设备间的通信如同人与人之间的对话,需要一套清晰、高效的规则。I2C总线协议,就是这样一个在微控制器、传感器、存储器等芯片间被广泛采用的“电话会议”系统。它仅凭两根线——串行数据线SDA和串行时钟线SCL,就能在多个“与会者”(主从设备)之间建立起有序的沟通。我接触过太多项目,从读取温湿度传感器的数据,到配置复杂的音频编解码器,I2C都是那个幕后功臣。它的技术价值不言而喻:极大地简化了PCB布局,减少了引脚占用,让系统设计更加紧凑优雅。然而,要真正驾驭它,尤其是精准地控制通信速率、理解其多样的数据格式和灵活的操作模式,往往需要深入其时钟生成与协议细节。本文就将从一个实践者的角度,拆解I2C模块的时钟心脏、数据语言和工作状态,让你不仅能配置出稳定可靠的I2C通信,更能洞悉其背后的运作逻辑,在调试时游刃有余。
2. I2C时钟生成机制:从心跳到步调
如果把I2C通信比作一场精心编排的舞蹈,那么时钟信号就是舞步的节拍器。这个节拍器并非直接使用芯片的主时钟,而是经过精心“裁剪”而来。理解时钟生成链,是配置正确通信速率、避免时序问题的第一步。
2.1 时钟生成链路全景
I2C模块的时钟并非凭空产生,它源自于设备的外设时钟(通常称为VBUS_CLK或类似)。这个输入时钟频率可能很高(例如几十MHz),直接用于I2C这种低速总线(通常为100kHz或400kHz)显然不合适。因此,I2C模块内部设计了两级分频器,像两个齿轮组,将高速的输入时钟“降速”到合适的频率。
第一级是一个可编程的预分频器(Prescaler),它通过I2CPSC寄存器进行配置。它的作用是将输入时钟进行初步分频,产生一个“模块时钟”。这个模块时钟是I2C模块内部逻辑(如状态机、中断控制器等)的工作时钟,其频率需要在一个合适的范围内(例如6.7MHz至13.3MHz),以确保模块稳定运行。
第二级分频器更为精细,它专门用于生成最终输出到SCL引脚上的“主时钟”。这个分频器独特之处在于,它分别对模块时钟的高电平和低电平周期进行独立分频,通过I2CCKH和I2CCKL两个寄存器控制。这样设计的好处是,我们可以灵活地调整SCL信号的高低电平占空比,以满足不同从设备对时钟波形的要求。
2.2 核心计算公式与参数选择
理论总是枯燥的,但结合公式和实际配置,一切就清晰了。假设我们的芯片外设输入时钟频率为CLK_IN。
第一步:计算模块时钟频率模块时钟频率由预分频器I2CPSC决定。其计算公式为:模块时钟频率 = 输入时钟频率 / (I2CPSC + 1)
这里有一个关键的细节:当I2CPSC=0时,分频因子d=8;当I2CPSC=1时,d=7;当I2CPSC大于1时,d=5。这个d值会影响到后续主时钟的计算。因此,更准确的模块时钟公式应考虑到一个固定的偏移量,但通常数据手册会直接给出上述简化公式,并注明I2CPSC的有效范围。实际操作心得:在配置时,我们首要目标是让计算出的模块时钟频率落在芯片手册推荐的范围内(如6.7-13.3 MHz)。例如,输入时钟为50MHz,若设置I2CPSC=4,则模块时钟为50/(4+1)=10MHz,符合要求。
第二步:计算主时钟(SCL)频率主时钟频率才是我们最终关心的I2C总线通信速率(如100kHz)。它由模块时钟经过I2CCKH和I2CCKL分频得到。计算公式为:主时钟频率 = 模块时钟频率 / [(I2CCKH + d) + (I2CCKL + d)]
其中,d值就是上一步中提到的,由I2CPSC决定的参数(0对应d=7,1对应d=6,>1对应d=5)。I2CCKH和I2CCKL的值就是我们直接写入寄存器的数值。
一个完整的配置实例: 目标:在输入时钟CLK_IN = 50 MHz 的系统上,配置I2C总线速度为标准的100 kHz,且要求SCL高低电平时间基本相等(占空比~50%)。
- 确定模块时钟:我们希望模块时钟在10MHz左右。计算I2CPSC = 50MHz / 10MHz - 1 = 4。写入I2CPSC=4,此时d=5,实际模块时钟 = 50/(4+1)=10MHz。
- 计算主时钟分频值:主时钟周期应为 1/100kHz = 10 us。模块时钟周期为 1/10MHz = 0.1 us。 因此,需要的总分频比 N = 10 us / 0.1 us = 100。 根据公式:N = (I2CCKH + d) + (I2CCKL + d) = (I2CCKH + 5) + (I2CCKL + 5) = 100。 为了占空比50%,令高电平时间和低电平时间相等:(I2CCKH + 5) = (I2CCKL + 5) = 50。 所以,I2CCKH = I2CCKL = 45。
最终配置:I2CPSC=4, I2CCKH=45, I2CCKL=45。这样就能得到约100kHz且占空比50%的SCL时钟。
重要提示:上述计算值是理想值。实际通信速率会略低于计算值,因为公式未计入SCL信号线的上升/下降时间以及模块内部同步器的延迟。在高速模式(400kHz或1MHz)下,这些因素影响更显著,需要预留余量。另外,在仲裁或时钟同步过程中,SCL周期可能会被拉长。
2.3 时钟配置的陷阱与实操要点
配置时钟寄存器时,有几个坑我踩过,你必须注意:
- 配置时机:预分频器I2CPSC只能在I2C模块处于复位状态(IRS位为0)时进行配置。一旦通过设置IRS=1启动了模块,再修改I2CPSC是无效的。这是一个常见的初始化顺序错误。正确的流程是:上电或复位后,IRS默认为0,此时配置I2CPSC、I2CCKH、I2CCKL等所有参数,最后再置位IRS=1启动模块。
- 频率误差与容差:从设备对SCL频率有一定容差,但主机应尽量配置在标准值(100k, 400k)。计算时使用整数分频,可能无法精确达到目标频率,只要误差在从设备允许范围内即可。例如,用50MHz输入时钟无法精确分频出100.000kHz,但计算出的99.8kHz通常是完全可接受的。
- 高低电平不对称配置:有些老式或特殊的从设备可能需要非对称的SCL时钟(如低电平时间更长以满足数据保持时间)。通过分别设置I2CCKH和I2CCKL,可以轻松实现。例如,确保低电平时间满足从设备的最小要求。
3. I2C数据格式:帧结构的语言艺术
时钟规定了通信的节奏,而数据格式则定义了对话的内容和顺序。I2C协议定义了几种不同的“句式”,以适应不同的寻址和数据传输需求。
3.1 数据有效性基础
在深入格式之前,必须牢记I2C数据有效性的黄金法则:SDA线上的数据必须在SCL为高电平期间保持稳定。数据线的状态只能在SCL为低电平期间改变。这意味着每一位数据的采样窗口都在SCL高电平的中点附近。任何在SCL高电平期间SDA的变化,都会被识别为起始条件或停止条件,而不是数据位。这是分析任何I2C波形时最基本的判断依据。
3.2 起始与停止条件:对话的起止符
这是I2C总线控制权的标志。
- 起始条件:当SCL为高电平时,SDA线上一个从高到低的跳变。它标志着一次传输的开始,并宣告主设备占据了总线。起始条件之后,总线状态寄存器中的BB位会被置1,表示总线忙。
- 停止条件:当SCL为高电平时,SDA线上一个从低到高的跳变。它标志着一次传输的终止,并释放总线控制权。停止条件之后,BB位被清零,总线空闲。
在代码中,我们通过设置模式寄存器I2CMDR的STT位来产生起始条件,设置STP位来产生停止条件。一个强大的特性是重复起始条件:在不停止总线(即不产生停止条件)的情况下,主设备可以再次产生一个起始条件,用于切换读写方向或寻址另一个从设备,而无需释放再重新竞争总线,提高了效率。
3.3 核心数据格式详解
I2C支持多种数据格式,核心区别在于地址字段的长度和含义。
3.3.1 7位寻址格式这是最常用、最经典的格式。起始条件后的第一个字节由7位从设备地址和1位读写方向位组成。
- 字节结构:[A6:A0] [R/W]。其中A6-A0是7位从机地址,R/W位为0表示主设备写(发送数据),为1表示主设备读(接收数据)。
- 后续流程:每个字节(8位数据)传输后,都会跟一个应答位。接收方(无论是主还是从)在第九个时钟周期将SDA拉低,表示应答。如果拉高,则为非应答。
- 配置方法:在I2CMDR寄存器中,设置XA=0(非扩展地址),FDF=0(非自由数据格式)。
3.3.2 10位寻址格式用于需要连接超过128个从设备的系统(7位地址空间为128个)。它通过两个字节来发送地址。
- 第一字节:固定为
11110 A9 A8 R/W。其中A9和A8是10位地址的最高两位。 - 第二字节:剩余的8位地址(A7-A0)。
- 特点:10位寻址向下兼容。一个7位地址的设备不会响应
11110xx开头的地址,因此可以混用。配置方法是设置I2CMDR寄存器的XA=1。
3.3.3 自由数据格式在这种格式下,起始条件后直接就是数据字节,没有地址字节。这要求通信双方预先约定好,且在整个传输过程中数据方向不变。它适用于点对点的、无需寻址的简单数据流传输。配置方法是设置I2CMDR寄存器的FDF=1。
3.3.4 数据字节长度一个容易忽略的细节是,I2C协议标准定义每个传输单元是8位数据加1位应答。但有些特定的I2C模块(如资料中提到的)支持可编程的数据位长度,通过BC字段可以设置为2到8位。这在与某些非标准设备通信时可能有用,但绝大多数标准外设都使用8位数据长度。
3.4 应答与非应答机制
应答是I2C保证数据可靠传输的关键机制。正常情况下,接收器在每字节后的第9个时钟周期发出低电平应答。但在某些情况下,需要发出非应答:
- 主设备读数据时:当主设备接收完最后一个字节数据后,应向从设备发送一个非应答,通知从设备停止发送,随后主设备产生停止条件。
- 从设备忙或出错:如果从设备无法处理数据,它可以在应答周期不回拉低SDA(即发出非应答),主设备应据此判断传输失败。
- 忽略非应答模式:有些从设备设计上可能无法发出正确的应答。主设备可以通过设置IGNACK位来忽略非应答,强制继续传输。但慎用此模式,因为它破坏了协议的可靠性保障,仅在确认从设备特性后使用。
在编程中,我们需要根据传输阶段和角色,妥善处理NACK。例如,在主机接收器模式下,当接收计数器减到0或我们想提前终止接收时,需要设置NACKMOD位或产生停止条件来发出非应答。
4. I2C操作模式:角色的切换与协作
I2C设备有四种基本操作模式,设备在通信过程中会在这几种模式间动态切换。理解这些模式,对于编写正确的状态机或中断服务程序至关重要。
4.1 主发送器模式
这是主设备的起始模式。主设备控制SCL,并主动向SDA发送起始条件、从机地址(写方向)以及后续的数据字节。
- 流程:启动后,主机将数据写入数据发送寄存器I2CDXR,硬件会自动将其加载到发送移位寄存器I2CXSR并逐位发出。每发送完一个字节,硬件会等待从机的应答。
- 关键状态位:
XSMT位。当发送缓冲区空时,此位为0,模块会拉低SCL以等待CPU或DMA填充下一个数据到I2CDXR。这是实现流控制的关键。 - 常见问题:在配置为双主传输的应用中,资料特别警告,必须在第一个传输的MST位和BB位都复位后,才能发起第二个传输。否则第二个传输的起始条件可能无法正确发出。实操建议:在第一个传输的停止条件产生后,不要仅仅轮询BB位变为0,最好也检查MST位是否已清零,或等待一个足够长的延时(如几个I2C位时间),确保状态完全切换。
4.2 主接收器模式
主设备控制SCL,但从SDA线读取数据。进入此模式的前提是,主设备先以发送器模式发出从机地址,且R/W位为1。
- 流程:地址和R/W位发送并收到应答后,主设备释放SDA线(输出高阻),并开始产生时钟。从设备则在每个时钟周期将数据位放到SDA上。主设备在SCL高电平期间采样SDA。
- 关键状态位:
RSFULL位。当接收移位寄存器I2CRSR的数据已满并拷贝到数据接收寄存器I2CDRR后,此位置1,模块会拉低SCL,等待CPU或DMA读取I2CDRR,防止数据溢出。 - 重复模式:当主设备不知道要接收多少字节数据时(数据长度由后续数据包定义),需要使用重复模式。设置RM=1,并在读取完倒数第二个数据后,手动设置STP=1产生停止条件。这是因为接收缓冲区是双缓冲的,需要提前通知。
4.3 从发送器与从接收器模式
从设备模式相对被动,SCL由主设备控制。
- 从接收器:所有从设备上电后的初始模式。它持续监听总线上的地址。当收到与自身地址匹配且R/W=0的地址时,进入从接收器模式,准备接收主设备发来的数据。同样依赖RSFULL位进行流控。
- 从发送器:当从设备收到与自身地址匹配且R/W=1的地址时,进入从发送器模式。它将数据放入I2CDXR,由主设备的SCL时钟控制下逐位发出。依赖XSMT位进行流控。
从设备开发要点:从设备的代码核心是一个中断或轮询循环,不断检查AAS(被寻址为从机)中断标志,然后根据地址字节中的R/W位,切换到对应的发送或接收处理流程中。要妥善处理自身的流控(XSMT/RSFULL),避免拖慢主设备。
4.4 特殊操作模式
- 低功耗模式:当系统进入全局低功耗模式时,I2C模块的时钟被关闭,所有寄存器不可访问。这需要软件在进入低功耗前,确保没有正在进行的I2C传输。
- 自由运行模式:通过设置FREE位为1,当调试器遇到断点时,I2C模块可以继续运行而不挂起。这在调试与实时性相关的通信时非常有用,可以避免总线超时。如果FREE=0,则调试断点会令I2C模块在安全的状态下暂停(例如,在SCL为低时立即停止,为高时等待变低后停止)。
- 忽略NACK模式:如前所述,用于应对无法正常应答的非常规从设备。
5. 总线完整性与高级功能
多主系统是I2C的一大优势,但这引入了总线竞争问题。协议通过仲裁和时钟同步机制优雅地解决了这个问题。
5.1 仲裁机制
当两个或更多主设备同时发起传输时,仲裁开始。仲裁发生在SDA线上,遵循“线与”逻辑(低电平优先)。
- 过程:所有主设备同时发送起始条件和地址/数据位。只要某个主设备发送高电平‘1’,而另一个发送低电平‘0’,那么发送‘1’的主设备检测到SDA线实际为‘0’(被拉低了),就知道自己失去了仲裁,会立即释放总线,切换到从接收器模式,并设置
AL(仲裁丢失)中断标志。 - 关键点:仲裁比较的是整个数据流,从起始条件后的地址位开始,直到出现差异。这意味着发送地址值更小的设备拥有更高优先级。仲裁不会发生在起始条件、重复起始条件或停止条件与数据位之间。
5.2 时钟同步
在仲裁期间,多个主设备同时驱动SCL线。时钟同步机制确保总线能产生一个统一的SCL。
- 原理:同样基于“线与”。任何一个主设备将SCL拉低,都会导致整条SCL线变低。SCL的低电平周期由驱动低电平时间最长的主设备决定,高电平周期则由最快释放SCL(结束低电平)的主设备决定。这实际上让最快的设备去适应最慢的设备,实现了同步。
- 实际影响:这意味着你的主设备代码中,SCL低电平时间的配置(I2CCKL)决定了你在总线竞争中对低电平周期的“话语权”。如果你配置了很长的低电平时间,在仲裁中可能会拖慢其他主设备。
5.3 噪声滤波与引脚功能
对于工作在恶劣电气环境中的系统,I2C模块内部的噪声滤波器至关重要。它通常能抑制短于50ns的毛刺。这相当于在模块时钟为6.7-13.3MHz时,能过滤掉1个时钟周期左右的噪声。在软件上,我们无法配置滤波器宽度,但需要知晓其存在,在通信异常时,除了检查软件配置,也要考虑硬件上的信号完整性问题。
此外,I2C引脚通常可以复用为通用GPIO。通过I2CPFNC和I2CDIR等寄存器控制。一个关键的注意事项:如果你想使用I2C功能,务必确保将引脚配置为I2C功能模式,而不是GPIO模式,否则通信根本无法进行。在初始化序列中,配置引脚功能应放在配置I2C模块本身之前。
6. 中断与DMA事件:高效处理的引擎
对于CPU来说,不断轮询I2C状态寄存器是低效的。中断和DMA才是解放CPU、实现高效通信的利器。
6.1 七大中断类型及其应用场景
I2C模块提供了7个中断源,每个都有对应的标志位和使能位。合理使用它们可以构建健壮的驱动。
- ARDY(寄存器访问就绪):这是最常用、也最容易用错的中断。当CPU通过写I2CDXR、I2CSAR等寄存器下发命令后,硬件需要时间来处理这些命令(如发出地址、启动传输)。在此期间,软件不应再次写入这些寄存器。ARDY中断正是在“上一次编程的操作已完成,状态已更新,寄存器可再次访问”时触发。最佳实践:在中断服务程序中,清除ARDY标志,并准备下一次传输的数据或命令。在轮询方式中,则等待ARDY位置1。
- RXRDY(接收就绪):当接收移位寄存器中的数据已完整转移到数据接收寄存器I2CDRR中时触发。这是读取接收数据的信号。
- TXRDY(发送就绪):当数据发送寄存器I2CDXR中的数据已转移到发送移位寄存器I2CXSR,即I2CDXR已空,可以写入下一个待发送数据时触发。
- NACK(无应答):当主设备发送地址或数据后,未收到从设备的应答时触发。通常意味着从设备不存在、忙或出错,是错误处理的关键。
- AL(仲裁丢失):在多主系统中,本设备失去总线控制权时触发。处理程序通常应释放总线,等待重试。
- SCD(停止条件检测):检测到总线上出现停止条件时触发。可用于判断一次传输的结束。
- AAS(被寻址为从机):当总线上出现的地址与本设备从机地址匹配时触发。是从设备代码的入口点。
中断向量读取技巧:I2CIVR寄存器存储了当前最高优先级待处理中断的编码值。读取I2CIVR会自动清除AL、NACK、SCD这三个中断的标志位(如果它们被使能的话)。但AAS、ARDY、RXRDY、TXRDY的标志位不会通过读I2CIVR清除,必须通过向特定寄存器执行写操作或直接写1清除标志位的方式来手动清除。这一点务必查阅具体芯片的数据手册。
6.2 DMA事件的应用
对于大批量数据传输,使用DMA可以极大减轻CPU负担。I2C模块提供两个DMA事件:
- 接收事件:与RXRDY中断同步,通知DMA控制器从I2CDRR读取数据。
- 发送事件:与TXRDY中断同步,通知DMA控制器向I2CDXR写入数据。
配置DMA的要点:需要将DMA的触发源配置为对应的I2C事件。当DMA控制器响应事件进行读/写操作时,会同时自动清除RXRDY或TXRDY标志位,无需软件干预。
一个重要的警告:资料中提到,在10位地址、主发送、重复模式下,可能会在起始条件之后、地址第一位发出之前,产生一个“意外的”DMA发送事件。此时从机尚未应答地址,因此DMA不应据此启动传输。解决方案:在配置DMA时,应确保DMA传输的启动是由更可靠的条件触发,例如在ARDY中断确认地址已发送成功后,再启用DMA通道。
7. 配置、调试与问题排查实录
理论最终要服务于实践。下面我将结合一个典型的I2C主设备初始化与读写流程,穿插讲解调试中常见的坑和解决方法。
7.1 主设备初始化与单字节写入流程
假设我们要向一个I2C EEPROM(地址0x50)的0x00地址写入一个字节数据0xAB。
初始化步骤:
- 确保模块复位:检查或确保I2CMDR中的IRS位为0。
- 配置引脚功能:将SDA和SCL对应的引脚功能寄存器设置为I2C模式,而非GPIO。
- 配置时钟:根据输入时钟频率和目标SCL速率,计算并写入I2CPSC、I2CCKH、I2CCKL寄存器。
- 配置工作模式:设置I2CMDR寄存器。例如,设置主模式MST=1,选择7位地址XA=0,禁止自由数据格式FDF=0,设置数据位长度BC=8(如果支持)。
- 使能模块:将IRS位置1,启动I2C模块。
- 配置中断:如果需要,使能ARDY、NACK等中断。
单字节写入操作流程(轮询方式):
- 写入从机地址:将目标从机地址(0x50 << 1)与写位(0)组合,即0xA0,写入I2CSAR寄存器。
- 写入数据并启动传输:将待发送数据0xAB写入I2CDXR寄存器。然后,同时设置I2CMDR中的STT位(启动起始条件)和STP位(本次传输后产生停止条件)。这一步是关键,很多新手会忘记设置STP,导致总线无法释放。
- 等待ARDY:轮询等待ARDY标志置位。这表示地址和数据已处理,传输已完成或进入下一阶段。
- 检查错误:读取状态寄存器,检查NACK标志是否置位。如果置位,说明从机未应答,写入失败。
- 清除标志:清除ARDY标志,准备下一次操作。
7.2 常见问题排查速查表
| 现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
| 通信完全无响应,SCL/SDA一直为高 | 1. 模块未使能(IRS=0)。 2. 引脚功能配置错误(仍为GPIO)。 3. 总线未上拉。SCL/SDA线缺少上拉电阻。 | 1. 检查I2CMDR.IRS位是否为1。 2. 检查引脚复用控制寄存器,确认已配置为I2C功能。 3. 用示波器或万用表测量SCL/SDA线,应为高电平。若无,检查上拉电阻(通常4.7kΩ)是否焊接。 |
| 能发出起始条件,但地址无应答(NACK) | 1. 从机地址错误。 2. 从设备电源或复位不正常。 3. 总线电平不匹配(如3.3V主机与5V从机未做电平转换)。 4. SCL频率过快,从设备跟不上。 | 1. 用逻辑分析仪抓取波形,确认发送的地址字节是否正确(7位地址左移1位+R/W)。 2. 检查从设备电源、复位引脚。 3. 检查双方IO电平,必要时增加电平转换芯片。 4. 降低I2CCKH/I2CCKL值,减小SCL频率。 |
| 通信时好时坏,随机出错 | 1. 总线电容过大,导致上升沿太慢,违反时序。 2. 电源噪声干扰。 3. 中断服务程序处理太慢,导致超时。 | 1. 测量SCL/SDA上升时间。标准模式下应小于1us,快速模式下小于300ns。可减小上拉电阻值(如从4.7kΩ换为2.2kΩ),但需注意驱动能力。 2. 检查电源纹波,在VDD和地之间就近放置去耦电容。 3. 优化中断服务程序,或考虑使用DMA。检查是否因其他高优先级中断阻塞导致I2C中断响应延迟。 |
| 多主系统中频繁仲裁丢失 | 1. 本设备软件响应慢,在仲裁中发送‘1’而对方发送‘0’。 2. 时钟配置差异,导致本设备在仲裁期间拉低SCL时间过短。 | 1. 确保中断优先级足够高,及时处理TXRDY中断填充发送数据,避免因数据未就绪而发送‘1’。 2. 检查并可能调整I2CCKL值,确保在需要竞争总线时,有足够的低电平时间“坚持己见”。 |
| 使用DMA时数据错乱 | 1. DMA传输长度设置错误。 2. 未处理“意外DMA事件”问题(见于10位地址模式)。 3. DMA与CPU访问寄存器冲突。 | 1. 仔细核对DMA传输字节数,包括地址字节和数据字节。 2. 在10位地址主发送模式下,考虑在ARDY中断(确认地址发送成功)后再启动DMA传输,而非仅依赖TXRDY事件。 3. 确保DMA和CPU不会同时访问I2CDRR/I2CDXR。通常DMA使能后,CPU不应再操作这些寄存器。 |
7.3 调试工具与技巧
- 逻辑分析仪:这是调试I2C的必备神器。不仅能解码出地址、数据、起始/停止条件,还能精确测量SCL频率、高低电平时间、建立保持时间等关键参数。将抓取到的波形与协议标准对比,大部分问题都能一目了然。
- 软件模拟I2C:当硬件I2C模块出现难以排查的问题时,可以尝试用两个GPIO口模拟I2C时序。如果能通,则问题很可能出在硬件I2C模块的配置或芯片本身;如果也不通,则问题可能在外围电路或从设备。
- 分步测试法:先只配置时钟,用示波器看SCL引脚是否有正确频率的方波输出。再尝试发送一个地址,用逻辑分析仪看波形。逐步增加复杂度,隔离问题点。
- 关注复位状态:记住,修改I2CPSC等关键配置前,必须确保IRS=0。在程序跑飞或看门狗复位后,要重新完整执行初始化流程。