嵌入式: 为什么中断服务函数必须尽快执行完毕?
实验现象:
在USART3_IRQHandler中的回调函数里存在打印日志操作(耗时多),当上位机一次性发送多个字节数据包时,会存在吞包行为如下如图所示
static void bl_rx_handler(const uint8_t *data, uint32_t size) { while (size--) { printf("recv: %02X\n", *data); // 打印日志 packet_buffer[packet_index++] = *data++; // 填入数据包数组 } } void USART3_IRQHandler(void) { if (USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) { if (rx_callback) { uint8_t data = (uint8_t)USART_ReceiveData(USART3); rx_callback(&data, 1); } USART_ClearITPendingBit(USART3, USART_IT_RXNE); } } int fputc(int ch, FILE *f) { USART_SendData(USART1, (uint8_t)ch); while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); return ch; } bl_usart_register_rx_callback(bl_rx_handler);现象分析:
串口3中USART_ReceiveData接收第一个字节数据后,RXNE变为0
进入回调函数—打印日志,此时TDR读取第二个数据,RXNE为1……不断读取并覆盖DR
打印日志即 串口1的波特率(115200)通常远低于 CPU 主频(168MHz)上位机以波特速率向单片机发送数据包,单片机以字节(1+8+1 位)的速率接收数据并进入串口中断10 / 115200 s内需要跳出中断,以接收下一个字节数据
串口接收数据流程:
移位寄存器 TDR → 数据寄存器 DR → 读取后 RXNE清零
