STM32 SPI的RXNE标志位始终未置位问题求助
STM32F303RE SPI2接收时RXNE标志始终未置位问题
问题描述
使用Nucleo开发板上的STM32F303RE微控制器开发SPI设备通信程序时功能异常,简化为单字节接收的最小实现代码后,程序卡在while (!(SPI2->SR & SPI_SR_RXNE));循环处,RXNE标志位始终未置位。
已尝试的解决方案
- 设置
SPI_CR2_FRXTH和SPI_CR2_SSOE位 - 确保GPIO及SPI时钟已使能
- 完成所有寄存器配置后再使能SPI2
最小复现代码
volatile char data = 'A'; int main(void) { HAL_Init(); SystemClock_Config(); RCC->AHBENR |= RCC_AHBENR_GPIOBEN; // Enable GPIOB clock RCC->APB1ENR |= RCC_APB1ENR_SPI2EN; // Enable SPI2 clock // PB12 Alternate Function mode [10] GPIOB->MODER &= ~GPIO_MODER_MODER12_0; GPIOB->MODER |= GPIO_MODER_MODER12_1; // PB13 Alternate Function mode [10] GPIOB->MODER &= ~GPIO_MODER_MODER13_0; GPIOB->MODER |= GPIO_MODER_MODER13_1; // PB14 Alternate Function mode [10] GPIOB->MODER &= ~GPIO_MODER_MODER14_0; GPIOB->MODER |= GPIO_MODER_MODER14_1; // PB15 Alternate Function mode [10] GPIOB->MODER &= ~GPIO_MODER_MODER15_0; GPIOB->MODER |= GPIO_MODER_MODER15_1; // PB12 High Speed [11] GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR12_0; GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR12_1; // PB13 High Speed [11] GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR13_0; GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR13_1; // PB14 High Speed [11] GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR14_0; GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR14_1; // PB15 High Speed [11] GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR15_0; GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR15_1; // Alternate function 5 [0101] GPIOB->AFR[1] = 0; // Reset register GPIOB->AFR[1] = 0b0101 << GPIO_AFRH_AFRH4_Pos; // PB12 GPIOB->AFR[1] = 0b0101 << GPIO_AFRH_AFRH5_Pos; // PB13 GPIOB->AFR[1] = 0b0101 << GPIO_AFRH_AFRH6_Pos; // PB14 GPIOB->AFR[1] = 0b0101 << GPIO_AFRH_AFRH7_Pos; // PB15 SPI2->CR1 |= SPI_CR1_MSTR; // Master Mode SPI2->CR2 |= SPI_CR2_FRXTH; // 8-bit reception threshold // 8-bit data length [0111] SPI2->CR2 &= ~SPI_CR2_DS_Msk; SPI2->CR2 |= 0b0111 << SPI_CR2_DS_Pos; SPI2->CR2 |= SPI_CR2_SSOE; // SS output enable SPI2->CR1 |= SPI_CR1_SPE; // SPI enable while (!(SPI2->SR & SPI_SR_TXE)); // Wait for TX SPI2->DR = 'T'; // Send some byte while (!(SPI2->SR & SPI_SR_RXNE)); // Wait for RX (Hangs) data = SPI2->DR; // Receive byte while (1) { } }
问题分析与解决建议
1. GPIO复用功能寄存器赋值错误
代码中配置GPIOB的AFR[1]时,每次使用=赋值会覆盖之前的配置,最终只有PB15的复用功能被正确设置,PB12(NSS)、PB13(SCK)、PB14(MISO)的复用功能未生效,导致SPI硬件无法正常通信,RXNE标志无法置位。
修复方式:使用|=代替=,保留已配置的位:
GPIOB->AFR[1] = 0; // Reset register GPIOB->AFR[1] |= 0b0101 << GPIO_AFRH_AFRH4_Pos; // PB12 GPIOB->AFR[1] |= 0b0101 << GPIO_AFRH_AFRH5_Pos; // PB13 GPIOB->AFR[1] |= 0b0101 << GPIO_AFRH_AFRH6_Pos; // PB14 GPIOB->AFR[1] |= 0b0101 << GPIO_AFRH_AFRH7_Pos; // PB15
2. 检查SPI时钟模式匹配性
SPI主模式下,CPOL(时钟极性)和CPHA(时钟相位)必须与从设备一致。默认配置为CPOL=0、CPHA=0,若从设备使用不同模式,需修改SPI_CR1寄存器的对应位:
- 若需CPOL=1:
SPI2->CR1 |= SPI_CR1_CPOL; - 若需CPHA=1:
SPI2->CR1 |= SPI_CR1_CPHA;
3. 增加传输完成等待
发送字节后,可先等待BSY位清零确保传输完成,再检查RXNE标志:
SPI2->DR = 'T'; // Send some byte while (SPI2->SR & SPI_SR_BSY); // Wait for transfer complete while (!(SPI2->SR & SPI_SR_RXNE)); // Wait for RX
内容的提问来源于stack exchange,提问作者nhg
相关产品推荐
相关产品推荐

