串口读取整数异常排查:客户端无法识别ATmega2560发送的数值
串口通信数据匹配问题排查与解决
初始代码与问题
客户端代码
int key=0; while (1) { int n_read=read(fd, &key, 4); printf("%d\n",key); fflush(stdout); if(key==1){ printf("in loop\n"); } }
ATmega2560服务端初始代码
while(1){ int key=1; printf("%d", key); }
服务端printf底层实现
void usart_putchar(char data) { // 等待发送缓冲区为空 while ( !(UCSR0A & (_BV(UDRE0))) ); // 开始发送 UDR0 = data; } // printf调用的流处理函数 int usart_putchar_printf(char var, FILE *stream) { // 把\n转成\r适配终端 if (var == '\n') usart_putchar('\r'); usart_putchar(var); return 0; }
初始问题
客户端始终无法打印"in loop",读取到的key值固定为825307441,从未等于1。怀疑是串口字节转整数的方式或read函数使用有问题。
修改后代码与新问题
修改服务端代码为直接按字节发送整数:
for(int j=0; j<4;j++){ while ( !(UCSR0A & (_BV(UDRE0))) ); UDR0=(key >> (8*j)) & 0xff;; }
客户端输出出现异常:
1 in loop 1 in loop 1 in loop 1 in loop 1 in loop 1 in loop 1 in loop 1 in loop 16777216 16777216 16777216 16777216 16777216 65536 65536 65536 65536 65536 256 256 256 1 in loop 1 in loop 1 in loop 1 in loop 1 in loop 1
疑问:这是不是大小端问题?有没有解决方法?如果无法解决将采用@the busybee的建议。
问题分析与解决
1. 初始问题根源
初始服务端用printf("%d", key)发送的是字符串形式的"1"(ASCII码0x31),而客户端直接把读取的4个字节当作int类型解析。4个连续的0x31组成的整数是0x31313131,转换成十进制正好是825307441,这就是初始问题的核心原因。
2. 修改后的大小端与丢包问题
修改后服务端按j从0到3的顺序发送key的每个字节,也就是先发送低字节(小端模式)。如果客户端所在系统是大端模式,就会把字节顺序反过来解析,导致出现16777216(0x01000000)、65536(0x00010000)、256(0x00000100)这类值——这些都是单个字节被解析到不同高位导致的。
另外,客户端的read调用可能没有每次都完整读取4个字节,字节错位也会导致解析出异常数值。
解决方法
方法一:统一字节序,固定发送接收顺序
约定两端使用统一的字节序(比如大端):
- 服务端按高字节到低字节发送:
for(int j=3; j>=0;j--){ // 从最高位字节开始发送 while ( !(UCSR0A & (_BV(UDRE0))) ); UDR0=(key >> (8*j)) & 0xff; }
- 客户端按约定的字节序手动拼接整数,避免系统字节序影响:
uint8_t buf[4]; while (1) { int n_read = read(fd, buf, 4); if(n_read !=4){ // 跳过不完整的读取,避免字节错位 continue; } // 按大端规则拼接成int int key = (buf[0] << 24) | (buf[1] << 16) | (buf[2] <<8) | buf[3]; printf("%d\n",key); fflush(stdout); if(key==1){ printf("in loop\n"); } }
方法二:校验读取完整性
如果客户端和服务端都是小端系统(比如x86架构),只需确保每次读取到完整的4字节:
int key=0; while (1) { int n_read=read(fd, &key, 4); if(n_read !=4){ continue; } printf("%d\n",key); fflush(stdout); if(key==1){ printf("in loop\n"); } }
内容的提问来源于stack exchange,提问作者beginner
相关产品推荐
相关产品推荐

