1. SPI协议基础:从物理层到通信规则
大家好,我是你们的嵌入式系统讲师。今天咱们开始SPI NOR Flash驱动开发的第一课。说实话,SPI协议看起来简单,但我在实际项目中见过太多人在这上面栽跟头。咱们先把地基打牢,后面写驱动才能得心应手。
1.1 SPI总线简介
SPI,全称Serial Peripheral Interface,串行外设接口。它是由摩托罗拉公司在上世纪80年代推出的。你想想看,一个80年代的技术到现在还在广泛使用,说明它确实有两把刷子。
SPI是一种同步、全双工、主从式的串行通信协议。同步意味着有独立的时钟线;全双工意味着可以同时收发数据;主从式则意味着总线上只有一个设备能控制时钟。
我个人习惯把SPI比作一个「对话场景」:
- 主机是老师,负责发号施令(产生时钟)
- 从机是学生,听老师的指令回应
- 数据线就像传纸条的通道
SPI总线的最大优势是什么?速度快。相比I2C的100kHz-400kHz,SPI轻松跑到几十MHz。我在一个项目中用过50MHz的SPI时钟,读Flash的速度那叫一个爽。
1.2 四线制详解:SCK/MOSI/MISO/CS
SPI总线通常需要4根线。咱们一个一个来看。
| 信号线 | 全称 | 方向 | 作用 |
|---|---|---|---|
| SCK | Serial Clock | 主机→从机 | 时钟信号,由主机产生 |
| MOSI | Master Out Slave In | 主机→从机 | 主机发送数据给从机 |
| MISO | Master In Slave Out | 从机→主机 | 从机发送数据给主机 |
| CS | Chip Select | 主机→从机 | 片选信号,低电平有效 |
SCK(时钟线):这是总线的「心跳」。没有时钟,SPI就玩不转。时钟频率决定了通信速度。我记得有一次调试,发现Flash读写偶尔出错,查了半天发现是时钟线走线太长,信号质量变差了。
MOSI(主机输出/从机输入):数据从主机流向从机。主机在时钟的某个边沿把数据放到这条线上,从机在另一个边沿采样。
MISO(主机输入/从机输出):数据从从机流向主机。注意,这条线在从机没有被选中时,必须处于高阻态。否则多个从机同时驱动这条线,就会打架。
CS(片选线):这条线决定了「谁在跟主机说话」。低电平有效,也就是说CS拉低时,对应的从机被选中。CS拉高时,从机释放总线。
重点提醒:CS信号必须在整个传输过程中保持低电平。我曾经见过一个新手,在发送每个字节之间把CS拉高再拉低,结果Flash根本不认数据。嗯,这里要注意,CS不能随便抖动。
1.3 SPI四种模式(CPOL/CPHA)配置
SPI有4种工作模式,由两个参数决定:CPOL(时钟极性)和CPHA(时钟相位)。
- CPOL:决定时钟空闲时的电平。CPOL=0,空闲时SCK为低电平;CPOL=1,空闲时SCK为高电平。
- CPHA:决定数据在哪个边沿采样。CPHA=0,在第一个边沿采样;CPHA=1,在第二个边沿采样。
说白了,这4种模式就是「时钟怎么摆,数据怎么取」的4种组合。咱们用表格来看:
| 模式 | CPOL | CPHA | 采样边沿 | 数据变化边沿 |
|---|---|---|---|---|
| 模式0 | 0 | 0 | 上升沿 | 下降沿 |
| 模式1 | 0 | 1 | 下降沿 | 上升沿 |
| 模式2 | 1 | 0 | 下降沿 | 上升沿 |
| 模式3 | 1 | 1 | 上升沿 | 下降沿 |
你可能会问:「这么多模式,我该用哪个?」
答案是:看从机的数据手册。大多数SPI NOR Flash默认工作在模式0或模式3。为什么?因为这两种模式下,时钟的上升沿和下降沿刚好对称,硬件实现最简单。
我的经验:如果你不确定从机支持哪种模式,先试试模式0。我做过的大多数Flash芯片,模式0都能正常工作。如果不行,再试模式3。模式1和模式2用得比较少。
配置模式时,你需要在MCU的SPI外设寄存器中设置CPOL和CPHA位。比如在STM32上:
// STM32 SPI配置示例 - 模式0
SPI_InitTypeDef SPI_InitStruct;
SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low; // CPOL=0
SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge; // CPHA=0
// 其他配置...
HAL_SPI_Init(&hspi);
为什么模式配置这么重要?因为主机和从机的模式必须一致。我曾经调试一个项目,Flash死活读不出正确数据,示波器一看,主机是模式0,从机配置成了模式3。时钟边沿对不上,数据全乱了。
1.4 多从机拓扑结构
一个SPI总线上可以挂多个从机。常见的连接方式有两种:
方式一:独立CS线
每个从机有自己的CS线,SCK、MOSI、MISO共享。这是最常用的方式。
- 优点:每个从机独立控制,互不干扰
- 缺点:占用GPIO多,N个从机需要N个CS引脚
方式二:菊花链(Daisy Chain)
所有从机共享CS、SCK,但数据像串糖葫芦一样传递。从机的MISO接到下一个从机的MOSI。
- 优点:节省GPIO,只需要一个CS
- 缺点:延迟大,所有从机必须支持菊花链模式
我个人在实际项目中几乎只用独立CS线的方式。为什么?因为简单可靠。菊花链虽然省引脚,但调试起来太痛苦了。我记得有一次用菊花链挂了4个Flash,数据传一圈回来,时序已经乱得没法看了。
避坑指南:多从机共享MISO线时,一定要确保未选中的从机输出高阻态。否则多个从机同时驱动MISO,轻则数据错误,重则烧坏IO口。我曾经见过一块板子,就是因为从机没有配置高阻态,MISO线上两个信号打架,最后MCU的IO口烧了。
多从机拓扑中还有一个容易忽略的问题:总线负载。每个从机都会给时钟线和数据线增加电容负载。挂的从机越多,信号质量越差。一般来说,一个SPI总线上挂3-4个从机是比较合理的。如果超过这个数,建议加SPI缓冲器或者分多个SPI接口。
小结
好了,这一章咱们把SPI协议的基础过了一遍。从四根信号线的功能,到4种模式的配置,再到多从机的连接方式。这些东西看起来简单,但都是后面写Flash驱动的基石。
下一章,咱们会深入SPI NOR Flash的内部结构,看看数据到底是怎么存进去、读出来的。到时候你会明白,为什么SPI协议要这么设计。