别再死记硬背了!用示波器抓波形,彻底搞懂STM32 SPI的四种工作模式

张开发
2026/4/20 18:27:30 15 分钟阅读

分享文章

别再死记硬背了!用示波器抓波形,彻底搞懂STM32 SPI的四种工作模式
示波器实战用波形分析彻底掌握STM32 SPI四种模式第一次接触SPI协议时你是否也被CPOL和CPHA这两个参数绕晕了手册上那些抽象的定义和时序图看十遍也不如实际抓一次波形来得直观。今天我们就用STM32F103C8T6和一块常见的W25Q64 Flash芯片通过示波器捕捉四种工作模式下的真实波形差异让你从知道变成真正理解。1. 实验准备硬件连接与基础配置在开始之前我们需要准备以下硬件STM32F103C8T6开发板蓝色小板W25Q64 Flash模块SPI接口数字示波器或逻辑分析仪杜邦线若干接线方式如下表示STM32引脚W25Q64引脚功能说明PB3CLK时钟线PB4DO主机输入PB5DI主机输出PA15CS片选信号基础初始化代码Mode 0配置示例void SPI_Init_Mode0(void) { SPI_InitTypeDef SPI_InitStruct; // 时钟极性低第一个边沿采样 SPI_InitStruct.SPI_CPOL SPI_CPOL_Low; SPI_InitStruct.SPI_CPHA SPI_CPHA_1Edge; // 其他配置 SPI_InitStruct.SPI_Mode SPI_Mode_Master; SPI_InitStruct.SPI_Direction SPI_Direction_2Lines_FullDuplex; SPI_InitStruct.SPI_DataSize SPI_DataSize_8b; SPI_InitStruct.SPI_FirstBit SPI_FirstBit_MSB; SPI_InitStruct.SPI_BaudRatePrescaler SPI_BaudRatePrescaler_64; SPI_InitStruct.SPI_NSS SPI_NSS_Soft; SPI_Init(SPI1, SPI_InitStruct); SPI_Cmd(SPI1, ENABLE); }提示建议将波特率预分频设置为64约1.125MHz这样示波器更容易捕捉完整波形。2. SPI模式本质CPOL与CPHA的四种组合SPI的四种模式本质上是时钟极性(CPOL)和时钟相位(CPHA)的排列组合。这两个参数决定了CPOL时钟极性时钟空闲时的电平状态0空闲时为低电平1空闲时为高电平CPHA时钟相位数据采样的边沿0在第一个时钟边沿采样1在第二个时钟边沿采样四种模式对应关系如下表模式CPOLCPHA空闲时钟采样边沿典型应用000低电平第一个上升沿W25Q64, SD卡101低电平第二个下降沿某些传感器210高电平第一个下降沿较少使用311高电平第二个上升沿某些RF模块3. 模式0实战W25Q64的标准工作模式让我们先看最常见的Mode 0这也是W25Q64 Flash芯片的默认工作模式。配置好Mode 0后发送一个简单的字节如0x55二进制01010101用示波器同时捕捉SCK、MOSI和CS信号。理想波形特征CS线从高变低表示通信开始SCK空闲时为低电平CPOL0MOSI数据在SCK的上升沿稳定采样点数据位按照MSB优先的顺序依次传输// 发送单个字节函数示例 void SPI_SendByte(uint8_t data) { while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) RESET); SPI_I2S_SendData(SPI1, data); }实际示波器截图分析文字描述t0时刻CS拉低通信开始t1时刻第一个SCK上升沿MOSI已经稳定为0MSBt2时刻第二个SCK上升沿MOSI为1...t8时刻第8个SCK上升沿后CS拉高注意如果发现数据采样不稳定检查示波器探头接地是否良好可以尝试降低波特率。4. 模式3分析另一种常见的工作模式虽然W25Q64支持Mode 0和Mode 3但让我们故意将其配置为Mode 3来观察波形差异。修改初始化代码void SPI_Init_Mode3(void) { SPI_InitTypeDef SPI_InitStruct; // 时钟极性高第二个边沿采样 SPI_InitStruct.SPI_CPOL SPI_CPOL_High; SPI_InitStruct.SPI_CPHA SPI_CPHA_2Edge; // 其他配置保持不变... }Mode 3的关键区别SCK空闲时为高电平CPOL1数据在SCK的下降沿变化在上升沿采样CPHA1第一个数据位在CS有效后的第一个SCK边沿前就需准备好常见问题排查如果发现读取的数据总是0xFF可能是模式不匹配某些设备要求模式切换时需要重新上电示波器触发建议设置为CS下降沿5. 模式1和模式2的对比实验为了全面理解我们再快速看看相对少用的Mode 1和Mode 2。Mode 1特点SCK空闲低电平CPOL0在SCK的下降沿采样CPHA1数据在上升沿变化Mode 2特点SCK空闲高电平CPOL1在SCK的下降沿采样CPHA0数据在上升沿变化可以通过以下代码快速切换模式void SPI_ChangeMode(uint8_t mode) { SPI_Cmd(SPI1, DISABLE); switch(mode) { case 0: SPI_InitStruct.SPI_CPOL SPI_CPOL_Low; SPI_InitStruct.SPI_CPHA SPI_CPHA_1Edge; break; case 1: // ...其他模式配置 } SPI_Init(SPI1, SPI_InitStruct); SPI_Cmd(SPI1, ENABLE); }6. 实际调试技巧与常见问题在调试SPI通信时我总结了一些实用技巧示波器设置技巧使用四通道同时捕捉SCK、MOSI、MISO和CS时间基准设为1μs/div左右触发模式设为CS下降沿典型问题排查表现象可能原因解决方法能发送但收不到响应模式不匹配检查从设备要求的SPI模式数据位错位位序(MSB/LSB)设置错误统一主从设备的FirstBit设置信号质量差波特率过高或线路过长降低波特率缩短连线偶尔通信失败CS信号抖动增加CS有效后的延时代码优化建议// 更好的SPI收发函数实现 uint8_t SPI_Transfer(uint8_t data) { while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) RESET); SPI_I2S_SendData(SPI1, data); while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) RESET); return SPI_I2S_ReceiveData(SPI1); }7. 进阶通过波形诊断通信问题最后我们来看几个实际的错误波形案例案例1模式不匹配现象主机Mode 0从机Mode 3波形特征数据采样边沿与数据变化边沿重合结果读取的数据随机错误案例2波特率过高现象信号出现振铃和过冲波形特征上升/下降沿出现振荡解决降低波特率或缩短连线案例3CS信号问题现象通信时好时坏波形特征CS信号上有毛刺解决加强软件CS控制或硬件滤波记得第一次调试SPI时我花了整整一天才意识到是模式配置错误。后来养成了习惯拿到新器件先查手册确认SPI模式然后用示波器验证波形省去了很多盲目调试的时间。

更多文章