SPI发送数据时TXE标志未清除且RXEN异常置位问题咨询
SPI发送函数异常问题分析
void SPI_SendData(SPI_RegDef_t *pSPIx ,uint8_t *pTxBuffer,uint32_t len) { while(len > 0) { // 1. 等待TXE标志置位(等待发送缓冲区为空) while (SPI_GetFlagStatus(pSPIx, SPI_FLAG_TXE) == FLAG_RESET); //2. 检查DFF位 if(((pSPIx->CR1 >> SPI_CR1_DFF) & 1) == SPI_DFF_16BIT) { // 16位模式 pSPIx->DR = *((uint16_t*) pTxBuffer); (uint16_t*) pTxBuffer++; len--; }else { pSPIx->DR = *pTxBuffer; pTxBuffer++; } len--; } }
根据SPI协议知识,写入SPI_DR寄存器应清除TXE标志,但实际执行上述发送数据代码时,TXE标志未被清除,RXEN标志却被置位。请问RXEN标志为何会被置位?TXE标志未清除的原因是什么?
问题分析与解答
1. RXEN标志被置位的原因
RXEN是SPI接收使能位,它的置位和发送操作本身无直接关联,核心原因是SPI初始化阶段就已开启接收功能:
- SPI本质是全双工总线,多数MCU的SPI外设默认或初始化配置中会自动使能接收(RXEN位置1)。因为全双工模式下,发送操作必然伴随接收动作——即使你不需要接收数据,硬件也会在发送时钟驱动下采样MISO线数据并填充接收缓冲区。
- 部分MCU的SPI外设中,RXEN位是只读属性,或仅能通过切换到单工发送模式关闭。如果你的初始化代码没有做这类特殊配置,RXEN会一直保持置位状态。
2. TXE标志未清除的原因
正常写入SPI_DR后硬件会自动清除TXE标志,你的代码出现异常是因为存在两处关键错误,导致DR寄存器未被正确写入:
- 16位模式下的指针操作错误:
(uint16_t*) pTxBuffer++;优先级逻辑错误,++优先级高于强制类型转换,实际执行的是(uint16_t*)(pTxBuffer++)——先把8位指针pTxBuffer自增1(仅移动1字节),再转成16位指针。这会导致写入DR的是错误内存地址的数据,甚至因地址不对齐触发硬件异常,直接跳过DR写入操作。正确写法应为((uint16_t*)pTxBuffer)++;,或用临时变量中转指针。 - len的重复递减:16位分支内已执行
len--;,但循环末尾又重复执行一次len--;,会导致len被多减1,提前退出循环。比如当len=1时,进入16位分支后len变为0,循环末尾再减1变成-1,直接终止循环,此时DR可能未被写入,TXE自然不会被清除。
内容的提问来源于stack exchange,提问作者metisai02
相关产品推荐
相关产品推荐

