深入解析I2C总线:时钟同步、仲裁机制与中断处理实战
2026/7/19 14:18:35 网站建设 项目流程

1. 项目概述与I2C总线核心价值

在嵌入式系统开发中,设备间的通信是构建复杂功能的基础。面对GPIO点对点通信的繁琐、SPI多线制的硬件开销以及UART异步通信的不可靠性,I2C总线以其简洁的两线制(SDA和SCL)和优雅的多主多从架构脱颖而出,成为连接微控制器与传感器、存储器、IO扩展器等外设的首选协议之一。我接触过不少项目,从简单的温湿度传感器读取到复杂的多板卡管理系统,I2C的身影无处不在。它的魅力不仅在于硬件连接的简化,更在于其协议层设计的精巧——特别是时钟同步仲裁机制,这两大特性是I2C总线在多主环境下实现“礼貌”且无冲突通信的基石。而深入理解模块的中断处理逻辑,则是编写高效、稳定驱动代码,避免数据丢失或总线锁死的必修课。

本文旨在超越简单的“如何配置寄存器”的层面,结合TI TMS320F28003x等微控制器中I2C模块的具体实现,深入剖析时钟同步与仲裁的工作细节,并拆解中断系统的运作方式。无论你是正在调试一个I2C通信不稳定问题的工程师,还是希望从原理层面夯实基础的学习者,这篇文章都将带你从信号线的微观变化,到状态寄存器的比特翻转,完整地走一遍I2C核心机制的实现路径。我们会看到,一个稳定的I2C通信背后,是硬件对协议严格且智能的守护。

2. I2C时钟同步机制:多主环境下的“心跳”协调

在单主设备系统中,时钟由主设备独家提供,一切井然有序。但I2C总线允许多个主设备,这就带来了一个根本性问题:如果两个主设备同时开始传输,它们的时钟频率可能不同,如何保证所有设备能在同一个节奏下“听”和“说”?这就是时钟同步要解决的问题。它不是简单地选择一个时钟源,而是通过硬件连线实现一种动态的、民主的协调机制。

2.1 “线与”逻辑:同步的物理基础

I2C总线的SCL和SDA线都采用开源输出结构,通过上拉电阻连接到正电源。这意味着任何设备都可以通过将线路拉至低电平来驱动它,而释放线路(输出高阻态)则靠上拉电阻将其恢复为高电平。这种结构天然实现了“线与”(Wired-AND)功能:只要有一个设备输出低电平,整条线就是低电平;只有当所有设备都输出高阻态时,线才是高电平。

时钟同步正是利用SCL线的“线与”特性实现的。想象一下,两个主设备(Master A和Master B)同时开始传输。它们各自内部都有一个时钟发生器,产生自己的SCL信号。在总线空闲时,SCL被上拉为高电平。当任一主设备开始传输,它首先会拉低SCL,启动一个时钟低电平周期。

2.2 同步过程详解:低电平的“霸权”与高电平的“谦让”

图26-14(在原始资料中)完美诠释了这一过程。我们假设Master A的时钟低电平周期较长,Master B的较短。

  1. 高到低的过渡(启动低周期):无论哪个主设备先拉低SCL,由于“线与”特性,总线SCL线会立刻变为低电平。此时,其他所有主设备检测到SCL线被外部拉低(尽管不是自己所为),会强制启动自己内部的低电平周期计时器。这就是“低电平霸权”——谁先拉低,谁就为所有设备开启了低电平周期。
  2. 低电平保持(最长者决定):所有设备的低电平周期同时开始,但结束时间不同。Master B的低电平周期先结束,它试图释放SCL线(输出高阻态,期望线变高)。然而,只要Master A还在保持其低电平输出,SCL线就被Master A牢牢地拉在低电平。Master B只能进入等待状态,直到检测到SCL线被释放为高电平。因此,低电平周期的实际长度由所有竞争主设备中低电平周期最长的那一个决定
  3. 高电平开始(最快者决定):当最后一个设备(Master A)结束其低电平周期并释放SCL线后,所有设备几乎同时检测到SCL线变为高电平(由上拉电阻实现)。此时,每个设备开始自己的高电平周期计时。第一个结束高电平周期并试图拉低SCL的设备,将开启下一个低电平周期。因此,高电平周期的长度由所有竞争主设备中高电平周期最短的那一个决定

最终,总线上的SCL信号是一个所有参与主设备时钟信号的“合成体”,其低电平由最慢的设备决定,高电平由最快的设备决定。这个过程在每个时钟周期动态发生,实现了无缝同步。

注意:这种同步机制有一个非常重要的副作用——时钟拉伸。当一个从设备(Slave)需要更多时间处理数据(例如,从缓冲区读取或准备下一个字节)时,它可以在应答位(ACK)或数据位期间主动拉低SCL线。此时,即便是主设备,也必须等待SCL线被释放后才能继续后续的时钟脉冲。这是从设备控制通信节奏、防止数据过冲的关键手段,在驱动程序中必须妥善处理。

2.3 同步机制的技术价值与实现考量

这种硬件实现的同步机制,其价值在于完全去中心化,无需额外的协调信号或复杂的软件协议。它允许不同速度的设备(例如,一个100kHz的主设备和一个400kHz的主设备)安全地共享总线。在软件实现上,这意味着我们的驱动程序无需关心总线上其他主设备的时钟速度,硬件已经为我们处理好了时序兼容性问题。

然而,在配置微控制器的I2C模块时钟分频器(如I2CCLKLI2CCLKH寄存器)时,我们必须意识到,我们设置的是本设备作为主设备时期望产生的时钟高低电平时间。一旦进入仲裁状态,实际的时钟周期可能会被其他设备拉长(低电平)或缩短(高电平)。因此,在超时处理的设计中,不能仅仅依赖基于本地时钟周期的严格计时,必须结合总线状态(如BB位)进行判断。

3. 仲裁机制:数据线上的“比大小”游戏

时钟同步解决了“步调一致”的问题,但还没有解决“谁先说”的问题。当两个或更多主设备几乎同时发起传输时,仲裁机制负责优雅地决定哪一个获得总线控制权,而不会导致数据冲突。仲裁发生在SDA数据线上,过程同样基于“线与”逻辑。

3.1 仲裁过程:比特级的竞争与退出

仲裁的核心原则是:总线上的实际电平与某个主设备发送的电平不一致时,该设备即仲裁失败。由于“线与”特性,只有当所有发送高电平的设备才会使总线呈现高电平;只要有一个设备发送低电平,总线就是低电平。

如图26-15所示,假设Master A和Master B同时开始发送起始条件(S),然后发送从设备地址和数据。我们跟踪前几个比特:

  1. 两个主设备都发送起始条件(SDA由高变低),总线电平与两者输出一致,仲裁继续。
  2. 假设它们发送的地址字节第一位都是1(高电平),总线为高,仲裁继续。
  3. 关键点出现在某个比特位。假设Master A要发送1(释放SDA为高),而Master B要发送0(拉低SDA)。Master A在输出高电平后,会回读SDA线电平,发现自己输出的是1,但总线实际电平是0(被Master B拉低了)。一旦检测到这种不一致,Master A立即知道自己仲裁失败。
  4. 仲裁失败的主设备(Master A)必须立即关闭其SDA输出驱动器,切换到仅接收模式(即变为从设备-接收器),并停止驱动SCL线。同时,它需要设置仲裁丢失标志(ARBL),并通常会产生一个仲裁丢失中断(ARBLINT),以便软件及时处理。
  5. 赢得仲裁的主设备(Master B)完全察觉不到任何冲突,继续完成整个传输过程。

仲裁会逐比特进行,直到一个设备胜出。如果两个主设备发送的地址字节完全相同,则仲裁会延续到后续的数据字节,直到出现不同的比特为止。这保证了发送二进制数值更小(即更多低电平0)的数据流具有更高的优先级。

3.2 仲裁的边界与特殊规则

仲裁并非在所有时刻都有效。原始资料明确指出,仲裁不允许在以下情况之间进行:

  • 重复起始条件(Repeated START)与数据位之间:重复起始条件有固定的格式,不能与数据位仲裁。
  • 停止条件(STOP)与数据位之间:停止条件也有固定格式。
  • 重复起始条件与停止条件之间:这是两个不同的控制序列,不能仲裁。

这意味着,如果一个主设备发送重复起始条件,而另一个发送停止条件或数据位,不会触发标准的比特仲裁,可能导致总线状态混乱。因此,协议要求所有参与竞争的主设备必须在格式帧的相同位置发送重复起始条件或停止条件。这通常意味着它们需要遵循相同的数据帧结构,仲裁机制才能正确工作。

3.3 仲裁失败后的软件处理

当我们的设备(配置为主发送器)仲裁失败时,硬件会自动完成几件事:清除主模式位(MST)和停止条件位(STP),将模块切换为从接收器模式,并设置状态寄存器中的ARBL标志。此时,软件在中断服务程序或轮询中检测到ARBL,应采取以下行动:

  1. 清除中断标志:通过向ARBL位写1或读取中断源寄存器I2CISRC来清除标志。
  2. 重置或重新配置模块:由于状态已改变,通常最安全的做法是将模块复位(设置IRS=0再置1),或者根据新的从模式重新检查配置。
  3. 可能的恢复策略:根据应用需求,可以选择等待总线空闲(BB=0)后重新发起传输。更复杂的系统可能需要实现一个退避算法,随机等待一段时间再重试,以减少再次冲突的概率。
// 示例:仲裁丢失中断服务例程中的处理片段 __interrupt void i2cArbLostIsr(void) { // 1. 读取中断源以清除仲裁丢失标志(可选,也可直接写I2CSTR) volatile uint16_t intSource = I2caRegs.I2CISRC.bit.INTCODE; // 2. 确认是仲裁丢失中断 if(intSource == 1) // INTCODE = 1 表示仲裁丢失 { // 3. 可选:记录错误或进行诊断 arbLostCount++; // 4. 复位I2C模块以恢复到已知状态(推荐做法) I2caRegs.I2CMDR.bit.IRS = 0; // 复位模块 DELAY_US(10); // 短暂延时 I2caRegs.I2CMDR.bit.IRS = 1; // 重新使能模块 // 5. 如果需要,可以在这里安排重传,但通常在主循环中处理更好 // transmissionRetryFlag = true; } // 清除PIE中断标志 PieCtrlRegs.PIEACK.all = PIEACK_GROUP8; }

4. I2C中断系统深度解析:从事件到响应

中断是高效处理I2C通信异步事件的关键。轮询方式会大量占用CPU资源,而合理利用中断可以让CPU在数据未就绪时处理其他任务。TMS320F28003x的I2C模块提供了两类中断:基本I2C中断FIFO中断,它们通过不同的路径最终产生两个可屏蔽的CPU中断请求。

4.1 基本I2C中断请求与优先级管理

基本I2C中断涵盖了通信过程中的核心状态事件。如表26-6所示,每个中断源都在状态寄存器I2CSTR中有对应的标志位(Flag),在中断使能寄存器I2CIER中有对应的使能位(Enable)。

中断产生与响应流程

  1. 事件发生:例如,发送数据寄存器空(XRDY置1)、接收数据就绪(RRDY置1)、仲裁丢失(ARBL置1)等。
  2. 标志置位:硬件自动将I2CSTR中对应的状态位置1。
  3. 中断使能检查:如果I2CIER中对应的使能位为1,则该中断请求被放行,进入仲裁器。
  4. 优先级仲裁:如图26-17,所有已触发且被使能的中断请求会进入一个硬件仲裁器。仲裁器根据固定的优先级(ARBLINT最高,AASINT最低)选择当前最高优先级的请求,将其编码写入中断源寄存器I2CISRCINTCODE字段。
  5. CPU中断:仲裁器输出一个统一的I2C中断信号(如I2CINT1A)给CPU。
  6. 中断服务:CPU跳转到中断服务程序(ISR),首先读取I2CISRC寄存器。这个读取操作会自动清除当前INTCODE对应的I2CSTR中的标志位(ARDY,RRDY,XRDY这三个标志位除外,它们需要手动写1清除)。
  7. 处理与返回:ISR根据INTCODE的值跳转到对应的处理子程序。处理完毕后,如果还有其他挂起的中断,仲裁器会更新I2CISRC并再次触发中断,直到所有中断被处理完毕。

关键中断源解析

  • XRDYINT (发送就绪):当数据从发送数据寄存器I2CDXR转移到发送移位寄存器I2CXSR后触发,表明I2CDXR已空,可以写入下一个数据字节。注意:在FIFO模式下不应使用此中断,应使用FIFO发送中断。
  • RRDYINT (接收就绪):当数据从接收移位寄存器I2CRSR转移到接收数据寄存器I2CDRR后触发,表明I2CDRR中有新数据可读。同样,FIFO模式下应使用FIFO接收中断。
  • ARDYINT (寄存器访问就绪):当模块已使用完先前编程的地址、数据和命令值,寄存器可以接受新配置时触发。在非重复模式(RM=0)下,如果STP=0,它会在内部数据计数器I2CCNT递减到0时置位;如果STP=1,则不会置位(而是产生停止条件)。在重复模式(RM=1)下,每传输完一个字节就置位一次。
  • NACKINT (无应答):当模块作为主发送器未收到从设备的应答信号时触发。这通常表示从设备地址错误、设备不存在或设备忙。
  • ARBLINT (仲裁丢失):如前所述,在仲裁中失败时触发。
  • SCDINT (停止条件检测):在I2C总线上检测到停止条件时触发。
  • AASINT (被寻址为从设备):当模块被总线上的另一个主设备寻址时触发。

4.2 FIFO中断:提升批量传输效率

对于需要连续传输大量数据的场景,频繁的字节级中断(XRDYINT/RRDYINT)会造成巨大的CPU开销。FIFO中断正是为了解决这个问题。

FIFO中断机制

  • 发送FIFO中断 (TXFFINT):当发送FIFO中的数据量少于或等于预设的触发水平(TXFFIL)时,TXFFINT标志置位。例如,设置TXFFIL=8,当FIFO中数据从9个减少到8个时,就会产生中断,提示CPU可以补充数据了。这允许CPU一次写入多个字节到FIFO,而不是每传一个字节就中断一次。
  • 接收FIFO中断 (RXFFINT):当接收FIFO中的数据量达到或超过预设的触发水平(RXFFIL)时,RXFFINT标志置位。例如,设置RXFFIL=8,当FIFO中累积了8个或更多数据字节时,产生中断,提示CPU可以批量读取。

发送和接收FIFO中断在内部“或”在一起,产生第二个CPU中断(如I2CINT2A)。在中断服务程序中,需要查询I2CFFTXI2CFFRX寄存器中的状态位来确定中断来源。

配置与使用要点

  1. 启用FIFO:必须将I2CFFTX.bit.I2CFFEN置1。
  2. 复位FIFO:在开始传输前,先将TXFFRSTRXFFRST置0(复位),再置1(使能)。
  3. 设置中断水平:根据你的数据处理能力设置TXFFILRXFFIL。例如,如果CPU响应快,可以设小一点以减少延迟;如果希望减少中断频率,可以设大一点(最大15,因为FIFO深度为16)。
  4. 清除中断标志:通过向TXFFINTCLRRXFFINTCLR位写1来清除对应的中断标志。
  5. 重要警告:原始资料特别指出,在使能FIFO操作并将I2C模块退出复位后,由于TXFFSTRXFFST初始为0,可能会立即触发FIFO中断(例如,发送FIFO空中断)。为了避免这个问题,建议在使能FIFO后,立即手动清除一次中断标志(写1到TXFFINTCLR/RXFFINTCLR)。

4.3 中断编程实战与避坑指南

在实际编程中,合理配置和使用中断是稳定通信的保障。以下是一些关键经验和常见陷阱:

1. 中断使能与标志清除顺序: 错误的顺序可能导致丢失中断或产生伪中断。推荐的初始化顺序是:

// 1. 首先,禁用模块 (IRS=0) 并进行所有静态配置(时钟分频、自身地址等) I2caRegs.I2CMDR.bit.IRS = 0; // ... 配置 I2CPSC, I2CCLKL, I2CCLKH, I2COAR 等 // 2. 清除所有可能挂起的中断标志(通过读取I2CISRC或写1到I2CSTR的位) I2caRegs.I2CSTR.all = 0xFFFF; // 写1清除所有可写清除的标志 // 或者更精确地:I2caRegs.I2CSTR.bit.ARDY = 1; I2caRegs.I2CSTR.bit.RRDY = 1; ... // 3. 配置中断使能寄存器 (I2CIER) 和 FIFO 中断使能 I2caRegs.I2CIER.all = 0; // 先全部禁用 I2caRegs.I2CIER.bit.ARDY = 1; // 例如,使能ARDY中断 // 如果使用FIFO,配置I2CFFTX/I2CFFRX并使能中断 I2caRegs.I2CFFTX.bit.TXFFIENA = 1; I2caRegs.I2CFFRX.bit.RXFFIENA = 1; // 4. 最后,使能模块 (IRS=1) 并启动传输 I2caRegs.I2CMDR.bit.IRS = 1; I2caRegs.I2CMDR.bit.STT = 1; // 产生START条件

2. 处理“陈旧数据”问题: 在非FIFO模式下,如果传输在字节中间被中止(例如,由于仲裁丢失或NACK),发送缓冲区I2CDXR中可能残留着未被发送的“陈旧数据”。当传输重新开始时,这个旧数据会被意外发送出去。原始资料提到了前向兼容模式位 (FCM)。当I2CEMDR.bit.FCM = 1时,发送数据就绪中断(XRDYINT)仅在总线事务真正需要数据时才产生(主模式下在收到地址字节的ACK后;从模式下在地址匹配后)。这可以避免在异常情况下请求不必要的数据写入,从而防止陈旧数据被发送。

3. 轮询与中断的混合使用: 对于一些简单操作或调试,轮询可能更直接。例如,在发送单个字节后,可以轮询ARDY位等待寄存器就绪,再发送停止条件。但要注意,在FIFO模式下,应避免使用XRDY/RRDY进行轮询,而应使用FIFO状态位TXFFST/RXFFST

4. 中断服务程序(ISR)的优化: ISR应尽可能短小精悍。对于数据收发,通常只在ISR中设置标志位、增减计数器,或将数据从FIFO复制到软件缓冲区。繁重的数据处理应放在主循环中。同时,要确保ISR能正确处理嵌套中断或优先级,避免重入问题。

5. 数字回环模式与NACK生成:调试与流控利器

除了核心通信机制,I2C模块还提供了一些高级功能,用于辅助调试和实现更精细的通信控制。

5.1 数字回环模式:无需外部连线的自检

数字回环模式(Digital Loopback Mode)通过设置I2CMDR.bit.DLB = 1来启用。在此模式下,从I2CDXR发送出去的数据,会经过一个内部路径,在n个模块时钟周期后到达I2CDRR寄存器,其中n = 8 * (SYSCLK) / (I2C模块时钟)

它的核心价值在于

  1. 硬件自检:在不连接任何外部I2C设备的情况下,验证I2C模块的发送、接收、时钟生成以及中断逻辑是否正常工作。你可以编写一个测试程序,发送一系列数据,然后检查接收到的数据是否一致。
  2. 软件调试:在开发通信协议栈或驱动程序时,可以先用回环模式测试数据流和状态机逻辑,排除软件错误,然后再接入真实的物理设备。
  3. 隔离硬件问题:如果实际通信失败,可以先切换到回环模式。如果回环测试通过,那么问题很可能出在外部电路(上拉电阻、设备地址、布线干扰等);如果回环测试也失败,则问题可能在微控制器配置或软件本身。

使用限制:需要注意的是,自由数据格式(FDF=1)在数字回环模式下不被支持。此外,在回环模式下,出现在外部SDA引脚上的地址是I2COAR寄存器中自身的地址。

5.2 NACK位的主动生成:接收端的流控制

NACK(无应答)通常被认为是错误状态,但主动、有策略地发送NACK是接收端进行流控制的重要手段。表26-5详细列出了在不同模式下生成NACK位的方法。

为什么需要主动发送NACK?

  1. 从接收器告知主设备“停止发送”:当从设备无法处理更多数据(例如缓冲区满)时,可以在某个字节的应答周期发送NACK。主设备检测到NACK后,通常会终止传输或采取错误处理流程。
  2. 主接收器结束读取:在主接收模式下,主设备在读取完所需字节后,需要在最后一个字节的应答周期发送NACK,告知从发送器“我不再需要数据了”,然后主设备发出停止条件。

生成NACK的几种方式

  • 从接收器模式
    • 允许溢出条件(RSFULL=1):当接收移位寄存器I2CRSR已满,而I2CDRR中旧数据还未被读取时,硬件会自动发送NACK。
    • 复位模块(IRS=0):极端情况下的强制措施。
    • 设置NACKMOD位:在打算接收的最后一个数据位的上升沿之前,将I2CMDR.bit.NACKMOD置1,模块会在下一个应答周期发送NACK。这是最常用、最可控的方式
  • 主接收器模式(重复模式RM=1
    • 生成停止条件(STP=1):这会在传输结束时产生停止条件,但之前的应答仍为ACK。
    • 复位模块或设置NACKMOD位:同上。
  • 主接收器模式(非重复模式RM=0
    • 如果STP=1,则依靠内部数据计数器I2CCNT减到0来强制产生停止条件(这之前会先发送NACK)。
    • 如果STP=0,可以通过设置STP=1NACKMOD来生成NACK。

实操心得:在编写主设备读取从设备数据的代码时,务必规划好NACK的发送时机。例如,读取一个24C02 EEPROM的连续数据时,你需要在读取倒数第二个字节后,在中断服务程序中或通过轮询判断,在最后一个字节开始前设置NACKMOD位,这样在收到最后一个字节后,主设备会回复NACK,然后紧接着发送停止条件,优雅地结束读取过程。忘记发送NACK可能导致从设备继续等待时钟,造成总线挂起。

6. 软件示例与寄存器精要

理论最终要落实到代码。原始资料提供了一系列软件示例,这些示例是理解如何将上述机制组合运用的最佳起点。

6.1 关键软件示例解析

  1. i2c_ex1_loopback.c(数字回环):此示例展示了如何使用FIFO和中断进行数字回环测试。它初始化I2C模块,启用数字回环模式,然后通过发送FIFO发送一个递增的数据模式,并在接收FIFO中断中检查接收到的数据是否匹配。学习重点:FIFO中断的配置、数字回环模式的启用、以及数据验证模式。
  2. i2c_ex2_eeprom.ci2c_ex6_eeprom_interrupt.c(EEPROM读写):这两个示例分别展示了使用轮询和中断方式与I2C EEPROM(如AT24C256)通信。它们涵盖了字节写、字节读、页写、页读等典型操作。学习重点:I2C与具体从设备的通信时序(包括设备地址、内存地址发送)、等待EEPROM内部写完成的时间处理(轮询或延时)、以及中断方式下的状态机管理。
  3. i2c_ex5_controller_target_interrupt.c(主从设备中断通信):这个示例非常综合,演示了两个I2C模块(I2CA和I2CB)如何互相作为主设备和从设备进行通信,并使用FIFO中断。学习重点:多主/从角色动态切换、中断协同、以及复杂的通信流程编排。

6.2 核心寄存器速查与配置流程

在编写驱动时,以下寄存器是必须熟练掌握的。配置流程通常遵循一个固定模式:

初始化流程

  1. 引脚复用:通过GPIO模块将对应的SDA和SCL引脚配置为I2C功能。
  2. 模块复位与使能:写I2CMDR.bit.IRS = 0复位模块,进行所有配置;完成后写IRS = 1使能。
  3. 时钟配置
    • 配置I2CPSC确定模块时钟频率:Fmod = Finput / (IPSC + 1)
    • 配置I2CCLKLI2CCLKH确定作为主设备时的SCL高低电平时间,以产生目标通信速率(如100kHz, 400kHz)。
  4. 地址配置
    • I2COAR:设置模块自身的从设备地址。
    • I2CSAR:当作为主设备时,设置目标从设备的地址。
  5. 模式配置 (I2CMDR)
    • MST:主/从模式选择。
    • TRX:发送/接收模式选择。
    • XA:7位/10位地址模式。
    • FDF:自由数据格式使能。
    • STB:起始字节模式(用于兼容慢速设备)。
    • BC:数据位计数(1-8位)。
    • RM:重复模式(用于不确定长度的流传输)。
    • DLB:数字回环模式。
  6. 中断与FIFO配置
    • I2CIER:使能所需的基本中断。
    • I2CFFTX/I2CFFRX:配置FIFO模式、中断水平、并使能FIFO中断。
    • 在PIE或CPU级别使能对应的I2C中断向量。
  7. 启动传输
    • 对于主发送:写入从地址到I2CSAR,写入数据到I2CDXR,设置STT=1启动。
    • 对于主接收:写入从地址到I2CSAR,设置TRX=0,设置STT=1启动,并在RRDY中断或FIFO中断中读取I2CDRR
    • 设置STP=1来在传输结束时产生停止条件(在非重复模式下,I2CCNT减到0时会自动产生)。

关键状态寄存器 (I2CSTR) 位解读

  • BB:总线忙。检测总线是否被占用,在发起传输前应检查。
  • ARDY:寄存器就绪。指示是否可以写入新的地址/数据/命令。
  • NACK:无应答。检测从设备是否应答。
  • ARBL:仲裁丢失。检测是否在多主竞争中失败。
  • RSFULL/XSMT:接收溢出/发送欠载。指示数据流问题。

理解并熟练运用这些寄存器的每一位,是编写健壮、高效I2C驱动程序的根本。调试时,通过实时观察这些状态位的变化,可以精准定位通信卡在哪一个环节。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询