【STM32学习笔记】SPI通信原理与标准库开发实践

前言

在嵌入式开发中,SPI(Serial Peripheral Interface)作为一种高速全双工的同步通信协议,被广泛应用于FLASH存储器、显示屏、传感器等外设的通信。本文将结合STM32F1系列芯片,分享如何通过标准外设库(Standard Peripheral Library)实现SPI通信的开发过程。

一、SPI协议基础

1.1 通信特点

  • 四线制:SCK(时钟)、MOSI(主出从入)、MISO(主入从出)、NSS(片选)

  • 全双工同步传输:主机控制时钟,主从设备同时收发数据

  • 通信模式:由CPOL(时钟极性)和CPHA(时钟相位)组合的4种模式

1.2 关键参数

参数说明
时钟频率可达几十MHz(取决于外设)
数据帧格式8位或16位数据帧
传输顺序MSB First或LSB First

二、STM32的SPI外设

2.1 硬件特性

  • 支持主/从模式切换

  • 3个独立SPI控制器(SPI1/SPI2/SPI3)

  • 8/16位数据帧可编程

  • 硬件CRC校验(可选)

2.2 时钟配置

SPI时钟源来自APB总线:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); // SPI1在APB2总线

三、标准库开发步骤

3.1 初始化配置

void SPI1_Init(void)
{
    SPI_InitTypeDef SPI_InitStructure;
    
    /* 引脚配置(以SPI1为例) */
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    
    // SCK:PA5, MOSI:PA7
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* SPI参数配置 */
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;       // 主模式
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;   // 8位数据
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;         // 模式3
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;           // 软件控制NSS
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;  // 高位先行
    SPI_Init(SPI1, &SPI_InitStructure);
    
    SPI_Cmd(SPI1, ENABLE); // 使能SPI外设
}

3.2 数据收发函数

uint8_t SPI1_ReadWriteByte(uint8_t TxData)
{
    while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); // 等待发送缓冲区空
    SPI_I2S_SendData(SPI1, TxData);
    
    while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); // 等待接收完成
    return SPI_I2S_ReceiveData(SPI1);
}

四、关键问题与调试技巧

4.1 常见问题排查

  1. 无数据收发

    • 检查SPI使能位是否开启

    • 确认NSS片选信号有效

    • 验证时钟极性/相位是否匹配从设备

  2. 数据错位

    • 检查MSB/LSB配置

    • 确认数据帧长度一致

4.2 调试建议

  • 逻辑分析仪:抓取SCK、MOSI、MISO波形

  • 示波器:验证时钟频率和信号质量

  • 分步调试:通过断点检查SPI状态寄存器

五、应用实例——读写FLASH芯片

以W25Q128为例:

// 读取设备ID
uint16_t W25Q_ReadID(void)
{
    uint16_t Temp = 0;
    W25Q_CS_LOW(); // 拉低片选
    
    SPI1_ReadWriteByte(0x90); // 发送读ID命令
    SPI1_ReadWriteByte(0x00);
    SPI1_ReadWriteByte(0x00);
    SPI1_ReadWriteByte(0x00);
    
    Temp |= SPI1_ReadWriteByte(0xFF) << 8;
    Temp |= SPI1_ReadWriteByte(0xFF);
    
    W25Q_CS_HIGH();
    return Temp;
}

六、总结

通过标准库开发SPI通信需要重点关注:

  1. 正确的GPIO模式配置(复用功能)

  2. SPI工作模式与从设备匹配

  3. 合理的时钟分频设置

  4. 严格的时序控制(特别是片选信号)

建议结合STM32参考手册的SPI章节(Chapter 23)和具体外设的数据手册进行开发。后续可继续探索DMA传输、中断模式等高级应用。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值