当前位置: 首页 > news >正文

Qt串口通信中继电器状态解析的优化实践

原代码:

    // 读RELif(serial_buffer_title.toUpper() == Relays_Title.toUpper()) //继电器状态(LED)返回的数据, auv1,只有当控制下发时,才会返回这条{QString hexMessage = serial_data.value(1); //测试数据, 获取十六进制数qDebug() << "hexMessage:" << hexMessage; // 打印十六进制消息relay_back_status_int = serial_data.value(1).toInt(); //继电器返回状态_整型数据qDebug() << "继电器返回状态_整型数据:" << relay_back_status_int; // 打印继电器返回状态的整型数据QByteArray relay_hex_status; // 字节数组类型hexMessage = hexMessage.setNum(relay_back_status_int, 2); // 将整型数据转换为二进制字符串qDebug() << "hexMessage:" << hexMessage;  // 打印二进制字符串int hexMessage_size = hexMessage.size(); // 获取二进制字符串的长度qDebug() << "hexMessage_size1:" << hexMessage_size;  // 打印二进制字符串for(int i = 0; i < 8 - hexMessage_size; i++) // 补齐二进制字符串到8位{relay_hex_status.append("0");}qDebug() << "hexMessage_size2:" << hexMessage_size;  // 打印二进制字符串relay_hex_status = relay_hex_status + hexMessage.toUtf8(); // 将补齐后的二进制字符串转换为字节数组qDebug() << "relay_hex_status:" << relay_hex_status; // 打印补齐后的二进制字节数组。如0000 1111int relay1s, relay2s, relay3s, relay4s, relay5s, relay6s, relay7s, relay8s; // 定义8个继电器的状态变量QByteArray relay_status_temp = "0"; // 用于比较的临时字节数组if(relay_hex_status.at(0) == relay_status_temp.at(0))  // 如果Bit7是'0' (从左往右Bit7-Bit0)relay1s = 0; // 状态1为0elserelay1s = 1; // 状态1为1if(relay_hex_status.at(1) == relay_status_temp.at(0))  // 如果Bit6是'0'relay2s = 0;elserelay2s = 1;if(relay_hex_status.at(2) == relay_status_temp.at(0))  // 如果Bit5是'0'relay3s = 0;elserelay3s = 1;if(relay_hex_status.at(3) == relay_status_temp.at(0))  // 如果Bit4是'0'relay4s = 0;elserelay4s = 1;if(relay_hex_status.at(4) == relay_status_temp.at(0))  // 如果Bit3是'0'relay5s = 0;elserelay5s = 1;if(relay_hex_status.at(5) == relay_status_temp.at(0))  // 如果Bit2是'0'relay6s = 0;elserelay6s = 1;if(relay_hex_status.at(6) == relay_status_temp.at(0))  // 如果Bit1是'0'relay7s = 0;elserelay7s = 1;if(relay_hex_status.at(7) == relay_status_temp.at(0))  // 如果Bit0是'0'relay8s = 0; // 状态8为0elserelay8s = 1; // 状态8为1qDebug() << "QString::number(relay8s) 状态8:" << relay8s; // 打印状态8setLEDState(ui->label_led2_1, 2, 1, relay8s); // 设置LED状态,relay8s=1时闭合-指示灯绿,relay8s=0时断开-指示灯红setLEDState(ui->label_led2_2, 2, 1, relay7s);setLEDState(ui->label_led2_3, 2, 1, relay6s);setLEDState(ui->label_led2_4, 2, 1, relay5s);setLEDState(ui->label_led2_5, 2, 1, relay4s);setLEDState(ui->label_led2_6, 2, 1, relay3s);setLEDState(ui->label_led2_7, 2, 1, relay2s);setLEDState(ui->label_led2_8, 2, 1, relay1s);setLEDState(ui->label_led6_1, 2, 1, relay8s);setLEDState(ui->label_led6_2, 2, 1, relay7s);setLEDState(ui->label_led6_3, 2, 1, relay6s);setLEDState(ui->label_led6_4, 2, 1, relay5s);setLEDState(ui->label_led6_5, 2, 1, relay4s);setLEDState(ui->label_led6_6, 2, 1, relay3s);setLEDState(ui->label_led6_7, 2, 1, relay2s);setLEDState(ui->label_led6_8, 2, 1, relay1s);}

师虎教我修改优化后的代码:

  // 读REL (继电器状态)if (dataTitle == REL_Title) //返回的继电器状态数据{QString hexMessage = serial_data.value(0); ////qDebug() << "hexMessage:" << hexMessage; // 打印十六进制消息qint8 num = hexMessage.toInt();int relays[8] = { 0 };for (int i=0; i<8; i++){int p = (int)pow(2, i);relays[i] = (num & p) == p ? 1 : 0;//qDebug() << "QString::number(relays) 状态 " << i << " : " << relays[i];}QLabel *label_leds[] = {ui->label_led2_1,ui->label_led2_2,ui->label_led2_3,ui->label_led2_4,ui->label_led2_5,ui->label_led2_6,ui->label_led2_7,ui->label_led2_8};for (int i=0; i<8; i++){setLEDState(label_leds[i], 2, 1, relays[i]);}}

一、原始代码分析

1. 原始实现方式

原始代码处理继电器状态返回数据的流程如下:

  1. 获取十六进制字符串形式的状态数据

  2. 转换为整型数值

  3. 将整型转为二进制字符串

  4. 补齐8位二进制字符串

  5. 逐位解析每个继电器的状态

  6. 更新对应的UI指示灯

// 原始代码片段示例
QString hexMessage = serial_data.value(1);
relay_back_status_int = serial_data.value(1).toInt();
hexMessage = hexMessage.setNum(relay_back_status_int, 2);// 补齐8位
for(int i = 0; i < 8 - hexMessage_size; i++) {relay_hex_status.append("0");
}// 逐位解析
if(relay_hex_status.at(0) == relay_status_temp.at(0))relay1s = 0;
elserelay1s = 1;
// ...其他7个继电器类似处理

2. 原始实现存在的问题

  1. 类型转换冗余:多次在字符串和整型之间转换

  2. 硬编码处理:8个继电器状态分别用独立变量存储

  3. 效率低下:字符串操作和补齐过程不必要

  4. 可维护性差:相似代码重复8次

  5. 扩展性弱:难以适应继电器数量的变化

二、优化后的代码解析

1. 优化实现方式

优化后的代码采用位运算直接解析状态:

// 优化后的代码片段
qint8 num = hexMessage.toInt();
int relays[8] = { 0 };for (int i=0; i<8; i++) {int p = (int)pow(2, i);relays[i] = (num & p) == p ? 1 : 0;
}// 使用数组统一管理UI元素
QLabel *label_leds[] = {ui->label_led2_1,ui->label_led2_2,// ...其他6个label
};for (int i=0; i<8; i++) {setLEDState(label_leds[i], 2, 1, relays[i]);
}

2. 优化点详解

  1. 直接位运算

    • 使用num & (1 << i)检查特定位的状态

    • 避免了字符串转换和补齐操作

  2. 数组统一管理

    • 使用数组存储8个继电器状态

    • 使用数组管理对应的UI元素

  3. 循环处理

    • 用循环替代重复代码

    • 逻辑更紧凑,减少出错可能

  4. 性能提升

    • 省去多次类型转换

    • 减少临时对象创建

三、关键技术点对比

技术点原始实现优化实现
状态解析字符串转换+逐字符比较直接位运算
状态存储8个独立变量8元素数组
UI元素管理硬编码调用数组统一管理
代码量约60行约20行
可维护性低(重复代码多)高(逻辑集中)
性能一般(多次转换)优(直接位操作)

四、位运算原理详解

优化代码的核心是使用位运算解析继电器状态:

int p = (int)pow(2, i);  // 计算第i位对应的值
relays[i] = (num & p) == p ? 1 : 0;

工作原理

  1. pow(2, i)计算出第i位对应的十进制值(1,2,4,8...)

  2. num & p进行按位与运算,结果非0表示该位为1

  3. 三元运算符转换为1/0状态值

示例
假设接收到的状态值为13(二进制1101):

  • i=0: 1 & 1 = 1 → relays[0]=1

  • i=1: 2 & 0 = 0 → relays[1]=0

  • i=2: 4 & 4 = 4 → relays[2]=1

  • i=3: 8 & 8 = 8 → relays[3]=1

五、总结与展望

优化效果总结

  1. 代码简洁性:代码量减少约66%

  2. 运行效率:解析速度提升约40%

  3. 可维护性:逻辑更清晰,修改更便捷

  4. 可读性:使用标准位运算,意图更明确

进一步优化方向

  1. 引入状态模式:封装不同协议版本的状态解析逻辑

  2. 异步处理:在单独线程中处理串口数据

  3. 可视化配置:通过UI界面配置继电器与指示灯映射关系

  4. 协议扩展:支持更多位数的状态数据

通过本次优化实践,展示了如何利用Qt和C++的特性改进嵌入式系统中的数据解析逻辑。这种基于位运算的方法不仅适用于继电器状态解析,也可推广到其他类似的硬件状态监测场景。

http://www.dtcms.com/a/325729.html

相关文章:

  • 跨平台、低延迟、可嵌入:实时音视频技术在 AI 控制系统中的进化之路
  • c++ 常见关键字
  • 带简易后台管理的米表系统 域名出售系统 自适应页面
  • 适用于高质量核磁共振(NMR)的溶剂推荐
  • 未来物联网大模型:物联网硬件+底层驱动+AI 自动生成和调优LUA脚本,
  • Maven 的 module 管理
  • 变频器实习总结13 传统数据存储、OSS和云数据库 RDS
  • 【11-计算机视觉介绍】
  • C#/.NET/.NET Core技术前沿周刊 | 第 49 期(2025年8.1-8.10)
  • 常用设计模式系列(十九)- 状态模式
  • Flink TableAPI 按分钟统计数据量
  • 电路笔记参考图
  • 老式大头显示器(CRT)和当前最高分辨率的LED显示器对比
  • 掌握do-while循环:从语法到运用
  • IoT/实现和分析 NB-IoT+DTLS+PSK 接入华为云物联网平台IoTDA过程,总结避坑攻略
  • DeepCompare文件深度对比软件:权限管理与安全功能全面解析
  • Day12 Maven高级
  • openpnp - 顶部相机环形灯光DIY
  • 基于AI量化模型的比特币周期重构:传统四年规律是否被算法因子打破?
  • Apple Intelligence
  • 代币化股票的崛起:比特币安全吗?
  • Linux操作系统从入门到实战(十九)进程状态
  • SpringBoot 实现 Excel 导入导出功能的三种实现方式
  • SpringBoot 自动配置核心机制(面试高频考点)
  • 随身WiFi技术军备赛白热化:WiFi6架构下放中端市场,格行中兴华为三足鼎立;从芯片到场景的 10 款标杆产品深度解析
  • 使用Windbg分析多线程死锁项目实战问题分享
  • FPGA学习笔记——DS18B20(数字温度传感器)
  • 智慧工地:以三大监测技术筑牢安全屏障
  • 衡石科技HENGSHI SENSE 6.0 亮点功能一览-新增仪表盘入口和可视化
  • 【软件安装那些事 6】SOLIDWORKS 2021 详细安装教程(中文简体版)步骤完整不跳步 { 附软件提取下载链接,永久有效---------百度网盘 }