printf 是一个“重型”函数。它内部可能涉及复杂的格式化、缓冲区管理,甚至可能是系统调用(在有操作系统的环境下)。在裸机上,它最终会循环调用底层的 fputc 或 _write,一个字节一个字节地通过UART发送出去。
-
中断上下文的限制:中断服务程序(ISR)应该尽可能地快。如果在中断处理期间花费了太长时间,可能会发生以下情况:
-
后续串口字节丢失:当你还在忙于 printf "收到" 这两个汉字(GBK编码是4个字节,UTF-8是6个字节)时,串口硬件的接收缓冲区(通常只有1-2个字节)可能已经被下一个字符 'P' 占满了。如果 'E' 来得太快,'P' 就会被覆盖,造成数据丢失。
-
中断嵌套或优先级问题:printf 内部的 HAL_UART_Transmit 可能会等待发送完成,或者也可能使用中断。如果在高优先级的中断里执行了一个依赖低优先级中断的耗时操作,系统可能就锁死了。
-
堆栈溢出:printf 需要相当大的栈空间来执行。中断的栈空间通常比主程序的栈要小。在中断里调用 printf 很容易导致栈溢出,程序直接跑飞到 HardFault_Handler。
-
程序很可能在执行第一个 printf("收到") 时就崩溃了。因为 printf 有缓冲,它可能还没来得及把任何字符真正发送出去,程序就死了。所以你看不到 "收到" 的打印,也因为程序死了,