1. I2C总线协议核心原理与工作模式解析
I2C(Inter-Integrated Circuit)总线是飞利浦公司(现恩智浦)在1980年代推出的一种同步、半双工、多主从架构的串行通信总线。它凭借其简洁的两线制(串行数据线SDA和串行时钟线SCL)设计,在嵌入式系统中占据了不可替代的地位,广泛应用于连接各类低速外设,如传感器、EEPROM、RTC、LCD驱动等。理解其底层工作原理,是进行高效、稳定配置和应用的前提。
I2C总线的通信完全由主设备(Master)发起和控制。一次完整的通信始于主设备发出的起始条件(START Condition):在SCL为高电平期间,SDA线产生一个由高到低的跳变。随后,主设备会发送一个7位或10位的从设备地址(Address Frame),紧跟着一位读写(R/W)位。地址匹配的从设备需在第9个时钟脉冲期间,通过拉低SDA线来发送一个应答(ACK)信号。此后,根据读写位的指示,进行数据帧(Data Frame)的传输,每个数据帧为8位,同样在第9个时钟脉冲由接收方进行应答。通信以停止条件(STOP Condition)结束:在SCL为高电平期间,SDA线产生一个由低到高的跳变。
总线上的所有设备都通过开漏或集电极开路输出连接到SDA和SCL线上,这意味着总线必须通过上拉电阻连接到正电源。这种设计实现了“线与”功能,即任何设备都可以拉低总线,但只有当所有设备都释放总线时,总线才恢复为高电平。这是实现多主设备仲裁和时钟同步的基础。多主竞争时,每个主设备在发送数据的同时会监听SDA线,如果发现总线上的电平与自己发送的不符,则立即失去仲裁权并转为从设备监听模式。
注意:上拉电阻的阻值选择至关重要,需要在总线电容、通信速度和功耗之间取得平衡。阻值过大会导致上升沿过慢,限制通信速度;阻值过小则会导致静态电流过大。一个经验公式是:Rp(min) = (Vcc - 0.4) / 3mA, Rp(max) = 1000 ns / (总线电容Cb)。对于标准模式(100kHz),通常使用4.7kΩ或10kΩ的电阻。
根据通信速度的不同,I2C协议定义了多种工作模式,这也是本文探讨的核心。标准模式(Standard-mode)支持最高100 kbps的速率,是兼容性最广的模式。快速模式(Fast-mode)将速率提升至400 kbps,并增加了输入滤波等功能以抑制毛刺。快速模式Plus(Fast-mode Plus)进一步将速率推至1 Mbps。而高速模式(High-speed mode, Hs-mode)则是一个特殊的模式,支持最高3.4 Mbps的传输速率,但它需要一个特定的“主设备代码(Master Code)”作为前导,在高速传输前后,总线仍运行在标准或快速模式下进行仲裁和握手。
2. TM4C1292NCZAD的I2C外设架构与寄存器概览
德州仪器(TI)的Tiva™ TM4C1292NCZAD微控制器集成了功能强大的I2C外设模块,它不仅完整支持从标准模式到高速模式的所有协议规范,还引入了FIFO(先进先出队列)和µDMA(微直接存储器访问)等高级特性,极大地减轻了CPU负担并提升了数据传输效率。
该I2C模块在硬件上被清晰地划分为主设备(Master)和从设备(Slave)两个逻辑上独立的部分,每个部分都有自己的一套控制、状态和数据寄存器。这种设计使得同一个I2C模块可以同时或分时工作在两种角色下,为复杂的通信拓扑提供了灵活性。所有寄存器都映射到特定的内存地址,开发者通过读写这些寄存器来配置模块行为、发起通信和监控状态。
对于主设备操作,最核心的寄存器包括:
- I2CMSA (Master Slave Address):用于设置目标从设备的7位地址和本次传输的方向(读/写)。
- I2CMCS (Master Control/Status):这是一个多功能寄存器。写入时,其低7位(RUN, START, STOP, ACK, HS, QCMD, BURST)的组合构成了控制命令字,用于发起特定类型的传输序列(如单字节发送、带重复起始条件的接收等)。读取时,它返回总线状态,如BUSY(忙)、ERROR(错误)、ARBLST(仲裁丢失)等,是轮询操作状态的关键。
- I2CMDR (Master Data):存放待发送或已接收的数据字节。
- I2CMTPR (Master Timer Period):这是配置SCL时钟频率的核心寄存器。其值(TPR)根据系统时钟频率和目标SCL频率计算得出,直接决定了通信速率。
从设备部分的核心寄存器则包括I2CSOAR (Slave Own Address)、I2CSCSR (Slave Control/Status)和I2CSDR (Slave Data),用于设置自身地址、响应主设备请求和交换数据。
此外,模块还提供了I2CFIFOCTL、I2CFIFODATA等寄存器来管理8字节深的发送/接收FIFO,以及I2CMIMR、I2CMRIS等寄存器用于丰富的中断管理。理解每个寄存器的位域定义,是进行精准控制和高效编程的基础。
3. SCL时钟配置:从标准模式到高速模式的参数计算
I2C通信的时序由SCL时钟严格规定。在TM4C1292NCZAD中,SCL的频率并非直接设置,而是通过配置I2CMTPR寄存器中的TPR值来间接生成的。其背后的时钟生成电路基于一个可编程的定时器,计算公式是理解配置的关键:
SCL_PERIOD = 2 × (1 + TIMER_PRD) × (SCL_LP + SCL_HP) × CLK_PRD
其中:
SCL_PERIOD:一个SCL时钟周期的总时间。TIMER_PRD:即写入I2CMTPR寄存器的值(TPR)。SCL_LP:SCL低电平相位的时间单位数,在标准/快速/快速Plus模式下固定为6。SCL_HP:SCL高电平相位的时间单位数,在标准/快速/快速Plus模式下固定为4。CLK_PRD:系统时钟周期(例如,对于20MHz系统时钟,CLK_PRD = 1/20MHz = 50 ns)。
SCL频率F_SCL = 1 / SCL_PERIOD。
由此可以推导出TPR的计算公式:TPR = (System_Clock / (2 × (SCL_LP + SCL_HP) × F_SCL)) - 1
3.1 标准、快速与快速Plus模式配置
在这三种模式下,SCL_LP=6,SCL_HP=4。假设系统时钟为20 MHz,我们需要配置为标准模式(100 kbps):TPR = (20,000,000 / (2 × (6+4) × 100,000)) - 1 = (20,000,000 / (2 × 10 × 100,000)) - 1 = (20,000,000 / 2,000,000) - 1 = 10 - 1 = 9因此,向I2CMTPR寄存器写入0x09即可。
对于快速模式(400 kbps):TPR = (20,000,000 / (2 × 10 × 400,000)) - 1 = (20,000,000 / 8,000,000) - 1 = 2.5 - 1 = 1.5TPR必须为整数,因此需要取整。通常向下取整(TPR=1)会得到高于目标值的频率,向上取整(TPR=2)会得到低于目标值的频率。根据数据手册的示例表格,对于20MHz系统时钟,400kbps对应的TPR为2,此时实际频率约为333kHz。若需精确达到400kbps,可能需要调整系统时钟频率。开发者应参考数据手册中的预计算表格进行快速查用。
3.2 高速模式(Hs-mode)的特殊配置
高速模式是I2C协议中的一个特殊分支。在TM4C1292NCZAD中启用高速模式,需要两个步骤:
- 配置高速时钟:在高速模式下,
SCL_LP=2,SCL_HP=1。公式变为:SCL_PERIOD = 2 × (1 + TIMER_PRD) × (2 + 1) × CLK_PRD。例如,要获得3.33 Mbps的速率,系统时钟为80 MHz(CLK_PRD=12.5 ns):TPR = (80,000,000 / (2 × 3 × 3,330,000)) - 1 ≈ (80,000,000 / 19,980,000) - 1 ≈ 4.00 - 1 = 3因此,需向I2CMTPR写入0x03。 - 发送主设备代码(Master Code):高速传输不能直接开始。主设备必须先以标准或快速模式发送一个特定的“主设备代码”字节(格式为00001XXX),通知总线上的高速从设备即将切换到高速模式。这个字节不应被任何从设备应答(NACK)。在TM4C1292NCZAD中,这通过���置I2CMCS寄存器中的HS位并执行一次特殊的传输命令来完成。具体操作是:将主设备代码写入I2CMSA,然后向I2CMCS写入0x13(用于标准高速传输)或0x50(用于高速突发传输)。此操作完成后,HS位会自动被硬件清除,后续的所有数据传输(直到下一个停止条件)都将以高速模式进行,而无需再设置HS位。
实操心得:高速模式对硬件有更高要求。除了精确的TPR计算,还必须确保SDA和SCL线有足够强的上拉(通常需要更小的上拉电阻,如1kΩ),以应对高速切换下的总线电容充电需求。布线时也应尽量缩短走线,减少寄生电容。在实际项目中,如果通信距离稍长或负载较多,高速模式可能不稳定,此时适度降低目标频率或换用快速模式Plus往往是更稳妥的选择。
4. 主设备通信流程与命令序列详解
掌握了时钟配置后,我们来看如何发起一次具体的I2C通信。TM4C1292NCZAD的I2C主设备操作遵循一套严谨的软件流程,核心是通过组合配置I2CMSA和I2CMCS寄存器来触发硬件状态机的转换。数据手册中提供的流程图(如Master Single TRANSMIT)是极佳的指导,但其背后的寄存器操作逻辑需要清晰理解。
4.1 单字节发送(Master Single Transmit)
这是最基本的操作,用于向从设备写入一个字节的数据。
- 等待总线空闲:读取I2CMCS寄存器,检查BUSBSY位是否为0。如果总线忙,需要等待或处理错误。
- 设置从机地址和方向:将目标从设备的7位地址左移一位,并与R/W位(0表示写)进行或运算,结果写入I2CMSA寄存器。例如,向地址0x3B(二进制0111011)写数据,则写入
(0x3B << 1) | 0x00 = 0x76。 - 准备待发数据:将数据字节写入I2CMDR寄存器。
- 发起传输命令:向I2CMCS寄存器写入命令字
0x07(二进制00000111)。这个值的含义是:RUN=1(启动操作),START=1(产生起始条件),STOP=1(传输后产生停止条件),ACK=X(此模式下忽略),HS=0,QCMD=0,BURST=0。 - 等待传输完成:轮询I2CMCS寄存器的BUSY位,直到其变为0,表示本次单次传输操作已完成。
- 检查错误:读取I2CMCS寄存器,检查ERROR位和ADRACK(地址无应答)、DATACK(数据无应答)位,确认传输是否成功。
4.2 单字节接收(Master Single Receive)
从从设备读取一个字节。
- 等待总线空闲:同发送流程。
- 设置从机地址和方向:地址左移一位后,与R/W位(1表示读)进行或运算。例如,读取地址0x3B的数据,则写入
(0x3B << 1) | 0x01 = 0x77。 - 发起接收命令:向I2CMCS写入命令字
0x07(与单字节发送相同)。注意,此时I2CMDR寄存器内容无关。 - 等待接收完成:轮询BUSY位至0。
- 读取数据:从I2CMDR寄存器中读取接收到的数据字节。
- 检查错误:主要检查ERROR和ADRACK位。
4.3 多字节传输与重复起始条件
实际应用中,连续读写多个字节更为常见。这时就不能在每次字节传输后都发送停止条件,而是使用重复起始条件(Repeated START)。它是在不释放总线控制权(不发送停止条件)的情况下,重新发起一次起始条件,常用于改变数据传输方向(例如,先写入设备寄存器地址,再读取该地址的数据)。
以“先写后读”为例,流程如下:
- 发送起始条件、从机地址(写方向)、数据字节(寄存器地址),但不发送停止条件(命令字中STOP=0,例如
0x03)。 - 发送一个重复起始条件,并改变方向为读。这通过再次写入I2CMSA(R/W位置1)和I2CMCS(命令字需包含START=1,例如
0x0B)来实现。 - 然后以接收模式读取多个字节,在最后一个字节接收后,主设备发送NACK并产生停止条件。
注意事项:在连续读取多个字节时,主设备需要在倒数第二个字节后发送ACK(ACK=1),在最后一个字节后发送NACK(ACK=0),以告知从设备传输结束。TM4C1292NCZAD的I2CMCS寄存器中的ACK位就是用于控制这个行为的。在流程图中,这体现为不同阶段写入不同的命令字(ACK位不同)。
5. FIFO与µDMA机制:实现高效数据搬运
当需要传输大量数据时,如果每个字节都通过CPU轮询寄存器来操作,将极大消耗CPU资源并影响系统实时性。TM4C1292NCZAD的I2C模块内置的8字节深度的FIFO和与µDMA控制器的无缝集成,正是为了解决这一问题。
5.1 FIFO工作机制
I2C模块包含独立的发送(TX)和接收(RX)FIFO,每个深度为8字节。通过I2CFIFOCTL寄存器,可以将这两个FIFO灵活地分配给主设备或从设备使用。例如,在纯主设备发送场景下,可以将TX FIFO和RX FIFO都分配给主设备。
使用FIFO后,数据传输流程变为:
- 发送:CPU或µDMA可以一次性将多个数据字节写入I2CFIFODATA寄存器,数据会暂存在TX FIFO中。I2C硬件模块在总线空闲时,自动从FIFO中取出数据发送,无需CPU频繁干预。
- 接收:I2C硬件模块接收到的数据会自动存入RX FIFO。CPU或µDMA可以定期或通过中断从I2CFIFODATA寄存器中批量读取。
FIFO还支持可编程的触发阈值。例如,可以设置当RX FIFO中的数据达到4字节时产生中断,通知CPU或µDMA来读取,这比每收到1字节就中断一次效率高得多。
5.2 µDMA突发(Burst)传输模式
这是发挥I2C+FIFO性能潜力的关键。通过设置I2CMCS寄存器中的BURST位,并预先在I2CMBLEN寄存器中设置好本次突发传输的总字节数,可以启动µDMA辅助的连续传输。
- 发送突发:在启动BURST命令前,软件或µDMA可以预先填充一部分数据到TX FIFO。当BURST启动后,I2C模块会根据FIFO的空闲程度,自动向µDMA控制器发出传输请求(
dma_sreq单次请求或dma_req突发请求),µDMA则从内存中搬运数据到I2CFIFODATA寄存器,直至完成I2CMBLEN设定的字节数。 - 接收突发:I2C模块将接收到的数据存入RX FIFO。当FIFO中的数据量达到触发阈值时,向µDMA发出请求,µDMA将数据从I2CFIFODATA寄存器搬移到内存中。
I2CMBCNT寄存器是一个递减计数器,实时显示突发传输中剩余的字节数,方便软件查询进度。如果传输中途从设备返回NACK,且I2CMCS中的STOP位已设置,则传输终止;若STOP位未设置,则需要软件干预处理。
5.3 配置示例与避坑指南
假设我们需要使用主设备模式和µDMA,以突发方式发送100字节的数据到I2C从设备。
- 初始化:配置好I2C时钟(I2CMTPR)、GPIO复用等。
- 配置µDMA通道:设置µDMA通道的源地址(内存数组)、目的地址(I2CFIFODATA)、传输大小等。注意配置为基本模式或自动请求模式,并启用通道。
- 配置I2C FIFO:通过I2CFIFOCTL寄存器,将TX FIFO分配给主设备,并设置合适的触发阈值(例如,TX FIFO空余大于4字节时请求DMA)。
- 设置突发传输:写入目标从设备地址到I2CMSA(写方向)。将突发长度100写入I2CMBLEN寄存器。
- 启动传输:向I2CMCS寄存器写入命令字,该命令字需设置
START=1,BURST=1,而RUN=0(���突发模式下,RUN位不使用,必须为0)。例如,对于带起始条件的突发发送,命令字可能是0x48(二进制01001000,即START=1, BURST=1)。 - 等待完成:可以通过查询I2CMBCNT寄存器是否为0,或使能µDMA传输完成中断,亦或查询I2CMCS中的BUSY位和错误标志,来确定传输是否结束。
避坑技巧:
- FIFO重分配时机:数据手册强调,必须在FIFO为空时才能重新分配FIFO的所有权(通过TXASGNMT和RXASGNMT位)。否则可能导致数据错乱或FIFO功能异常。
- 中断屏蔽:在进行接收突发(RX Burst)时,建议先屏蔽TX FIFO空中断(清除I2CMIMR中的TXFEIM位),防止误触发。在开始TX FIFO传输前再取消屏蔽。
- 模式切换:避免在连续的事务中混合使用直接寄存器(I2CMDR/I2CSDR)访问和FIFO访问。最好为一种外设固定一种访问方式。
6. 中断管理与错误处理实战
轮询方式简单,但效率低下。在实际产品中,使用中断驱动是更优选择。TM4C1292NCZAD的I2C模块提供了丰富的中断源,分为主设备中断和从设备中断两组,通过I2CMIMR/I2CSIMR(中断屏蔽)、I2CMRIS/I2CSRIS(原始中断状态)和I2CMMIS/I2CSMIS(已屏蔽中断状态)寄存器进行管理。
6.1 关键中断源解析
主设备中断:
RIS:主设备事务完成。这是最常用的中断,表示一次单次或突发传输操作完成。ARBLOSTRIS:仲裁丢失。在多主系统中,当本设备与其他主设备同时发起传输且失去仲裁时触发。NACKRIS:无应答。发送的地址或数据未收到从设备的ACK响应。STOPRIS/STARTRIS:检测到总线上的停止/起始条件。在从设备模式下更有用,但在监听总线活动时也可用。DMARXRIS/DMATXRIS:µDMA接收/发送中断,指示DMA传输完成。TXRIS/RXRIS:TX/RX FIFO达到触发阈值。TXFERIS/RXFFRIS:TX FIFO空 / RX FIFO满。
从设备中断:
DATARIS:从设备事务相关中断,包含多种情况:收到自身地址、被请求发送数据、被请求接收数据等,需要结合状态寄存器进一步判断。
6.2 中断服务程序(ISR)设计要点
一个健壮的I2C中断处理流程通常如下:
- 读取状态:在ISR中,首先读取I2CMMIS(主设备)或I2CSMIS(从设备)寄存器。这个寄存器只显示已使能且已发生的中断,便于快速判断中断源。
- 分支处理:根据中断标志位,跳转到相应的处理例程。
- 如果是
RIS(事务完成),则读取数据(如果是接收)或准备下一批数据(如果是发送),并清除相应的中断标志(通过写I2CMICR寄存器对应位)。 - 如果是
NACKRIS,说明通信失败。应读取I2CMCS中的ADRACK或DATACK位判断是地址错误还是数据错误,然后根据应用逻辑决定重试、报错还是切换从设备。 - 如果是
ARBLOSTRIS,说明总线竞争失败。通常的处理方式是稍作延迟后重试发送起始条件。 - 如果是FIFO阈值中断,则进行相应的数据填充或读取操作。
- 如果是
- 清除中断:通过向I2CMICR(主)或I2CSICR(从)寄存器的对应位写1来清除中断标志。务必在ISR结束前完成此操作,否则会导致中断持续触发。
6.3 常见错误排查与调试技巧
- 总线锁死(Bus Hang):这是最令人头疼的问题。表现为SCL线被持续拉低,总线无法恢复。可能原因:
- 从设备故障,在传输中崩溃并持续拉低SCL。
- 主设备在发送停止条件前发生异常复位。
- 解决方法:TM4C1292NCZAD的I2C模块提供了总线超时(Clock Timeout)功能。通过配置I2CMCLKOCNT寄存器,可以设置SCL线被拉低的最长时间。一旦超时,模块会产生CLKTO中断,并尝试通过内部逻辑复位总线状态。在软件上,可以在初始化时使能此功能。作为最后手段,也可以尝试临时切换GPIO引脚模式,手动产生几个时钟脉冲来“唤醒”从设备。
- 通信速度不达标或出错:
- 检查TPR计算:确保I2CMTPR寄存器的值根据系统时钟频率正确计算。使用示波器测量实际的SCL频率进行验证。
- 检查上拉电阻:速度越高,所需上拉电阻越小。在高速模式下,1kΩ-2.2kΩ是常见选择。用示波器观察SDA/SCL信号的上升沿,如果上升沿过缓(圆角),说明上拉能力不足。
- 检查总线电容:过长的走线或连接过多的设备会增加总线电容,导致信号边沿变差。尽量缩短走线,并确保总电容在规范内(标准模式400pF,快速模式400pF,高速模式通常要求更低)。
- 从设备无应答:
- 确认从设备地址是否正确(7位地址需要左移一位)。
- 确认从设备电源和复位是否正常。
- 使用逻辑分析仪抓取I2C波形,查看起始条件、地址帧、ACK位是否符合预期。这是定位I2C问题最直接有效的方法。
7. 从设备模式配置与快速命令解析
虽然大多数时候微控制器作为I2C主设备,但理解从设备模式对于实现多主系统或设备间对等通信至关重要。TM4C1292NCZAD的I2C模块可以同时独立地作为主设备和从设备运行。
7.1 从设备基本配置
- 设置自身地址:将本设备的7位I2C地址写入I2CSOAR寄存器。模块可以响应两个地址,第二个地址可写入I2CSOAR2。
- 使能从设备:向I2CSCSR寄存器写入
0x0001,这将设置DA(Device Active)位,使能从设备响应。 - 中断或轮询:可以使能
DATARIS等中断,或者在循环中轮询I2CSCSR寄存器的RREQ(接收请求)和TREQ(发送请求)位。- 当
RREQ=1时,表示主设备正在向本从设备写数据,应从I2CSDR寄存器读取数据。 - 当
TREQ=1时,表示主设备正在从本从设备读数据,应向I2CSDR寄存器写入待发送的数据。
- 当
7.2 快速命令(Quick Command)处理
快速命令是I2C协议中一种特殊的单字节通信形式。主设备发送一个地址字节(R/W位指示方向)后,不发送数据字节,而是直接产生停止条件。对于从设备而言:
- 如果收到的是快速写命令(R/W=0),则意味着主设备只是“ping”了一下从设备,通常用于检测从设备是否存在。从设备应正常应答地址,并在检测到停止条件后,通过
STOPRIS中断或查询得知命令结束。 - 如果收到的是快速读命令(R/W=1),情况则特殊一些。如数据手册所述,当主设备发送快速读命令时,从设备的
DATARIS位会被置位,通知从设备需要向I2CSDR寄存器写入一个数据字节,且该字节的最高位(bit 7)必须置1。手册建议进行一次“虚拟写”操作,即向I2CSDR写入0xFF。之后,STOP中断产生,并且QCMDST和QCMDRW状态位会被置位,表明发生了一次快速命令读操作。
注意事项:从设备在响应快速读命令时,写入I2CSDR的数据(bit 7为1)实际上并不会被发送到总线上,因为主设备在发送地址并收到ACK后,会立刻产生停止条件。这个机制是硬件要求的特定行为,软件只需遵循即可。在设计从设备固件时,需要对快速命令这种特殊情况做专门处理。
8. 回环测试与实战初始化代码剖析
在驱动开发初期或硬件调试阶段,回环测试(Loopback)是一个极其有用的功能。TM4C1292NCZAD的I2C模块支持内部回环模式,无需外部连接,即可验证软件配置和基本通信流程是否正确。
8.1 启用回环模式
通过设置I2C Master Configuration (I2CMCR)寄存器中的LPBK位为1,即可使能内部回环。在此模式下,主设备模块的SDA和SCL输出在内部直接连接到从设备模块的输入,形成一个自闭环。你可以编写测试代码,让主设备向一个虚拟的从设备地址发送数据,然后切换为从设备模式(或使用另一个I2C实例的从设备)来接收,从而验证整个数据通路。
8.2 完整初始化与单字节发送示例
以下是一个基于TM4C1292NCZAD,配置I2C0为主设备,在标准模式下发送一个字节数据的完整C代码示例,结合了之前的理论分析:
#include <stdint.h> #include "tm4c1292nczad.h" // 包含设备头文件 #define I2C0_MASTER_BASE 0x40020000 #define SYS_CLK_FREQ 20000000 // 假设系统时钟20MHz #define I2C_TARGET_ADDR 0x3B // 7位从设备地址 #define I2C_STANDARD_MODE 100000 // 100 kHz void I2C0_MasterInit(void) { // 1. 使能I2C0和外设GPIO端口(假设使用PA6-SCL, PA7-SDA) SYSCTL->RCGCI2C |= 0x01; // 使能I2C0时钟 SYSCTL->RCGCGPIO |= 0x01; // 使能GPIO Port A时钟 __asm__ volatile("NOP"); // 等待时钟稳定 __asm__ volatile("NOP"); __asm__ volatile("NOP"); // 2. 配置GPIO引脚为I2C功能 GPIOA->AFSEL |= 0xC0; // 使能PA6、PA7的复用功能 GPIOA->ODR |= 0x80; // 配置PA7 (SDA) 为开漏输出 GPIOA->PCTL &= ~0xFF000000;// 清除PA6、PA7的引脚控制位 GPIOA->PCTL |= 0x33000000; // 配置PA6、PA7为I2C功能 (0x3) GPIOA->DEN |= 0xC0; // 使能PA6、PA7的数字功能 // 3. 初始化I2C主设备 I2C0_MASTER->MCR = 0x0010; // 初始化主设备,使能I2C模块 // 4. 配置SCL时钟频率 (标准模式 100kHz @ 20MHz SysClk) // TPR = (20,000,000 / (2 * (6+4) * 100,000)) - 1 = 9 uint32_t tpr = (SYS_CLK_FREQ / (20 * I2C_STANDARD_MODE)) - 1; I2C0_MASTER->MTPR = tpr; // 写入定时器周期值 // 5. (可选) 使能所需的中断,此处以轮询为例,故不使能 } uint8_t I2C0_MasterSendByte(uint8_t slaveAddr, uint8_t data) { // 等待总线空闲 while(I2C0_MASTER->MCS & 0x40) {} // 检查BUSBSY位 // 设置从机地址和写方向 I2C0_MASTER->MSA = (slaveAddr << 1) & 0xFE; // R/W位为0(写) // 将要发送的数据放入数据寄存器 I2C0_MASTER->MDR = data; // 发起单次发送命令:START, RUN, STOP I2C0_MASTER->MCS = 0x07; // 二进制: 0000 0111 // 等待传输完成 while(I2C0_MASTER->MCS & 0x01) {} // 检查BUSY位 // 检查错误 if(I2C0_MASTER->MCS & 0x02) { // 检查ERROR位 // 可进一步检查ADRACK或DATACK位确定错误类型 return 1; // 发送失败 } return 0; // 发送成功 } int main(void) { I2C0_MasterInit(); uint8_t dataToSend = 0xAA; if(I2C0_MasterSendByte(I2C_TARGET_ADDR, dataToSend) == 0) { // 发送成功处理 } else { // 发送失败处理 } while(1){} }这段代码清晰地展示了从时钟使能、GPIO配置、时钟计算到发起一次完整通信的每一步。在实际项目中,需要将错误处理、中断服务、超时重试等机制补充完善。通过深入理解每个寄存器位的含义和协议状态机的跳转,开发者就能灵活运用TM4C1292NCZAD强大的I2C外设,构建稳定高效的嵌入式通信网络。