嵌入式串行通信:SCI与SPI协议原理、配置与工程选型指南
1. 串行通信接口:嵌入式系统的“对话”基石
在嵌入式系统开发中,设备间的“对话”能力是项目成败的关键。无论是让主控芯片读取传感器数据,还是驱动一块显示屏,亦或是实现多个微控制器之间的协同工作,都离不开一种高效、可靠的数据交换机制。串行通信接口(Serial Communication Interface)正是实现这种“对话”的核心技术。它不像并行通信那样需要多根数据线同时传输一个字节的各个位,而是将数据拆分成一个个比特(bit),通过单根数据线(或一对差分线)按顺序依次发送出去。这种“排队上车”的方式,虽然牺牲了部分瞬时带宽,却换来了引脚资源的大幅节省、PCB布线的极大简化以及长距离传输的可靠性,使其成为嵌入式领域无可争议的主流。
在众多串行协议中,SCI(Serial Communications Interface)和SPI(Serial Peripheral Interface)是两种应用最广泛、也最常被拿来对比的“明星”协议。简单来说,你可以把SCI想象成两个人通过写信交流:双方有各自的时钟(异步),约定好写信的格式(波特率、数据位、停止位),写好一封信(一帧数据)就寄出去,对方收到后回信。这种方式灵活、独立,适合点对点的长距离通信,比如通过UART(通用异步收发器,SCI的一种常见实现)连接GPS模块或蓝牙模块。而SPI则更像一场面对面的快速会议:有一个明确的主持人(主设备)控制着会议的节奏(时钟),所有参会者(从设备)都根据主持人的时钟信号同步发言和接收。这种方式速度快、效率高,是全双工的(可以同时收发),非常适合板级设备间的高速数据流传输,比如连接Flash存储器、ADC芯片或TFT屏幕。
理解这两种协议的核心原理、配置细节和应用场景,是每一位嵌入式工程师的必修课。本文将以经典的飞思卡尔(Freescale,现为NXP)微控制器文档为蓝本,结合我多年的实战经验,为你深入拆解SCI和SPI的运作机制。我们不仅会看懂数据手册上的寄存器描述,更会探讨在实际项目中如何根据需求做出正确的选择和配置,避开那些手册上不会写的“坑”。无论你是刚接触嵌入式的新手,还是希望深化理解的老手,这篇文章都将为你提供一份可直接参考的“实战指南”。
2. SCI接口深度解析:异步通信的稳定之道
SCI,特别是其最常见的实现形式UART,是嵌入式世界中最古老也最经典的通信方式之一。它的核心思想是“异步”,即通信双方没有共享的时钟线,完全依靠预先约定好的速率(波特率)来同步数据的采样。这种独立性带来了极大的灵活性,但也对配置的精确性提出了更高要求。
2.1 核心工作机制与寄存器映射
一个典型的SCI模块包含几个关键部分:波特率发生器、发送器、接收器以及一系列控制与状态寄存器。发送器负责将并行数据装入发送移位寄存器,并按位串行输出到TXD引脚;接收器则监听RXD引脚,将串行数据流重新组装成并行数据。整个过程由状态寄存器中的标志位来指示,例如TDRE(发送数据寄存器空)和RDRF(接收数据寄存器满),这些标志位既可以用于查询,也可以触发中断,是实现高效通信的基础。
以飞思卡尔的SCI模块为例,其寄存器控制逻辑非常清晰。CTRL1(控制寄存器1)和STAT(状态寄存器)是工程师最常打交道的两个寄存器。CTRL1用于全局使能(TE发送使能,RE接收使能)、配置中断(如TEIE发送空中断使能、REIE接收错误中断使能)以及设置一些高级功能。STAT寄存器则实时反映了模块的工作状态,是软件判断“该发送下一字节了”还是“有新数据收到了”的直接依据。
注意:在编写驱动程序时,一个良好的习惯是,在中断服务程序(ISR)中读取STAT寄存器后,应立即将数据从数据寄存器中读出或写入。这个动作本身会清除相应的状态标志位(如RDRF)。如果先进行其他耗时操作,可能会错过清除标志的最佳时机,导致中断重复触发或状态判断错误。
2.2 波特率生成:通信同步的生命线
异步通信的同步完全依赖于双方精确一致的波特率。波特率发生器通常由系统总线时钟(IP Bus Clock)分频而来。计算公式一般为:目标波特率 = 系统时钟频率 / (16 * BR)其中BR(Baud Rate Divisor)是一个可编程的分频系数,写入特定的寄存器(如SCIBDH和SCIBDL)。这里的“16”是因为标准的UART接收器会对每个数据位进行16倍过采样,以提高抗干扰能力和定位中心采样点的准确性。
配置心得:计算出的BR值往往不是整数。例如,在16MHz系统时钟下生成115200的波特率,BR = 16,000,000 / (16 * 115200) ≈ 8.68。此时必须取整(通常为8或9)。取整带来的误差必须控制在可接受范围内(一般要求小于2%)。计算误差公式为:误差 = |(实际波特率 - 目标波特率) / 目标波特率| * 100%。选择BR=8时,实际波特率为125000,误差高达8.5%,通信极不稳定;选择BR=9时,实际波特率为111111,误差约3.5%,仍在临界点。因此,在16MHz下稳定实现115200波特率通常需要更高精度的时钟源或使用分数分频器(如果模块支持)。
2.3 低功耗模式下的行为管理
在电池供电的嵌入式设备中,功耗管理至关重要。微控制器常会进入低功耗的等待模式(Wait Mode)或停止模式(Stop Mode)。SCI模块在这些模式下的行为需要仔细配置,否则可能导致数据丢失或无法唤醒系统。
等待模式(Wait Mode):当CPU进入等待模式,如果**CTRL1[SWAI]**位被置位,则SCI模块的时钟生成会停止,模块进入省电状态,此时寄存器不可访问。任何正在进行的发送或接收都会暂停,直到一个内部或外部中断将CPU唤醒,传输才会从中断处恢复。这里有一个关键点:如果通过复位(Reset)退出等待模式,则会中止所有进行中的传输并复位整个SCI模块。因此,在进入低功耗前,务必确保当前没有关键数据传输,或者设计好数据重传机制。
停止模式(Stop Mode):SCI在停止模式下的行为取决于系统集成模块(SIM)中相关停止禁用寄存器的配置位。如果该位被清零,SCI在停止模式下不活动以降低功耗,但寄存器状态得以保持。被中断唤醒后,操作继续。同样,通过复位退出会中止传输。如果该位置位,则SCI在停止模式下正常工作。这个特性非常有用,例如,你可以让系统主CPU进入深度睡眠,而SCI模块保持监听状态,一旦收到特定唤醒字符(如一个‘@’符号)就产生中断唤醒CPU,实现极低功耗的串口唤醒功能。
配置建议:对于需要持续监听串口命令的设备,可以将SCI配置为在停止模式下保持活动,并启用接收中断。同时,将CTRL1[RWU](接收器唤醒)功能与空闲线(Idle Line)或地址标记(Address Mark)唤醒机制结合使用,可以进一步过滤无效的唤醒事件,只在收到特定格式的数据帧时才真正唤醒系统,从而最大化省电效果。
2.4 中断机制与错误处理
高效的程序通常采用中断驱动而非轮询。SCI提供了丰富的中断源:
- 发送数据寄存器空中断(TDRE):当数据从发送数据寄存器转移到发送移位寄存器后触发,表明可以写入下一个待发送字节。
- **发送空闲中断(TIDLE)**���当发送器空闲(无数据、前导符或间隔符在发送)时触发,可用于判断一帧数据发送完毕,或用于自动生成总线空闲状态。
- 接收数据寄存器满中断(RDRF):当新数据被接收到数据寄存器时触发,这是最常用的接收中断。
- 接收错误中断:当发生帧错误(FE,停止位不是预期的‘1’)、噪声错误(NF,在采样点附近检测到电平抖动)、奇偶校验错误(PE)或溢出错误(OR,新数据覆盖未读旧数据)时触发。
错误处理实战:在中断服务程序中,除了读取数据,必须检查错误标志。一个健壮的接收ISR应该如下所示:
void SCI_ISR(void) { uint8_t status = SCI_STATUS_REG; // 读取状态寄存器 uint8_t data; if (status & RDRF_MASK) { data = SCI_DATA_REG; // 读取数据,此操作会清除RDRF标志 // 处理有效数据 data... } if (status & (FE_MASK | NF_MASK | PE_MASK | OR_MASK)) { // 发生错误 if (status & OR_MASK) { // 溢出错误:数据丢失,通常需要清空接收缓冲区并重置状态 flush_receive_buffer(); } // 清除错误标志:通常通过先读状态寄存器,再写状态寄存器(或读数据寄存器)来完成 volatile uint8_t dummy = SCI_STATUS_REG; // 读状态 dummy = SCI_DATA_REG; // 读数据(或进行一个虚拟写操作),具体请查阅数据手册 // 记录错误日志或采取恢复措施 } }避坑指南:溢出错误(OR)是初学者常遇到的问题。它发生在CPU来不及读取已接收的数据,而新数据已经到来并准备覆盖数据寄存器时。除了优化代码确保及时读取外,启用接收FIFO(如果硬件支持)并设置合适的水位线中断,是缓解该问题的有效手段。此外,帧错误常常意味着波特率不匹配或线路受到强干扰,需要从硬件和软件配置两方面排查。
3. SPI接口深度解析:同步高速传输的引擎
如果说SCI是稳健的“书信使者”,那么SPI就是高效的“会议总管”。它是一种同步、全双工、主从式的串行总线。其核心特征是由主设备(Master)完全控制通信的发起和时钟(SCLK),一个主设备可以连接多个从设备(Slave),通过片选信号(SS)来选择当前与谁通信。
3.1 信号定义与主从架构
SPI通常使用四根线:
- SCLK (Serial Clock):串行时钟,由主设备产生。
- MOSI (Master Out Slave In):主设备数据输出,从设备数据输入。
- MISO (Master In Slave Out):主设备数据输入,从设备数据输出。
- SS (Slave Select):从设备片选,低电平有效。主设备通过拉低对应从设备的SS线来选中它。
在一个多从设备的系统中,主设备的MOSI、MISO、SCLK通常分别并联到所有从设备的对应引脚,而每个从设备都有自己独立的SS线连接到主设备的某个GPIO。这样,主设备通过控制不同的SS线来选择与哪个从设备通信。SPI支持全双工,意味着数据在MOSI和MISO线上同时、同步地传输。主设备在发出一个bit的同时,也会收到从设备发回的一个bit。
配置核心:SPI的配置灵活性很高,但也更复杂。关键的配置寄存器是SPI_SCTRL(状态与控制寄存器)和SPI_DSCTRL(数据大小与控制寄存器)。
3.2 时钟极性(CPOL)与相位(CPHA):时序匹配的关键
这是SPI配置中最容易混淆,也最关键的部分。CPOL和CPHA共同决定了数据在时钟信号的哪个边沿被采样和输出,共有四种模式(模式0-3)。通信双方必须使用相同的模式。
- CPOL (Clock Polarity):时钟极性。
- CPOL=0:SCLK空闲时为低电平。
- CPOL=1:SCLK空闲时为高电平。
- CPHA (Clock Phase):时钟相位。
- CPHA=0:数据在第一个时钟边沿(即SCLK从空闲状态第一次跳变时)被采样。对于输出,数据需要在时钟边沿之前准备好。
- CPHA=1:数据在第二个时钟边沿被采样。对于输出,数据在第一个边沿变化。
为了直观理解,我们将其对应到常见的模式编号:
| 模式 | CPOL | CPHA | SCLK空闲状态 | 数据采样边沿 | 数据输出边沿 |
|---|---|---|---|---|---|
| 0 | 0 | 0 | 低电平 | 上升沿 | 下降沿 |
| 1 | 0 | 1 | 低电平 | 下降沿 | 上升沿 |
| 2 | 1 | 0 | 高电平 | 下降沿 | 上升沿 |
| 3 | 1 | 1 | 高电平 | 上升沿 | 下降沿 |
实战选择:模式0和模式3是最常用的。很多传感器、Flash芯片默认使用模式0。关键在于,你必须查阅从设备的数据手册,严格按照其要求的模式进行配置。一个常见的错误是主从设备模式不匹配,导致读回的数据全是0xFF或0x00。
3.3 主从模式配置与数据传输流程
主模式(SPMSTR=1):主设备控制SCLK并发起传输。配置步骤通常为:
- 配置GPIO,将MOSI、SCLK、SS引脚设置为外设功能(而非普通GPIO)。
- 在SPI_SCTRL寄存器中设置SPMSTR=1,选择主模式。
- 设置CPOL和CPHA。
- 通过SPR[2:0]和BD2X等位设置波特率分频器。波特率 = 总线时钟 / 分频系数。需注意,SPI作为从设备时,其能接受的最高SCLK频率通常有上限(如总线时钟的1/4)。
- 设置数据位宽(DS[3:0],2-16位)、数据移位顺序(DSO,MSB或LSB先行)。
- 置位SPE,使能SPI模块。
- 拉低目标从设备的SS线(如果MODFEN=0,需软件控制GPIO;如果MODFEN=1且配置了自动SS,硬件可能自动控制)。
- 检查SPTE(发送器空)标志为1后,向SPI_DXMIT寄存器写入数据,传输立即开始。
- 等待SPRF(接收器满)标志置位,然后从SPI_DRCV读取接收到的数据。
从模式(SPMSTR=0):从设备等待主设备的时钟和片选。配置相对简单:
- 配置GPIO,将MISO、MOSI、SCLK、SS引脚设置为外设功能。SS引脚必须配置为输入。
- 在SPI_SCTRL寄存器中设置SPMSTR=0。
- 设置与主设备相同的CPOL和CPHA。
- 设置相同的数据位宽和移位顺序。
- 置位SPE,使能SPI模块。
- 当SS被主设备拉低后,从设备即被选中。主设备产生的SCLK会驱动从设备内部的移位寄存器。
- 从设备应提前将要发送的数据写入SPI_DXMIT寄存器。如果未写入,则上一次发送的数据会被重复发送。
- 从设备通过中断或轮询SPRF标志来读取主设备发来的数据。
重要警告:在CPHA=0的模式下,SS引脚的行为至关重要。它不仅仅是一个片选,还参与了时序的启动。如图11-9所示,SS必须在每个数据字传输之间产生一个高电平脉冲(即先拉高再拉低),以指示一个新数据字的开始。而在CPHA=1模式下,SS可以在一次通信会话中保持持续低电平,传输多个数据字。如果忽略了这一点,在CPHA=0时SS持续拉低,会导致数据帧边界混乱。
3.4 高级功能与错误处理
多主与线或(Wired-OR)模式:SPI本身不是多主总线,但通过MODF(模式错误)标志可以实现简单的多主冲突检测。当主设备的MODFEN位置1时,如果其SS引脚(此时应配置为输入)被拉低(意味着另一个设备试图成为主设备),则MODF标志置位,SPE被自动清零,SPI模块被禁用,从而防��总线冲突。WOM(Wired-OR Mode)位则将SPI引脚配置为开漏输出,配合上拉电阻,可以实现真正的多设备“线与”,方便构建多个从设备共享MISO线的拓扑结构。
中断与错误:SPI主要提供两个数据中断:SPTE(发送空)和SPRF(接收满)。此外,还有两个错误中断:OVRF(溢出错误)和MODF(模式错误)。溢出错误发生在接收数据寄存器中的数据尚未被读取,而新的数据已经准备移入时。模式错误如上所述。在中断服务程序中,必须依次读取状态寄存器、数据寄存器来清除标志位,顺序错误可能导致标志无法清除或数据丢失。
数据长度与移位顺序:SPI_DSCTRL寄存器的DS[3:0]位可以灵活设置2到16位的数据长度,这使其能够适配不同字长的外设。DSO位控制MSB先行还是LSB先行。一个极易出错的细节是:无论DSO如何设置,软件读写数据寄存器(SPI_DXMIT/SPI_DRCV)时,数据总是以LSB对齐在bit 0的方式存放。例如,设置8位数据长度、MSB先行,你要发送的数据0x8A (1000 1010b),在写入SPI_DXMIT时,仍然应该写入0x8A。硬件会自动处理移位顺序。
4. SCI与SPI的工程应用选型与配置实战
理解了原理,最终要落到应用上。如何为你的项目选择合适的通信接口?如何配置它们才能稳定可靠地工作?下面结合常见场景进行分析。
4.1 应用场景对比与选型指南
| 特性维度 | SCI (UART) | SPI |
|---|---|---|
| 通信方式 | 异步 | 同步 |
| 全双工 | 是 | 是 |
| 线数 | 最少2线(TX, RX),通常3线(加GND) | 至少3线(SCLK, MOSI, MISO),每增加一个从设备需多一根SS线 |
| 时钟信号 | 无共享时钟,依赖波特率匹配 | 由主设备提供SCLK |
| 速度 | 较低,常见115200 bps ~ 1 Mbps,受波特率误差限制 | 很高,可达数十Mbps甚至上百Mbps,受限于器件特性 |
| 寻址方式 | 无硬件寻址,靠协议软件寻址(如MODBUS地址) | 硬件片选(SS)寻址 |
| 通信距离 | 较远(几米到几十米),可使用RS-232/485增强 | 很短(通常板级,几十厘米内) |
| 典型应用 | 连接PC调试口、GPS模块、蓝牙/WIFI模块、工业传感器(RS-485) | 连接Flash、EEPROM、SD卡、显示屏、ADC/DAC、传感器(如IMU) |
| 软件复杂度 | 较低,协议简单 | 中等,需管理片选、时钟模式 |
选型建议:
- 选择SCI/UART当:你需要连接另一个独立的系统(如电脑)、通信距离较长、对速度要求不高、或者从设备只支持UART(很多蓝牙模块、GPS模块)。它的“即插即用”和调试便利性(printf到串口)是无与伦比的。
- 选择SPI当:你需要极高的数据传输速率(如刷屏、读写大容量Flash)、连接多个板载外设、或者外设本身是SPI接口(如大多数NOR Flash和OLED屏)。SPI的吞吐量和实时性通常更好。
4.2 配置流程与代码示例(以SPI模式0驱动OLED为例)
假设我们使用一款MCU,以SPI模式0驱动一个SSD1306 OLED屏(通常支持4线SPI)。
步骤1:硬件连接
- MCU MOSI -> OLED SDA (数据线)
- MCU SCLK -> OLED SCL (时钟线)
- MCU GPIO -> OLED DC (数据/命令选择)
- MCU GPIO -> OLED RES (复位)
- MCU GPIO -> OLED CS (片选,如果模块有)
步骤2:初始化配置
// 伪代码,具体寄存器名称因MCU而异 void SPI_OLED_Init(void) { // 1. 使能SPI模块时钟 CLOCK_EnableClock(kCLOCK_Spi0); // 2. 配置GPIO复用为SPI功能 GPIO_SetPinMux(SPI_MOSI_PORT, SPI_MOSI_PIN, kGPIO_MuxAlt2); GPIO_SetPinMux(SPI_SCLK_PORT, SPI_SCLK_PIN, kGPIO_MuxAlt2); // CS和DC用普通GPIO控制 GPIO_SetPinDir(SPI_CS_PORT, SPI_CS_PIN, kGPIO_DigitalOutput); GPIO_SetPinDir(SPI_DC_PORT, SPI_DC_PIN, kGPIO_DigitalOutput); GPIO_WritePinOutput(SPI_CS_PORT, SPI_CS_PIN, 1); // 初始不选中 // 3. 配置SPI为主模式,模式0 (CPOL=0, CPHA=0) SPI_MASTER->CTRL1 &= ~(SPI_CTRL1_CPOL_MASK | SPI_CTRL1_CPHA_MASK); // CPOL=0, CPHA=0 SPI_MASTER->CTRL1 |= SPI_CTRL1_MSTR_MASK; // 主模式 // 4. 设置波特率 (假设系统时钟16MHz,目标SCLK 4MHz) // 分频系数 = 16MHz / 4MHz = 4 SPI_MASTER->BR = SPI_BR_SPR(0x01); // 根据寄存器定义设置分频值 // 5. 设置数据位宽为8位,MSB先行 SPI_MASTER->CTRL2 = SPI_CTRL2_DS(0x07); // 8位数据,对应DS=0x07 SPI_MASTER->CTRL1 &= ~SPI_CTRL1_LSBFE_MASK; // MSB先行 // 6. 使能SPI模块 SPI_MASTER->CTRL1 |= SPI_CTRL1_SPE_MASK; }步骤3:数据传输函数
void SPI_WriteByte(uint8_t data) { // 等待发送缓冲区空 while(!(SPI_MASTER->STATUS & SPI_STATUS_SPTE_MASK)) { // 可加入超时机制 } // 写入数据,启动传输 SPI_MASTER->DATA = data; // 等待接收完成(全双工,同时也会收到一个字节,可忽略) while(!(SPI_MASTER->STATUS & SPI_STATUS_SPRF_MASK)) { // 可加入超时机制 } // 读取数据以清除SPRF标志(可选,但建议读取以避免遗留状态) volatile uint8_t dummy = SPI_MASTER->DATA; } void OLED_WriteCommand(uint8_t cmd) { GPIO_WritePinOutput(SPI_DC_PORT, SPI_DC_PIN, 0); // DC=0,写命令 GPIO_WritePinOutput(SPI_CS_PORT, SPI_CS_PIN, 0); // CS=0,选中器件 SPI_WriteByte(cmd); GPIO_WritePinOutput(SPI_CS_PORT, SPI_CS_PIN, 1); // CS=1,取消选中 } void OLED_WriteData(uint8_t data) { GPIO_WritePinOutput(SPI_DC_PORT, SPI_DC_PIN, 1); // DC=1,写数据 GPIO_WritePinOutput(SPI_CS_PORT, SPI_CS_PIN, 0); SPI_WriteByte(data); GPIO_WritePinOutput(SPI_CS_PORT, SPI_CS_PIN, 1); }实操心得:在SPI通信中,片选(CS)的时序控制非常重要。拉低CS是通信的开始,拉高是通信的结束。对于支持连续写入的设备,可以在一次拉低CS期间发送多个字节。此外,有些设备对CS拉高后的延迟有要求(Tcss),需要在两次操作间插入微小延时(
__NOP()或delay_us(1))。
4.3 常见问题排查与调试技巧
问题1:SCI通信乱码或完全无数据。
- 检查电平:首先用示波器或逻辑分析仪查看TX和RX引脚是否有波形。确认电平是否符合要求(TTL电平一般是0V/3.3V)。
- 确认波特率:这是最常见的问题。双方面板率必须绝对一致,且误差在允许范围内。用示波器测量一个字节的时长(如发送0x55,波形为10101010),计算实际波特率。
- 检查数据格式:数据位(8位/9位)、停止位(1位/2位)、奇偶校验位是否匹配。
- 检查硬件流控:如果使用了RTS/CTS硬件流控,确保流控信号线连接正确且未被意外使能。
问题2:SPI通信能写不能读,或读回数据固定为0xFF/0x00。
- 确认模式(CPOL/CPHA):这是SPI的头号杀手。务必确保主从设备模式完全相同。用逻辑分析仪捕获SCLK、MOSI、MISO波形,对照数据手册的时序图逐个边沿检查。
- 检查片选(SS):确认SS信号在通信期间保持有效(低电平)。对于CPHA=0模式,确认SS在每个数据字间有正确的跳变。
- 检查MISO线路:在从设备被选中时,测量MISO线是否有输出。可能从设备本身需要特定的命令序列才会在MISO上输出数据。
- 检查数据位宽和顺序:确认主从设备设置的数据长度(8位、16位)和移位顺序(MSB/LSB)一致。
问题3:SPI通信速度达不到预期。
- 检查时钟分频配置:确认SPI波特率寄存器的配置值是否正确计算。
- 检查软件开销:如果采用查询方式(检查SPTE/SPRF标志),在高速传输时,循环检查标志位的时间可能成为瓶颈。考虑使用DMA或中断来传输数据。
- 检查从设备极限:查阅从设备数据手册,确认其支持的最高SCLK频率。有些低速设备(如某些传感器)可能最高只支持1MHz。
调试利器:一个哪怕是最基础款的逻辑分析仪(如Saleae Logic 8或国产平价型号),配合上位机软件,可以直观地捕获SCI/SPI的波��,解析出具体的字节数据、波特率、时序关系,是排查通信问题不可或缺的工具。在问题面前,“让波形说话”远比盲目猜测有效得多。
5. 低功耗设计中的通信接口考量
在物联网和便携式设备中,功耗是核心指标。SCI和SPI在低功耗设计中有不同的策略。
SCI的低功耗策略:
- 利用唤醒功能:如前所述,配置SCI在停止模式下保持活动,并启用空闲线或地址标记唤醒。设备大部分时间深度睡眠,只有收到特定格式的报文时才被唤醒处理,可极大降低平均功耗。
- 动态波特率:在需要主动上报数据的场景,可以在低速波特率下监听唤醒指令,唤醒后再切换到高速波特率进行大数据量传输,减少高速接口的活动时间。
- 关闭接收器:如果设备只需要发送而不需要接收,可以只使能发送器(TE),关闭接收器(RE)及其相关电路。
SPI的低功耗策略:
- 及时释放总线:通信完成后,主设备应立即拉高所有从设备的SS线。对于开漏配置(WOM=1)的MISO线,从设备在SS为高时会进入高阻态,避免不必要的电流通路。
- 关闭从设备电源:对于支持掉电模式的从设备(如某些传感器),主设备在不需要时可以通过GPIO控制其电源开关,彻底断电。
- 降低通信频率:在满足应用需求的前提下,使用尽可能低的SCLK频率。动态调整波特率分频器,在传输空闲期降低时钟频率(如果从设备支持)。
- 模块化关闭:如果MCU有多个SPI模块,只使能正在使用的那一个,其他模块的时钟和电源域可以关闭。
一个综合案例:一个由电池供电的无线传感器节点。它使用SPI接口的高速加速度计持续采集数据,并使用带蓝牙的UART模块间歇性上报。设计如下:
- MCU主循环以低功耗运行模式(VLPR)运行,使用SPI(配置为较低速度)定时读取加速度计数据并做本地滤波和缓存。
- UART(SCI)模块被配置为在停止模式下可唤醒,且接收器始终使能。
- 大部分时间,MCU处于深度停止模式,只有RTC和SCI接收器在极低功耗下工作。
- 当手机APP通过蓝牙发送一个特定唤醒指令(如“WAK”+节点地址)时,SCI产生接收中断唤醒MCU。
- MCU被唤醒后,切换到高速运行模式,将SPI时钟提速,快速读取一批缓存的高精度传感器数据,通过UART(此时已切换到高速波特率)经蓝牙发送出去。
- 数据发送完毕后,MCU重新配置外设进入低功耗状态,并再次进入停止模式。
通过这种策略,设备在99%的时间处于微安级的待机电流下,只在必要时才短暂进入毫安级的工作状态,从而实现了长达数年的电池寿命。这其中的关键,正是对SCI和SPI模块在各种功耗模式下行为的精准理解和配置。
