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个位时间(包括起始位和停止位)时触发。这通常是通信对方主动发送的一个“断线”信号,用于通信复位或协议帧分隔。
错误处理流程实录:
- 在接收中断或轮询中,发现
RXRDY=1。 - 读取
SCIRXST寄存器的值,暂存。 - 检查
RX ERROR (Bit 7)或直接检查BRKDT/FE/OE/PE。 - 如果无错误,读取
SCIRXBUF获取数据。 - 如果有错误,先根据错误类型处理(例如,发生OE,说明程序太慢,需要紧急提升处理优先级或清空缓冲区;发生FE,应检查双方波特率),然后再决定是否读取
SCIRXBUF(发生OE时,数据已丢失,读取也无意义;发生PE,数据可能错误,但仍在缓冲区里)。 - 所有错误标志只能通过
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输出给外设模块的时钟频率。实操中的关键点:
- 计算与取舍:你需要根据想要的波特率(如115200)和已知的
CLKOUT(如50MHz)反算BRR。BRR = (CLKOUT / (波特率 * 8)) - 1。计算出的BRR很可能不是整数,必须进行四舍五入取整。这会引入误差,误差率需控制在可接受范围内(通常<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%,完全可接受。
- 理论
- 高低字节写入顺序:将计算出的16位
BRR值分解为高8位和低8位,分别写入SCIHBAUD和SCILBAUD。一个易错点:有些平台要求先写高字节,再写低字节,或者反过来。最稳妥的做法是查阅具体芯片的勘误表或应用笔记。通常,在SW RESET=0的配置阶段写入这些寄存器是安全的。 - 极限速率:注意,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数据交换的核心三兄弟,理解它们的关系至关重要。
- SPIDAT:这是移位寄存器。数据发送时,从
SPIDAT移出到MOSI线;数据接收时,从MISO线移入SPIDAT。它是一个16位的寄存器。 - SPITXBUF:这是发送缓冲寄存器。当你想发送数据时,首先将数据(左对齐)写入
SPITXBUF。当SPIDAT中的当前字符发送完毕且SPITXBUF中有数据时,SPITXBUF中的数据会自动加载到SPIDAT中,开始下一次发送。它是双缓冲的,意味着你可以在当前数据正在发送时,提前写入下一个数据到SPITXBUF,从而实现连续发送。 - SPIRXBUF:这是接收缓冲寄存器。当
SPIDAT接收完一个完整字符后,数据会自动从SPIDAT转存到SPIRXBUF(右对齐),同时SPI INT FLAG置位。CPU通过读取SPIRXBUF来获取接收到的数据。读取操作会清除SPI INT FLAG。
一次典型的SPI主模式数据传输流程(查询方式):
- 检查
TX BUF FULL FLAG是否为0(表示SPITXBUF空)。 - 将待发送数据(左对齐)写入
SPITXBUF。 - (可选)等待
SPI INT FLAG置1,表示收发完成。 - 读取
SPIRXBUF,得到从设备返回的数据(右对齐)。 - 清除
SPI INT FLAG(通过读SPIRXBUF已自动完成)。
3.4 主从模式配置详解与SPISTE引脚使用
主模式配置要点:
- 设置
MASTER/SLAVE=1。 - 根据从设备要求,配置
CPOL和CPHA。 - 根据通信速率要求,配置
SPIBRR。 - 置
TALK=1,使能发送。 - 使能或禁止相关中断(
SPI INT ENA,OVERRUN INT ENA)。 - 最后释放
SW RESET。 在主模式下,SPICLK由本机产生,SPISIMO是数据输出(MOSI),SPISOMI是数据输入(MISO)。
从模式配置要点:
- 设置
MASTER/SLAVE=0。 - 根据主设备时钟,配置相同的
CPOL和CPHA。 - 从模式无需设置
SPIBRR,时钟由外部主设备提供。 - 通常置
TALK=0,使SPISOMI为高阻,等待主设备通过SPISTE引脚选中自己。 - 使能接收中断(
SPI INT ENA),以便在收到数据时被通知。 - 释放
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)控制。这是一个错误状态中断。溢出处理流程:- 进入中断后,首先判断是
SPI INT FLAG触发还是RECEIVER OVERRUN FLAG触发(通过读取SPISTS判断)。 - 如果是溢出中断,立即读取
SPIRXBUF(虽然数据可能已错乱,但此操作能清除SPI INT FLAG并获取当前缓冲区的值)。 - 必须软件清除溢出标志:向
SPISTS.7写1。这是很多初学者容易遗漏的一步,不清除会导致无法检测到下一次溢出。 - 记录溢出错误,并采取恢复措施,例如复位SPI模块、清空缓冲区、向上层报告错误。
- 进入中断后,首先判断是
SPI FIFO功能(高级特性): 在一些增强型的SPI模块(如TI C2000系列DSP)中,会包含FIFO(First In First Out)缓冲区。如图9-1模块框图所示,TX FIFO和RX FIFO深度通常为16级。FIFO可以大幅减少中断频率。你可以设置当FIFO中数据量达到某个阈值(例如一半满)时才产生中断,然后在中