这里学习分俩部分内容,STM32打包数据发送、以及Python打开串口接收保存位.csv表格
这个例程与STM32的具体型号没太大关系,就是简单的发送数据包
文章提供测试代码讲解、完整工程下载、测试效果图
目录
STM32部分的内容:
测试数据结构体:
这里我准备了一个结构体来存储测试数据,它的定义与初始化如下:
这里是他的初始化:
cpp// 定义一个结构体来存储测试数据 typedef struct { float temperature; float humidity; float pressure; } SensorData; // 定义一个结构体数组来存储测试数据 SensorData testData[] = { {25.5, 60.0, 1013.25}, {30.0, 70.5, 1010.0}, {22.3, 55.0, 1015.75}, {29.6, 59.0, 1011.15}, };
打包发送逻辑:
这里就简单地加上包头包尾,也不校验了:
UsartPrintf函数本质与printf相同,只不过是我改写后能任意选择串口号了而已:
代码如下:
cpp// 假设发送模拟的温度、湿度、压力信息 void sendCSVData(float temperature, float humidity, float pressure) { char dataBuffer[50]; int i; // 计算校验和(累加和) unsigned char checksum = 0; // 构建完整的数据包:报头 + 数据 + 报尾 char packet[60]; sprintf(dataBuffer, "temperature,humidity,pressure\r\n%.1f,%.1f,%.1f\r\n", temperature, humidity, pressure); for (i = 0; i < strlen(dataBuffer); i++) { checksum += dataBuffer[i]; } strcpy(packet, "HEAD"); // 报头 strcat(packet, dataBuffer); //sprintf(packet + strlen(packet), "%02X", checksum); // 校验和(以十六进制表示) strcat(packet, "TAIL"); // 报尾 //发送整个数据包: for(i=0;i<strlen(packet);i++) UsartPrintf(USART1, "%c", packet[i]); }
发送测试数据:
我的测试工程是有UCOS操作系统的,但实际上当成裸机的没有操作系统看待就行:
具体的发送逻辑都在 #include "ComTask.h" 文件里面:
cppvoid comTask(void * p_arg) { OS_ERR err; int i=0; // 定义一个结构体数组来存储测试数据 SensorData testData[] = { {25.5, 60.0, 1013.25}, {30.0, 70.5, 1010.0}, {22.3, 55.0, 1015.75}, {29.6, 59.0, 1011.15}, }; p_arg = p_arg; OSTaskDel((OS_TCB*)&MessageTaskTaskTCB,&err); //删除MessageTaskTaskTCB OSTaskDel((OS_TCB*)&CalculateTaskTaskTCB,&err); //删除CalculateTask //sendCSVData(1.123,456.6,666.7); while (DEF_TRUE) { //发送i下标的测试数据: sendCSVData(testData[i].temperature,testData[i].humidity,testData[i].pressure); i++; if(i>3) {i=0;} OSTimeDlyHMSM(0,0,0,500,OS_OPT_TIME_HMSM_STRICT,&err); //延时500ms } }
Python接收部分内容:
这里写的也是比较简陋,串口号记得根据实际情况改写一下:
可以通过串口助手软件来帮忙验证是哪个串口:
python
import serial
import time
# 配置串口参数
ser = serial.Serial('COM5', 115200, timeout=1) # 根据实际串口端口号进行调整
def receive_and_save_csv_data():
try:
buffer = ''
while True:
if ser.in_waiting > 0:
data = ser.read(ser.in_waiting).decode('utf-8')
buffer += data
# 检查是否接收到完整的数据包
while 'TAIL' in buffer:
# 查找第一个TAIL的位置
tail_index = buffer.find('TAIL')
# 检查前面是否有HEAD
if 'HEAD' in buffer[:tail_index]:
packet = buffer[:tail_index + 4] # 提取完整的数据包
buffer = buffer[tail_index + 4:] # 移除已处理的数据包
# 校验报头和报尾
if packet.startswith("HEAD") and packet.endswith("TAIL"):
# 提取CSV数据
csv_data = packet[4:-4] # 跳过报头和报尾
# 保存CSV数据到文件
with open('received_data.csv', 'a') as file:
file.write(csv_data + '\n')
print("Data saved successfully!")
else:
print("Invalid packet format!")
else:
break # 如果没有HEAD,则中断当前循环,继续等待更多数据
time.sleep(0.1) # 稍作延时,避免占用过多CPU资源
except KeyboardInterrupt:
print("Program interrupted by user.")
finally:
ser.close()
if __name__ == "__main__":
receive_and_save_csv_data()
测试效果截图:
先用串口助手打开串口接收正常:
后关闭串口助手,验证Python接收数据正常:表格也是正常生成: