3、SPI总线协议详解:四线制、模式配置、全双工通信、与I2C的对比
各位同学,今天我们来聊聊SPI。这个协议在嵌入式系统里,尤其是像血糖仪这种需要高速数据吞吐的场景,几乎是必选项。我个人习惯把SPI叫做“四线制闪电侠”,因为它简单、快速、全双工,跟I2C那种“慢悠悠”的风格完全不同。
3.1 四线制:谁负责什么?
SPI的全称是Serial Peripheral Interface,串行外设接口。它用四根线搞定一切通信。你想想看,这比I2C的两根线多了两根,但换来的是速度和全双工能力。
- SCLK(串行时钟):由主机产生,决定通信速率。我在项目中遇到过,时钟频率设得太高,从机跟不上,数据全乱套。所以,先看从机的手册,再定时钟。
- MOSI(主机输出,从机输入):主机发数据给从机。说白了,就是主机在“说”。
- MISO(主机输入,从机输出):从机发数据给主机。这是从机在“回应”。
- CS/SS(片选,低电平有效):主机选通哪个从机。一次只能选一个,否则总线会打架。
核心要点:SPI是主从架构,主机控制时钟和片选。从机永远被动,只能等主机叫它。
3.2 模式配置:CPOL和CPHA的“四重奏”
SPI有四种模式,由时钟极性(CPOL)和时钟相位(CPHA)决定。嗯,这里要注意,主机和从机必须工作在同一个模式下,否则数据对不上。
| 模式 | CPOL | CPHA | 时钟空闲电平 | 数据采样边沿 |
|---|---|---|---|---|
| 模式0 | 0 | 0 | 低电平 | 上升沿 |
| 模式1 | 0 | 1 | 低电平 | 下降沿 |
| 模式2 | 1 | 0 | 高电平 | 下降沿 |
| 模式3 | 1 | 1 | 高电平 | 上升沿 |
我曾经在调试一块SPI Flash时,怎么读写都不对。折腾了半天,发现是模式配错了。从机手册上写的是模式0,我代码里配成了模式3。从那以后,我每次都会先确认从机的模式要求,再写代码。
我的习惯:大多数SPI器件默认用模式0。如果你不确定,先试试模式0,不行再换。
3.3 全双工通信:同时收发,效率翻倍
SPI最大的优势就是全双工。什么意思?主机在发送数据的同时,也能接收从机发来的数据。这跟I2C那种半双工(发的时候不能收,收的时候不能发)完全不同。
举个例子,你读取一个SPI ADC的转换结果。主机发一个读命令,同时从机就把上次的结果发回来了。一个时钟周期,数据双向流动。效率非常高。
// 伪代码示例:SPI全双工读写
uint8_t spi_transfer(uint8_t tx_data) {
// 发送tx_data,同时接收rx_data
SPI_DR = tx_data; // 写发送寄存器
while(!(SPI_SR & TX_EMPTY)); // 等待发送完成
while(!(SPI_SR & RX_FULL)); // 等待接收完成
return SPI_DR; // 读接收寄存器
}
你看,一个函数搞定收发。这就是全双工的魅力。在血糖仪里,我们经常用SPI连接显示屏或存储芯片,全双工能显著提升刷新速度。
3.4 与I2C的对比:什么时候选SPI?
很多初学者会问,SPI和I2C到底选哪个?我的回答是:看需求。
| 特性 | SPI | I2C |
|---|---|---|
| 线数 | 4根(SCLK, MOSI, MISO, CS) | 2根(SCL, SDA) |
| 通信方式 | 全双工 | 半双工 |
| 速度 | 快(可达几十MHz) | 慢(标准100kHz,快速400kHz) |
| 从机数量 | 每个从机需独立CS线 | 通过地址区分,最多127个 |
| 硬件复杂度 | 简单,无地址仲裁 | 需要地址和仲裁逻辑 |
| 典型应用 | 高速ADC/DAC、显示屏、存储芯片 | 传感器、EEPROM、实时时钟 |
我个人习惯是:如果设备需要高速、大数据量传输,比如血糖仪的波形显示或历史数据存储,我首选SPI。如果只是读个温度传感器或配置寄存器,I2C就够了,省线。
避坑指南:我曾经在一个项目里,用SPI连接了三个从机,结果CS线太多,PCB走线很乱。后来改用了带片选译码器的方案,用3根线控制8个从机。如果你从机多,可以考虑这个办法。
3.5 实战中的小技巧
最后,分享几个我在血糖仪项目中积累的经验:
- 时钟极性要匹配:主机和从机的CPOL、CPHA必须一致。否则数据采样点错位,读出来全是乱码。
- 片选信号要稳定:在传输过程中,CS必须保持低电平。我见过有人用GPIO模拟CS,结果中断里把CS拉高了,传输中断。
- 注意信号完整性:SPI速率高时,线长超过10cm就可能出现反射。加个小电阻(22-33欧姆)串联在时钟线上,能有效抑制过冲。
- 调试时先看波形:用逻辑分析仪抓一下SCLK、MOSI、MISO和CS的时序。一眼就能看出问题,比盯着代码猜快多了。
好了,SPI的内容就讲到这里。下一章我们会深入I2C,看看它跟SPI到底有哪些不同。记住,没有最好的协议,只有最合适的协议。