1. 项目概述与I2C总线核心价值在嵌入式系统开发尤其是涉及复杂信号处理的应用中如何高效、可靠地连接主处理器与周边的传感器、编解码器、存储器等外设始终是架构设计的关键一环。从业十多年我见过太多项目因为通信接口选择不当或配置不深导致后期调试困难、系统不稳定。今天我们就来深入聊聊在TI的TMS320C672x系列高性能浮点DSP上那个看似简单却至关重要的内置外设——I2C模块。I2C全称Inter-Integrated Circuit是一种由Philips现NXP推出的两线制串行通信总线。它的魅力在于极简的物理连接仅需SDA数据线和SCL时钟线和强大的寻址能力特别适合板级芯片间的短距离、中低速通信。在C672x这类专注于音频处理、电机控制或精密测量的DSP系统中I2C常被用来配置音频编解码器的参数、读取温度传感器数据、或者访问板上的EEPROM是构建完整系统不可或缺的“神经网络”。C672x系列DSP通常集成了两个独立的I2C模块I2C0和I2C1这为系统设计带来了极大的灵活性。你可以用一个模块专用于控制本板的模拟前端如ADC/DAC另一个模块则用于与系统内其他主控制器如另一个DSP或MCU通信甚至实现一个简单的人机接口。这种双模块设计避免了总线竞争简化了软件架构。然而要把这颗DSP的I2C用稳、用透仅仅知道基本的读写操作是远远不够的必须深入到寄存器层面理解每一个配置位背后的硬件逻辑和电气特性。官方数据手册Datasheet和用户指南User‘s Guide是宝库但信息分散且偏重描述缺乏连贯的实战视角。本文就将结合手册要点与我的实际调试经验为你拆解C672x I2C模块的配置精髓、寄存器详解以及那些手册上不会明写的“坑”。2. C672x I2C模块架构与核心特性解析2.1 模块整体框图与数据流要驾驭一个外设首先得在脑子里建立起它的硬件模型。C672x的I2C模块是一个高度集成化的数字逻辑单元其核心架构可以理解为由几个协同工作的子模块构成时钟生成、总线控制、数据移位、中断/事件管理以及引脚控制。时钟生成是总线速度的基石。模块的输入时钟来源于DSP的SYSCLK2外设时钟。这个时钟频率可能很高例如上百MHz而I2C标准模式100kbps或快速模式400kbps所需的SCL频率要低得多。因此模块内部首先通过一个可编程的预分频器Prescaler 由I2CPSC寄存器控制对SYSCLK2进行初次降频得到一个中间时钟IPSC_CLK。然后这个IPSC_CLK再经过一个位时钟发生器Bit Clock Generator该发生器由I2CCLKH时钟高电平分频和I2CCLKL时钟低电平分频两个寄存器共同控制最终产生符合I2C时序规范的SCL时钟。这种两级分频的结构提供了非常精细的时钟调节能力你可以独立设置SCL高电平和低电平的持续时间以适配总线上不同器件的时序要求或者在存在较大布线电容时适当延长低电平时间以保证数据稳定。数据流的核心是移位寄存器和缓冲器。当DSP作为发送方Master-Transmitter或Slave-Transmitter时你将要发送的数据写入数据发送寄存器I2CDXR。该寄存器中的数据会被自动加载到发送移位寄存器I2CXSR中在SCL时钟的同步下一位一位地通过SDA线移出。反之当接收数据时SDA线上的串行数据先被移入接收移位寄存器I2CRSR凑满一个字节8位后再自动转存到数据接收寄存器I2CDRR中供CPU读取。这种双缓冲机制DXR/XSR RSR/DRR是实现连续、流式数据传输而不产生间隙的关键。控制逻辑是模块的大脑主要由模式寄存器I2CCMDR和扩展模式寄存器I2CEMDR掌控。I2CCMDR决定了模块的基本工作模式是作为主机Master还是从机Slave是发送器Transmitter还是接收器Receiver是否产生起始START和停止STOP条件是否应答ACK/NACK而I2CEMDR则控制一些高级功能比如是否使能数字噪声滤波器Digital Noise Filter。这个滤波器对于工业环境等存在干扰的场景至关重要它可以滤除宽度小于50ns的毛刺防止误触发起始或停止条件极大地提升了总线在恶劣电气环境下的鲁棒性。中断与DMA事件是提高效率的关键。模块内部有丰富的状态标志集中在中断状态寄存器I2CSTR中例如数据发送完成XRDY、数据接收就绪RRDY、仲裁丢失ARDY、无应答NACK等。你可以通过中断使能寄存器I2CIER有选择地开启这些事件的中断。更高效的方式是配合DSP的dMAX直接内存访问控制器使用将I2C配置为DMA事件源。这样一旦发送缓冲空或接收缓冲满就会自动触发DMA传输在后台完成大批量数据的搬移彻底解放CPU使其能专注于核心算法运算。中断源寄存器I2CSRC则在多个中断事件同时发生时帮助软件快速识别是哪一个具体事件触发了中断。引脚控制寄存器组I2CPFUNC I2CPDIR等提供了额外的灵活性。当I2C功能未被启用时这两组引脚I2Cx_SDA I2Cx_SCL可以被配置为通用的输入/输出GPIO使用。这在引脚资源紧张的系统中非常有用。但需要注意的是一旦使能I2C功能模块会自动接管引脚的方向控制与GPIO配置寄存器无关。2.2 关键特性与电气规范要点C672x的I2C模块并非简单的IP核移植它针对高性能DSP的应用场景做了一些特别的优化和限制这些是配置前必须清楚的。首先它完全兼容Philips I2C规范v2.1支持标准模式0-100 kbps和快速模式高达400 kbps。这意味着你可以放心地将其与市面上绝大多数I2C从设备连接。其次关于电气特性有一个至关重要的警告CAUTION这也是很多工程师初次使用容易栽跟头的地方C672x的I2C引脚使用的是标准的±8mA驱动能力的LVCMOS缓冲器而不是I2C规范中定义的具有“线与”特性的开漏缓冲器。这是一个本质区别。I2C总线的多主机仲裁和时钟拉伸等功能依赖于开漏输出和外部上拉电阻实现的“线与”逻辑。C672x的推挽输出虽然驱动能力强但无法与其他开漏输出的设备直接实现“线与”。那怎么办TI的建议是在PCB设计时为SDA和SCL线串联一个小电阻通常22Ω到100Ω。这个电阻的作用是限流并在多个设备输出冲突时比如一个输出高另一个输出低起到一定的隔离作用防止大电流损坏引脚。同时总线两端依然需要连接上拉电阻典型值3.3V系统用4.7kΩ。这样虽然DSP内部是推挽输出但通过外部电阻的配合在总线电平上仍然可以近似实现开漏的逻辑行为。忽视这一点直接连接很可能导致通信不稳定甚至损坏引脚。噪声滤波器是另一个亮点。在工业环境或长距离走线时总线容易引入噪声。使能内置的数字噪声滤波器后模块会对SDA和SCL输入信号进行采样只有持续超过滤波器窗口时间可滤除≤50ns噪声的电平变化才会被识别为有效跳变。这相当于给总线加了一个软件可配置的“硬件RC滤波”比单纯依靠外部电容滤波更精准可靠。地址模式支持7位和10位两种。7位地址是最常用的寻址空间为128个。10位地址扩展了寻址范围但在实际应用中相对少见需要主从设备双方都支持。工作模式全面支持主发送、主接收、从发送、从接收。这意味着C672x的I2C既可以主动发起通信控制其他芯片也可以被动响应其他主机如系统主控MCU的访问非常适合在复杂主从系统中作为协处理器。3. 寄存器详解与实战配置指南寄存器是软件与硬件对话的窗口。对C672x I2C的精准控制完全依赖于对二十多个寄存器的理解。下面我们抛开枯燥的位域列表从功能分组和实战配置的角度深入解读关键寄存器。3.1 时钟与速率配置寄存器组这是配置的第一步决定了通信的“心跳”频率。总线速度不匹配是通信失败的最常见原因之一。I2CPSC预分频寄存器 这是第一级分频。假设你的SYSCLK2频率是SYSCLK2_FREQ那么预分频后的时钟IPSC_CLK SYSCLK2_FREQ / (I2CPSC 1)。I2CPSC是一个8位寄存器因此分频系数范围为1到256。它的主要作用是将高速的系统时钟降到一个中间频率为后续的位时钟生成提供合适的时基。通常我们会先根据目标SCL频率反推出需要的IPSC_CLK再计算I2CPSC的值。I2CCLKH 与 I2CCLKL时钟高低电平分频寄存器 这是第二级分频也是产生标准I2C波形占空比的关键。IPSC_CLK经过这两个寄存器分频后分别产生SCL高电平时间和低电平时间。SCL高电平时间t_high (I2CCLKH 5) * (1 / IPSC_CLK)SCL低电平时间t_low (I2CCLKL 5) * (1 / IPSC_CLK)因此一个完整的SCL周期t_SCL t_high t_low最终的I2C总线速率I2C_BITRATE 1 / t_SCL这里的“5”是模块内部的固定延迟因子在计算时必须考虑进去。I2CCLKH和I2CCLKL也是8位寄存器。为了产生标准的I2C波形通常高、低电平时间接近1:1我们需要让t_high和t_low近似相等。这需要通过调整I2CPSC、I2CCLKH和I2CCLKL三个值来协同计算。实战配置示例 假设SYSCLK2 100 MHz 目标I2C速率 400 kHz (快速模式)。估算IPSC_CLK 为了给高低电平分频留出足够精度通常让IPSC_CLK在10-20MHz左右。我们暂定目标t_SCL 1/400kHz 2.5 µs。如果希望t_high ≈ t_low ≈ 1.25µs那么IPSC_CLK周期需要远小于1.25µs。取IPSC_CLK 20 MHz周期50ns则分频数I2CPSC 100MHz / 20MHz - 1 4。计算I2CCLKH和I2CCLKL对于高电平t_high (I2CCLKH 5) * 50ns 1.25µsI2CCLKH 1.25µs / 50ns - 5 25 - 5 20。对于低电平t_low (I2CCLKL 5) * 50ns 1.25µsI2CCLKL 20。验证与微调 实际t_SCL (205205)*50ns 50*50ns 2.5µs速率正好400kHz。但需注意数据手册的时序表对快速模式有要求例如t_high和t_low均需≥0.6µs我们的1.25µs满足要求。同时要确保计算出的I2CCLKH和I2CCLKL值在0-255范围内。3.2 地址与模式控制寄存器组这组寄存器定义了“我是谁”以及“我要干什么”。I2COAR自身地址寄存器 当DSP的I2C模块工作在从机模式时这个寄存器定义了它在总线上的“门牌号”。主设备通过发送这个地址来寻址它。你可以配置为7位地址写入高7位最低位无效或10位地址通过模式寄存器I2CCMDR中的XA位选择。重要提示在7位地址模式下写入I2COAR的地址值需要左移一位即实际地址1。这是因为I2C协议中7位地址在发送时占据一个字节的高7位最低位是读写方向位。模块硬件会自动处理方向位但要求你提供左移后的地址值。I2CSAR从设备地址寄存器 当DSP的I2C模块作为主机时这个寄存器存放了你想要通信的从设备的地址。同样对于7位地址模式需要写入左移一位后的值。I2CCMDR模式寄存器 这是I2C模块的“命令中心”几乎所有的操作指令都通过写入此寄存器发起。关键位域包括MST主/从模式 1主机 0从机。TRX发送/接收模式 1发送器写操作 0接收器读操作。注意此设置在主机和从机模式下含义不同。XA扩展地址 1使用10位从机地址 0使用7位地址。RM重复模式 1使能自动重复模式。在此模式下当一次数据传输字节数由I2CCNT设定完成后模块会自动重新开始一次传输发送重复起始条件而无需软件干预。这对于连续读取传感器数据非常高效。STB起始字节模式 用于与不支持I2C高速模式的微控制器兼容不常用。IRSI2C模块复位/使能 这是最重要的位之一。在配置任何其他寄存器之前必须先将此位清零以复位模块。完成所有配置后再将此位置1以使能模块。任何对I2CCMDR、I2CPSC、I2CCLKH/L等寄存器的修改都必须在IRS0的情况下进行修改完成后再置1生效。STP停止条件 在主机模式下软件置位此位将在当前字节传输结束后产生一个停止条件。通常用于结束一次传输。STT起始条件 在主机模式下软件置位此位将产生一个起始条件或重复起始条件。当总线空闲BB位为0且模块已使能IRS1时置位STT将启动一次主机传输序列。FDF自由数据格式 1使能自由数据格式此时不检查地址直接进行数据收发用于某些特殊协议。BC位计数 在主机模式下指示当前正在传输的字节中已经移出了多少位。只读。I2CEMDR扩展模式寄存器 主要控制数字噪声滤波器NFE位和输出驱动模式但如前所述驱动模式受硬件限制。使能噪声滤波器NFE1在噪声环境下是推荐做法。3.3 数据与状态寄存器组这是数据传输和状态监控的通道。I2CDXR数据发送寄存器 CPU将待发送的数据字节写入此寄存器。如果发送移位寄存器I2CXSR为空数据会自动加载进去并开始发送。在重复模式或DMA模式下需要连续向此寄存器写入数据。I2CDRR数据接收寄存器 当接收移位寄存器I2CRSR收满一个字节后数据会自动转存到此寄存器并置位RRDY状态标志。CPU从此寄存器读取接收到的数据。I2CCNT数据计数寄存器 这是一个非常实用的寄存器用于在重复模式RM1下定义一次传输过程中要发送或接收的字节数。当传输的字节数达到I2CCNT设定的值时模块会自动停止如果STP已设置或产生中断。这简化了软件对传输长度的管理。I2CSTR中断状态寄存器 实时反映模块的内部状态。关键状态位BB总线忙 1表示I2C总线正被占用SDA或SCL为低。RSF重复起始条件检测 在从机模式下检测到重复起始条件时置位。XRDY发送就绪 1表示I2CDXR为空可以写入下一个待发送数据。RRDY接收就绪 1表示I2CDRR中有新数据可读。ARDY寄存器访问就绪 当对I2CCMDR的写入操作已完成例如STT STP命令已执行或一次重复模式传输完成时置位。NACK无应答 作为主机时发送完地址或数据后未收到从机的应答信号此位置位。AL仲裁丢失 在多主机系统中当本机在仲裁中失败时置位。I2CIER中断使能寄存器 其位域与I2CSTR一一对应。将某位置1则当I2CSTR中对应状态位置位时会向CPU产生中断请求。你可以根据需要开启中断例如开启XRDY和RRDY用于查询式传输或开启ARDY、NACK、AL用于事件处理。I2CSRC中断源寄存器 当产生中断时读取此寄存器可以快速确定是哪个具体事件XRDY RRDY ARDY等触发了中断。在多个中断使能的情况下这比轮询I2CSTR更高效。3.4 引脚控制寄存器组GPIO功能当I2C功能未启用时通过PINMUX或其他系统配置将引脚功能设置为GPIO这组寄存器用于控制引脚。I2CPFUNC引脚功能寄存器 决定引脚是用于I2C功能0还是GPIO功能1。I2CPDIR引脚方向寄存器 当为GPIO时0输入1输出。I2CPDOUT引脚数据输出寄存器 当为GPIO输出时写入此寄存器控制输出电平。I2CPDIN引脚数据输入寄存器 当为GPIO输入时读取此寄存器获取引脚电平。I2CPDSET/I2CPDCLR引脚数据置位/清零寄存器 提供原子操作方便对GPIO输出位进行置1或清0而不影响其他位。重要提醒一旦通过系统级引脚复用控制将引脚功能切换到I2C模块将自动管理SDA和SCL的方向开漏输出/输入此时GPIO方向寄存器I2CPDIR不再起作用。试图在I2C通信过程中通过GPIO寄存器去操作这些引脚是无效且危险的。4. 完整配置流程与代码实战理解了寄存器我们来看如何将它们串联起来完成一次完整的I2C主设备读写操作。以下流程基于查询模式非中断/DMA适合初学者理解底层机制。4.1 初始化配置步骤引脚复用配置 首先需要通过系统控制模块例如PINMUX寄存器将对应的I2Cx_SDA和I2Cx_SCL引脚功能设置为I2C而不是GPIO或其他功能。这是前提否则后续所有I2C寄存器配置都不会生效。复位并禁用I2C模块 向I2CCMDR寄存器写入0确保IRS位为0。这会复位整个I2C模块到默认状态。配置时钟预分频器I2CPSC 根据你的SYSCLK2频率和目标I2C速率计算并写入I2CPSC值。配置时钟高低分频器I2CCLKH I2CCLKL 根据计算出的值写入以设定精确的SCL周期和占空比。配置自身地址I2COAR 仅从机模式需要 如果DSP可能作为从机被访问在此设置它的7位或10位地址注意左移。配置扩展模式I2CEMDR 通常使能数字噪声滤波器NFE1。使能I2C模块 向I2CCMDR寄存器写入一个值将IRS位置1同时根据初始需求设置其他位例如MST1为主机模式。此时模块已上电但总线尚未启动。4.2 主机发送写数据流程假设我们要作为主机向一个7位地址为0x50的EEPROM设备写入数据。写入从机地址 将目标从机地址左移一位后写入I2CSAR。例如0x50 1 0xA0。注意最低位是读写位但写入I2CSAR时我们只关心地址部分方向由后续操作决定。实际上在启动传输后模块会自动将I2CSAR中的值0xA0与方向位0表示写组合成第一个发送字节0xA0 0xFE 0xA0。设置数据计数可选 如果使用重复模式将要发送的字节数包括从机地址字节写入I2CCNT。例如要发送3个数据字节则I2CCNT 41地址3数据。配置模式寄存器并启动传输构建I2CCMDR命令字设置MST1主机 TRX1发送 STT1产生起始条件 STP1在传输结束后产生停止条件。如果不使用重复模式STP1是必要的。如果需要使用重复模式则设置RM1并且STP位的行为取决于具体需求。在确保总线空闲通过读取I2CSTR的BB位确认后将上述命令字写入I2CCMDR。等待并发送数据写入I2CCMDR后等待ARDY位置位表示起始条件已成功发出模块就绪。然后轮询I2CSTR的XRDY位。当XRDY1时表示发送缓冲I2CDXR为空可以写入第一个数据字节即要写入EEPROM的数据。将数据写入I2CDXR。写入后XRDY会清零直到这个字节被移出发送缓冲。重复“轮询XRDY - 写入I2CDXR”的过程直到所有数据发送完毕。等待传输结束发送完最后一个数据字节后等待ARDY再次置位。这表示STP命令已执行停止条件已产生整个传输序列结束。在整个过程中务必监控NACK和AL位。如果NACK置位说明从机未应答需要错误处理。如果AL置位说明在多主机仲裁中失败。4.3 主机接收读数据流程假设我们要从地址0x50的EEPROM读取3个字节数据。写入从机地址写方向 同样将0xA0写入I2CSAR。发送“伪写”以设置从机内部地址很多存储器设备需要此步骤 这个过程和主机发送流程完全一样先发送起始条件从机地址写 存储器内部地址。发送完成后不要产生停止条件。发送重复起始条件Repeated Start并切换为读方向重新配置I2CCMDR MST1 TRX0接收 STT1产生重复起始条件 STP1读完后停止。注意此时从机地址寄存器I2CSAR需要更新吗实际上在重复起始后模块会自动重新发送I2CSAR中的地址字节但会将方向位置1读。所以我们只需要确保I2CSAR中仍然是0xA0即可。写入此I2CCMDR命令字。等待并接收数据等待ARDY表示重复起始条件已发出。轮询I2CSTR的RRDY位。当RRDY1时表示接收缓冲I2CDRR中有新数据。从I2CDRR中读取数据。关键点在读取最后一个字节之前软件需要通过对I2CCMDR的操作告诉模块在接收到最后一个字节后不发送应答NACK并向从机发出停止条件。这通常通过在一个特定的时机比如接收倒数第二个字节后清除I2CCMDR中的ACK位来实现。具体操作需要仔细查阅数据手册中关于主机接收模式的描述。等待传输结束 读取完所有数据并产生停止条件后等待ARDY置位。4.4 示例代码片段概念性以下是用C语言伪代码展示的主机发送单字节的流程假设已定义好寄存器映射指针如I2C0_REGS。// 1. 初始化配置 (假设SYSCLK2100MHz 目标400kHz) I2C0_REGS-I2CCMDR 0x0000; // IRS0 复位模块 // 配置时钟 使用前面计算的值 I2C0_REGS-I2CPSC 4; // 预分频 I2C0_REGS-I2CCLKH 20; // 高电平分频 I2C0_REGS-I2CCLKL 20; // 低电平分频 I2C0_REGS-I2CEMDR | 0x01; // 使能噪声滤波器 (NFE1) // 2. 使能模块 设置为主机模式 I2C0_REGS-I2CCMDR 0x4000; // IRS1 MST1 模块使能为主机 // 3. 准备发送数据到地址0x50的从机 uint16_t slaveAddr 0x50 1; // 左移一位得到I2C格式地址 I2C0_REGS-I2CSAR slaveAddr; // 设置从机地址 // 4. 启动传输 (发送起始条件地址一个数据字节停止条件) // 构建命令: IRS1 MST1 TRX1 STT1 STP1 uint16_t cmd 0x4620; // 二进制: 0100 0110 0010 0000 // 位15-10: 保留 | IRS1 | 保留 | MST1 | TRX1 | XA0 | RM0 | STB0 // 位7-0: 保留 | STT1 | 保留 | STP1 | 保留 | BC位(只读) // 等待总线空闲 while (I2C0_REGS-I2CSTR 0x8000); // 等待BB位为0 I2C0_REGS-I2CCMDR cmd; // 写入命令启动传输 // 5. 等待ARDY表示起始条件已发出可以发送数据了 while (!(I2C0_REGS-I2CSTR 0x0004)); // 等待ARDY置位 // 6. 等待发送缓冲空然后写入数据 while (!(I2C0_REGS-I2CSTR 0x0008)); // 等待XRDY置位 I2C0_REGS-I2CDXR 0xAB; // 发送数据字节 0xAB // 7. 等待传输完成 (ARDY再次置位表示停止条件已产生) while (!(I2C0_REGS-I2CSTR 0x0004)); // 8. 检查错误 if (I2C0_REGS-I2CSTR 0x0010) { // NACK错误处理 } if (I2C0_REGS-I2CSTR 0x0002) { // 仲裁丢失处理 }5. 高级应用与调试技巧5.1 中断与DMA驱动配置对于需要高效处理大量数据或实时响应的应用查询模式会占用大量CPU资源。使用中断或DMA是必然选择。中断驱动 你需要初始化DSP的中断控制器将I2C中断事件如XRDY RRDY ARDY NACK映射到特定的中断线并编写中断服务程序ISR。在ISR中通过读取I2CSRC寄存器判断中断源然后进行相应的数据处理如填充I2CDXR或读取I2CDRR。关键是要确保ISR执行时间尽可能短避免丢失后续数据或总线超时。DMA驱动 这是最高效的方式尤其适合音频流等大数据量传输。你需要配置dMAX控制器将I2C的XRDY或RRDY事件作为DMA传输的触发源。例如当I2CDXR空XRDY事件时自动触发DMA将内存中的一个数据块搬运到I2CDXR当I2CDRR满RRDY事件时自动触发DMA将I2CDRR的数据搬运到内存。CPU只需要在传输开始前设置好DMA参数传输完成后处理一个完成中断即可。这几乎实现了零CPU开销的I2C数据传输。5.2 时序计算与电气匹配手册中的时序表Table 4-36 Table 4-37是设计的金科玉律。在配置I2CCLKH和I2CCLKL时计算出的t_high和t_low必须满足快速模式或标准模式下的最小值要求。同时还要考虑总线电容Cb对上升时间tr的影响。公式tr 20 0.1Cbns给出了在快速模式下总线电容对上升时间的贡献。如果你的总线上挂载设备多、走线长导致Cb接近400pF的最大值那么上升时间可能会达到60ns你需要确保这个值仍然小于300ns的最大限制。上拉电阻的选择 这是一个经典的权衡。电阻值小如1kΩ上升时间快驱动能力强但功耗大低电平电流大。电阻值大如10kΩ功耗低但上升时间慢可能在高电容总线上无法满足时序。对于3.3V系统在总线电容不大100pF时4.7kΩ是一个常用的折中选择。务必使用示波器测量SCL和SDA的实际波形确保上升/下降沿干净高低电平稳定。串联电阻的必要性 再次强调由于C672x使用LVCMOS推挽输出强烈建议在DSP的I2C引脚输出端串联一个22Ω-100Ω的小电阻。这能有效抑制信号振铃并在总线冲突时保护DSP引脚。5.3 常见问题排查与实战心得通信完全无响应SCL/SDA线始终为高检查引脚复用这是最容易被忽略的一步。确认系统PINMUX配置已将对应引脚功能设置为I2C而非GPIO。检查模块使能确认I2CCMDR中的IRS位已置1。检查物理连接测量上拉电阻是否焊接电压是否为3.3V。用示波器查看发起起始条件时SCL和SDA是否有下拉动作。能发出起始条件但地址无应答NACK检查从机地址确认写入I2CSAR的地址是否正确是否左移了一位。用逻辑分析仪抓取波形看发出的地址字节是否与预期一致。检查从机设备确认从设备已上电地址无误且本身功能正常。检查总线竞争是否有其他设备拉低了总线断开其他设备测试。通信时好时坏数据错误检查时序用示波器测量SCL频率、高低电平时间、建立保持时间是否满足从设备的数据手册要求。重点检查tsu(SDA-SCLH)数据建立时间和th(SDA-SCLL)数据保持时间。检查噪声使能I2CEMDR中的数字噪声滤波器NFE1。检查PCB布局I2C走线是否远离高频噪声源如时钟线、开关电源。检查电源完整性DSP和从设备的电源是否干净在VDD和GND之间就近放置去耦电容。从机模式下无法被寻址检查自身地址确认I2COAR寄存器配置正确地址左移。检查模块模式确保I2CCMDR中的MST位为0从机模式。检查总线拉高确保总线上有上拉电阻并且没有被持续拉低。使用DMA时数据错位或丢失检查DMA触发对齐确保DMA的传输宽度8位/16位/32位与I2C数据寄存器8位匹配。通常设置为8位传输。检查DMA和I2C中断优先级如果同时使用了I2C事件中断和DMA完成中断要合理设置中断优先级避免处理不及时导致缓冲区溢出或下溢。核对DMA传输数量I2CCNT寄存器设置的字节数需要与DMA配置的传输数量协调好。在重复模式下I2CCNT计数到零会产生事件可以用于触发DMA链的切换或中断。个人心得调试I2C一个可靠的逻辑分析仪或带I2C解码功能的示波器是必不可少的。它能直观地展示起始、停止、地址、数据、ACK/NACK位让你迅速定位问题是出在协议层还是物理层。另外在软件中增加丰富的状态打印和错误计数器记录每次通信的BB、ARDY、NACK、AL等状态对于追踪间歇性故障非常有帮助。最后对于C672x牢记其I2C输出非纯开漏的特性在设计PCB时就预留串联电阻的位置能避免很多后续的麻烦。