STM32微控制器SPI通信功能配置详解
扫描二维码
随时随地手机看文章
在嵌入式系统开发中,串行通信协议是连接微控制器与外围设备的核心技术。SPI(Serial Peripheral Interface)作为一种高速、全双工、同步的串行通信总线,因其简单高效的特点,被广泛应用于传感器、存储器、显示屏等设备的连接。本文以STM32系列微控制器为例,系统阐述SPI通信的原理、配置方法及实践应用,帮助开发者快速掌握这一关键技术。
一、SPI通信协议基础
1.1 SPI协议的核心特性
SPI协议采用主从架构设计,支持一主多从的通信模式。其核心优势包括:
全双工通信:支持同时发送和接收数据,提高传输效率。
同步时钟:通过主设备产生的时钟信号实现数据同步,避免时序混乱。
灵活配置:支持多种数据帧格式(如8位、16位)和时钟频率。
硬件支持:STM32的硬件SPI模块可减轻CPU负担,提升系统性能。
1.2 SPI信号线定义
SPI总线由4根信号线构成:
SCK(Serial Clock):时钟信号线,由主设备产生,控制数据传输时序。
MOSI(Master Out Slave In):主设备数据输出,从设备数据输入。
MISO(Master In Slave Out):主设备数据输入,从设备数据输出。
NSS(Slave Select):从设备选择信号,低电平有效,用于选择特定从设备。
1.3 SPI通信模式
SPI协议通过时钟极性和相位(CPOL/CPHA)组合定义4种工作模式:
模式0:CPOL=0(时钟空闲低电平),CPHA=0(数据采样于第1个边沿)。
模式1:CPOL=0,CPHA=1(数据采样于第2个边沿)。
模式2:CPOL=1(时钟空闲高电平),CPHA=0。
模式3:CPOL=1,CPHA=1。
二、STM32硬件SPI模块特性
2.1 STM32的SPI外设优势
STM32系列微控制器集成硬件SPI模块,具有以下特点:
多通道支持:部分型号提供3个独立SPI接口(如SPI1/SPI2/SPI3)。
时钟分频:支持1/2~1/256的分频系数,适应不同速度需求。
数据帧格式:支持8/16位数据长度,MSB/LSB优先传输。
中断/DMA支持:可配置中断或DMA传输,降低CPU占用率。
2.2 关键寄存器配置
STM32的SPI模块通过以下寄存器实现功能控制:
CR1(控制寄存器1):配置CPOL/CPHA、数据长度、时钟分频等。
CR2(控制寄存器2):设置NSS管理方式(硬件/软件控制)。
DR(数据寄存器):用于数据读写操作。
SR(状态寄存器):提供传输完成标志(TXE/RXNE)。
三、SPI通信配置步骤
3.1 引脚配置
使用STM32CubeMX工具可快速完成引脚分配:
选择SPI接口(如SPI1)。
配置SCK、MOSI、MISO为复用推挽输出(AF_PP)。
设置NSS引脚为推挽输出(GPIO_Mode_Out_PP)。
3.2 参数初始化
通过HAL库函数配置SPI参数:
cCopy CodeSPI_HandleTypeDef hspi1;
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; // CPOL=0
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; // CPHA=0
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
HAL_SPI_Init(&hspi1);
3.3 数据传输实现
3.3.1 轮询方式
cCopy Codeuint8_t tx_data = 0x55;
uint8_t rx_data;
HAL_SPI_TransmitReceive(&hspi1, &tx_data, &rx_data, 1, HAL_MAX_DELAY);
3.3.2 中断方式
cCopy CodeHAL_SPI_TransmitReceive_IT(&hspi1, &tx_data, &rx_data, 1);
// 在中断回调函数中处理接收数据
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) {
if (hspi->Instance == SPI1) {
// 处理接收数据
}
}
3.3.3 DMA方式
cCopy CodeHAL_SPI_TransmitReceive_DMA(&hspi1, &tx_data, &rx_data, 1);
// 在DMA完成回调中处理数据
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) {
if (hspi->Instance == SPI1) {
// 处理接收数据
}
}
四、SPI通信实践案例
4.1 连接W25Q128 Flash存储器
配置步骤:
初始化SPI1(模式0,8MHz时钟)。
发送Flash指令序列:
写使能:0x06
页编程:0x02 + 地址 + 数据
读数据:0x03 + 地址
实现数据读写函数:
cCopy Codevoid SPI_Flash_Write(uint32_t addr, uint8_t *data, uint32_t len) {
HAL_SPI_Transmit(&hspi1, (uint8_t*)&addr, 4, 100);
HAL_SPI_Transmit(&hspi1, data, len, 100);
}
void SPI_Flash_Read(uint32_t addr, uint8_t *data, uint32_t len) {
HAL_SPI_Transmit(&hspi1, (uint8_t*)&addr, 4, 100);
HAL_SPI_Receive(&hspi1, data, len, 100);
}
4.2 连接OLED显示屏
配置要点:
设置SPI为模式3(CPOL=1, CPHA=1)。
实现显示函数:
cCopy Codevoid OLED_Write_Command(uint8_t cmd) {
uint8_t data = {0x80 | (cmd & 0x3F), 0x00};
HAL_SPI_Transmit(&hspi1, data, 2, 10);
}
void OLED_Write_Data(uint8_t data) {
uint8_t cmd = {0x40 | (data & 0x3F), 0x00};
HAL_SPI_Transmit(&hspi1, cmd, 2, 10);
}
五、SPI通信常见问题及解决方案
5.1 通信失败问题
现象:数据传输错误或超时。
排查步骤:
检查硬件连接(SCK/MOSI/MISO/NSS)。
验证时钟频率是否超过从设备支持范围。
确认CPOL/CPHA模式与从设备匹配。
检查NSS信号是否正常拉低。
5.2 性能优化技巧
DMA传输:对于大数据量传输,使用DMA可显著提升效率。
时钟分频:根据实际需求调整时钟频率,避免过高导致信号失真。
中断优先级:合理设置SPI中断优先级,避免与其他外设冲突。
5.3 多从机系统设计
硬件NSS:每个从设备连接独立的NSS引脚,由主设备控制。
软件NSS:通过GPIO模拟NSS信号,需手动控制选择时序。
菊花链拓扑:多个从设备串联,但需支持菊花链模式的芯片。
STM32的硬件SPI模块为开发者提供了高效可靠的通信解决方案。通过合理配置参数、选择适当的传输方式,可满足绝大多数外设连接需求。随着物联网技术的发展,SPI协议在低功耗、实时性方面的优势将进一步凸显。未来,SPI可能会与新兴技术如PCIe协议相结合,在保持简单性的同时提升传输性能。





