SSI与I2C寄存器配置全解析:从FIFO到总线仲裁的嵌入式通信实战

发布时间:2026/7/26 1:53:35
SSI与I2C寄存器配置全解析:从FIFO到总线仲裁的嵌入式通信实战 1. 项目概述在嵌入式系统开发中串行通信接口是连接微控制器与各类传感器、存储器和外设的“血管”。其中同步串行接口SSI和I2C总线是两种应用极其广泛但又设计迥异的通信协议。我接触过不少项目从简单的温湿度传感器数据采集到复杂的多节点工业控制网络都离不开对这两种接口的深入理解和精准配置。很多新手工程师拿到芯片手册看到一堆寄存器描述时常常感到无从下手其实只要理解了其核心设计逻辑配置起来就会得心应手。本文将以德州仪器TICC26x0/CC13x0系列芯片的官方文档为蓝本结合我多年的调试经验为你深入拆解SSI和I2C接口的寄存器配置细节与通信原理。无论你是正在调试一块新的传感器板卡还是试图优化现有系统的通信效率理解DR寄存器如何与FIFO交互、I2C的仲裁机制如何避免总线冲突都是绕不开的实战课题。我们将从最底层的寄存器位域讲起一直延伸到实际应用中的配置流程和避坑指南目标是让你看完后不仅能读懂手册更能写出稳定、高效的驱动代码。2. SSI接口核心机制与寄存器深度解析SSI全称Synchronous Serial Interface是一种全双工、同步的串行通信接口。它依赖独立的时钟线SCLK来同步数据线上的位传输这意味着通信双方必须共享同一个时钟源通常由主机Master提供。这种设计带来了高速度和强抗干扰性非常适合ADC、DAC、数字音频接口如I2S其变种之一以及高速存储器等场景。其核心围绕着几个关键寄存器展开它们共同构成了SSI模块的“控制中枢”。2.1 数据寄存器DR数据传输的枢纽数据寄存器DR Offset 8h是SSI接口中与用户程序交互最频繁的寄存器。它扮演着数据进出FIFO缓冲区的“门户”角色。2.1.1 读写操作的本质很多人容易误解认为直接读写DR寄存器就是在直接操纵收发引脚。实际上DR寄存器是FIFOFirst In, First Out缓冲区的访问窗口。这一点至关重要。写操作发送数据当你向DR寄存器写入一个16位数据时这个数据实际上被存放到了发送FIFO中位置由当前的写指针决定。发送逻辑会从FIFO中逐个取出数据加载到内部的发送移位寄存器中然后在SCLK的节拍下将数据一位一位地从TXD引脚移出。手册中特别强调“When written, the entry in the transmit FIFO, pointed to by the write pointer, is written to.” 这清晰地表明了其FIFO缓冲特性。读操作接收数据当你从DR寄存器读取数据时你读取的是接收FIFO中队首的数据位置由当前的读指针决定。接收逻辑从RXD引脚串行移入数据组装成完整的数据帧后会将其放入接收FIFO中。“When read, the entry in the receive FIFO, pointed to by the current FIFO read pointer, is accessed.”2.1.2 数据对齐与“右对齐”原则SSI支持可配置的数据位宽通过CR0寄存器的DSS字段设置例如8位、12位、16位。当数据位宽小于16位时操作DR寄存器有一个必须遵守的“右对齐”规则。发送时你必须将有效数据放在DR寄存器的低有效位高位补零。例如如果你配置为8位数据模式要发送数据0xA5则应写入0x00A5到DR寄存器。发送逻辑会自动忽略高8位15:8。如果你错误地写成了0xA500那么实际发送出去的将是0x00这会导致通信彻底失败。接收时硬件会自动帮你完成右对齐。无论接收到的是8位还是12位数据它都会被放置在DR寄存器的低有效位高位读取为0。这简化了软件处理流程。实操心得在编写发送函数时我习惯做一个数据对齐的强制转换。例如在8位模式下我会定义一个宏或内联函数#define SSI_DATA_ALIGN(x) ((uint16_t)(x) 0x00FF)。这能有效避免因疏忽导致的数据错位问题。另外在调试初期如果发现收发数据异常第一个要检查的就是数据对齐是否正确。2.2 状态寄存器SR通信状态的“仪表盘”状态寄存器SR Offset Ch提供了SSI模块实时运行状态的快照。它就像汽车仪表盘告诉你引擎是否在转、油箱是否满、是否有故障灯亮起。轮询这个寄存器或者在中断服务程序中检查是确保通信可靠性的关键。2.2.1 关键状态位详解SR寄存器包含几个核心状态位理解它们之间的逻辑关系对编写健壮的驱动至关重要BSYBit 4 - 串行接口忙这是最高级别的状态指示。当BSY1时表示SSI模块正在发送或接收一个完整的数据帧或者发送FIFO非空。这意味着即使主机CPU已经写完了所有数据只要发送FIFO里的数据还没完全发完BSY就会保持为1。在准备关闭SSI模块或进入低功耗模式前必须等待BSY变为0。TFEBit 0 - 发送FIFO空TNFBit 1 - 发送FIFO非满TFE1发送FIFO完全为空。这是一个安全信号表明所有数据都已物理发出。TNF1发送FIFO未满可以继续写入数据。在采用中断或DMA方式发送时通常检查TNF来判断是否可以填充下一个数据避免FIFO溢出Overrun。在查询方式下向FIFO写数据前也应检查TNF。RNEBit 2 - 接收FIFO非空RFFBit 3 - 接收FIFO满RNE1接收FIFO中至少有一个数据可读。这是触发读操作或接收中断的主要条件。RFF1接收FIFO已满。这是一个错误预警信号如果RFF1时还有新数据到来就会发生接收溢出Overrun新数据会丢失。稳健的驱动必须在RFF变1前及时读取数据。2.2.2 状态机的配合使用一个典型的查询式发送流程如下// 等待发送FIFO有空间 while(!(SSI0_SR_R SSI_SR_TNF)) { // 可选加入超时机制防止死循环 } // 写入待发送数据确保右对齐 SSI0_DR_R SSI_DATA_ALIGN(tx_data);一个典型的查询式接收流程如下// 检查是否有数据到达 if(SSI0_SR_R SSI_SR_RNE) { // 读取数据 rx_data SSI0_DR_R DATA_MASK; // 根据位宽使用掩码 }2.3 时钟预分频寄存器CPSR与中断控制寄存器组2.3.1 CPSR通信速率的“节拍器”时钟预分频寄存器CPSR Offset 10h用于生成SSI模块的内部工作时钟SSIClk。其公式为SSIClk SysClk / CPSDVSR其中CPSDVSR是CPSR寄存器中CPSDVSR字段的值。手册中有一个极易被忽略但至关重要的限制“The value programmed into this field must be an even non-zero number (2-254). The least significant bit of the programmed number is hard-coded to zero.”这意味着分频系数必须是偶数2, 4, 6, ..., 254。如果你写入一个奇数值例如3硬件会强制将其最低位置零实际生效的值将是2。这可能导致你计算出的波特率与实际波特率不符。不能设置为0或1。波特率计算示例假设系统时钟SysClk 50 MHz我们希望SSI波特率为5 Mbps。 所需分频系数CPSDVSR SysClk / SSIClk 50e6 / 5e6 10。 10是偶数符合要求。因此应向CPSR寄存器的CPSDVSR字段写入10。2.3.2 中断管理寄存器高效通信的“触发器”对于需要高效处理、非阻塞的通信中断是必不可少的。SSI提供了一组精细的中断控制寄存器中断屏蔽设置/清除寄存器IMSC Offset 14h用于使能或禁用特定中断源。例如设置TXIM1使能发送FIFO中断当发送FIFO空间充足时触发设置RXIM1使能接收FIFO中断当接收FIFO有数据时触发。RTIM和RORIM则分别对应接收超时和接收溢出错误中断。原始中断状态寄存器RIS Offset 18h反映中断源的原始状态无论IMSC是否屏蔽只要条件满足对应的位就会置1。例如当发送FIFO中的数据少于等于4个时TXRIS自动置1。屏蔽后中断状态寄存器MIS Offset 1Ch这是实际触发CPU中断的信号。MIS RIS IMSC。只有在IMSC中使能的中断其状态才会体现在MIS中并可能产生中断请求。中断清除寄存器ICR Offset 20h用于清除RTIM接收超时和RORIM接收溢出对应的原始中断状态位RIS中的RTRIS和RORRIS。注意发送和接收FIFO中断TXRIS/RXRIS不是通过写ICR清除的而是通过读写DR寄存器即操作FIFO来改变FIFO状态从而自动清除的。这是一个常见的误区。避坑指南在中断服务程序ISR中正确的操作顺序是1. 读取MIS寄存器判断中断源。2. 根据中断源进行相应处理如从DR读数据清除接收中断或向DR写数据填充发送FIFO。3. 如果是超时或溢出错误则需要向ICR的对应位写1以清除错误标志否则会持续触发中断。切勿在ISR中盲目清除所有中断标志。2.4 DMA控制寄存器DMACR解放CPU的“搬运工”当需要高速、大批量传输数据时频繁的中断仍会给CPU带来负担。此时直接内存访问DMA是理想选择。DMACR寄存器Offset 24h非常简单TXDMAE置1使能发送DMA。当发送FIFO有空闲位置时DMA控制器会自动从内存中搬运数据到DR寄存器。RXDMAE置1使能接收DMA。当接收FIFO中有数据时DMA控制器会自动将DR寄存器中的数据搬运到指定内存。配置DMA时需要同时设置DMA控制器的源/目标地址、传输数据量等。SSI的DMA请求信号与FIFO状态TNF/RNE紧密关联使得数据传输可以在硬件层面自动完成CPU得以处理其他任务。3. I2C总线协议精要与寄存器配置实战I2CInter-Integrated Circuit是一种多主从、半双工、串行、同步通信总线。它仅需两根线SDA-数据线SCL-时钟线就能连接多个设备在引脚资源紧张的嵌入式系统中大放异彩。其协议比SSI复杂包含了寻址、仲裁、应答等机制。3.1 I2C核心协议机制解析3.1.1 起止信号、数据有效性及应答这是I2C通信的“语法”必须严格遵守起始S与停止P条件SCL为高电平时SDA的下降沿表示起始条件SDA的上升沿表示停止条件。总线在起始条件后处于“忙”状态在停止条件后处于“空闲”状态。数据有效性在SCL高电平期间SDA线上的数据必须保持稳定只有SCL为低电平时SDA才允许变化。这保证了数据在时钟的上升沿被采样。应答ACK每个字节8位传输后跟随一个应答时钟脉冲。发送器在此脉冲期间释放SDA线接收器必须将SDA拉低以表示正确接收ACK。若接收器未拉低保持高电平则为非应答NACK通常意味着传输结束或出错。3.1.2 7位地址格式与数据传输一次完整的I2C数据传输帧结构如下[起始条件] [7位从机地址] [1位读写方向位(R/W)] [应答位] [数据字节] [应答位] ... [停止条件]其中R/W位为0表示主机向从机写数据发送为1表示主机从从机读数据接收。3.1.3 仲裁与时钟同步当多个主机同时尝试发起传输时仲裁机制确保只有一个主机胜出。仲裁发生在SDA线上每个主机在发送位的同时检测SDA线电平。如果某个主机发送了高电平‘1’但检测到SDA线为低电平‘0’说明有其他主机正在发送‘0’则该主机立即失去仲裁关闭其输出驱动器转为从机监听总线。仲裁可以持续多个位包括地址位和数据位。SCL线的“线与”特性实现了时钟同步所有主机都在SCL低电平期间准备由拉低SCL时间最长的主机决定低电平周期由最先释放SCL的主机决定高电平周期。3.2 I2C主模式关键寄存器与配置流程我们以TI CC26xx的I2C主模式寄存器为例解析如何驱动一次通信。3.2.1 主模式核心寄存器I2C主定时器周期寄存器I2C_MTPR用于配置SCL时钟频率。计算公式为SCL_PERIOD 2 × (1 TIMER_PRD) × (SCL_LP SCL_HP) × CLK_PRD其中SCL_LP和SCL_HP通常是固定值如6和4CLK_PRD是系统时钟周期TIMER_PRD是写入I2C_MTPR的值。手册提供了常用系统时钟下的参考值例如16MHz系统时钟下标准模式100kbps对应TIMER_PRD 0x07快速模式400kbps对应TIMER_PRD 0x01。I2C主从机地址寄存器I2C_MSA高7位存放目标从机地址最低位LSB存放R/W方向位0-写1-读。I2C主数据寄存器I2C_MDR存放待发送或已接收的数据。I2C主控制/状态寄存器I2C_MCTRL I2C_MSTATMCTRL的RUN、START、STOP、ACK位控制单次传输的启停和应答行为。MSTAT的BUSY、ERROR、ARBLST位反映传输状态、错误和仲裁丢失情况。3.2.2 主模式单字节发送配置流程详解参考手册21.4节的示例我们详细拆解将一个字节作为主机发送出去的每一步使能模块时钟这是第一步但常被遗忘。需要通过电源与时钟管理模块PRCM启用I2C模块的时钟域。使用库函数如PRCMPeripheralRunEnable(PRCM_PERIPH_I2C0)并执行PRCMLoadSet()使能设置生效。配置GPIO复用将对应引脚如GPIO_PIN2,GPIO_PIN3配置为I2C功能SDA和SCL。这两根线必须配置为**开漏输出Open-Drain**模式并启用内部上拉电阻或外接上拉电阻这是I2C总线“线与”特性的硬件基础。初始化主控器向I2C_MCR寄存器写入0x00000010。这个值通常表示使能I2C主模式具体位定义需查手册但关键是要确保主模式功能被激活。设置SCL时钟频率根据系统时钟和目标速率计算并写入I2C_MTPR。例如系统时钟24MHz目标100kbps计算如下TPR (24e6 / (2 * (64) * 100e3)) - 1 11。因此写入I2C_MTPR 0x0B。指定从机地址和操作方向假设从机地址为0x3B(7位地址为0x76 1)本次为写操作R/W0。则写入I2C_MSA 0x76。这里0x76是(0x3B 1) | 0的结果。装载待发送数据将数据字节例如0xAA写入I2C_MDR寄存器。启动传输向I2C_MCTRL寄存器写入0x07。这通常对应设置ACK0主机发送模式最后一个字节后发NACK此处需根据手册确认示例中ACKX表示任意STOP1本次传输后产生停止条件START1产生起始条件RUN1启动传输。这个组合命令意味着启动一次带起始和停止条件的单字节发送。等待传输完成轮询I2C_MSTAT寄存器的BUSY位直到它变为0。在中断方式中此步骤由中断服务程序替代。检查错误传输完成后检查I2C_MSTAT的ERROR位。如果为0表示从机已应答ACK传输成功。如果为1表示从机无应答NACK需要检查从机地址、连接或从机状态。实战技巧步骤7中的控制位组合是理解I2C主控操作的关键。START和STOP位控制着数据帧的边界。通过灵活组合例如START1, STOP0可以产生“重复起始条件”用于组合读写操作可以实现复杂的复合传输。务必参考手册中的流程图如图21-7至21-12来编写不同场景下的驱动序列。3.3 I2C中断处理与从机模式要点3.3.1 主模式中断处理I2C主中断主要用于通知一次传输发送或接收的完成。使能主中断需要设置I2C_MIMR寄存器。中断发生后在中断服务程序中检查I2C_MSTAT的ERROR和ARBLST位判断是否发生错误或仲裁丢失。如果是接收完成中断从I2C_MDR读取数据。清除中断标志通常通过写I2C_MICR寄存器的特定位完成。3.3.2 从机模式简述从机模式的配置相对简单但需要实时响应主机的呼叫。设置自身地址通过I2C_SOAR寄存器设置本设备作为从机时的7位地址。响应数据请求当主机寻址到本设备并发出读请求R/W1时从机的I2C_SSTAT寄存器中的TREQ位会置位表示主机请求数据。此时从机程序应将待发送数据写入I2C_SDR寄存器。接收数据当主机寻址到本设备并发出写请求R/W0时从机在接收到数据后会产生中断或置位状态位RREQ从机程序应从I2C_SDR中读取数据。检测起止信号从机可以通过I2C_SRIS/I2C_SMIS寄存器检测到总线上的起始和停止条件这对于某些需要感知总线状态的从机应用很有用。4. SSI与I2C应用对比与选型指南虽然都是串行通信但SSI和I2C的设计哲学和应用场景有显著区别。特性维度SSI (Synchronous Serial Interface)I2C (Inter-Integrated Circuit)通信方式全双工同步有独立时钟线半双工同步时钟由主机提供总线拓扑通常点对点或一主一从多主多从总线式结构信号线数量至少3线SCLK, TXD, RXD有时加片选CS2线SDA, SCL速度通常较高可达数十Mbps标准模式100kbps快速模式400kbps高速模式可达3.4Mbps通信距离较短高速时受时钟同步限制较短受总线电容限制加驱动器可延长硬件复杂度相对简单主从双方需时钟同步协议复杂需支持仲裁、时钟同步、应答软件开销较低协议简单主要是数据搬运较高需处理寻址、协议状态、错误恢复典型应用高速ADC/DAC、音频编解码器I2S、Flash存储器、数字传感器低速传感器温湿度、压力、EEPROM、RTC、IO扩展芯片、LCD控制器选型建议追求速度、点对点通信选择SSI或其衍生协议如SPI。例如驱动一个高速的ADC芯片或NOR Flash。连接多个低速外设、引脚资源极度紧张选择I2C。例如在单片机上挂载一个温度传感器、一个EEPROM和一个IO扩展芯片总共只需2个引脚。需要长距离通信两者都不擅长。应考虑RS-485、CAN或工业以太网等。系统中有多个潜在的主控器如果需要多主架构I2C是内置支持的选择。SSI通常是一主一从多主需要额外的冲突管理机制。5. 常见问题排查与调试心得在实际项目中调试串行通信接口总会遇到各种问题。以下是我总结的一些常见故障点和排查思路。5.1 SSI常见问题问题数据收发全为0或乱码。检查时钟首先用示波器或逻辑分析仪测量SCLK引脚。确认时钟是否存在、频率是否正确、极性CPOL和相位CPHA是否与从设备匹配。SSI的时钟极性和相位配置通常在另一个控制寄存器如CR0中这是最容易出错的地方之一。检查数据对齐确认数据位宽DSS设置并严格遵守DR寄存器的右对齐规则。发送和接收的位宽必须一致。检查FIFO状态在查询方式下确保在写DR前检查TNF在读DR前检查RNE。在中断方式下检查中断是否正确使能并触发。问题只能发送一次数据后续发送失败。检查BSY位在每次发起新传输前确保BSY位为0。如果BSY一直为1可能是之前的传输未完成如FIFO未空或模块处于错误状态。检查发送FIFO确认是否在发送完成后清空了发送FIFO的相关状态。在某些配置下如果FIFO未完全发完就禁用模块可能导致状态卡死。问题接收数据丢失溢出。监控RFF位这是接收FIFO满的标志。如果程序读取数据的速度跟不上接收速度RFF会置1此时新数据会丢失。优化数据读取逻辑或使用DMA。确保接收中断的优先级足够高服务程序执行要快。5.2 I2C常见问题问题总线死锁SCL被持续拉低。这是I2C调试中最经典的问题。原因通常是从设备在传输中发生异常如程序跑飞未能完成当前字节的传输从而将SCL线钳位在低电平Clock Stretching。排查方法用示波器观察SDA和SCL。如果SCL持续为低而SDA状态固定基本可断定是某从设备死锁。软件恢复尝试作为主机在软件中模拟产生多个SCL时钟脉冲需将SCL引脚临时配置为推挽输出手动产生9个以上的时钟同时监视SDA直到从设备释放总线。许多MCU的I2C模块硬件也支持此恢复功能。硬件预防为每个I2C从设备设计电源管理必要时可对其进行硬件复位。问题主机发送地址后无应答NACK。检查从机地址确认7位地址是否正确是否包含了R/W位。用逻辑分析仪抓取波形直接看发出的地址字节。检查物理连接测量SDA和SCL线的上拉电压是否正常通常为3.3V或5V。上拉电阻值是否合适常用4.7kΩ总线电容大时需减小。确保从设备已正确上电。检查从设备状态某些从设备如EEPROM在写周期内会不响应需要等待其内部操作完成。问题通信速度不稳定或错误率随速度升高而增加。检查总线电容I2C总线有最大容限通常400pF左右。线缆过长、连接设备过多都会增加电容导致上升沿变缓破坏数据时序。解决方法缩短走线、减少设备、使用更小的上拉电阻如2.2kΩ或增加I2C总线驱动器。检查时序参数确保主机配置的SCL高低电平时间满足所有从设备的最小时序要求。在快速模式下尤其要注意。5.3 通用调试工具与技巧逻辑分析仪是必备神器Saleae、DSLogic等廉价逻辑分析仪配合PulseView或DSView软件可以直观地解码SSI/I2C波形直接看到地址、数据、起始停止位、ACK/NACK极大提升调试效率。没有逻辑分析仪调试串行通信如同盲人摸象。示波器看模拟特性当怀疑信号完整性时如过冲、振铃、边沿太缓需要用示波器观察波形。分而治之如果条件允许先用一个已知好的设备如一块成熟的开发板与你的从设备通信验证从设备本身是否正常。或者用你的主机去连接一个已知好的从设备如常见的EEPROM芯片验证主机配置是否正确。编写鲁棒的驱动在驱动层加入超时机制。任何等待状态如等待BSY变低、等待总线空闲都必须有超时退出和错误返回避免程序因硬件故障而永久卡死。