SPI — 全双工主机(DMA)(HAL 库)
固件库: PY32F0xx_Firmware V1.5.0
芯片: PY32F030
源文件:PUYA/PY32F0xx_Firmware_V1.5.0/Projects/PY32F030-STK/Example/SPI/SPI_TwoBoards_FullDuplexMaster_DMA/Src/main.c
功能简介
SPI(Serial Peripheral Interface)是一种四线制、全双工、同步串行总线,速率远高于 I2C,常用于 LCD、Flash、ADC、无线通信模块等。
本示例演示 SPI1 主机 + DMA 全双工通信:
- 主机通过
HAL_SPI_TransmitReceive_DMA()同时收发 15 字节; - 数据搬运由 DMA 完成,CPU 在传输期间可腾出手做别的事;
- 传输完成后回调函数里校验收发是否一致,一致则点亮绿灯。
- 本工程仅提供主机(Master DMA)示例;同目录另有时钟/引脚由
HAL_SPI_MspInit配置(在py32f0xx_hal_msp.c中绑定 SPI1 引脚与 DMA 通道)。
说明:PY32F0xx V1.5.0 的 STK 示例里 SPI 全双工只提供了 DMA 版(无纯轮询版)。若想用轮询,可把
HAL_SPI_TransmitReceive_DMA换成HAL_SPI_TransmitReceive(轮询版 API 同样存在),二者配置完全一致。
硬件准备
- 两块 PY32F030 开发板(一主一从),或用一块板把 MOSI↔MISO 短接做回环
- 交叉连接:主 MOSI↔从 MOSI,主 MISO↔从 MISO,主 SCK↔从 SCK,主 NSS↔从 NSS,共地
- 板载 LED / 按键用于交互(示例需按键触发一次传输)
完整代码(主机部分)
|
|
代码分段讲解
1. 时钟极性 / 相位(CPOL / CPHA)
SPI 通信双方必须 CPOL、CPHA 一致,否则收到的是错位数据:
- 本例
CPOL=LOW, CPHA=1EDGE对应 Mode 0(常用默认)。 - 四种组合:Mode0(0,0)、Mode1(0,1)、Mode2(1,0)、Mode3(1,1),按从设备手册选择。
2. 全双工本质
SPI 移位寄存器决定了“发的同时也在收”。HAL_SPI_TransmitReceive 把 TxBuff 逐位发出,同时把 MISO 上的数据逐位存入 RxBuff。回环(MOSI 接 MISO)时,发什么就收到什么,便于自测。
3. DMA vs 轮询
- DMA 版:
HAL_SPI_TransmitReceive_DMA启动后由 DMA 控制器搬运数据,CPU 立刻返回,可在回调/状态查询里做别的事,适合大数据量。 - 轮询版:把上面函数换成
HAL_SPI_TransmitReceive(&Spi1Handle, Tx, Rx, len)(阻塞直到完成),代码更短,适合小数据量教学。
4. NSS 片选
本例 SPI_NSS_HARD_OUTPUT:主机 NSS 引脚由硬件自动在传输时拉低、结束后拉高,省去手动控制。若用软件片选,改 SPI_NSS_SOFT 并自行 HAL_GPIO_WritePin(NSS, RESET/SET)。
实验现象
- 按下用户键后启动一次 15 字节全双工收发;
- 回环或正确对接从机时,收发一致,绿灯常亮;
- 数据异常则绿灯 500ms 周期闪烁。
常见问题
-
收不到数据 / 全是 0xFF?
- 检查 CPOL/CPHA 是否与从机一致。
- 确认接线:MOSI-MOSI、MISO-MISO、SCK-SCK、NSS-NSS,并共地。
- 波特率(
BaudRatePrescaler)不要超过从机最大 SPI 时钟。
-
想用轮询版?
- 直接调用
HAL_SPI_TransmitReceive()(不带_DMA),其余配置不变。
- 直接调用
-
DMA 传输只发不收 / 卡在 BUSY?
- 确认
HAL_SPI_MspInit中已为 SPI1 的 TX/RX 绑定正确的 DMA 通道并使能 DMA 时钟;传输完成需等State == HAL_SPI_STATE_READY。
- 确认
小结
- SPI 主机配置要点:波特率分频、CPOL/CPHA、数据位宽、MSB/LSB、NSS 方式、主/从模式。
- 全双工 = 同时收发;回环自测最方便。
- DMA 适合大批量数据,轮询版更简单;两者配置相同,仅启动函数不同。
拓展应用
- 驱动 SPI Flash(W25Qxx)、LCD(ST7735/ILI9341)、SD 卡(SPI 模式)。
- 对接 SPI ADC(如 ADS1118)、无线模块(nRF24L01、SX1278)。
- 改用
SPI_NSS_SOFT一主多从,用不同 NSS 选片。 - 把 DMA 版改为中断/DMA 双缓冲,实现连续高速数据流(音频、屏幕刷新)。