如何修改Tmote Sky代码实现串口接收浮点数/整数及与Arduino UART通信
解决Tmote Sky通过UART接收整数/浮点数的问题
你的问题核心在于原来的代码只处理ASCII字符串,而你尝试发送的是二进制数值,或者错误地解析了字符串数据。下面分两种常用方案帮你实现需求:
方案一:ASCII文本解析(推荐,兼容现有代码)
这种方式是把数字转换成字符串(比如"10.48")发送,Tmote Sky收到字符串后再解析成数值,操作简单,不容易出错。
修改后的Tmote Sky代码
#include "contiki.h" #include "dev/serial-line.h" #include <stdlib.h> // 引入字符串转数值的标准库函数 PROCESS(main_process, "main process"); AUTOSTART_PROCESSES(&main_process); PROCESS_THREAD(main_process, ev, data) { PROCESS_BEGIN(); for(;;) { PROCESS_WAIT_EVENT(); if (ev == serial_line_event_message && data != NULL) { const char* input_str = (const char*)data; printf("Received string: '%s'\n", input_str); // 解析为整数 int int_value = atoi(input_str); printf("Parsed integer: %d\n", int_value); // 解析为浮点数 float float_value = atof(input_str); printf("Parsed float: %.2f\n", float_value); } } PROCESS_END(); }
关键说明
- 发送端操作:必须发送ASCII格式的数字字符串,比如用串口助手发送
10.48(记得加换行/回车,因为serial_line模块默认以换行符作为字符串结束标记)。 - 之前的错误原因:你发送整数
5却收到5408,大概率是发送端直接发送了二进制的int类型数据(4字节的0x00000005),而Tmote把这些非ASCII字节当成字符串解析,自然得到乱码结果。
方案二:二进制传输(高效传输场景)
如果需要更高效的传输(比如节省带宽、减少解析开销),可以直接发送浮点数的二进制字节,这时候需要跳过serial_line模块,直接操作UART底层。
Tmote Sky代码
#include "contiki.h" #include "dev/uart0.h" #include <string.h> #define FLOAT_BYTE_COUNT 4 // AVR架构下float占4字节 uint8_t float_buffer[FLOAT_BYTE_COUNT]; uint8_t buffer_pos = 0; // UART接收字节的回调函数 static void uart_receive_handler(unsigned char c) { if (buffer_pos < FLOAT_BYTE_COUNT) { float_buffer[buffer_pos++] = c; // 凑满4字节后重组为float if (buffer_pos == FLOAT_BYTE_COUNT) { float received_float; memcpy(&received_float, float_buffer, FLOAT_BYTE_COUNT); printf("Received binary float: %.2f\n", received_float); buffer_pos = 0; // 重置缓冲区准备下一次接收 } } } PROCESS(main_process, "main process"); AUTOSTART_PROCESSES(&main_process); PROCESS_THREAD(main_process, ev, data) { PROCESS_BEGIN(); // 初始化UART0,波特率115200,注册接收回调 uart0_init(UART_BAUD_RATE(115200)); uart0_set_input(uart_receive_handler); for(;;) { PROCESS_YIELD(); } PROCESS_END(); }
发送端示例(Python)
需要把浮点数打包成二进制字节(注意Tmote Sky是小端字节序,要对应打包方式):
import serial import struct # 替换为你的串口端口号和波特率 ser = serial.Serial('COM3', 115200, timeout=1) target_float = 10.48 # 按小端打包为4字节二进制 ser.write(struct.pack('<f', target_float)) ser.close()
关键注意点
- 必须保证发送端和接收端的字节序一致(AVR是小端,所以用
<f打包)。 - 这种方式不会处理字符串终止符,所以要严格按固定字节数接收。
内容的提问来源于stack exchange,提问作者Haider Ali
相关产品推荐
相关产品推荐

