深入解析I2C从机寄存器组:从数据交换到中断与FIFO配置
1. I2C从机通信的核心:寄存器组概览与设计哲学
在嵌入式开发中,I2C总线因其简洁的两线制(SDA和SCL)和灵活的多主多从架构,成为了连接微控制器与各类传感器、存储器、IO扩展芯片的首选协议。当你需要让一个微控制器(比如TI的Tiva™系列)扮演从机角色,被动响应主机的读写请求时,深入理解其从机控制寄存器组就不再是“可选技能”,而是“必备内功”。这组寄存器,远不止是数据搬运的通道,它更像是一个精密的状态机与控制中枢,直接决定了从机响应的实时性、数据处理的效率以及整个通信链路的健壮性。
我们手头这份关于Tiva™ TM4C1294NCPDT的I2C从机寄存器手册,详细列出了从偏移地址0x808到0xFC4的一系列关键寄存器。乍看之下是枯燥的位域定义,但背后隐藏的是一套完整的从机通信解决方案。这套方案的核心思想可以概括为:状态感知、事件驱动、高效缓冲。寄存器被清晰地划分为几个功能模块:数据交换(I2CSDR, I2CFIFODATA)、中断管理(I2CSIMR, I2CSRIS, I2CSMIS, I2CSICR)、地址识别(I2CSOAR2)、应答控制(I2CSACKCTL)以及FIFO与DMA控制(I2CFIFOCTL, I2CFIFOSTATUS)。理解它们之间的联动关系,是编写出稳定、高效I2C从机驱动代码的关键。
对于嵌入式软件工程师而言,仅仅知道“这个位写1是使能中断”是远远不够的。我们必须追问:为什么需要这么多层次的中断状态寄存器(RIS, MIS)?FIFO触发阈值设置为多少才能平衡响应速度和CPU负载?在什么场景下应该使用DMA,什么场景下又应该用中断配合FIFO?这篇文章,我将结合多年的实际项目调试经验,为你层层剥开这些寄存器的设计奥秘,并分享从寄存器配置到代码实现的完整避坑指南。无论你是在调试一个I2C温湿度传感器,还是在设计一个复杂的多从机通信背板,这些细节都将决定项目的成败。
2. 数据交换核心:I2CSDR与I2CFIFODATA的抉择与陷阱
数据寄存器是I2C通信的起点和终点。Tiva™的I2C从机模块提供了两条数据路径:传统的单字节数据寄存器(I2CSDR)和基于FIFO的数据寄存器(I2CFIFODATA)。选择哪条路径,是第一个关键决策。
2.1 I2C Slave Data Register (I2CSDR):简单场景的直通车
I2CSDR寄存器位于偏移地址0x808,是一个可读可写的32位寄存器,但只有低8位(DATA[7:0])有效。它的行为模式完全取决于I2C从机的状态(由硬件自动切换)以及FIFO的使能状态。
当从机控制状态寄存器(I2CSCSR)中的RXFIFO或TXFIFO位被禁用(即为0)时,I2CSDR是数据交换的唯一窗口。在从机接收状态下,主机发送的每一个字节都会在接收完成后,自动更新到I2CSDR的DATA字段,同时置位相应的原始中断状态位(例如DATARIS)。此时,你的中断服务程序需要尽快读取I2CSDR以获取数据,并为接收下一个字节做好准备。在从机发送状态下,当主机发起读请求并发送时钟时,从机硬件会自动将I2CSDR中DATA字段的当前值移出到SDA线上。因此,你必须在主机读取操作发生前,将待发送的数据预先写入I2CSDR。
这里有一个极其重要的细节,手册用“Important”和“Note”双重强调:I2CSDR是一个读敏感(read-sensitive)寄存器。在某些架构的I2C模块中,读取I2CSDR这个动作本身,可能会清除某些内部状态标志或触发下一轮数据传输的准备工作。虽然Tiva™手册没有明确说明读取I2CSDR的具体副作用,但最佳实践是,在中断服务程序中,一旦确定是因为数据就绪中断而进入,就应该立即读取I2CSDR,避免后续操作被不可预知的硬件行为影响。
避坑指南:I2CSDR的“一次性”与“实时性”在非FIFO模式下,
I2CSDR本质上是一个单字节缓冲区。这意味着:
- 数据覆盖风险:在从机接收时,如果上一个字节还未被CPU读取,主机又发送了下一个字节,新数据会覆盖旧数据,导致丢包。你必须确保中断响应足够快,或者在轮询模式下保证足够的查询频率。
- 发送准备时机:在从机发送时,你写入
I2CSDR的数据就是下一个时钟周期将要发送的数据。如果写入太晚,总线可能会读出无效数据(通常是旧值或0xFF);如果写入过早,又可能被其他意外操作修改。可靠的作法是在收到主机读请求的起始信号(START中断)或上一个字节发送完成后的DATA中断中,立即写入下一个要发送的字节到I2CSDR。
2.2 I2C FIFO Data Register (I2CFIFODATA):吞吐量与性能的保障
当I2CSCSR寄存器中的RXFIFO或TXFIFO位被使能后,数据交换的重心就转移到了I2CFIFODATA寄存器(偏移0xF00)。这是一个非常有趣的寄存器,它拥有两个不同的物理视图:读操作时,它映射到RX FIFO的栈顶;写操作时,它映射到TX FIFO的栈顶。这种设计巧妙地用同一个地址空间,管理了两个独立的数据流。
对于接收(RX):使能RXFIFO后,主机发送来的数据字节将不再进入I2CSDR,而是被硬件自动压入一个深度为8字节的RX FIFO。当你读取I2CFIFODATA时,你读取的是FIFO中最早进入的那个字节(先进先出),读取操作会自动将下一个字节移到栈顶。你可以通过I2CFIFOSTATUS寄存器实时查询FIFO中的数据量(RXFE空,RXFF满,RXABVTRIG高于触发阈值)。
对于发送(TX):使能TXFIFO后,你需要发送的数据不再写入I2CSDR,而是写入I2CFIFODATA。写入的数据会被压入TX FIFO队列。当主机发起读操作并产生时钟时,硬件自动从TX FIFO的队首取出一个字节发送出去。同样,你可以通过I2CFIFOSTATUS寄存器查询TX FIFO的状态(TXFE空,TXFF满,TXBLWTRIG低于触发阈值)。
使用FIFO的最大优势在于解耦和批处理。它允许CPU在一次性中断中处理多个数据字节(例如,读取RX FIFO中积压的4个字节),或者预先装载多个待发送字节到TX FIFO,从而大幅减少中断频率,提升系统效率,尤其适合连续块数据传输。
致命陷阱:数据路径的不可逆切换手册在
I2CSDR和I2CFIFODATA的描述中,都用“Note”郑重警告:“应用程序不应在连续的事务处理中,在I2CSDR寄存器与TX FIFO之间切换,反之亦然。”这是什么意思?假设你的从机需要先响应一个主机读请求(发送数据),然后紧接着响应一个主机写请求(接收数据)。如果你在第一个事务(发送)中使用了TX FIFO模式(向I2CFIFODATA写数据),而在第二个事务(接收)中却想切换回非FIFO模式(从I2CSDR读数据),这种操作是不被推荐且可能导致未定义行为的。 硬件内部的数据路径和状态机可能无法在极短的总线周期内完成这种模式的动态切换。正确的做法是,在从机初始化阶段,就根据应用的数据流特征,确定好是使用FIFO模式还是非FIFO模式,并在整个设备运行期间保持该模式不变。如果应用场景复杂,必须切换,也应在总线空闲期(无START信号)进行,并做好充分的寄存器重新配置和FIFO刷新(Flush)操作。
3. 中断系统的精密控制:从屏蔽、状态到清除
I2C从机的中断系统是一个典型的三级流水线:原始状态 -> 屏蔽控制 -> 有效状态 -> 清除操作。理解这套流程,是编写稳定中断服务程序(ISR)的基础。相关寄存器包括:I2CSIMR(中断屏蔽)、I2CSRIS(原始中断状态)、I2CSMIS(被屏蔽后的有效中断状态)和I2CSICR(中断清除)。
3.1 中断源与原始状态寄存器 (I2CSRIS)
I2CSRIS寄存器是中断系统的“传感器”。它实时反映了硬件内部发生的各种事件,无论你是否关心这些事件。其位域清晰地反映了从机通信的整个生命周期:
DATARIS(位0):数据中断。这是一个“总括性”中断,在从机接收或发送完一个字节数据(非FIFO模式),或需要进行下一字节操作时触发。在FIFO模式下,它的行为可能变化,需参考具体手册。STARTRIS(位1) /STOPRIS(位2):起始/停止条件中断。检测到总线上的START或STOP信号时置位。这对于识别一次完整I2C传输帧的开始与结束至关重要,常用于重置内部状态机或准备新的数据缓冲区。DMARXRIS(位3) /DMATXRIS(位4):DMA传输完成中断。当使能DMA且一次DMA传输完成时置位。TXRIS(位5) /RXRIS(位6):TX/RX FIFO请求中断。这是FIFO模式下的核心中断。当TX FIFO中的数据量低于TXTRIG设定的阈值,或RX FIFO中的数据量高于RXTRIG设定的阈值时置位。用于通知CPU该向TX FIFO填充数据,或从RX FIFO取走数据了。TXFERIS(位7) /RXFFRIS(位8):TX FIFO空 / RX FIFO满中断。当FIFO达到空或满的极端状态时置位,通常作为FIFO请求中断的补充或告警。
这些RIS位是只读的,并且只能通过向I2CSICR寄存器对应的位写1来清除。简单地读取I2CSRIS寄存器不会清除任何标志。
3.2 中断屏蔽寄存器 (I2CSIMR) 与有效状态寄存器 (I2CSMIS)
不是所有原始中断都需要CPU立即处理。I2CSIMR寄存器就是你的“兴趣过滤器”。将I2CSIMR中的某个位置1,意味着你允许对应的原始中断(RIS)升级为一个能触发CPU中断控制器的“有效中断”。
I2CSMIS寄存器则是这个过滤结果的直观展示。它等于I2CSRIS & I2CSIMR。只有当某个中断事件发生(RIS=1)并且你使能了它的屏蔽位(IMR=1),它在MIS寄存器中的对应位才会是1。你的中断服务程序在入口处,应该首先读取I2CSMIS寄存器,而不是I2CSRIS,以快速确定究竟是哪个已使能的中断源触发了本次调用。
这种设计带来了极大的灵活性。例如,在初始化阶段,你可能只使能STARTRIS和STOPRIS来跟踪传输边界。在数据阶段,再使能DATARIS或TXRIS/RXRIS。在DMA传输时,则使能DMARXRIS或DMATXRIS。通过动态配置I2CSIMR,可以实现精细化的中断管理,避免不必要的CPU打扰。
3.3 中断清除寄存器 (I2CSICR) 与清除时序
I2CSICR是一个只写寄存器。向它的某个位写1,会同时清除I2CSRIS和I2CSMIS寄存器中的对应位。这是清除中断标志的唯一正确方式。
这里有一个关键时序问题:必须先处理中断事件,再清除中断标志。一个常见的错误流程是:进入ISR -> 立即清除标志 -> 然后处理数据(如读取FIFO)。在高速或临界情况下,这可能导致问题。因为在清除标志后、处理完成前,如果硬件又产生了同一个中断事件(例如,FIFO又达到了触发条件),这个新事件会立即置位RIS。但由于你刚刚清除了标志,并且正在ISR中,这个新事件可能无法立即触发新的中断(取决于中断控制器是边沿触发还是电平触发),从而导致事件被遗漏。
最佳实践:ISR内的安全操作序列
- 读取并保存状态:进入ISR后,首先读取
I2CSMIS的值,保存到局部变量mis_status。- 处理事件:根据
mis_status的位,执行相应的操作。例如,如果RXMIS为1,则循环读取I2CFIFODATA直到RX FIFO为空或低于阈值。- 清除标志:在处理完所有待处理事件后,根据之前保存的
mis_status,向I2CSICR的相应位写1以清除标志。注意,I2CSICR的写入通常具有“写1清除”的特性,直接写入mis_status的值即可。- 特别注意事项:对于
TXFERIS(TX FIFO空)中断,手册特别注明:如果在TX FIFO为空时清除了此中断,即使TX FIFO之后仍然为空,该中断也不会再次断言。这意味着你不能依赖“空中断”来持续触发填充操作。更常见的做法是使用TXRIS(TX FIFO请求中断),并设置一个合理的TXTRIG阈值(例如≤4),在FIFO空间充裕时提前请求CPU填充。
4. FIFO与DMA的协同:实现零拷贝高速数据流
对于需要传输大量数据的I2C从机应用(例如作为数据采集器的从机,需要向上位机发送大量采样数据),频繁的字节级中断会消耗大量CPU资源。此时,FIFO与DMA的协同工作模式就成为提升性能的利器。
4.1 FIFO控制寄存器 (I2CFIFOCTL) 的配置策略
I2CFIFOCTL寄存器(偏移0xF04)是FIFO和DMA功能的总开关,其复位值为0x0004.0004,暗示了默认的触发阈值是4。
TXASGNMT/RXASGNMT(位15/31):FIFO分配。对于纯从机应用,这两个位都应设置为1,将TX和RX FIFO都分配给从机模块使用。TXTRIG/RXTRIG(位[2:0]/[18:16]):触发阈值。这是配置的核心,决定了中断产生的“节奏”。TXTRIG:当TX FIFO中剩余的数据字节数小于或等于此阈值时,TXRIS中断被置位。例如,设置TXTRIG=2,当TX FIFO中只剩2个或更少字节待发送时,就会产生中断,提醒你该补充数据了。这给了CPU一段缓冲时间去准备数据,避免FIFO完全排空导致总线时钟被拉低等待(Clock Stretching,如果支持的话)。RXTRIG:当RX FIFO中已存入的数据字节数大于此阈值时,RXRIS中断被置位。例如,设置RXTRIG=6,当RX FIFO接收到第7个字节时产生中断。这样你可以一次读取多个字节(最多8个),减少中断次数。- 阈值选择经验:阈值的设置需要在中断响应延迟和单次中断处理量之间权衡。对于低优先级、数据量大的任务,可以设置较高的
RXTRIG(如6)和较低的TXTRIG(如1),以减少中断频率。对于要求实时响应的任务,则设置较低的RXTRIG(如1)和较高的TXTRIG(如6),让CPU更早介入。
DMATXENA/DMARXENA(位13/29):DMA通道使能。置1后,当FIFO达到触发条件时,将产生DMA请求,而非CPU中断。TXFLUSH/RXFLUSH(位14/30):FIFO刷新。写1可立即清空对应的FIFO。该位会自清除。在初始化或通信协议切换时,刷新FIFO是一个好习惯,可以确保从一个干净的状态开始。
4.2 配合DMA实现自动数据搬运
使能DMA后,I2C从机模块将与芯片的DMA控制器联动。以接收数据(DMA RX)为例:
- 配置DMA控制器:设置源地址为
I2CFIFODATA寄存器地址,目标地址为内存中的缓冲区,传输宽度为字节,并启用外设到存储器的传输模式。 - 配置
I2CFIFOCTL:使能DMARXENA,设置RXTRIG(例如=4)。 - 当主机发送数据,使得RX FIFO中的数据量超过
RXTRIG阈值时,I2C模块会向DMA控制器发出请求。 - DMA控制器响应请求,自动从
I2CFIFODATA读取一个字节(或按配置的突发长度)写入内存。这个过程完全不需要CPU干预。 - 当DMA完成预设的数据块传输(例如传输了128个��节)后,会触发
DMARXRIS中断。此时CPU进入中断服务程序,只需要处理“一批数据已就绪”这个事件,进行后续的数据处理或缓冲区切换即可。
这种“FIFO + DMA”的模式,几乎将CPU从繁重的数据搬运工作中解放出来,实现了接近“零拷贝”的高效数据传输,特别适合音频流、图像数据块等场景。
调试心得:FIFO状态寄存器 (I2CFIFOSTATUS) 的妙用
I2CFIFOSTATUS寄存器(偏移0xF08)提供了FIFO的实时快照。在调试FIFO相关问题时,它比任何仿真工具都直观。
TXFE/RXFE: 快速判断FIFO是否为空。在发送前检查TXFE,在读取前检查RXFE,可以避免无效操作。TXFF/RXFF: 判断FIFO是否已满。在向TX FIFO写入数据前检查TXFF,可以防止数据丢失;在主机持续发送时监控RXFF,可以判断是否因CPU处理不及时导致数据溢出。TXBLWTRIG/RXABVTRIG: 直接反映了当前FIFO深度与触发阈值的关系。当你怀疑中断为什么没产生时,首先查看这两个位,结合TXTRIG/RXTRIG的配置,就能立刻明白原因。 在编写FIFO操作函数时,养成加入状态检查的习惯,能极大增强代码的健壮性。例如,一个安全的TX FIFO填充函数应该先检查TXFF,如果为1则等待或返回错误;否则持续写入数据直到TXBLWTRIG变为0(表示数据量已高于阈值,无需立即再填)。
5. 高级控制与配置:地址、应答与模块属性
除了核心的数据和中断控制,剩下的几个寄存器负责更底层的通信协议控制和模块功能配置。
5.1 从机地址与应答控制
- I2C Slave Own Address 2 (I2CSOAR2): 这个寄存器允许从机响应第二个I2C地址。
OAR2[6:0]存放7位从机地址(注意,I2C地址通常是7位,存放在字节的低7位,最高位是读写位)。OAR2EN位用于使能这个备用地址。这在需要让一个物理设备扮演两个逻辑从机时非常有用,例如,一个EEPROM芯片可能用地址0x50响应数据读写,用地址0x51响应命令写入。 - I2C Slave ACK Control (I2CSACKCTL): 这是一个非常强大的低级控制寄存器。在标准I2C协议中,从机在接收到每个字节后,必须发出一个应答(ACK)或非应答(NACK)信号。通常这个行为是硬件自动完成的。但
I2CSACKCTL寄存器允许软件覆盖这一行为。ACKOEN(应答覆盖使能): 置1后,从机的应答信号将由ACKOVAL位的值决定,而非内部自动生成。ACKOVAL: 0表示发送ACK,1表示发送NACK。应用场景:1)数据校验:当从机作为接收方,发现接收到的数据包CRC校验错误时,可以在最后一个数据字节后的应答周期,通过软件置ACKOVAL=1来发送NACK,告知主机数据无效。2)流控制:如果从机的接收缓冲区已满,可以通过发送NACK来通知主机暂停发送。手册中提到“I2C时钟在最后一个数据位后被拉低,直到此寄存器被写入”,这意味着你必须在应答时钟周期到来前的极短时间内完成对此寄存器的写入操作,通常这需要在DATARIS中断中立即判断并处理。
5.2 模块属性与配置
- I2C Peripheral Properties (I2CPP): 这是一个只读寄存器,用于查询硬件能力。目前仅
HS位有意义。如果HS位为1,表示该I2C模块支持高速模式(High-Speed mode, 最高3.4 Mbps)。这对于需要高速传输的应用选型很重要。 - I2C Peripheral Configuration (I2CPC): 这是一个可写寄存器,用于配置模块的工作模式。同样,目前主要关注
HS位。重要警告:只有I2CPP.HS读为1时,你才能将I2CPC.HS写为1来启用高速模式。如果硬件不支持而强行启用,通信必然失败。
6. 实战配置流程与常见问题排查
理解了每个寄存器后,让我们串联起来,看一个典型的I2C从机初始化与数据收发流程,并附上常见问题的排查思路。
6.1 从机初始化配置步骤
- 使能时钟与引脚配置:首先使能对应I2C模块的系统时钟,并将SCL和SDA引脚配置为I2C复用功能,并使能上拉电阻(通常I2C总线需要上拉)。
- 禁用模块进行配置:将
I2CMCR(主控寄存器)的I2CEN位清零,确保在配置过程中模块处于复位状态。 - 配置时钟参数:虽然是从机,但某些模块的时钟分频器可能仍需配置以满足内部时序要求。配置
I2CMTPR或I2CMCLKOCNT等寄存器(具体取决于型号)。 - 配置从机地址:将主7位从机地址写入
I2CSOAR寄存器。如果需要备用地址,则配置I2CSOAR2。 - 配置FIFO与中断:
- 根据应用需求,决定是否使用FIFO。如果使用,配置
I2CFIFOCTL:设置TXASGNMT和RXASGNMT为1,设置TXTRIG和RXTRIG阈值,如果需要DMA则使能DMATXENA/DMARXENA。 - 配置
I2CSIMR(中断屏蔽寄存器)。例如,如果使用FIFO接收,则使能RXIM;如果使用FIFO发送,则使能TXIM;通常也会使能STOPIM以知道一次传输结束。暂时禁用不需要的中断源。
- 根据应用需求,决定是否使用FIFO。如果使用,配置
- 使能模块与中断:将
I2CMCR.I2CEN位置1使能I2C模块。最后,在芯片的NVIC(嵌套向量中断控制器)中使能对应的I2C中断。
6.2 数据收发流程示例(基于FIFO和中断)
场景:从机需要接收来自主机的一串命令数据,处理后再发送回复数据。
- 初始化:如上所述,使能
RXIM,TXIM,STOPIM。设置RXTRIG=4,TXTRIG=2。 - 接收数据(中断服务程序):
- 中断发生,ISR读取
I2CSMIS,发现RXMIS=1。 - 循环读取
I2CFIFODATA寄存器,将数据存入软件缓冲区,直到I2CFIFOSTATUS.RXFE变为1(FIFO空)。 - 向
I2CSICR寄存器的RXIC位写1,清除中断标志。 - 如果
STOPMIS也为1,说明本次传输结束,可以处理接收到的完整命令包,并准备回复数据。清除STOPIC标志。
- 中断发生,ISR读取
- 发送数据(主程序或另一个ISR):
- 将处理好的回复数据,写入
I2CFIFODATA。可以一次性写入多个字节,但需注意不要超过8字节深度,且要避免在TXFF为1(FIFO满)时写入。 - 硬件会在主机发起读请求时,自动从TX FIFO中取出数据发送。
- 当TX FIFO数据量低于阈值2时,会触发
TXIM中断。在TXIM的ISR中,继续补充数据到TX FIFO,直到所有回复数据发送完毕。
- 将处理好的回复数据,写入
6.3 常见问题排查表
| 现象 | 可能原因 | 排查步骤与解决方法 |
|---|---|---|
| 从机无应答(主机收NACK) | 1. 从机地址配置错误。 2. 从机模块未使能( I2CEN=0)。3. 从机正处于复位或低功耗状态。 4. 总线SCL/SDA引脚配置错误或上拉电阻缺失。 | 1. 用逻辑分析仪抓取总线波形,核对主机发送的地址与I2CSOAR设置是否一致。2. 检查 I2CMCR.I2CEN位。3. 检查系统时钟和低功耗模式配置。 4. 检查引脚复用配置,测量总线电压,确认上拉有效。 |
| 能收到地址应答,但数据收发失败 | 1. 数据路径配置冲突(混合使用I2CSDR和FIFO)。 2. 中断标志未正确清除,阻塞后续中断。 3. FIFO触发阈值设置不合理,导致中断不产生或产生过频。 4. 从机应答控制( I2CSACKCTL)被意外修改。 | 1. 严格遵守手册,不要在事务中切换数据路径。统一使用FIFO或非FIFO模式。 2. 在ISR中,确保在处理完事件后,向 I2CSICR正确写1清除标志。3. 调整 TXTRIG/RXTRIG值,并通过I2CFIFOSTATUS观察FIFO状态与触发位的变化。4. 检查代码,确保没有在不当的时候写 I2CSACKCTL寄存器。 |
| 数据传输速度慢,CPU占用高 | 1. 使用非FIFO模式,每个字节都产生中断。 2. FIFO阈值设置过小,中断过于频繁。 3. ISR处理逻辑���于复杂或存在阻塞。 | 1. 启用FIFO功能。 2. 增大 RXTRIG,减小TXTRIG(根据角色调整),让单次中断处理更多数据。3. 优化ISR:只做最必要的数据搬运和标志清除,将复杂处理放到主循环中。考虑使用DMA。 |
| 使用DMA时数据错乱或丢失 | 1. DMA源/目标地址、传输长度配置错误。 2. DMA传输完成中断处理不当,未及时切换缓冲区或重新配置DMA。 3. I2C的DMA使能位( DMARXENA/DMATXENA)与DMA控制器通道未同时正确使能。 | 1. 仔细核对DMA配置,特别是地址对齐和传输宽度(应为字节)。 2. 在DMA完成中断中,必须正确清除I2C的 DMARXRIS/DMATXRIS标志,并准备好下一块数据的DMA传输。3. 确保I2C模块和DMA控制器的使能顺序正确,通常先配置DMA,最后使能I2C的DMA控制位。 |
| 只能收发一次数据,后续失败 | 1. 在STOP中断中未正确重置内部状态或缓冲区索引。 2. FIFO在多次传输间未正确刷新,残留旧数据。 3. 中断标志“挂起”,导致后续中断无法进入。 | 1. 在STOPIM中断处理中,重置软件状态机,准备下一次传输。2. 在每次传输开始前或STOP中断中,考虑使用 TXFLUSH/RXFLUSH清除FIFO。3. 检查 I2CSRIS和I2CSMIS寄存器,确认是否有未清除的旧标志。确保ISR能执行到清除操作(未被意外提前退出)。 |
调试I2C从机,最强大的工具是逻辑分析仪。通过抓取SCL和SDA的实际波形,可以清晰地看到起始信号、地址、读写位、每个数据位、应答位以及停止信号。将波形与你的软件逻辑(寄存器状态、中断触发点)对照分析,绝大多数问题都能迎刃而解。记住,寄存器是软件与硬件对话的窗口,而波形则是硬件世界真实的语言。