stm32f10x_spi

STM32F10x SPI/I2S 外设标准库函数参考文档

数据类型定义

SPI_InitTypeDef - SPI初始化结构体

typedef struct
{
  uint16_t SPI_Direction;           /* SPI单向或双向数据模式 */
  uint16_t SPI_Mode;                /* SPI工作模式 */
  uint16_t SPI_DataSize;            /* SPI数据大小 */
  uint16_t SPI_CPOL;                /* 串行时钟稳定状态 */
  uint16_t SPI_CPHA;                /* 位捕获的时钟有效边沿 */
  uint16_t SPI_NSS;                 /* NSS信号管理方式 */
  uint16_t SPI_BaudRatePrescaler;   /* 波特率预分频值 */
  uint16_t SPI_FirstBit;            /* 数据传输起始位 */
  uint16_t SPI_CRCPolynomial;       /* CRC计算多项式 */
} SPI_InitTypeDef;

成员说明:

  • SPI_Direction:指定SPI单向或双向数据模式,可选值见SPI数据方向定义
  • SPI_Mode:指定SPI工作模式(主机/从机),可选值见SPI模式定义
  • SPI_DataSize:指定SPI数据大小(8位/16位),可选值见SPI数据大小定义
  • SPI_CPOL:指定串行时钟的稳定状态,可选值见SPI时钟极性定义
  • SPI_CPHA:指定位捕获的时钟有效边沿,可选值见SPI时钟相位定义
  • SPI_NSS:指定NSS信号是由硬件(NSS引脚)还是软件(SSI位)管理,可选值见SPI从机选择管理定义
  • SPI_BaudRatePrescaler:指定波特率预分频值,用于配置发送和接收的SCK时钟,可选值见SPI波特率预分频器定义
  • SPI_FirstBit:指定数据传输是从MSB还是LSB位开始,可选值见SPI MSB/LSB传输定义
  • SPI_CRCPolynomial:指定用于CRC计算的多项式

I2S_InitTypeDef - I2S初始化结构体

typedef struct
{
  uint16_t I2S_Mode;         /* I2S工作模式 */
  uint16_t I2S_Standard;     /* I2S通信标准 */
  uint16_t I2S_DataFormat;   /* I2S通信数据格式 */
  uint16_t I2S_MCLKOutput;   /* I2S MCLK输出控制 */
  uint32_t I2S_AudioFreq;    /* I2S通信音频频率 */
  uint16_t I2S_CPOL;         /* I2S时钟空闲状态 */
} I2S_InitTypeDef;

成员说明:

  • I2S_Mode:指定I2S工作模式,可选值见I2S模式定义
  • I2S_Standard:指定I2S通信使用的标准,可选值见I2S标准定义
  • I2S_DataFormat:指定I2S通信的数据格式,可选值见I2S数据格式定义
  • I2S_MCLKOutput:指定是否启用I2S MCLK输出,可选值见I2S MCLK输出定义
  • I2S_AudioFreq:指定I2S通信的音频频率,可选值见I2S音频频率定义
  • I2S_CPOL:指定I2S时钟的空闲状态,可选值见I2S时钟极性定义

SPI常量定义

SPI数据方向定义

#define SPI_Direction_2Lines_FullDuplex ((uint16_t)0x0000)  /* 双线全双工 */
#define SPI_Direction_2Lines_RxOnly     ((uint16_t)0x0400)  /* 双线仅接收 */
#define SPI_Direction_1Line_Rx          ((uint16_t)0x8000)  /* 单线接收 */
#define SPI_Direction_1Line_Tx          ((uint16_t)0xC000)  /* 单线发送 */

SPI模式定义

#define SPI_Mode_Master                 ((uint16_t)0x0104)  /* 主机模式 */
#define SPI_Mode_Slave                  ((uint16_t)0x0000)  /* 从机模式 */

SPI数据大小定义

#define SPI_DataSize_16b                ((uint16_t)0x0800)  /* 16位数据 */
#define SPI_DataSize_8b                 ((uint16_t)0x0000)  /* 8位数据 */

SPI时钟极性定义

#define SPI_CPOL_Low                    ((uint16_t)0x0000)  /* 时钟空闲时为低电平 */
#define SPI_CPOL_High                   ((uint16_t)0x0002)  /* 时钟空闲时为高电平 */

SPI时钟相位定义

#define SPI_CPHA_1Edge                  ((uint16_t)0x0000)  /* 第一个边沿采样 */
#define SPI_CPHA_2Edge                  ((uint16_t)0x0001)  /* 第二个边沿采样 */

SPI从机选择管理定义

#define SPI_NSS_Soft                    ((uint16_t)0x0200)  /* 软件管理NSS */
#define SPI_NSS_Hard                    ((uint16_t)0x0000)  /* 硬件管理NSS */

SPI波特率预分频器定义

#define SPI_BaudRatePrescaler_2         ((uint16_t)0x0000)  /* 2分频 */
#define SPI_BaudRatePrescaler_4         ((uint16_t)0x0008)  /* 4分频 */
#define SPI_BaudRatePrescaler_8         ((uint16_t)0x0010)  /* 8分频 */
#define SPI_BaudRatePrescaler_16        ((uint16_t)0x0018)  /* 16分频 */
#define SPI_BaudRatePrescaler_32        ((uint16_t)0x0020)  /* 32分频 */
#define SPI_BaudRatePrescaler_64        ((uint16_t)0x0028)  /* 64分频 */
#define SPI_BaudRatePrescaler_128       ((uint16_t)0x0030)  /* 128分频 */
#define SPI_BaudRatePrescaler_256       ((uint16_t)0x0038)  /* 256分频 */

SPI MSB/LSB传输定义

#define SPI_FirstBit_MSB                ((uint16_t)0x0000)  /* MSB优先传输 */
#define SPI_FirstBit_LSB                ((uint16_t)0x0080)  /* LSB优先传输 */

I2S常量定义

I2S模式定义

#define I2S_Mode_SlaveTx                ((uint16_t)0x0000)  /* 从机发送 */
#define I2S_Mode_SlaveRx                ((uint16_t)0x0100)  /* 从机接收 */
#define I2S_Mode_MasterTx               ((uint16_t)0x0200)  /* 主机发送 */
#define I2S_Mode_MasterRx               ((uint16_t)0x0300)  /* 主机接收 */

I2S标准定义

#define I2S_Standard_Phillips           ((uint16_t)0x0000)  /* Phillips标准 */
#define I2S_Standard_MSB                ((uint16_t)0x0010)  /* MSB对齐标准 */
#define I2S_Standard_LSB                ((uint16_t)0x0020)  /* LSB对齐标准 */
#define I2S_Standard_PCMShort           ((uint16_t)0x0030)  /* PCM短帧标准 */
#define I2S_Standard_PCMLong            ((uint16_t)0x00B0)  /* PCM长帧标准 */

I2S数据格式定义

#define I2S_DataFormat_16b              ((uint16_t)0x0000)  /* 16位数据 */
#define I2S_DataFormat_16bextended      ((uint16_t)0x0001)  /* 16位扩展数据 */
#define I2S_DataFormat_24b              ((uint16_t)0x0003)  /* 24位数据 */
#define I2S_DataFormat_32b              ((uint16_t)0x0005)  /* 32位数据 */

I2S MCLK输出定义

#define I2S_MCLKOutput_Enable           ((uint16_t)0x0200)  /* 启用MCLK输出 */
#define I2S_MCLKOutput_Disable          ((uint16_t)0x0000)  /* 禁用MCLK输出 */

I2S音频频率定义

#define I2S_AudioFreq_192k               ((uint32_t)192000)  /* 192kHz */
#define I2S_AudioFreq_96k                ((uint32_t)96000)   /* 96kHz */
#define I2S_AudioFreq_48k                ((uint32_t)48000)   /* 48kHz */
#define I2S_AudioFreq_44k                ((uint32_t)44100)   /* 44.1kHz */
#define I2S_AudioFreq_32k                ((uint32_t)32000)   /* 32kHz */
#define I2S_AudioFreq_22k                ((uint32_t)22050)   /* 22.05kHz */
#define I2S_AudioFreq_16k                ((uint32_t)16000)   /* 16kHz */
#define I2S_AudioFreq_11k                ((uint32_t)11025)   /* 11.025kHz */
#define I2S_AudioFreq_8k                 ((uint32_t)8000)    /* 8kHz */
#define I2S_AudioFreq_Default            ((uint32_t)2)       /* 默认频率 */

I2S时钟极性定义

#define I2S_CPOL_Low                    ((uint16_t)0x0000)  /* 时钟空闲时为低电平 */
#define I2S_CPOL_High                   ((uint16_t)0x0008)  /* 时钟空闲时为高电平 */

SPI/I2S中断标志定义

基本中断类型

#define SPI_I2S_IT_TXE                  ((uint8_t)0x71)  /* 发送缓冲区空中断 */
#define SPI_I2S_IT_RXNE                 ((uint8_t)0x60)  /* 接收缓冲区非空中断 */
#define SPI_I2S_IT_ERR                  ((uint8_t)0x50)  /* 错误中断 */

具体中断标志

#define SPI_I2S_IT_OVR                  ((uint8_t)0x56)  /* 溢出错误中断 */
#define SPI_IT_MODF                     ((uint8_t)0x55)  /* 模式错误中断 */
#define SPI_IT_CRCERR                   ((uint8_t)0x54)  /* CRC错误中断 */
#define I2S_IT_UDR                      ((uint8_t)0x53)  /* 下溢错误中断 */

SPI/I2S状态标志定义

#define SPI_I2S_FLAG_RXNE               ((uint16_t)0x0001)  /* 接收缓冲区非空标志 */
#define SPI_I2S_FLAG_TXE                ((uint16_t)0x0002)  /* 发送缓冲区空标志 */
#define I2S_FLAG_CHSIDE                 ((uint16_t)0x0004)  /* 通道边标志 */
#define I2S_FLAG_UDR                    ((uint16_t)0x0008)  /* 下溢标志 */
#define SPI_FLAG_CRCERR                 ((uint16_t)0x0010)  /* CRC错误标志 */
#define SPI_FLAG_MODF                   ((uint16_t)0x0020)  /* 模式错误标志 */
#define SPI_I2S_FLAG_OVR                ((uint16_t)0x0040)  /* 溢出标志 */
#define SPI_I2S_FLAG_BSY                ((uint16_t)0x0080)  /* 忙标志 */

其他定义

DMA传输请求定义

#define SPI_I2S_DMAReq_Tx               ((uint16_t)0x0002)  /* DMA发送请求 */
#define SPI_I2S_DMAReq_Rx               ((uint16_t)0x0001)  /* DMA接收请求 */

NSS内部软件管理定义

#define SPI_NSSInternalSoft_Set         ((uint16_t)0x0100)  /* 设置内部NSS */
#define SPI_NSSInternalSoft_Reset       ((uint16_t)0xFEFF)  /* 重置内部NSS */

CRC发送接收定义

#define SPI_CRC_Tx                      ((uint8_t)0x00)  /* 发送CRC */
#define SPI_CRC_Rx                      ((uint8_t)0x01)  /* 接收CRC */

方向传输接收定义

#define SPI_Direction_Rx                ((uint16_t)0xBFFF)  /* 接收方向 */
#define SPI_Direction_Tx                ((uint16_t)0x4000)  /* 发送方向 */

标准库函数详解

1. SPI_I2S_DeInit

/**
 * @brief  将 SPI/I2S 所有寄存器恢复为复位默认值,用于重新配置前清空旧状态
 * @param  SPIx: 选择SPI外设,可以是SPI1、SPI2或SPI3
 * @retval
 * @example
 *     SPI_I2S_DeInit(SPI1);  // 复位SPI1外设
 */
void SPI_I2S_DeInit(SPI_TypeDef* SPIx);

功能说明:

  • 调用后外设回到上电默认,SPI 与 I2S 模式均被清除
  • 切换工作模式(如 SPI 改 I2S)或更换引脚复用前先 DeInit
  • 异常通信后可配合重新 Init 恢复

2. SPI_Init

/**
 * @brief  初始化 SPI 工作参数(主从、时钟、数据位宽等),是 Flash/屏/传感器通信的基础
 * @param  SPIx: 选择SPI外设,可以是SPI1、SPI2或SPI3
 * @param  SPI_InitStruct: 指向SPI_InitTypeDef结构体的指针,包含SPI的配置信息
 * @retval
 * @example
 *     SPI_InitTypeDef SPI_InitStructure;
 *     SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
 *     SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
 *     SPI_Init(SPI1, &SPI_InitStructure);
 */
void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct);

功能说明:

  • 配置全双工/半双工、CPOL/CPHA、波特率分频、8/16 位帧
  • 主机模式需匹配从设备时钟极性与相位
  • 需在 GPIO 与时钟使能后、SPI_Cmd 前调用

3. I2S_Init

/**
 * @brief  初始化 I2S 音频参数(标准、采样率、数据格式),将 SPI 外设切换为 I2S 音频传输
 * @param  SPIx: 选择SPI外设,可以是SPI2或SPI3
 * @param  I2S_InitStruct: 指向I2S_InitTypeDef结构体的指针,包含I2S的配置信息
 * @retval
 * @example
 *     I2S_InitTypeDef I2S_InitStructure;
 *     I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx;
 *     I2S_InitStructure.I2S_Standard = I2S_Standard_Phillips;
 *     I2S_Init(SPI2, &I2S_InitStructure);
 */
void I2S_Init(SPI_TypeDef* SPIx, I2S_InitTypeDef* I2S_InitStruct);

功能说明:

  • 选择 Philips/MSB/LSB 标准及 16/24/32 位音频格式
  • 主机 TX 向 DAC/功放送数,主机 RX 从 ADC/麦克风采集
  • 与 SPI_Init 互斥,同一外设只能处于 SPI 或 I2S 模式

4. SPI_StructInit

/**
 * @brief  将 SPI_InitTypeDef 成员填为安全默认值,避免未赋值字段导致随机配置
 * @param  SPI_InitStruct: 指向SPI_InitTypeDef结构体的指针
 * @retval
 * @example
 *     SPI_InitTypeDef SPI_InitStructure;
 *     SPI_StructInit(&SPI_InitStructure);
 */
void SPI_StructInit(SPI_InitTypeDef* SPI_InitStruct);

功能说明:

  • 默认 8 位、主机、全双工、软件 NSS 等常用设置
  • 先 StructInit 再按需修改,减少遗漏
  • 适合快速搭建可工作的 SPI 初始模板

5. I2S_StructInit

/**
 * @brief  将 I2S_InitTypeDef 成员填为安全默认值,避免未赋值字段导致随机配置
 * @param  I2S_InitStruct: 指向I2S_InitTypeDef结构体的指针
 * @retval
 * @example
 *     I2S_InitTypeDef I2S_InitStructure;
 *     I2S_StructInit(&I2S_InitStructure);
 */
void I2S_StructInit(I2S_InitTypeDef* I2S_InitStruct);

功能说明:

  • 默认 Philips 标准、16 位扩展、48kHz 等常见音频参数
  • 先 StructInit 再修改 Mode/Standard/Frequency
  • 降低 I2S 多字段配置的出错概率

6. SPI_Cmd

/**
 * @brief  启动或停止 SPI 外设;ENABLE 后开始移位收发,DISABLE 后停止
 * @param  SPIx: 选择SPI外设,可以是SPI1、SPI2或SPI3
 * @param  NewState: SPI外设的新状态,可以是ENABLE或DISABLE
 * @retval
 * @example
 *     SPI_Cmd(SPI1, ENABLE);   // 使能SPI1
 *     SPI_Cmd(SPI1, DISABLE);  // 禁用SPI1
 */
void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState);

功能说明:

  • SPI_Init 完成后必须 ENABLE 才能 SendData/ReceiveData
  • DISABLE 可用于低功耗或切换 NSS 片选前暂停时钟
  • 全双工下每发送一字节同时接收一字节

7. I2S_Cmd

/**
 * @brief  启动或停止 I2S 功能;ENABLE 后开始音频流传输,DISABLE 后静音停止
 * @param  SPIx: 选择SPI外设,可以是SPI2或SPI3
 * @param  NewState: I2S外设的新状态,可以是ENABLE或DISABLE
 * @retval
 * @example
 *     I2S_Cmd(SPI2, ENABLE);   // 使能I2S功能
 *     I2S_Cmd(SPI2, DISABLE);  // 禁用I2S功能
 */
void I2S_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState);

功能说明:

  • I2S_Init 后调用以开始向编解码器送/收采样数据
  • 配合 DMA 可实现连续音频流而不占 CPU
  • DISABLE 常用于停止播放或切换采样率前

8. SPI_I2S_ITConfig

/**
 * @brief  打开/关闭 SPI/I2S 中断(TXE/RXNE 等),配合 NVIC 实现异步收发
 * @param  SPIx: 选择SPI外设,可以是SPI1、SPI2或SPI3
 * @param  SPI_I2S_IT: 指定要配置的SPI/I2S中断类型
 * @param  NewState: 中断的新状态,可以是ENABLE或DISABLE
 * @retval
 * @example
 *     SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_RXNE, ENABLE);  // 使能接收中断
 *     SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_TXE, ENABLE);   // 使能发送中断
 */
void SPI_I2S_ITConfig(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT, FunctionalState NewState);

功能说明:

  • TXE:发送缓冲空,可写入下一字节
  • RXNE:接收缓冲非空,应读取 DR
  • 中断驱动适合不定长或高吞吐 SPI 通信

9. SPI_I2S_DMACmd

/**
 * @brief  打开/关闭 SPI/I2S 的 DMA 请求,实现大批量数据无 CPU 参与的连续搬运
 * @param  SPIx: 选择SPI外设,可以是SPI1、SPI2或SPI3
 * @param  SPI_I2S_DMAReq: 指定要配置的DMA传输请求
 * @param  NewState: DMA请求的新状态,可以是ENABLE或DISABLE
 * @retval
 * @example
 *     SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);  // 使能DMA发送
 *     SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, ENABLE);  // 使能DMA接收
 */
void SPI_I2S_DMACmd(SPI_TypeDef* SPIx, uint16_t SPI_I2S_DMAReq, FunctionalState NewState);

功能说明:

  • 适合 LCD 刷屏、Flash 读写、I2S 音频缓冲等大块传输
  • 需先配置 DMA 通道指向 SPI DR 寄存器
  • Tx/Rx 可独立使能,全双工需双通道配合

10. SPI_I2S_SendData

/**
 * @brief  向 DR 写入待发数据,硬件在 SCK 驱动下逐位串行发出
 * @param  SPIx: 选择SPI外设,可以是SPI1、SPI2或SPI3
 * @param  Data: 要发送的数据
 * @retval
 * @example
 *     SPI_I2S_SendData(SPI1, 0x55);  // 发送数据0x55
 */
void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data);

功能说明:

  • 写入前确认 TXE 置位,避免覆盖未发送数据
  • 全双工模式下写 DR 同时触发时钟接收对端数据
  • 8 位模式下仅低 8 位有效

11. SPI_I2S_ReceiveData

/**
 * @brief  从 DR 读取最近接收到的数据,全双工或只读模式下使用
 * @param  SPIx: 选择SPI外设,可以是SPI1、SPI2或SPI3
 * @retval 接收到的数据
 * @example
 *     uint16_t received_data = SPI_I2S_ReceiveData(SPI1);
 */
uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx);

功能说明:

  • 读取前确认 RXNE 置位
  • 全双工发送时每次 SendData 后通常需 Read 丢弃/获取回读
  • 读 DR 自动清除 RXNE

12. SPI_NSSInternalSoftwareConfig

/**
 * @brief  在软件 NSS 模式下手动置位/复位内部片选,选中或释放 SPI 从设备
 * @param  SPIx: 选择SPI外设,可以是SPI1、SPI2或SPI3
 * @param  SPI_NSSInternalSoft: 指定内部NSS信号状态
 * @retval
 * @example
 *     SPI_NSSInternalSoftwareConfig(SPI1, SPI_NSSInternalSoft_Set);
 */
void SPI_NSSInternalSoftwareConfig(SPI_TypeDef* SPIx, uint16_t SPI_NSSInternalSoft);

功能说明:

  • Set 通常表示片选有效(低有效硬件需配合 GPIO)
  • 多从机时软件控制 NSS 切换目标芯片
  • 需在 SPI_NSS_Soft 模式下使用

13. SPI_SSOutputCmd

/**
 * @brief  控制 NSS 引脚作为 SS 输出驱动从机片选,多从机硬件片选场景使用
 * @param  SPIx: 选择SPI外设,可以是SPI1、SPI2或SPI3
 * @param  NewState: SS输出的新状态,可以是ENABLE或DISABLE
 * @retval
 * @example
 *     SPI_SSOutputCmd(SPI1, ENABLE);  // 使能SS输出
 */
void SPI_SSOutputCmd(SPI_TypeDef* SPIx, FunctionalState NewState);

功能说明:

  • 主机模式下使 NSS 引脚输出片选信号
  • 与硬件 NSS 管理配合,自动拉低选中从机
  • 单从机且用 GPIO 片选时通常不需要此功能

14. SPI_DataSizeConfig

/**
 * @brief  运行时切换 SPI 帧长(8/16 位),适配不同外设的数据宽度要求
 * @param  SPIx: 选择SPI外设,可以是SPI1、SPI2或SPI3
 * @param  SPI_DataSize: 指定SPI数据大小
 * @retval
 * @example
 *     SPI_DataSizeConfig(SPI1, SPI_DataSize_8b);   // 设置为8位数据
 *     SPI_DataSizeConfig(SPI1, SPI_DataSize_16b);  // 设置为16位数据
 */
void SPI_DataSizeConfig(SPI_TypeDef* SPIx, uint16_t SPI_DataSize);

功能说明:

  • 8 位常用于 Flash、传感器;16 位用于部分 ADC/屏
  • 切换前建议 DISABLE SPI,避免帧边界错乱
  • 与 Init 中 DataSize 作用相同,但可动态修改

15. SPI_TransmitCRC

/**
 * @brief  触发发送 CRC 寄存器中的校验值,用于帧尾完整性验证
 * @param  SPIx: 选择SPI外设,可以是SPI1、SPI2或SPI3
 * @retval
 * @example
 *     SPI_TransmitCRC(SPI1);  // 发送CRC值
 */
void SPI_TransmitCRC(SPI_TypeDef* SPIx);

功能说明:

  • 数据发送完毕后调用,发出硬件计算的 CRC
  • 对端可用相同多项式验证传输正确性
  • 需先使能 CalculateCRC 并完成数据阶段

16. SPI_CalculateCRC

/**
 * @brief  打开/关闭硬件 CRC 累加,对后续发送/接收数据自动计算校验值
 * @param  SPIx: 选择SPI外设,可以是SPI1、SPI2或SPI3
 * @param  NewState: CRC计算的新状态,可以是ENABLE或DISABLE
 * @retval
 * @example
 *     SPI_CalculateCRC(SPI1, ENABLE);   // 使能CRC计算
 *     SPI_CalculateCRC(SPI1, DISABLE);  // 禁用CRC计算
 */
void SPI_CalculateCRC(SPI_TypeDef* SPIx, FunctionalState NewState);

功能说明:

  • 使能后对每帧数据硬件更新 CRC 寄存器
  • 适合工业 SPI 协议要求数据完整性校验
  • 多项式由 CRCPR 配置,默认常用 0x0007

17. SPI_GetCRC

/**
 * @brief  读取 Tx/Rx CRC 寄存器值,用于发送前取出或接收后比对校验
 * @param  SPIx: 选择SPI外设,可以是SPI1、SPI2或SPI3
 * @param  SPI_CRC: 指定要读取的CRC寄存器
 * @retval CRC寄存器值
 * @example
 *     uint16_t tx_crc = SPI_GetCRC(SPI1, SPI_CRC_Tx);  // 获取发送CRC
 *     uint16_t rx_crc = SPI_GetCRC(SPI1, SPI_CRC_Rx);  // 获取接收CRC
 */
uint16_t SPI_GetCRC(SPI_TypeDef* SPIx, uint8_t SPI_CRC);

功能说明:

  • SPI_CRC_Tx:取发送侧累加结果供 TransmitCRC 发出
  • SPI_CRC_Rx:取接收侧结果与对端 CRC 比较
  • 需在 CalculateCRC 使能且传输完成后读取

18. SPI_GetCRCPolynomial

/**
 * @brief  读取当前 CRC 多项式配置,确认与对端校验算法一致
 * @param  SPIx: 选择SPI外设,可以是SPI1、SPI2或SPI3
 * @retval CRC多项式寄存器值
 * @example
 *     uint16_t polynomial = SPI_GetCRCPolynomial(SPI1);
 */
uint16_t SPI_GetCRCPolynomial(SPI_TypeDef* SPIx);

功能说明:

  • 返回 CRCPR 寄存器中的多项式值
  • 调试 CRC 不匹配时可核对双方多项式
  • 写入 CRCPR 需在 CRC 计算关闭时进行

19. SPI_BiDirectionalLineConfig

/**
 * @brief  在单线双向模式下选择当前引脚方向为发送或接收
 * @param  SPIx: 选择SPI外设,可以是SPI1、SPI2或SPI3
 * @param  SPI_Direction: 指定数据传输方向
 * @retval
 * @example
 *     SPI_BiDirectionalLineConfig(SPI1, SPI_Direction_Tx);  // 设置为发送
 *     SPI_BiDirectionalLineConfig(SPI1, SPI_Direction_Rx);  // 设置为接收
 */
void SPI_BiDirectionalLineConfig(SPI_TypeDef* SPIx, uint16_t SPI_Direction);

功能说明:

  • 半双工单线模式:一根数据线分时收发
  • 发送前切 Tx,接收前切 Rx
  • 节省引脚,常见于单线 Flash 或传感器

20. SPI_I2S_GetFlagStatus

/**
 * @brief  查询 SPI/I2S 标志位(TXE/RXNE/BSY 等),判断收发就绪或忙状态
 * @param  SPIx: 选择SPI外设,可以是SPI1、SPI2或SPI3
 * @param  SPI_I2S_FLAG: 指定要检查的标志位
 * @retval 标志位状态(SET或RESET)
 * @example
 *     if(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == SET)
 *     {
 *         // 发送缓冲区为空,可以发送数据
 *     }
 */
FlagStatus SPI_I2S_GetFlagStatus(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG);

功能说明:

  • TXE:可写 DR;RXNE:应读 DR
  • BSY:移位器忙,连续传输间需等 BSY 清零
  • 轮询收发与错误检测的基础 API

21. SPI_I2S_ClearFlag

/**
 * @brief  清除 SPI/I2S 可清标志(如 CRCERR),避免错误状态持续
 * @param  SPIx: 选择SPI外设,可以是SPI1、SPI2或SPI3
 * @param  SPI_I2S_FLAG: 指定要清除的标志位
 * @retval
 * @example
 *     SPI_I2S_ClearFlag(SPI1, SPI_FLAG_CRCERR);  // 清除CRC错误标志
 */
void SPI_I2S_ClearFlag(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG);

功能说明:

  • 主要用于清除 CRCERR、MODF 等错误标志
  • TXE/RXNE 等由读写 DR 自动清除
  • 错误恢复后继续通信前必须清除

22. SPI_I2S_GetITStatus

/**
 * @brief  在中断服务程序中判断具体 SPI/I2S 中断源是否挂起
 * @param  SPIx: 选择SPI外设,可以是SPI1、SPI2或SPI3
 * @param  SPI_I2S_IT: 指定要检查的中断类型
 * @retval 中断状态(SET或RESET)
 * @example
 *     if(SPI_I2S_GetITStatus(SPI1, SPI_I2S_IT_RXNE) == SET)
 *     {
 *         // 处理接收中断
 *     }
 */
ITStatus SPI_I2S_GetITStatus(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT);

功能说明:

  • 同时检查中断使能与挂起位
  • ISR 中区分 TXE/RXNE/ERR 分支处理
  • 比 GetFlagStatus 更适合中断上下文

23. SPI_I2S_ClearITPendingBit

/**
 * @brief  清除 SPI/I2S 中断挂起位,ISR 处理完毕后调用以免重复进中断
 * @param  SPIx: 选择SPI外设,可以是SPI1、SPI2或SPI3
 * @param  SPI_I2S_IT: 指定要清除的中断类型
 * @retval
 * @example
 *     SPI_I2S_ClearITPendingBit(SPI1, SPI_IT_CRCERR);  // 清除CRC错误中断
 */
void SPI_I2S_ClearITPendingBit(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT);

功能说明:

  • 处理完 CRCERR、MODF 等错误中断后清除
  • TXE/RXNE 通常读/写 DR 即清除,部分需显式调用
  • 未清除会导致中断反复触发

使用示例

SPI主机模式基本配置示例

#include "stm32f10x.h"

void SPI1_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    SPI_InitTypeDef SPI_InitStructure;
    
    // 使能时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1, ENABLE);
    
    // 配置SPI1引脚:SCK、MISO、MOSI
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    // 配置NSS引脚为推挽输出
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    // SPI1配置
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_CRCPolynomial = 7;
    SPI_Init(SPI1, &SPI_InitStructure);
    
    // 使能SPI1
    SPI_Cmd(SPI1, ENABLE);
}

uint8_t SPI1_ReadWriteByte(uint8_t TxData)
{
    uint8_t retry = 0;
    
    // 等待发送缓冲区空
    while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET)
    {
        retry++;
        if(retry > 200) return 0;
    }
    
    // 发送数据
    SPI_I2S_SendData(SPI1, TxData);
    retry = 0;
    
    // 等待接收缓冲区非空
    while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET)
    {
        retry++;
        if(retry > 200) return 0;
    }
    
    // 读取接收到的数据
    return SPI_I2S_ReceiveData(SPI1);
}

SPI中断模式示例

void SPI1_IT_Init(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
    
    // 配置SPI1(同上面的配置)
    SPI1_Init();
    
    // 配置SPI1中断
    NVIC_InitStructure.NVIC_IRQChannel = SPI1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    
    // 使能SPI1接收中断
    SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_RXNE, ENABLE);
}

void SPI1_IRQHandler(void)
{
    uint8_t received_data;
    
    if(SPI_I2S_GetITStatus(SPI1, SPI_I2S_IT_RXNE) == SET)
    {
        // 读取接收到的数据
        received_data = SPI_I2S_ReceiveData(SPI1);
        
        // 处理接收到的数据
        // ... 用户代码 ...
    }
}

I2S音频配置示例

void I2S2_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    I2S_InitTypeDef I2S_InitStructure;
    
    // 使能时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    
    // 配置I2S2引脚
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_15;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    
    // I2S2配置
    I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx;
    I2S_InitStructure.I2S_Standard = I2S_Standard_Phillips;
    I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b;
    I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Enable;
    I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_44k;
    I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low;
    I2S_Init(SPI2, &I2S_InitStructure);
    
    // 使能I2S2
    I2S_Cmd(SPI2, ENABLE);
}

注意事项

  1. 时钟配置:使用SPI/I2S外设前必须先使能相应的时钟,包括外设时钟和GPIO时钟。

  2. 引脚配置:SPI引脚必须配置为复用推挽输出模式,I2S引脚也需要正确的复用配置。

  3. 模式选择:SPI1支持所有功能,SPI2和SPI3还支持I2S功能,但某些高级功能可能有限制。

  4. 波特率设置:主机模式下需要合理设置波特率分频器,确保通信速率满足外设要求。

  5. 数据同步:在查询模式下,必须检查相应的标志位再进行数据收发操作。

  6. 中断处理:使用中断模式时,需要在中断服务函数中及时处理数据,避免溢出。

  7. CRC功能:使用CRC功能时,需要正确配置多项式并在数据传输完成后发送CRC值。

  8. I2S音频:I2S配置时需要根据具体的音频格式选择合适的标准和数据格式。

总结

STM32F10x的SPI/I2S外设提供了灵活而强大的串行通信功能。SPI支持主从模式、全双工/半双工通信、硬件CRC校验等特性,适用于与各种外设器件通信。I2S功能则专门针对音频应用优化,支持多种音频标准和采样率。

通过合理配置相关寄存器和使用标准库函数,可以轻松实现高可靠性的串行通信。无论是简单的传感器数据读取,还是复杂的音频数据处理,SPI/I2S外设都能提供良好的解决方案。在实际应用中,建议根据具体需求选择合适的工作模式和参数配置,并充分利用中断和DMA功能提高系统效率。