以下是 STM32F1 和 STM32F4 在配置 硬件SPI1 时的关键差异对比,涵盖时钟、GPIO、外设配置和性能优化等方面:
一、时钟配置差异
| 特性 | STM32F1 | STM32F4 |
|---|---|---|
| SPI1时钟总线 | APB2 (最高72MHz) | APB2 (最高84MHz/90MHz) |
| 时钟使能函数 | RCC_APB2PeriphClockCmd() |
RCC_APB2PeriphClockCmd() |
| GPIO时钟总线 | APB2 | AHB1 (速度更快) |
F4示例代码:
c
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); // GPIO时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); // SPI1时钟
二、GPIO配置差异
| 特性 | STM32F1 | STM32F4 |
|---|---|---|
| 复用功能配置 | GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP |
GPIO_Mode_AF + GPIO_PinAFConfig() |
| 引脚复用映射 | 无独立函数,直接配置复用模式 | 需调用GPIO_PinAFConfig() |
| 速度设置 | 无明确速度配置 | 支持GPIO_Speed_50MHz/100MHz |
F1配置示例:
c
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7; // SCK, MOSI
GPIO_Init(GPIOA, &GPIO_InitStruct);
F1系列MISO直接配置成上拉输入模式即可
F4系列MISO必须配置成复用+上拉
F4配置示例:
c
GPIO_InitTypeDef GPIO_InitStruct = {
.GPIO_Mode = GPIO_Mode_AF,
.GPIO_OType = GPIO_OType_PP,
.GPIO_Speed = GPIO_Speed_100MHz,
.GPIO_PuPd = GPIO_PuPd_NOPULL,
.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7
};
GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1); // SCK
GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1); // MOSI
三、SPI外设配置差异
| 特性 | STM32F1 | STM32F4 |
|---|---|---|
| SPI结构体成员 | 较简单,无独立CRCPolynomial字段 | 支持更复杂的CRC和DMA配置 |
| 波特率分频系数 | 固定分频值(如2,4,8,...) | 支持更灵活的分频(如2,4,8,...,256) |
| 数据位宽 | 仅支持8位/16位 | 支持8位/16位,部分型号支持32位 |
F1 SPI初始化:
c
SPI_InitTypeDef SPI_InitStruct = {
.SPI_Direction = SPI_Direction_2Lines_FullDuplex,
.SPI_Mode = SPI_Mode_Master,
.SPI_DataSize = SPI_DataSize_8b,
.SPI_CPOL = SPI_CPOL_Low,
.SPI_CPHA = SPI_CPHA_1Edge,
.SPI_NSS = SPI_NSS_Soft,
.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8,
.SPI_FirstBit = SPI_FirstBit_MSB
};
SPI_Init(SPI1, &SPI_InitStruct);
F4 SPI初始化(支持CRC):
c
SPI_InitTypeDef SPI_InitStruct = {
.SPI_Direction = SPI_Direction_2Lines_FullDuplex,
.SPI_Mode = SPI_Mode_Master,
.SPI_DataSize = SPI_DataSize_8b,
.SPI_CPOL = SPI_CPOL_Low,
.SPI_CPHA = SPI_CPHA_1Edge,
.SPI_NSS = SPI_NSS_Soft,
.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4,
.SPI_FirstBit = SPI_FirstBit_MSB,
.SPI_CRCPolynomial = 7 // F4特有
};
SPI_Init(SPI1, &SPI_InitStruct);
四、DMA配置差异
| 特性 | STM32F1 | STM32F4 |
|---|---|---|
| DMA控制器 | 1个DMA控制器(DMA1) | 2个DMA控制器(DMA1/DMA2) |
| 流(Stream)概念 | 无 | 支持流(Stream)和通道(Channel) |
| 触发源选择 | 固定映射 | 灵活配置(通过DMA_InitStruct.DMA_Channel) |
F4 DMA配置示例:
c
DMA_InitTypeDef DMA_InitStruct = {
.DMA_Channel = DMA_Channel_3,
.DMA_PeripheralBaseAddr = (uint32_t)&SPI1->DR,
.DMA_Memory0BaseAddr = (uint32_t)tx_buffer,
.DMA_DIR = DMA_DIR_MemoryToPeripheral,
.DMA_BufferSize = BUFFER_SIZE,
.DMA_PeripheralInc = DMA_PeripheralInc_Disable,
.DMA_MemoryInc = DMA_MemoryInc_Enable,
.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte,
.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte,
.DMA_Mode = DMA_Mode_Normal,
.DMA_Priority = DMA_Priority_High,
.DMA_FIFOMode = DMA_FIFOMode_Enable,
.DMA_FIFOThreshold = DMA_FIFOThreshold_Full,
.DMA_MemoryBurst = DMA_MemoryBurst_INC4,
.DMA_PeripheralBurst = DMA_PeripheralBurst_INC4
};
DMA_Init(DMA2_Stream3, &DMA_InitStruct);
五、中断与性能优化
| 特性 | STM32F1 | STM32F4 |
|---|---|---|
| 中断优先级配置 | 仅4位抢占优先级 | 支持4位抢占优先级+4位子优先级 |
| 最大SPI时钟 | 18MHz (APB2=72MHz, 分频4) | 21MHz (APB2=84MHz, 分频4) |
| 硬件CRC | 不支持 | 支持硬件CRC计算 |
F4中断配置示例:
c
NVIC_InitTypeDef NVIC_InitStruct = {
.NVIC_IRQChannel = SPI1_IRQn,
.NVIC_IRQChannelPreemptionPriority = 1,
.NVIC_IRQChannelSubPriority = 0, // F4特有子优先级
.NVIC_IRQChannelCmd = ENABLE
};
NVIC_Init(&NVIC_InitStruct);
六、实际应用注意事项
-
F1的特殊性:
无需配置引脚复用映射(AF配置内置于GPIO模式)- DMA功能较简单,适合低速传输
-
F4的特殊性:
- 必须配置引脚复用映射:
c
/*引脚复用映射 未配置复用功能时,GPIO无法连接到SPI外设,导致信号无法传输*/
GPIO_PinAFConfig(SPI_CLK_GPIO_PORT, GPIO_PinSource5, GPIO_AF_SPI1); // SCK
GPIO_PinAFConfig(SPI_MISO_GPIO_PORT, GPIO_PinSource6, GPIO_AF_SPI1); // MISO
GPIO_PinAFConfig(SPI_MOSI_GPIO_PORT, GPIO_PinSource7, GPIO_AF_SPI1); // MOSI
- 必须将MISO配置成复用+上拉
(这里有些难理解,MISO正常情况下应该是上拉输入,F4系列却强行需要配置为AF+上拉,这里与F1配置不同,尤为需要注意)
- F4的优势:
- 支持更高的时钟频率和更精细的DMA控制
- 通过
GPIO_PinAFConfig()灵活分配引脚功能
-
跨平台兼容代码 :
c#if defined(STM32F10X) // F1专用配置 GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; #elif defined(STM32F40XX) // F4专用配置 GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1); #endif
七、调试技巧
-
F1常见问题:
- 检查
GPIO_Mode_AF_PP是否正确配置 - 确保APB2时钟使能
- 检查
-
F4常见问题:
- 确认
GPIO_PinAFConfig()调用 - 检查DMA流(Stream)和通道(Channel)是否匹配
- 确认
-
通用验证方法:
c// 读取SPI状态寄存器 printf("SPI1->SR = 0x%04X\n", SPI1->SR); /* 关键位: - BIT 1: TXE (发送缓冲区空) - BIT 0: RXNE (接收数据就绪) - BIT 5: MODF (模式错误) */
总结
- STM32F1 :配置简单,适合低速场景,注意复用模式为
GPIO_Mode_AF_PP - STM32F4 :功能强大,
需额外配置引脚复用映射,支持高性能DMA和CRC - 移植建议:使用条件编译区分芯片型号,优先验证SPI基础通信功能