STM32F103C8T6芯片SPI功能详细描述+通用模板+关键代码参数修改解析

STM32F103C8T6芯片集成了两个SPI(Serial Peripheral Interface)外设模块(SPI1和SPI2),支持高速全双工或半双工的同步串行通信。其SPI功能专为连接外部设备(如存储器、传感器、显示屏等)设计,具备灵活的配置选项和高效的数据传输能力。

​1.核心特性

  1. 工作模式

    • 主模式(Master)​:控制通信时钟(SCK)并发起数据传输。
    • 从模式(Slave)​:响应主设备的时钟,被动接收或发送数据。
    • 多主支持:支持多主总线仲裁,避免数据冲突。
  2. 通信配置

    • 时钟极性(CPOL)与相位(CPHA)​
      • CPOL=0:SCK空闲时为低电平;CPOL=1:SCK空闲时为高电平。
      • CPHA=0:数据在时钟第一个边沿采样;CPHA=1:数据在时钟第二个边沿采样。
        组合形成四种SPI模式(0-3),兼容不同外设的时序要求。
    • 数据帧格式
      • 数据长度可配置为8位或16位。
      • 支持MSB(高位先行)或LSB(低位先行)传输顺序。
    • 通信速率
      • 主模式下SCK频率可配置(最高18 MHz @ 72 MHz系统时钟)。
      • 分频系数通过寄存器设置,支持灵活调整。
  3. 数据传输方式

    • 轮询模式:通过状态寄存器查询传输状态,适用于低频率或简单应用。
    • 中断模式:数据发送/完成时触发中断,提升CPU利用率。
    • DMA模式:通过DMA控制器自动搬运数据,减少CPU负载,适合高速大数据量传输。
  4. 片选管理(NSS)​

    • 硬件模式:使用专用NSS引脚(如SPI1的PA4),自动控制片选信号。
    • 软件模式:通过GPIO手动控制片选引脚电平,支持多从设备切换。
  5. 高级功能

    • CRC校验:内置硬件CRC计算单元,支持数据传输完整性校验。
    • TI模式兼容:支持TI串行协议格式,适配特定外设需求。
    • 单线半双工:通过配置,复用MOSI和MISO为单一数据线。

2.​硬件资源与引脚分配

  • SPI1
    • 全功能主/从接口,支持高速通信。
    • 引脚:SCK(PA5)、MISO(PA6)、MOSI(PA7)、NSS(PA4)。
  • SPI2
    • 功能与SPI1相同,但时钟速率较低。
    • 引脚:SCK(PB13)、MISO(PB14)、MOSI(PB15)、NSS(PB12)。

​3.错误检测与处理

  • 溢出错误(Overrun)​:从设备未及时读取接收数据寄存器,导致新数据覆盖旧数据。
  • 模式错误(Mode Fault)​:多主竞争时检测到总线冲突。
  • CRC错误:接收数据的CRC校验值与预期不符。
  • 状态寄存器标志:通过查询或中断处理这些错误,确保通信可靠性。

4.上完整程序模版,复制可用,已详细注释

/* 包含STM32标准外设库头文件 */
#include "stm32f10x.h"

/* 硬件配置宏定义(示例:SPI1,全双工主模式,SCK=PA5, MISO=PA6, MOSI=PA7) */
#define SPIx                   SPI1
#define SPI_GPIO_PORT          GPIOA
#define SPI_SCK_PIN            GPIO_Pin_5
#define SPI_MISO_PIN           GPIO_Pin_6
#define SPI_MOSI_PIN           GPIO_Pin_7
#define SPI_BAUDRATE_PRESCALER SPI_BaudRatePrescaler_4  // 18 MHz @72MHz系统时钟
#define SPI_MODE               SPI_Mode_Master          // 主模式
#define SPI_CPOL               SPI_CPOL_Low             // 时钟极性(空闲低电平)
#define SPI_CPHA               SPI_CPHA_1Edge            // 数据采样在第1个边沿
#define SPI_DATASIZE           SPI_DataSize_8b          // 8位数据帧
#define SPI_FIRSTBIT           SPI_FirstBit_MSB         // 高位先行
#define SPI_NSS                SPI_NSS_Soft              // 软件控制NSS

/**
  * @brief  SPI初始化函数(配置GPIO和SPI参数)
  * @param  无
  * @retval 无
  */
void SPI_Config(void) {
    GPIO_InitTypeDef GPIO_InitStruct;
    SPI_InitTypeDef SPI_InitStruct;
    
    /* 1. 使能时钟(SPI1在APB2总线,GPIOA在APB2) */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 | RCC_APB2Periph_GPIOA, ENABLE);
    
    /* 2. 配置SPI引脚(复用推挽输出用于SCK/MOSI,浮空输入用于MISO) */
    GPIO_InitStruct.GPIO_Pin = SPI_SCK_PIN | SPI_MOSI_PIN;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;       // 复用推挽输出
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(SPI_GPIO_PORT, &GPIO_InitStruct);
    
    GPIO_InitStruct.GPIO_Pin = SPI_MISO_PIN;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入
    GPIO_Init(SPI_GPIO_PORT, &GPIO_InitStruct);
    
    /* 3. 配置SPI工作参数 */
    SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // 全双工
    SPI_InitStruct.SPI_Mode = SPI_MODE;              // 主/从模式
    SPI_InitStruct.SPI_DataSize = SPI_DATASIZE;      // 数据位宽
    SPI_InitStruct.SPI_CPOL = SPI_CPOL;               // 时钟极性
    SPI_InitStruct.SPI_CPHA = SPI_CPHA;               // 时钟相位
    SPI_InitStruct.SPI_NSS = SPI_NSS;                // 软件/硬件NSS控制
    SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BAUDRATE_PRESCALER; // 波特率分频
    SPI_InitStruct.SPI_FirstBit = SPI_FIRSTBIT;      // 数据传输顺序
    SPI_InitStruct.SPI_CRCPolynomial = 7;            // CRC多项式(默认7)
    SPI_Init(SPIx, &SPI_InitStruct);
    
    /* 4. 使能SPI模块 */
    SPI_Cmd(SPIx, ENABLE);
}

/**
  * @brief  SPI发送单字节数据(轮询模式)
  * @param  data: 待发送的字节
  * @retval 接收到的字节
  */
uint8_t SPI_SendByte(uint8_t data) {
    /* 等待发送缓冲区空 */
    while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET);
    
    /* 发送数据 */
    SPI_I2S_SendData(SPIx, data);
    
    /* 等待接收完成 */
    while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET);
    
    /* 返回接收到的数据 */
    return SPI_I2S_ReceiveData(SPIx);
}

/**
  * @brief  SPI发送多字节数据(轮询模式)
  * @param  pTxData: 发送数据缓冲区指针
  * @param  pRxData: 接收数据缓冲区指针
  * @param  len: 数据长度
  * @retval 无
  */
void SPI_TransmitReceive(uint8_t *pTxData, uint8_t *pRxData, uint16_t len) {
    for (uint16_t i = 0; i < len; i++) {
        pRxData[i] = SPI_SendByte(pTxData[i]);  // 全双工传输
    }
}

/*********************​ 模板使用示例 ​*********************
int main(void) {
    uint8_t txData[4] = {0x01, 0x02, 0x03, 0x04};
    uint8_t rxData[4];
    
    SystemInit();  // 系统时钟初始化(72MHz)
    SPI_Config();  // 配置SPI
    
    // 手动控制NSS引脚(示例使用PA4作为软件NSS)
    GPIO_ResetBits(GPIOA, GPIO_Pin_4);  // 拉低NSS(选中从机)
    SPI_TransmitReceive(txData, rxData, 4);  // 传输数据
    GPIO_SetBits(GPIOA, GPIO_Pin_4);    // 拉高NSS(释放从机)
    
    while(1);
}
********************************************************/

5.模板程序功能说明

  1. 模块化初始化

    • SPI_Config():完成GPIO复用配置、SPI参数设置及模块使能,支持主/从模式切换。
    • 通过宏定义硬件参数,适配不同SPI外设(SPI1/SPI2)及通信需求。
  2. 数据传输函数

    • SPI_SendByte():单字节全双工传输,返回接收到的数据(轮询模式)。
    • SPI_TransmitReceive():多字节数据传输封装,支持连续读写操作。
  3. 软件NSS控制
    示例中使用PA4作为手动控制的片选引脚,用户可根据需要修改为硬件NSS或扩展多从机管理。


​6.关键参数详解

  1. SPI模式(SPI_Mode)​

    SPI_Mode_Master  // 主模式(控制SCK)
    SPI_Mode_Slave   // 从模式(响应SCK)
  2. 时钟相位与极性组合

    CPOLCPHA模式数据采样边沿
    00(1Edge)0上升沿采样(奇数边沿)
    01(2Edge)1下降沿采样
    10(1Edge)2下降沿采样
    11(2Edge)3上升沿采样(偶数边沿)
  3. 波特率分频系数(SPI_BAUDRATE_PRESCALER)​

    SPI_BaudRatePrescaler_2    // 36 MHz (72MHz/2)
    SPI_BaudRatePrescaler_4    // 18 MHz (72MHz/4)
    SPI_BaudRatePrescaler_256  // 281.25 kHz (72MHz/256)
  4. 数据帧格式

    SPI_DataSize_8b  // 8位数据(常用)
    SPI_DataSize_16b // 16位数据(某些ADC/DAC使用)

​7.使用注意事项

  1. NSS信号管理

    • 硬件NSS模式下,自动控制片选信号但灵活性较低。
    • 软件NSS需手动控制GPIO电平,多从机系统需独立片选引脚。
  2. 电气匹配

    • 主从设备需共享GND,长距离通信建议添加终端电阻(100Ω)。
    • MISO引脚上拉电阻(4.7kΩ)可增强信号稳定性。
  3. 中断/DMA扩展

    • 修改传输函数为中断或DMA模式,需配置SPI_ITConfig()和NVIC/DMA通道。
    • 示例代码为轮询模式,适用于低速传输;高速场景建议使用DMA。
  4. 全双工与半双工

    • 若仅需单向传输(如只发送),可配置为SPI_Direction_1Line_Tx半双工模式。
    • 单线模式需复用MOSI/MISO引脚。

8.典型应用场景

  • 存储器扩展:连接SPI Flash(如W25Q128)或EEPROM存储数据。
  • 传感器读取:采集温度(如MAX6675)、加速度(MPU6050)等传感器数据。
  • 显示驱动:控制OLED或TFT屏幕(如ILI9341)。
  • 通信桥接:作为主设备管理多个从设备(如多个ADC或DAC芯片)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值