UART接收3位数字转整数异常:atoi及Hterm配置问题排查
核心问题分析与修复
1. ISR中使用_delay_ms破坏中断流程
中断服务函数(ISR)必须尽可能精简,_delay_ms会占用大量CPU时间,导致后续字节(包括你要检测的\r)无法被及时接收,直接跳过了if(received_char == '\r')的判断。必须删除ISR内所有的_delay_ms,如果需要数码管显示延迟,放到主循环或单独定时任务中,绝对不能在ISR里做延迟操作。
2. 字符串缺少终止符导致atoi转换失败
atoi要求输入标准C字符串(以\0结尾),你的代码仅将接收字符和\r存入buffer,未添加字符串结束符,会导致atoi读取内存垃圾数据,无法正确转换数字。
3. 缓冲区边界处理逻辑错误
buffer设为4字节足够存3位数字+\0终止符,无需存储\r。接收到\r时,应先给buffer添加\0,再调用atoi。
修正后的ISR代码
ISR(USART1_RX_vect) { static char buffer[4]; // 3位数字 + '\0'终止符 static uint8_t i = 0; char received_char = UDR1; if (received_char == '\r') { if(i > 0){ // 避免空输入触发转换 buffer[i] = '\0'; // 添加字符串终止符 int number = atoi(buffer); segment_num(number); } i = 0; // 重置缓冲区索引 } else { // 仅接收数字字符,过滤非数字输入 if(received_char >= '0' && received_char <= '9' && i < 3){ buffer[i] = received_char; i++; } else{ // 接收到非数字或超过3位,直接重置缓冲区 i = 0; } } }
额外排查点
- 确认Hterm设置:选择
ASCII编码,仅附加CR(不要选CR+LF),发送"222"时需通过发送按钮或回车触发完整发送,避免逐个字符输入导致中断拆分触发。 - 核对UART波特率与Hterm完全一致,波特率不匹配会导致接收字符乱码,自然检测不到
\r。 - 确认AVR的USART1接收中断标志位会自动清除(AVR的
USART1_RX_vect会自动处理RXC1标志,无需手动操作)。
内容的提问来源于stack exchange,提问作者Dakalaom
相关产品推荐
相关产品推荐

