中断里不读DR,RXNE不清,系统卡死
短文标题:中断里不读DR,RXNE不清,系统卡死
你有没有想过一个问题:USART接收中断配置好了,一上电程序就卡死,一直在中断里出不来。很可能你没读DR。RXNE标志置1后,只有读DR才能清除。RXNE:接收数据寄存器非空,USART收到一个字节,硬件把数据存入DR,同时RXNE标志置1。如果RXNEIE使能,触发中断。中断里必须读DR,硬件才自动清除RXNE。
void USART1_IRQHandler(void)
{
if (USART1->SR & USART_SR_RXNE) {
uint8_t data = USART1->DR; // 读DR,硬件自动清RXNE
// 处理数据...
}
}
不读DR,RXNE永远为1,退出中断立即再进,系统卡死。ORE溢出错误:第二个陷阱,上一字节还没读,下一字节又收到了,ORE标志置1。ORE置1后,USART停止接收新数据,直到软件清除。清除ORE的正确顺序:先读SR,再读DR。
if (USART1->SR & USART_SR_ORE) {
volatile uint32_t tmp = USART1->SR; // 读SR
tmp = USART1->DR; // 再读DR
}
顺序错了,ORE清不掉。
回环实验,通过串口回环理解中断收发:
- 配置USART接收中断
- PC发送数据,单片机在中断中接收
- 将收到的数据立即发送回去(回环)
void USART1_IRQHandler(void)
{
if (USART1->SR & USART_SR_RXNE) {
uint8_t data = USART1->DR;
// 回环:将收到的数据立即发送
while (!(USART1->SR & USART_SR_TXE));
USART1->DR = data;
}
}
标志清除方式汇总
这个故事的启示,外设标志位是硬件给软件的“信号”,不清理,硬件就认为你还没忙完。收到信号(中断),回应信号(读DR清标志)。不回应,硬件一直喊,系统卡死。写在最后,写USART接收中断,记住三件事:读DR清RXNE,读SR再读DR清ORE,不清楚清除方式查手册。不读DR,中断不停。不清ORE,接收卡死。
(本文灵感源于于振南《新概念ARM32单片机》教程第4.9节。)
觉得有用?点赞、转发,让更多人避开“不读DR”的坑。
