TMS320F28335串行通信接口(SCI/SPI/I2C)配置与调试实战指南

📅 2026/7/27 1:30:31 👁️ 阅读次数 📝 编程学习
TMS320F28335串行通信接口(SCI/SPI/I2C)配置与调试实战指南

1. 项目概述与核心价值

在嵌入式系统开发,尤其是工业控制、电机驱动和数字电源这些对实时性和可靠性要求极高的领域,TMS320F28335这颗德州仪器(TI)的经典DSP芯片是很多工程师的老朋友。它的强大性能不仅体现在200MHz的主频和浮点运算单元上,更在于其丰富且灵活的外设资源。其中,串行通信接口(SCI、SPI、I2C)是连接芯片与外部世界、构建复杂系统网络的“咽喉要道”。

很多新手,甚至是有一定经验的工程师,在面对F28335的串口配置时,常常会陷入一种困境:手册上的寄存器列表和公式看起来都懂,但一上手调试,通信就是不通,或者数据时对时错。问题往往出在对这些接口底层工作机制和配置细节的理解不够透彻。比如,为什么SCI的波特率计算要分BRR是否为0两种情况?SPI的时钟极性和相位到底怎么组合才匹配从设备?GPIO复用配置时,那个让人头疼的输入量化(Qualification)到底在什么场景下必须用?

这篇文章,我就结合自己多年在电机控制器和逆变器项目上“踩坑”的经验,把F28335的这三个核心串行通信接口掰开揉碎了讲清楚。我们不只讲寄存器怎么填,更要讲清楚每个配置项背后的“为什么”,以及在实际工程中,如何根据你的具体需求(比如通信距离、抗干扰要求、从设备特性)做出最合适的选择和配置。目标是让你读完以后,不仅能配通通信,更能理解其原理,在遇到问题时能快速定位根源。

2. 串行通信接口(SCI)深度解析与实战配置

SCI是F28335上最常用的异步串行通信接口,也就是我们常说的UART。它的特点是通信双方没有统一的时钟线,依靠事先约定好的波特率进行数据传输,因此硬件连接简单(仅需TX和RX两根线),非常适合与上位机、调试终端或其他微控制器进行中低速、中远距离的数据交换。

2.1 SCI核心工作机制与寄存器精讲

F28335提供了三个独立的SCI模块(SCI-A, SCI-B, SCI-C),每个模块的功能完全一致。理解其工作,核心是抓住几个关键点:双缓冲、NRZ格式和可编程波特率。

双缓冲机制:这是确保通信效率和数据完整性的关键。无论是发送还是接收,都有两级缓冲区:一个数据缓冲寄存器(SCITXBUF/SCIRXBUF)和一个移位寄存器(TXSHF/RXSHF)。当你向SCITXBUF写入一个字节后,CPU就可以去处理其他任务,硬件会自动将这个字节加载到TXSHF中,并按位从SCITXD引脚发送出去。接收过程反之亦然。这种设计避免了因CPU处理不及时而导致的数据覆盖(Overrun)或发送延迟,是实现中断驱动通信的基础。

NRZ格式与数据帧:SCI采用标准的非归零(NRZ)格式。一帧数据通常由1个起始位(低电平)、5-8个数据位、1个可选的奇偶校验位和1-2个停止位(高电平)组成。这些格式都在**SCICCR(通信控制寄存器)**中配置。例如,SCICCR.5-3位决定数据位长度,SCICCR.2位决定是否启用奇偶校验,SCICCR.1位决定奇校验还是偶校验。

波特率计算——最容易出错的地方:波特率发生器是SCI的“心脏”,其时钟源是低速外设时钟LSPCLK。手册给出的公式是:

  • 当波特率寄存器BRR(由SCIHBAUDSCILBAUD组成)不为0时:波特率 = LSPCLK / [(BRR + 1) * 8]
  • BRR为0时:波特率 = LSPCLK / 16

这里有一个至关重要的细节:LSPCLK默认等于SYSCLKOUT/4,但它是可以通过系统控制寄存器配置分频的。在计算波特率前,你必须先确认系统中LSPCLK的实际频率。假设系统主频SYSCLKOUT为150MHz,默认LSPCLK为37.5MHz。如果你想得到115200的波特率,计算过程如下:

  1. 计算目标分频系数:N = LSPCLK / (波特率 * 8) = 37.5e6 / (115200 * 8) ≈ 40.69
  2. 计算BRR值:BRR = N - 1 = 39.69,取整为40。
  3. 验算实际波特率:实际波特率 = 37.5e6 / [(40+1)*8] = 114332.5,误差约为0.75%,在异步通信允许的误差范围内(通常<2%即可)。

注意:波特率误差是异步通信稳定的关键。误差过大会导致采样点偏移,最终产生帧错误。对于高波特率(如921600)或非标准波特率,需要仔细计算并可能调整LSPCLK的分频比。

2.2 增强功能:FIFO与自动波特率检测

除了基本功能,F28335的SCI还提供了两个非常实用的增强功能:16级FIFO和自动波特率检测。

16级FIFO:这是对双缓冲机制的极大增强。通过配置SCIFFTXSCIFFRXSCIFFCT寄存器,可以启用发送和接收FIFO。启用后,你可以连续向FIFO写入最多16个字节的数据,硬件会依次发送,大大减少了CPU中断的频率,提升了大数据块传输的效率。例如,在通过Modbus RTU协议与多个传感器通信时,启用接收FIFO并设置一个合适的触发深度(如8字节),可以确保一帧完整的数据包接收完成后才产生一次中断,让CPU处理更高效。

自动波特率检测:这个功能在需要与未知波特率设备建立初始通信的场景下非常有用(比如Bootloader)。其原理是检测起始位下降沿的宽度。启用该功能(SCICTL2.5位)后,SCI模块会测量起始位的持续时间,并自动计算出对应的波特率,更新到波特率寄存器中。使用时,主机需要发送一个特定的同步字符(通常是0x550xAA,其二进制位包含连续的01跳变),从机在自动检测模式下去测量并锁定波特率。

2.3 实战配置步骤与代码示例

下面以SCI-A配置为115200波特率、8位数据、无校验、1位停止位、启用发送中断为例,展示典型的初始化流程。这里假设使用CPU定时器0进行简单的延时。

// 首先,在系统初始化阶段正确配置LSPCLK // 假设SYSCLKOUT = 150MHz, 希望LSPCLK = 37.5MHz (即四分频) // 这通常在InitSysCtrl()函数中通过配置HISPCP和LOSPCP寄存器完成 void InitSciA(void) { // 1. 使能SCI-A时钟 (在PCLKCR0寄存器中) EALLOW; // 解除寄存器保护 SysCtrlRegs.PCLKCR0.bit.SCIAENCLK = 1; // 使能SCI-A外设时钟 EDIS; // 2. 配置GPIO复用为SCI功能 (GPIO28->RX, GPIO29->TX) EALLOW; GpioCtrlRegs.GPAMUX2.bit.GPIO28 = 1; // 将GPIO28配置为SCIRXDA功能 GpioCtrlRegs.GPAMUX2.bit.GPIO29 = 1; // 将GPIO29配置为SCITXDA功能 // 注意:根据具体硬件连接,可能需要配置上拉/下拉电阻(GPAPUD寄存器) EDIS; // 3. 初始化SCI-A寄存器 (注意:先软复位,再配置) SciaRegs.SCICCR.all = 0x0007; // 1位停止位,无校验,8位数据,异步模式 // 计算波特率寄存器值 BRR = 40 (对于LSPCLK=37.5MHz, 目标115200) SciaRegs.SCIHBAUD = 0x0000; // BRR高字节为0 SciaRegs.SCILBAUD = 0x0028; // BRR低字节为40 (0x28) // 4. 配置控制寄存器 SciaRegs.SCICTL1.all = 0x0003; // 使能发送器和接收器,禁止休眠模式 // 如果需要错误中断,可以配置SCICTL1.6 (RX ERR INT ENA) SciaRegs.SCICTL2.all = 0x0002; // 使能发送中断(TX INT ENA),接收中断由SCICTL2.1单独控制 SciaRegs.SCICTL2.bit.RXBKINTENA = 0; // 本例不使能接收中断,采用查询方式 // 5. 可选:配置FIFO SciaRegs.SCIFFTX.all = 0xE040; // 使能SCI FIFO,复位TXFIFO,TX中断级别设为0(每发送1字产生中断) SciaRegs.SCIFFRX.all = 0x2040; // 复位RXFIFO,RX中断级别设为0(每接收1字产生中断) SciaRegs.SCIFFCT.all = 0x0000; // 禁止自动波特率检测,FIFO发送延迟为0 // 6. 最后,重新使能SCI SciaRegs.SCICTL1.bit.SWRESET = 1; // 退出复位状态,SCI开始工作 } // 发送一个字符的函数(查询方式) void scia_send_char(char c) { while (SciaRegs.SCICTL2.bit.TXRDY != 1) {} // 等待发送缓冲区就绪 SciaRegs.SCITXBUF = c; } // 发送字符串的函数 void scia_send_string(char *s) { while (*s != '\0') { scia_send_char(*s++); } }

3. 串行外设接口(SPI)主从模式详解与时钟方案

SPI是一种高速、全双工、同步的串行通信总线。与SCI不同,SPI通信双方共用一根时钟线(SPICLK),由主机产生,因此数据传输速率可以很高,且时序严格同步。F28335的SPI模块(SPI-A)功能强大,支持主从模式、可编程数据位宽(1-16位)以及灵活的时钟配置。

3.1 SPI主从模式与四线制

SPI通常采用四线制:

  • SPISIMO: Slave In, Master Out。主机输出,从机输入。
  • SPISOMI: Slave Out, Master In。主机输入,从机输出。
  • SPICLK: 串行时钟,由主机产生。
  • SPISTE: 从机片选(低电平有效),由主机控制。这是一个关键点,SPISTE并非SPI协议强制要求的,但F28335的SPI模块将其作为标准功能集成。主机通过拉低对应从机的SPISTE引脚来选中该从机进行通信。一个主机可以连接多个从机,通过多个GPIO引脚模拟片选信号,或者使用外部译码器。

主从模式配置:通过SPICTL.2 (MASTER/SLAVE)位选择。作为主机时,SPICLK由内部波特率发生器产生;作为从机时,SPICLK由外部主机提供。一个常见的坑是:在从机模式下,必须保证SPICLK的时钟质量,如果主机时钟不稳定或毛刺多,从机很容易采样出错。

3.2 时钟极性(CPOL)与相位(CPHA)——四种模式

这是SPI配置中最容易混淆的部分,它决定了数据在时钟的哪个边沿被采样和输出。F28335通过SPICCR.6 (CLOCK POLARITY)SPICTL.3 (CLOCK PHASE)两位来控制,组合出四种模式:

模式CPOL (SPICCR.6)CPHA (SPICTL.3)时钟空闲状态数据采样边沿数据输出边沿
000低电平上升沿下降沿
101低电平下降沿上升沿
210高电平下降沿上升沿
311高电平上升沿下降沿

如何理解?关键在于抓住“采样”和“输出”的时刻。

  • CPOL=0:时钟空闲时为低电平。CPHA=0时,在时钟的第一个边沿(即上升沿)采样数据,在时钟的前一个边沿(即下降沿)输出数据。CPHA=1时,在时钟的第二个边沿(即下降沿)采样,在第一个边沿(上升沿)输出。
  • CPOL=1:时钟空闲时为高电平。逻辑与CPOL=0类似,只是边沿反过来。

实战口诀:绝大多数SPI从设备的数据手册都会明确要求工作在哪种模式。配置时,主从设备的CPOL和CPHA必须完全一致。一个快速判断的方法是:观察从设备数据手册的时序图,看它的数据是在时钟上升沿还是下降沿保持稳定(即被主机采样),那个稳定的边沿就是采样边沿。然后看时钟空闲时的电平,就是CPOL。

3.3 波特率计算与FIFO使用

SPI的波特率计算比SCI简单,公式为:

  • 3 ≤ SPIBRR ≤ 127时:波特率 = LSPCLK / (SPIBRR + 1)
  • SPIBRR = 0, 1, 2时:波特率 = LSPCLK / 4

同样,LSPCLK是基准时钟。假设LSPCLK=37.5MHz,需要1MHz的SPI时钟,则SPIBRR = LSPCLK / 波特率 - 1 = 37.5 - 1 = 36.5,取整为37,实际波特率约为0.9868MHz,误差很小。

FIFO功能:与SCI类似,SPI也支持16级深度的发送/接收FIFO,通过SPIFFTXSPIFFRXSPIFFCT寄存器配置。启用FIFO可以显著提升大数据量传输时的效率,减少中断开销。特别是在作为主机连续读取ADC芯片或发送显示数据时,FIFO非常有用。

3.4 SPI初始化配置示例(主机模式,模式0)

下面配置SPI-A为主机,模式0(CPOL=0, CPHA=0),8位数据,波特率1MHz,使用FIFO。

void InitSpiA_Master(void) { // 1. 使能SPI-A时钟 EALLOW; SysCtrlRegs.PCLKCR0.bit.SPIAENCLK = 1; EDIS; // 2. 配置GPIO复用为SPI功能 (假设使用GPIO16-SPISIMOA, GPIO17-SPISOMIA, GPIO18-SPICLKA, GPIO19-SPISTEA) EALLOW; GpioCtrlRegs.GPAMUX2.bit.GPIO16 = 1; // SPISIMOA GpioCtrlRegs.GPAMUX2.bit.GPIO17 = 1; // SPISOMIA GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 1; // SPICLKA GpioCtrlRegs.GPAMUX2.bit.GPIO19 = 1; // SPISTEA (作为主机,此引脚可配置为通用GPIO手动控制片选) // 或者,如果想让SPISTEA作为自动片选,需在SPI配置中设置SPICTL.4 (TALK)位 EDIS; // 3. 初始化SPI寄存器前,先进入复位状态 SpiaRegs.SPICCR.bit.SPISWRESET = 0; // 将SPI置于复位状态 // 4. 配置SPI参数 SpiaRegs.SPICCR.all = 0x000F; // 复位值,SPI软件复位保持,时钟极性低,16位数据?不,先配置为8位 SpiaRegs.SPICCR.bit.SPICHAR = 0x07; // 8位数据 (SPICHAR=7, 表示字符长度-1) SpiaRegs.SPICCR.bit.CLK_POLARITY = 0; // CPOL = 0, 时钟空闲低 SpiaRegs.SPICCR.bit.SPILBK = 0; // 禁止回环模式 SpiaRegs.SPICTL.all = 0x0006; // 主机模式,正常时钟相位(CPHA=0),使能发送,禁止超时中断 // SPICTL.3 (CLOCK PHASE) = 0 对应模式0 // SPICTL.1 (MASTER/SLAVE) = 1 主机模式 // SPICTL.0 (SPI INT ENA) = 0 先禁止中断,用查询方式 // 5. 设置波特率 (LSPCLK=37.5MHz, 目标1MHz) // SPIBRR = 37.5 / 1 - 1 = 36.5 -> 取37 SpiaRegs.SPIBRR = 37; // 6. 配置FIFO SpiaRegs.SPIFFTX.all = 0xE040; // 使能FIFO,复位TXFIFO,TXFIFO深度为16 SpiaRegs.SPIFFRX.all = 0x2040; // 复位RXFIFO,RXFIFO深度为16 SpiaRegs.SPIFFCT.all = 0x00; // FIFO发送延迟为0 // 7. 退出复位状态,启动SPI SpiaRegs.SPICCR.bit.SPISWRESET = 1; // 8. 可选:如果使用SPISTEA作为自动片选,需要配置SPI引脚控制 // 但更常见的做法是将SPISTEA对应的GPIO(如GPIO19)配置为普通输出,手动拉低/拉高以控制从机片选 } // SPI发送并接收一个字节(查询方式) Uint16 SpiA_Transfer(Uint16 data) { // 等待发送缓冲区空(非FIFO模式看SPISTS.5, FIFO模式看SPIFFTX.7) while (SpiaRegs.SPIFFTX.bit.TXFFST != 0) { // 等待TX FIFO有空间 } SpiaRegs.SPITXBUF = data; // 写入数据,启动传输 // 等待接收数据就绪(非FIFO模式看SPISTS.6, FIFO模式看SPIFFRX.6) while (SpiaRegs.SPIFFRX.bit.RXFFST == 0) { // 等待RX FIFO有数据 } return SpiaRegs.SPIRXBUF; // 读取接收到的数据 }

4. 集成电路总线(I2C)协议与F28335实现要点

I2C是一种由Philips(现NXP)开发的双线制、半双工、多主多从的串行通信总线。它只需要两根线:串行数据线SDA和串行时钟线SCL,通过地址寻址方式与总线上多个从设备通信,非常节省IO口资源。F28335的I2C模块完全兼容I2C V2.1规范,支持标准模式(100kbps)和快速模式(400kbps)。

4.1 I2C总线协议基础与F28335特性

I2C总线是**开源集电极(Open-Drain)**结构,需要外接上拉电阻。通信由主机发起,包括起始条件(S)、从机地址(7位或10位)、读写位、数据字节和停止条件(P)。F28335的I2C模块将这些复杂的时序全部用硬件实现,程序员主要通过操作一系列寄存器来完成通信。

关键特性

  • 支持7位和10位地址模式:通过I2CMDR寄存器配置。7位地址是主流,10位地址用于连接更多设备。
  • 16字深的FIFO:大幅提升了连续读写操作的效率。
  • 自由数据格式模式:在此模式下,I2C模块不解析地址和数据,只是简单地收发位流,可用于实现非标准的串行协议。
  • 时钟拉伸:从机可以通过拉低SCL来通知主机“我需要更多时间处理数据”,F28335的I2C模块支持此功能。

4.2 I2C时钟配置与波特率计算

I2C模块的时钟源是系统时钟SYSCLKOUT。其通信速率(波特率)由I2CPSC(预分频寄存器)和I2CCLKL/I2CCLKH(时钟低/高时间寄存器)共同决定。计算稍微复杂一些:

  1. IPSCI2CPSC寄存器决定对SYSCLKOUT的预分频,产生I2C模块的输入时钟I2C_CLK = SYSCLKOUT / (I2CPSC + 1)
  2. 波特率I2CCLKLI2CCLKH分别定义SCL时钟低电平和高电平的持续时间(以I2C_CLK周期为单位)。波特率 = I2C_CLK / [(I2CCLKL + d) + (I2CCLKH + d)],其中d是一个固定值,根据数据手册,对于F28335通常为5-7个I2C_CLK周期。

一个简化的配置方法是使用TI提供的库函数或参考例程中的经验值。例如,对于SYSCLKOUT=150MHz,要配置为标准模式100kbps,一种常见的配置是:

  • I2CPSC = 9, 则I2C_CLK = 150MHz / 10 = 15MHz
  • 设置I2CCLKL = I2CCLKH = 70
  • 计算:SCL周期 = (70+6) + (70+6) = 152个I2C_CLK周期
  • 波特率 ≈ 15MHz / 152 ≈ 98.68kHz,接近100kHz。

4.3 I2C通信流程与寄存器操作

I2C通信是状态机驱动的,需要严格按照流程操作寄存器。以下是一个向7位地址从设备(地址0x50)的寄存器0x00写入一个字节数据0xAB的主发送流程:

void I2CA_WriteByte(Uint16 slaveAddr, Uint16 regAddr, Uint16 data) { // 1. 等待I2C总线空闲 (I2CSTR.bit.BB = 0) while (I2caRegs.I2CSTR.bit.BB != 0) {} // 2. 配置为主机发送模式,产生起始条件,发送7位地址+写位 I2caRegs.I2CMDR.all = 0x6E20; // 主模式,发送器,7位地址,起始条件,不停止 // 0x6E20 = 0110 1110 0010 0000b // bit15: MST=1 (主机), bit14: TRX=1 (发送), bit13: XA=0 (7位地址), // bit12: RM=0, bit11: DLB=0, bit10: IRS=1 (I2C模块使能), // bit9: STB=0, bit8: FDF=0, bit7: BC=000 (1字节), // bit6-0: 地址未设置,通过I2CSAR设置 I2caRegs.I2CSAR = slaveAddr; // 设置从机地址 (0x50) // 3. 将数据(寄存器地址)放入数据发送寄存器 I2caRegs.I2CDXR = regAddr; // 4. 等待数据传输完成 (I2CSTR.bit.XRDY=1 或 检查中断标志) while (I2caRegs.I2CSTR.bit.XRDY != 1) {} // 5. 清除XRDY标志 (通过读取I2CSTR,然后写1清除) I2caRegs.I2CSTR.bit.XRDY = 1; // 6. 发送要写入的数据 I2caRegs.I2CDXR = data; while (I2caRegs.I2CSTR.bit.XRDY != 1) {} I2caRegs.I2CSTR.bit.XRDY = 1; // 7. 发送停止条件 I2caRegs.I2CMDR.bit.STP = 1; // 在发送完最后一个字节后产生停止条件 // 或者,重新配置I2CMDR,包含停止位 // I2caRegs.I2CMDR.all = 0x4E20; // 与之前相同,但STP=1 // 8. 等待停止条件完成 (I2CSTR.bit.BB=0) while (I2caRegs.I2CSTR.bit.BB != 0) {} }

重要提示:I2C操作中,状态寄存器I2CSTR的位清除方式比较特殊。大多数标志位(如XRDY, RRDY)需要通过读取该寄存器,然后向该位写1来清除。直接写0是无效的。这是I2C模块一个常见的“坑”。

4.4 I2C中断与FIFO操作

对于连续读写操作,使用中断和FIFO是更高效的方式。需要配置I2CIER(中断使能寄存器)来使能相应中断(如XRDYARDY等),并在PIE向量表中配置好I2C中断服务程序。

启用FIFO(通过I2CFFTXI2CFFRX寄存器)后,可以一次性向发送FIFO写入多个数据字节,或从接收FIFO读取多个字节,硬件会自动处理数据的搬移,并在FIFO达到设定的触发深度时产生中断,极大地减轻了CPU负担。

5. GPIO复用配置与输入量化机制

F28335拥有多达88个可编程的GPIO引脚,其强大之处在于几乎每个引脚都可以通过GPxMUXGPxQSEL寄存器复用到2-3个不同的外设功能上。这是灵活进行硬件设计的基础,但也容易配置错误。

5.1 复用配置流程与避坑指南

配置一个引脚功能的正确流程如下:

  1. 禁用引脚功能:在系统初始化时,如果不确定引脚状态,可以先将其配置为GPIO输入模式(GPxDIR.bit = 0),并禁用上拉(GPxPUD.bit = 1)。
  2. 选择量化模式:通过GPxQSEL寄存器选择输入量化模式。这是抗干扰的关键一步,下文详述。
  3. 选择具体功能:通过GPxMUX寄存器选择引脚的具体功能(GPIO、外设1、外设2或外设3)。
  4. 如果是GPIO输出:设置GPxDIR相应位为1。
  5. 如果是外设功能:方向通常由外设自动控制,但有些外设的输入/输出方向也需要额外配置。

一个真实案例:在某个电机驱动板上,我将GPIO12配置为EPWM模块的故障输入引脚(TZ1)。上电后,即使没有故障,电机也经常误触发保护。排查后发现,是因为GPIO12引脚靠近功率回路,有严重的开关噪声。解决方案是:在GPxQSEL寄存器中,为该引脚配置了“采用采样窗口量化”模式,并设置了合适的采样周期(QUALPRD),滤除了高频毛刺,问题得以解决。

5.2 输入量化(Qualification)——数字滤波器的实现

输入量化是F28335 GPIO一个非常独特且重要的功能,它本质上是一个数字滤波器,用于消除引脚上的毛刺噪声。有三种模式:

  • 仅同步到SYSCLKOUTGPxQSELn=00):输入信号仅经过两个系统时钟周期的同步器,用于滤除亚稳态,但抗毛刺能力弱。适用于干净、低速的信号。
  • 采用采样窗口量化GPxQSELn=01或10):这是最常用的抗干扰模式。它在一个可配置的采样窗口(3次或6次采样)内对输入信号进行多次采样,只有当所有采样值一致时,才认为输入有效。采样窗口的周期由GPxCTRL寄存器中的QUALPRD位域控制,该设置按每组8个引脚进行。
  • 无同步GPxQSELn=11):信号直接进入外设,不经过任何同步或滤波。仅用于某些内部已做同步处理的外设输入。

如何配置采样窗口

  1. 确定需要滤除的噪声脉宽。例如,要滤除宽度小于100ns的毛刺。
  2. 计算采样周期。假设系统时钟SYSCLKOUT为150MHz(周期约6.67ns)。QUALPRD定义的是采样间隔的SYSCLKOUT倍数。若设置QUALPRD=2,则采样间隔为3个SYSCLKOUT周期(20ns)。
  3. 选择采样次数。6次采样比3次更可靠,但延迟更大。总滤波时间 = 采样次数 * 采样间隔。上例中,6次采样的总窗口为120ns,足以滤除100ns的毛刺。
  4. GPxCTRL中为对应的引脚组设置QUALPRD值,并在GPxQSEL中为该引脚选择6采样模式。

5.3 外设引脚冲突与默认状态

查阅数据手册的GPIO Mux表格(如Table 4-16)至关重要。需要注意两点:

  1. 引脚冲突:一个外设输入信号可能映射到多个GPIO引脚(例如CANTXB可以映射到GPIO8或GPIO16)。但同一时间只能有一个引脚被选为此外设功能,其他映射引脚应配置为其他功能或GPIO,否则会产生冲突。
  2. 未选择时的默认状态:当一个引脚未被选为某个外设功能时,该外设对应的输入信号在芯片内部会被拉到一个默认状态(0或1)。在设计电路时,尤其是使用外部中断或捕获引脚时,需要了解这个默认状态,避免误触发。

6. 常见问题排查与调试心得

串行通信调试是嵌入式开发的必修课。下面总结一些我在这颗芯片上调试SCI、SPI、I2C时最常遇到的问题和解决方法。

6.1 通信完全不通

  1. 时钟与波特率:这是头号嫌疑犯。首先确认LSPCLK(对于SCI/SPI)或SYSCLKOUT(对于I2C分频)的频率是否与你的计算假设一致。用示波器测量SPICLKSCITXD引脚,看波形频率是否正确。对于SCI,计算出的波特率误差是否在2%以内。
  2. GPIO复用错误:这是最容易被忽略的步骤。用仿真器单步调试,检查GPxMUXGPxQSEL寄存器的值是否与你的硬件连接图匹配。一个技巧:在初始化函数里,将这些寄存器的配置值通过SCI打印出来,与预期值对比。
  3. 硬件连接:检查TX/RX是否接反(SCI),MOSI/MISO是否接反(SPI),SDA/SCL是否接反且已接上拉电阻(I2C)。测量引脚电压,确认没有对地或对电源短路。
  4. 外设时钟未使能:确认PCLKCR0/1寄存器中对应外设(SCIAENCLK, SPIAENCLK, I2CAENCLK)的时钟使能位已经置1。
  5. 软件复位锁:对于SCI和SPI,配置寄存器前需要将其软件复位位(SCICTL1.0 (SW RESET)SPICCR.7 (SPISWRESET))清0,配置完成后再置1。顺序错误会导致配置不生效。

6.2 通信数据错误或时好时坏

  1. 电气噪声与干扰:对于长距离或噪声环境下的SCI通信,检查是否使用了RS-232电平转换或RS-485收发器。对于SPI和I2C,检查走线是否过长,是否靠近功率线。为I2C的SCL和SDA增加串联电阻(如22Ω-100Ω)有助于抑制信号反射。
  2. 时序不匹配:SPI的时钟极性和相位(CPOL, CPHA)必须与从设备严格一致。用示波器同时抓取SPICLKSPISIMO/SPISOMI波形,对照从设备数据手册的时序图逐一检查建立时间和保持时间。
  3. 中断与FIFO配置:如果使用了中断或FIFO,检查中断服务程序(ISR)是否及时清除了中断标志(PIEACK和IFR)。检查FIFO的触发深度设置是否合理。过浅的触发深度会导致频繁中断,增加CPU负载;过深则可能导致响应延迟。
  4. 从设备忙状态:很多I2C或SPI从设备(如EEPROM, ADC)在完成内部操作(如写周期)时需要时间。主机在发送下一次命令前,必须通过查询或延时等待从设备就绪。对于I2C EEPROM,写操作后需要发送“查询ACK”的流程。

6.3 调试工具与技巧

  1. 示波器/逻辑分析仪:这是最强大的调试工具。不仅能看波形、测频率,还能解码SPI、I2C、UART协议,直观地看到地址、数据、ACK/NACK位,是定位硬件和底层时序问题的利器。
  2. 软件模拟:在硬件做好之前,可以先用GPIO模拟SPI或I2C的时序进行初步验证和算法开发。虽然效率低,但有助于理解协议。
  3. 利用仿真器查看寄存器:在CCS的调试模式下,实时查看和修改SCI、SPI、I2C的相关寄存器,特别是状态寄存器(如SCIRXSTSPISTSI2CSTR),里面的错误标志位(FE, OE, PE, ARDY, NACK等)能直接指明问题方向。
  4. 分步测试法:先调通最简单的功能。对于SCI,先让芯片自发自收(回环模式)。对于SPI,先尝试单字节收发。对于I2C,先尝试向一个已知地址的设备发送START和STOP信号,看总线是否有应答。

最后,保持耐心和细心。串行通信调试往往需要软硬件结合排查,系统地按照“电源->时钟->配置->波形->数据”的顺序进行检查,大部分问题都能迎刃而解。F28335的这些串行接口功能非常稳定和强大,一旦理解透彻并配置正确,将成为你项目中可靠的数据通道。