1. 项目概述与核心价值

串行通信,说白了就是让两个电子设备“说上话”的最基础方式。想象一下,你手里有一块单片机,需要从传感器读取温度,或者驱动一块显示屏,它们之间总得有条“路”来传递数据。这条“路”如果像高速公路一样,用8根、16根甚至32根线并行传输,虽然速度快,但线路复杂、成本高、占地方。而串行通信就像一条乡间小道,数据排着队,一位一位地按顺序通过,虽然单次传输的“车道”窄了,但通过精密的时序控制,同样能高效、可靠地完成任务,极大地简化了硬件设计。

在嵌入式开发领域,SCI(Serial Communications Interface)和SPI(Serial Peripheral Interface)是两条最常用、也最经典的“乡间小道”。我干了十多年嵌入式,从8位机到32位ARM,再到各种DSP,几乎每个项目都会和它们打交道。SCI,我们更常称之为UART,是一种异步通信协议。它就像两个人写信,不需要严格同步时钟,但约定好写信的速度(波特率)和格式(起始位、数据位、停止位),就能可靠通信,非常适合与PC串口、GPS模块、蓝牙模块等设备连接。而SPI则是一种同步通信协议,它有一个“指挥家”(主设备)和一个或多个“乐手”(从设备)。指挥家不仅提供数据,还提供一个统一的节拍(时钟信号),所有乐手都跟着这个节拍演奏,因此速度可以非常快,常用于连接Flash存储器、ADC芯片、触摸屏控制器等对速度要求较高的外设。

这篇文章的价值,就在于帮你彻底搞懂这两种通信方式在芯片内部是如何被“驯服”的。芯片厂商(比如TI的C2000系列DSP)会提供SCI和SPI的硬件模块,但硬件只是提供了能力,如何配置、如何使用,完全取决于开发者对一堆寄存器的操作。这些寄存器就像是控制这个通信模块的“开关面板”和“状态指示灯”。很多人看芯片手册时,面对几十页的寄存器描述容易发懵,照着例程配置能跑通,但一出问题就抓瞎。我将结合手册中的核心寄存器片段,为你拆解每一个关键比特位的实际含义、配置时的“坑”,以及调试时如何通过它们快速定位问题。这不仅是一篇寄存器说明的翻译,更是一个老工程师的实战笔记,目标是让你看完后,不仅能配置,更能理解为什么这么配,出了问题知道该看哪里。

2. SCI模块寄存器深度解析与实战配置

SCI模块的寄存器是控制异步通信的“大脑”。手册里给出了SCICTL1、SCIRXST等一系列寄存器的位定义,我们不仅要看懂它“是什么”,更要理解“怎么用”和“为什么”。

2.1 核心控制寄存器:SCICTL1的配置哲学

SCICTL1(SCI Control Register 1)是SCI的“总开关”,地址通常在 0x7051 。它的每一个位都直接关系到通信链路的基本状态。

Bit 0 (RXENA) 与 Bit 1 (TXENA):收发使能 这是最基础的两个位。 RXENA 置1,接收器才开始工作,把SCIRXD引脚上的数据搬进缓冲区; TXENA 置1,发送器才被允许通过SCITXD引脚向外发送数据。这里有个关键细节:当你关闭 TXENA 时,发送并不会立即停止,而是会等 SCITXBUF 和发送移位寄存器里现有的数据全部发完才会停下。这保证了数据帧的完整性,避免产生残缺的字符。 实战心得 :在初始化SCI时,我习惯先配置好所有参数(如波特率、数据格式),最后再同时打开 RXENA 和 TXENA ,避免参数配置过程中产生意外的数据收发。

Bit 2 (SLEEP) 与 Bit 3 (TXWAKE):多处理器通信模式 这两个位用于多处理器通信(地址位模式或空闲线模式),在单机通信中通常置0。 SLEEP 置1时,接收器进入“睡眠”状态,只有收到地址字节(地址位为1)时才会“醒来”并产生中断,这用于在多个设备共享总线时,只有被寻址的设备响应。 TXWAKE 则用于在发送数据前,主动发送一个地址帧或空闲周期来唤醒目标设备。 注意事项 :如果你用不到多机通信,务必确保 SLEEP=0 ,否则你的设备可能永远收不到数据。

Bit 5 (SW RESET):软件复位键 这是 最重要的位之一 ,但也是最容易用错的。手册明确写道:向该位写0会复位SCI的状态机和操作标志(如TXRDY, RXRDY, 各种错误标志),但 不会 影响配置位(如波特率、数据长度等)。复位后,必须向该位写1,SCI才能重新开始工作。

关键操作流程 :任何对SCI通信参数(如波特率寄存器 SCIHBAUD / SCILBAUD 、通信控制寄存器 SCICCR )的修改,都必须在 SW RESET=0 的情况下进行。修改完成后,再置 SW RESET=1 来释放复位,让新参数生效。这是一个标准的“配置-复位-激活”流程,能有效避免因寄存器写入时序问题导致的通信异常。

Bit 6 (RX ERR INT ENA):接收错误中断使能 当接收端出现帧错误(FE)、溢出错误(OE)、奇偶校验错误(PE)或断线检测(BRKDT)时, SCIRXST.7 (RX ERROR) 会被置1。如果 RX ERR INT ENA 也置1,就会产生接收错误中断。 强烈建议 在可靠性要求高的应用中使能此中断。在中断服务程序里,第一时间读取 SCIRXST 寄存器,检查具体的错误标志(FE/OE/PE/BRKDT),并做相应处理(如清空缓冲区、记录错误日志、通知上位机),而不是简单地丢弃数据。

2.2 状态与数据流:SCIRXST与数据缓冲区

SCIRXST (Receiver Status Register)是你的“诊断仪”。所有接收相关的状态都从这里读取。

Bit 6 (RXRDY):数据就绪标志 这是最常用的标志。当 RXRDY=1 时,表示 SCIRXBUF 寄存器里有一个新字符可以读取。读取 SCIRXBUF 的操作会自动清除 RXRDY 标志。 这里有个大坑 :手册提到了 SCIRXEMU 寄存器,它和 SCIRXBUF 是同一块物理内存的 两个不同地址映射 。读取 SCIRXBUF 会清除 RXRDY ,但读取 SCIRXEMU 不会! SCIRXEMU 是给仿真器(如CCS的Watch窗口)查看数据用的,防止调试时单步执行读取 SCIRXBUF 意外清除标志位,影响程序逻辑。 在正常应用程序中,你必须读取 SCIRXBUF ,而不是 SCIRXEMU 。

错误标志位 (Bits 5-2: BRKDT, FE, OE, PE)

  • FE (Framing Error) :帧错误。检测到有效的起始位后,在预期的停止位位置检测到低电平。通常由波特率不匹配、线路干扰或发送方突然停止导致。
  • OE (Overrun Error) :溢出错误。CPU还没读取 SCIRXBUF 中的上一个字符,新字符已经接收完毕并要覆盖进来。这说明你的程序处理速度跟不上数据接收速度,需要优化接收中断服务程序(ISR)的效率,或者使用FIFO/DMA。
  • PE (Parity Error) :奇偶校验错误。仅在使能了奇偶校验功能时有效。说明传输过程中可能发生了单比特错误。
  • BRKDT (Break Detect) :断线检测。当接收数据线(SCIRXD)持续保持低电平超过10个位时间(包括起始位和停止位)时触发。这通常是通信对方主动发送的一个“断线”信号,用于通信复位或协议帧分隔。

错误处理流程实录 :

  1. 在接收中断或轮询中,发现 RXRDY=1 。
  2. 读取 SCIRXST 寄存器的值,暂存。
  3. 检查 RX ERROR (Bit 7) 或直接检查 BRKDT/FE/OE/PE 。
  4. 如果无错误,读取 SCIRXBUF 获取数据。
  5. 如果有错误, 先根据错误类型处理 (例如,发生OE,说明程序太慢,需要紧急提升处理优先级或清空缓冲区;发生FE,应检查双方波特率),然后再决定是否读取 SCIRXBUF (发生OE时,数据已丢失,读取也无意义;发生PE,数据可能错误,但仍在缓冲区里)。
  6. 所有错误标志只能通过 SW RESET 或系统复位清除,软件无法直接写0。所以通常的处理是:记录错误 -> 必要时复位通信模块( SW RESET )-> 恢复通信。

2.3 波特率计算:不止是套公式

波特率寄存器 SCIHBAUD 和 SCILBAUD 组成一个16位的 BRR 值。手册给出了公式:

  • 当 1 ≤ BRR ≤ 65535 时: SCI Asynchronous Baud = CLKOUT / ((BRR + 1) * 8)
  • 当 BRR = 0 时: SCI Asynchronous Baud = CLKOUT / 16

这里 CLKOUT 是你的CPU输出给外设模块的时钟频率。 实操中的关键点 :

  1. 计算与取舍 :你需要根据想要的波特率(如115200)和已知的 CLKOUT (如50MHz)反算 BRR 。 BRR = (CLKOUT / (波特率 * 8)) - 1 。计算出的 BRR 很可能不是整数,必须进行四舍五入取整。这会引入误差,误差率需控制在可接受范围内(通常<2%)。
  2. 误差计算示例 : CLKOUT=50MHz ,目标波特率 115200 。
    • 理论 BRR = (50,000,000 / (115200 * 8)) - 1 ≈ 53.25
    • 取整 BRR = 53
    • 实际波特率 = 50,000,000 / ((53+1)*8) ≈ 115740.7
    • 误差率 = (115740.7 - 115200) / 115200 ≈ 0.47% ,完全可接受。
  3. 高低字节写入顺序 :将计算出的16位 BRR 值分解为高8位和低8位,分别写入 SCIHBAUD 和 SCILBAUD 。 一个易错点 :有些平台要求先写高字节,再写低字节,或者反过来。最稳妥的做法是查阅具体芯片的勘误表或应用笔记。通常,在 SW RESET=0 的配置阶段写入这些寄存器是安全的。
  4. 极限速率 :注意,SCI异步通信对时钟精度有要求。过高的波特率(接近理论极限)在时钟有抖动或线路有噪声时,误码率会急剧上升。在工业环境下,对于长距离通信,我通常会保守选择较低的波特率,如9600或19200,以保证稳定性。

2.4 发送流程与中断控制

发送数据相对简单:检查 SCICTL2.7 (TXRDY) 标志是否为1(表示发送缓冲区 SCITXBUF 空),然后将数据写入 SCITXBUF 即可。写入操作会自动清除 TXRDY 标志,数据会自动加载到发送移位寄存器并开始发送。发送完成后, TXRDY 会再次置1。

SCICTL2.0 (TX INT ENA) 是发送中断使能。如果使能,当 TXRDY 从0变1(即 SCITXBUF 空,可写入新数据)时,会产生发送中断。 使用心得 :在查询方式下,我们轮询 TXRDY ;在中断方式下,使能 TX INT ENA ,在中断服务程序里写入下一个要发送的字符。对于连续发送一长串数据(如发送一个字符串),中断方式能更高效地利用CPU。

SCICTL2.6 (TX EMPTY) 标志表示发送移位寄存器和 SCITXBUF 都空了,即整个发送通道完全空闲。这个标志在判断一帧数据是否完全发送完毕时非常有用,比如在需要等待一帧数据发完才能切换引脚状态的场景。

3. SPI模块寄存器精讲与主从模式实战

SPI是同步通信的典型代表,其寄存器配置逻辑与SCI有相通之处,但更强调时钟和主从控制。

3.1 配置控制寄存器SPICCR与时钟极性相位

SPICCR (SPI Configuration Control Register)是SPI的配置基石。

  • Bits 3-0 (SPI CHAR3-0) :这4位共同决定一次传输的数据位长度,从1位到16位可调。 这里有一个至关重要的对齐规则 :写入发送数据寄存器 SPIDAT 或 SPITXBUF 的数据,必须是 左对齐 的。例如,你设置字符长度为12位,那么你的16位数据必须放在高12位(Bit15-Bit4),低4位会被忽略。而接收到的数据,在 SPIRXBUF 中是 右对齐 的。这个“左写右读”的规则必须牢记,否则数据会错位。
  • Bit 6 (CLOCK POLARITY) :时钟极性 CPOL 。它决定SPICLK时钟线在空闲时的状态。
    • CPOL=0 :时钟空闲时为低电平。
    • CPOL=1 :时钟空闲时为高电平。
  • Bit 7 (SPI SW RESET) :软件复位位。与SCI的 SW RESET 类似,写0复位SPI状态机,写1使能操作。 特别注意 :手册提到C240xA的此位极性可能与老版本芯片相反,务必确认你所用的具体芯片型号的数据手册。

时钟相位由 SPICTL.3 (CLOCK PHASE) 控制。时钟相位 CPHA 决定数据在时钟的哪个边沿被采样。

  • CPHA=0 :数据在时钟的第一个边沿(若 CPOL=0 则为上升沿, CPOL=1 则为下降沿)被采样。
  • CPHA=1 :数据在时钟的第二个边沿被采样。

CPOL 和 CPHA 的组合构成了SPI的四种模式(Mode 0-3),这是SPI设备互联时必须严格匹配的参数。通常从设备(如传感器、Flash芯片)的数据手册会明确规定其支持的SPI模式。

模式 CPOL CPHA 时钟空闲态 数据采样边沿 数据变化边沿
0 0 0 低电平 第一个上升沿 下降沿
1 0 1 低电平 第二个下降沿 上升沿
2 1 0 高电平 第一个下降沿 上升沿
3 1 1 高电平 第二个上升沿 下降沿

配置口诀 :先根据从设备手册确定模式,从而定下 CPOL 和 CPHA ;在 SW RESET=0 时配置 SPICCR 和 SPICTL ;最后置 SW RESET=1 。

3.2 操作控制与状态寄存器:SPICTL与SPISTS

SPICTL (SPI Operation Control Register)控制操作行为。

  • Bit 0 (SPI INT ENA) :SPI中断总使能。控制由 SPISTS.6 (SPI INT FLAG) 和 SPISTS.7 (RECEIVER OVERRUN FLAG) 触发的中断是否被允许。
  • Bit 1 (TALK) :主从模式下含义不同。在 主模式 下,此位必须置1以启用发送。在 从模式 下,此位控制SPISOMI输出是否使能。 TALK=0 时,从设备的SPISOMI引脚呈高阻态,这在多从设备共享总线时用于选择当前通信的从机。 重要提示 :即使 TALK 被清零,正在进行的传输也会完成,这保证了通信的完整性。
  • Bit 2 (MASTER/SLAVE) :主从模式选择。 1 为主模式,SPI模块产生SPICLK; 0 为从模式,SPI模块接收外部SPICLK。
  • Bit 4 (OVERRUN INT ENA) :接收溢出中断使能。当 SPISTS.7 置1时,若此位使能,也会产生中断(与 SPI INT FLAG 共享中断向量)。

SPISTS (SPI Status Register)是状态观察窗口。

  • Bit 6 (SPI INT FLAG) :SPI中断标志。当一次完整的数据传输(发送和接收同时完成)后,此位置1。如果 SPI INT ENA 使能,则产生中断。 清除方式 :读取 SPIRXBUF 寄存器,或者进行软件复位( SPICCR.7=0 ),或者系统复位。 注意 :读取 SPIRXEMU 不会清除此标志,这与SCI类似。
  • Bit 7 (RECEIVER OVERRUN FLAG) :接收溢出标志。当 SPIRXBUF 中的数据还未被CPU读取,新数据又已接收完毕并准备覆盖时,此位置1。 这是一个错误状态 ,表明CPU处理速度跟不上SPI接收速度。此标志必须由 软件手动清除 (向该位写1清零)。不清除它,后续的溢出将无法被再次标记。
  • Bit 5 (TX BUF FULL FLAG) :发送缓冲区满标志。当 SPITXBUF 中有数据时,此位置1;当数据被转移到 SPIDAT 后,此位清零。可用于查询方式下判断是否可以写入下一个发送数据。

3.3 波特率设置与数据寄存器操作

波特率寄存器SPIBRR :在主模式下,SPI的波特率由 SPIBRR 决定,计算公式为:当 SPIBRR = 3 to 127 时, SPI Baud Rate = LSPCLK / (SPIBRR + 1) 。其中 LSPCLK 是低速外设时钟。在从模式下,波特率由外部主设备提供,但不得超过 LSPCLK/4 。

数据流核心:SPIDAT, SPITXBUF, SPIRXBUF 这是SPI数据交换的核心三兄弟,理解它们的关系至关重要。

  1. SPIDAT :这是 移位寄存器 。数据发送时,从 SPIDAT 移出到MOSI线;数据接收时,从MISO线移入 SPIDAT 。它是一个16位的寄存器。
  2. SPITXBUF :这是 发送缓冲寄存器 。当你想发送数据时,首先将数据(左对齐)写入 SPITXBUF 。当 SPIDAT 中的当前字符发送完毕且 SPITXBUF 中有数据时, SPITXBUF 中的数据会自动加载到 SPIDAT 中,开始下一次发送。它是双缓冲的,意味着你可以在当前数据正在发送时,提前写入下一个数据到 SPITXBUF ,从而实现连续发送。
  3. SPIRXBUF :这是 接收缓冲寄存器 。当 SPIDAT 接收完一个完整字符后,数据会自动从 SPIDAT 转存到 SPIRXBUF (右对齐),同时 SPI INT FLAG 置位。CPU通过读取 SPIRXBUF 来获取接收到的数据。读取操作会清除 SPI INT FLAG 。

一次典型的SPI主模式数据传输流程(查询方式) :

  1. 检查 TX BUF FULL FLAG 是否为0(表示 SPITXBUF 空)。
  2. 将待发送数据(左对齐)写入 SPITXBUF 。
  3. (可选)等待 SPI INT FLAG 置1,表示收发完成。
  4. 读取 SPIRXBUF ,得到从设备返回的数据(右对齐)。
  5. 清除 SPI INT FLAG (通过读 SPIRXBUF 已自动完成)。

3.4 主从模式配置详解与SPISTE引脚使用

主模式配置要点 :

  1. 设置 MASTER/SLAVE=1 。
  2. 根据从设备要求,配置 CPOL 和 CPHA 。
  3. 根据通信速率要求,配置 SPIBRR 。
  4. 置 TALK=1 ,使能发送。
  5. 使能或禁止相关中断( SPI INT ENA , OVERRUN INT ENA )。
  6. 最后释放 SW RESET 。 在主模式下,SPICLK由本机产生,SPISIMO是数据输出(MOSI),SPISOMI是数据输入(MISO)。

从模式配置要点 :

  1. 设置 MASTER/SLAVE=0 。
  2. 根据主设备时钟,配置相同的 CPOL 和 CPHA 。
  3. 从模式无需设置 SPIBRR ,时钟由外部主设备提供。
  4. 通常置 TALK=0 ,使SPISOMI为高阻,等待主设备通过SPISTE引脚选中自己。
  5. 使能接收中断( SPI INT ENA ),以便在收到数据时被通知。
  6. 释放 SW RESET 。

SPISTE引脚的关键作用 :在从模式下, SPISTE 通常作为片选(Chip Select, CS)或从机使能(Slave Enable)引脚。当主设备要与此从机通信时,将对应从机的 SPISTE 线拉低(有效)。从机检测到 SPISTE 为低后,才会激活其SPISOMI输出驱动器(如果 TALK=1 ),并开始响应SPICLK时钟。通信结束后,主设备将 SPISTE 拉高。 硬件连接上 ,主设备的某个GPIO口连接从设备的 SPISTE 引脚。 软件操作上 ,主设备在发起传输前,先拉低对应GPIO,传输结束后再拉高。这实现了多个SPI从设备共享SPICLK、MOSI、MISO三根线,仅通过不同的 SPISTE (片选)线进行寻址。

4. 中断机制与FIFO应用深度剖析

高效利用中断是提升系统实时性和CPU效率的关键。SCI和SPI都提供了丰富的中断源。

4.1 SCI中断策略与优先级管理

SCI的中断主要分为发送中断、接收中断和接收错误中断。

  • 发送中断 :由 SCICTL2.0 (TX INT ENA) 和 SCICTL2.7 (TXRDY) 共同控制。当发送缓冲区空( TXRDY=1 )且中断使能时触发。适用于需要连续发送大量数据的场景。在中断服务程序中,你需要判断是否还有待发送数据,如果有则写入 SCITXBUF ,否则关闭发送中断以避免空触发。
  • 接收中断 :由 SCICTL2.1 (RX/BK INT ENA) 和 SCIRXST.6 (RXRDY) 共同控制。当接收到一个新字符时触发。这是最常用的中断。在中断服务程序中,必须首先读取 SCIRXST 检查错误,然后读取 SCIRXBUF 获取数据。
  • 接收错误中断 :由 SCICTL1.6 (RX ERR INT ENA) 和 SCIRXST.7 (RX ERROR) 共同控制。当发生帧错误、溢出、奇偶错误或断线时触发。 强烈建议使能 。错误中断的优先级通常应设置为最高,以便及时处理通信故障,防止错误累积。

中断优先级配置 :通过 SCIPRI 寄存器可以设置发送和接收中断的优先级(高/低)。在复杂的系统中,你需要根据通信任务的关键性来分配优先级。例如,一个用于紧急命令传输的SCI端口,其接收中断优先级应高于一个仅用于打印调试信息的SCI端口。

4.2 SPI中断与溢出处理

SPI的中断逻辑相对统一,但包含了数据就绪和溢出两种状态。

  • 数据收发中断 :由 SPICTL.0 (SPI INT ENA) 和 SPISTS.6 (SPI INT FLAG) 控制。一次完整的字符传输完成后触发。在中断服务程序中,你应该读取 SPIRXBUF 来获取数据,并检查 SPITXBUF 是否为空,以决定是否需要写入下一个待发送数据。
  • 接收溢出中断 :由 SPICTL.4 (OVERRUN INT ENA) 和 SPISTS.7 (RECEIVER OVERRUN FLAG) 控制。这是一个错误状态中断。 溢出处理流程 :
    1. 进入中断后,首先判断是 SPI INT FLAG 触发还是 RECEIVER OVERRUN FLAG 触发(通过读取 SPISTS 判断)。
    2. 如果是溢出中断,立即读取 SPIRXBUF (虽然数据可能已错乱,但此操作能清除 SPI INT FLAG 并获取当前缓冲区的值)。
    3. 必须软件清除溢出标志 :向 SPISTS.7 写1。这是很多初学者容易遗漏的一步,不清除会导致无法检测到下一次溢出。
    4. 记录溢出错误,并采取恢复措施,例如复位SPI模块、清空缓冲区、向上层报告错误。

SPI FIFO功能(高级特性) : 在一些增强型的SPI模块(如TI C2000系列DSP)中,会包含FIFO(First In First Out)缓冲区。如图9-1模块框图所示, TX FIFO 和 RX FIFO 深度通常为16级。FIFO可以大幅减少中断频率。你可以设置当FIFO中数据量达到某个阈值(例如一半满)时才产生中断,然后在中

更多推荐