百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

Qt编写的嵌入式工业控制系统(嵌入式控制系统)

ccwgpt 2024-09-21 13:53 29 浏览 0 评论

一、前言

此系统用于扭力控制,嵌入式平台,采用的开发板为335X,这个还是比较稳定的。

二、开发环境

硬件平台:335X

软件:Qt+嵌入式linux

三、实现功能

1:QSS界面换肤

2:更换主界面背景

3:中文双拼输入法

4:数据图形曲线显示

5:数据统计柱状图显示。

6:串口网络通信

四、效果图

五、核心代码

void Com_RS232_API::ReadData()
{
 if (com->bytesAvailable() <= 0) {
 return;
 }
 myHelper::Sleep(sleep);
 QByteArray data = com->readAll();
 int dataLen = data.length();
 if (dataLen <= 0) {
 return;
 }
 //更新最后心跳时间
 lastHeartTime = QDateTime::currentDateTime();
 QString buffer = myHelper::ByteArrayToAsciiStr(data);
 int len = buffer.length();
 qDebug() << TIMEMS << "接收数据:" << buffer;
 emit ReceiveData(buffer);
 // //将数据加入处理队列,用线程处理数据
 // mutex.lock();
 // App::Buffer.append(data);
 // mutex.unlock();
 // currentFlag=255;
 // sleep=50;
 if (buffer.startsWith("667") && currentFlag == 0) {
 qDebug() << TIMEMS << "命令解析:" << "握手成功" ;
 isOk = true;
 //握手成功后将心跳间隔改为500毫秒
 timerHeart->setInterval(500);
 emit ReceiveHelloOk();
 //如果未启用自动执行,则将心跳和开机交互完成置为真
 if (!isAuto) {
 isHeart = true;
 allFinsh = true;
 }
 //握手成功后自动执行开机交互命令
 if (isAuto) {
 QTimer::singleShot(10, this, SLOT(ReadPsetIDNameAll()));
 }
 } else if (buffer.startsWith("301PST") && currentFlag == 1) {
 if (buffer.length() < 7) {
 return;
 }
 qDebug() << TIMEMS << "命令解析:" << "所有Pset索引返回" ;
 QMap<int, QString> psetIDName;
 QString temp = buffer.mid(6, len - 1);
 QStringList list = temp.split("'");
 int count = list.count() - 1;
 for (int i = 0; i < count; i++) {
 QStringList t = list.at(i).split(":");
 int id = t.at(0).toInt();
 QString name = t.at(1);
 psetIDName.insert(id, name);
 }
 emit ReceivePsetIDNameAll(psetIDName);
 qDebug() << TIMEMS << "命令解析:" << "psetIDName:" << psetIDName;
 } else if (buffer.startsWith("001") && currentFlag == 2) {
 qDebug() << TIMEMS << "命令解析:" << "授权1成功返回" ;
 emit ReceiveAuthor1Ok();
 //握手成功后自动执行开机交互命令
 if (isAuto) {
 QTimer::singleShot(10, this, SLOT(Author2()));
 }
 } else if (buffer.startsWith("001") && currentFlag == 3) {
 qDebug() << TIMEMS << "命令解析:" << "授权2成功返回" ;
 emit ReceiveAuthor2Ok();
 //握手成功后自动执行开机交互命令
 if (isAuto) {
 QTimer::singleShot(10, this, SLOT(ReadPsetIDCurrent()));
 }
 } else if (buffer.startsWith("332") && currentFlag == 4) {
 if (buffer.length() < 6) {
 return;
 }
 qDebug() << TIMEMS << "命令解析:" << "当前Pset索引返回" ;
 int psetIDCurrent = buffer.mid(3, 3).toInt();
 emit ReceivePsetIDCurrent(psetIDCurrent);
 qDebug() << TIMEMS << "命令解析:" << "psetIDCurrent:" << psetIDCurrent;
 //如果是重发命令确认的回复,则不需要继续执行开机交互命令
 if (isRecheck) { 
 isRecheck = false;
 return;
 }
 //握手成功后自动执行开机交互命令
 if (isAuto) {
 QTimer::singleShot(10, this, SLOT(Cooperate()));
 }
 } else if (buffer.startsWith("5691") && currentFlag == 5) {
 qDebug() << TIMEMS << "命令解析:" << "配合成功返回" ;
 emit ReceiveCooperateOk();
 //握手成功后自动执行开机交互命令
 if (isAuto) {
 QTimer::singleShot(10, this, SLOT(ReadPsetIDAll()));
 }
 } else if (buffer.startsWith("5710") && currentFlag == 6) {
 qDebug() << TIMEMS << "命令解析:" << "所有已经使用的Pset索引返回" ;
 QList<int> psetIDAll;
 QStringList list = buffer.split(":");
 if (list.count() < 3) {
 return;
 }
 QStringList t = list.at(2).split(";");
 int count = t.count();
 for (int i = 0; i < count; i++) {
 psetIDAll.append(t.at(i).toInt());
 }
 emit ReceivePsetIDAll(psetIDAll);
 qDebug() << TIMEMS << "命令解析:" << "psetIDAll:" << psetIDAll;
 //启动心跳命令
 isHeart = true;
 allFinsh = true;
 } else if (buffer.startsWith("001") && currentFlag == 7) {
 qDebug() << TIMEMS << "命令解析:" << "指定Pset成功返回" ;
 emit ReceiveSelectPset();
 QTimer::singleShot(10, this, SLOT(ReadPsetIDCurrent()));
 isRecheck = true; 
 //延时启动心跳定时器,防止结果未读成功而停止了心跳
 QTimer::singleShot(500, this, SLOT(StartHeart()));
 } else if (buffer.startsWith("113P") && currentFlag == 8) {
 if (buffer.length() < 8) {
 return;
 }
 qDebug() << TIMEMS << "命令解析:" << "Pset参数返回" ;
 QMap<int, QString> config;
 int psetID = buffer.mid(4, 3).toInt();
 QString temp = buffer.mid(7, len - 1);
 QStringList list = temp.split("'");
 int count = list.count() - 1;
 for (int i = 0; i < count; i++) {
 QString t = list.at(i);
 int pID = t.mid(0, 3).toInt();
 QString pValue = t.mid(4, t.length());
 //如果参数号为406则需要转换为正常的日期格式
 //传过来的是从1970年1月1日0时0分0秒到现在经过的秒数
 if (pID == 406) {
 QDateTime d = myHelper::IntToDateTime(pValue.toUInt());
 pValue = d.toString("yyyy-MM-dd HH:mm:ss");
 }
 config.insert(pID, pValue);
 }
 emit ReceivePsetConfig(psetID, config);
 qDebug() << TIMEMS << "命令解析:" << "psetID:" << psetID << "config:" << config;
 qApp->processEvents();
 } else if (buffer.startsWith("001") && currentFlag == 9) {
 qDebug() << TIMEMS << "命令解析:" << "更新Pset准备成功" ;
 emit ReceiveUpdatePsetPrepareOk();
 } else if (buffer.startsWith("001") && currentFlag == 10) {
 qDebug() << TIMEMS << "命令解析:" << "更新Pset成功" ;
 emit ReceiveUpdatePsetOk();
 } else if (buffer.startsWith("00101") && currentFlag == 11) {
 qDebug() << TIMEMS << "命令解析:" << "新建Pset成功" ;
 emit ReceiveNewPsetOk();
 } else if (buffer.startsWith("00101") && currentFlag == 12) {
 qDebug() << TIMEMS << "命令解析:" << "删除Pset成功" ;
 emit ReceiveDeletePsetOk();
 } else if (buffer.startsWith("003")) {
 qDebug() << TIMEMS << "命令解析:" << "心跳应答成功" ;
 emit ReceiveHeartOk();
 //003\x02=003 003\\ACK为有新的结果通知
 if (buffer.startsWith("003\\STX") || buffer.startsWith("003\\ACK")) {
 qDebug() << TIMEMS << "命令解析:" << "有新的拧紧结果可读取" ;
 //立马启动执行读取结果值
 if (isAuto) {
 QTimer::singleShot(10, this, SLOT(ReadResultNmDeg()));
 //延时启动心跳定时器,防止结果未读成功而停止了心跳
 QTimer::singleShot(1800, this, SLOT(StartHeart()));
 }
 }
 } else if (buffer.startsWith("113R")) {
 if (buffer.length() < 8) {
 return;
 }
 qDebug() << TIMEMS << "命令解析:" << "拧紧数值结果返回" ;
 int psetID = buffer.mid(4, 3).toInt();
 double nm = 0;
 int nmOk = 1;
 int deg = 0;
 int degOk = 1;
 int id = 0;
 QString strDate = "";
 QString num = "0";
 QString temp = buffer.mid(7, len - 1);
 QStringList list = temp.split("'");
 int count = list.count() - 1;
 for (int i = 0; i < count; i++) {
 QString t = list.at(i);
 int pID = t.mid(0, 3).toInt();
 QString pValue = t.mid(4, t.length());
 if (pID == 100) {
 nm = pValue.toDouble();
 } else if(pID == 101) {
 nmOk = pValue.toInt();
 } else if (pID == 102) {
 deg = pValue.toInt();
 } else if(pID == 103) {
 degOk = pValue.toInt();
 } else if (pID == 300) {
 id = pValue.toInt();
 } else if (pID == 301) {
 strDate += pValue;
 } else if (pID == 302) {
 strDate = QString("%1 %2").arg(strDate).arg(pValue);
 } else if (pID == 305) {
 num = pValue;
 }
 }
 emit ReceiveResultNmDeg(psetID, id, strDate, num, nm, nmOk, deg, degOk);
 qDebug() << TIMEMS << "命令解析:" << "psetID:" << psetID << "结果编号:" << id << "时间:" << strDate << "工具系列号:" << num
 << "扭矩值:" << nm << "扭矩结果:" << nmOk << "角度值:" << deg << "角度结果:" << degOk;
 //立马读取扭矩对时间曲线结果
 if (isAuto) {
 QTimer::singleShot(10, this, SLOT(ReadResultNmTimePlot()));
 //延时启动心跳定时器,防止结果未读成功而停止了心跳
 QTimer::singleShot(1800, this, SLOT(StartHeart()));
 }
 qApp->processEvents();
 } else if (buffer.startsWith("123G")) {
 if (buffer.length() < 5) {
 return;
 }
 qDebug() << TIMEMS << "命令解析:" << "扭矩对时间曲线返回" ;
 int psetID = 0;
 int id = 0;
 QString strDate = "";
 QString num = "0";
 double interval = 0;
 int fenzi = 1;
 int fenmu = 1;
 double targetNm = 0;
 double minNm = 0;
 double maxNm = 0;
 QList<double> result;
 QString temp = buffer.mid(4, len - 1);
 QStringList l = temp.split(";");
 if (l.count() < 2) {
 return;
 }
 //取出分号前的数值
 QStringList list = l.at(0).split("'");
 int count = list.count() - 1;
 for (int i = 0; i < count; i++) {
 QString t = list.at(i);
 int pID = t.mid(0, 3).toInt();
 QString pValue = t.mid(4, t.length());
 if (pID == 100) {
 id = pValue.toInt();
 } else if (pID == 101) {
 strDate += pValue;
 } else if (pID == 102) {
 strDate = QString("%1 %2").arg(strDate).arg(pValue);
 } else if (pID == 105) {
 num = pValue;
 } else if (pID == 114) {
 psetID = pValue.toInt();
 } else if (pID == 201) {
 interval = pValue.toDouble();
 } else if (pID == 203) {
 fenzi = pValue.toInt();
 } else if (pID == 204) {
 fenmu = pValue.toInt();
 } else if (pID == 206) {
 targetNm = pValue.toDouble();
 } else if (pID == 210) {
 minNm = pValue.toDouble();
 } else if (pID == 211) {
 maxNm = pValue.toDouble();
 }
 }
 //分号后的数据代表结果
 QString str1 = l.at(1);
 QByteArray ba = myHelper::AsciiStrToByteArray(str1);
 QString str2 = myHelper::ByteArrayToHexStr(ba);
 //保存获取到的扭矩对角度数据
 if (isSaveNm) {
 QString fileName = QString("%1/save/Nm_%2.txt").arg(App::AppPath)
 .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd-HH-mm-ss"));
 QFile file(fileName);
 file.open(QFile::WriteOnly | QFile::Text);
 file.write(str2.toLatin1());
 file.close();
 }
 QStringList tempList = str2.split(" ");
 int currentCount = tempList.count();
 //如果不是2的倍数则长度要减去1
 if ( currentCount % 2 != 0) {
 currentCount = (currentCount - 1);
 }
 //逐个取出扭矩值
 for (int i = 0; i < currentCount; i = i + 2) {
 qint16 value = myHelper::StrHexToShort(QString("%1%2").arg(tempList.at(i)).arg(tempList.at(i + 1)));
 double r = (double)(value * fenzi) / fenmu;
 result.append(r);
 }
 emit ReceiveResultNmTimePlot(psetID, id, strDate, num, interval, targetNm, minNm, maxNm, result);
 qDebug() << TIMEMS << "命令解析:" << "psetID:" << psetID << "结果编号:" << id << "时间:" << strDate << "工具系列号:" << num
 << "间隔:" << interval << "目标扭矩:" << targetNm << "扭矩最小:" << minNm << "扭矩最大:" << maxNm
 << "结果集合:" << result;
 //立马读取角度对时间曲线结果
 if (isAuto) {
 QTimer::singleShot(10, this, SLOT(ReadResultDegTimePlot()));
 //延时启动心跳定时器,防止结果未读成功而停止了心跳
 QTimer::singleShot(1800, this, SLOT(StartHeart()));
 }
 qApp->processEvents();
 } else if (buffer.startsWith("125G")) {
 if (buffer.length() < 5) {
 return;
 }
 qDebug() << TIMEMS << "命令解析:" << "角度对时间曲线返回" ;
 int psetID = 0;
 int id = 0;
 QString strDate = "";
 QString num = "0";
 double interval = 0;
 int fenzi = 1;
 int fenmu = 1;
 double targetDeg = 0;
 double minDeg = 0;
 double maxDeg = 0;
 QList<double> result;
 QString temp = buffer.mid(4, len - 1);
 QStringList l = temp.split(";");
 if (l.count() < 2) {
 return;
 }
 //取出分号前的数值
 QStringList list = l.at(0).split("'");
 int count = list.count() - 1;
 for (int i = 0; i < count; i++) {
 QString t = list.at(i);
 int pID = t.mid(0, 3).toInt();
 QString pValue = t.mid(4, t.length());
 if (pID == 100) {
 id = pValue.toInt();
 } else if (pID == 101) {
 strDate += pValue;
 } else if (pID == 102) {
 strDate = QString("%1 %2").arg(strDate).arg(pValue);
 } else if (pID == 105) {
 num = pValue;
 } else if (pID == 114) {
 psetID = pValue.toInt();
 } else if (pID == 201) {
 interval = pValue.toDouble();
 } else if (pID == 204) {
 fenzi = pValue.toInt();
 } else if (pID == 205) {
 fenmu = pValue.toInt();
 } else if (pID == 229) {
 targetDeg = pValue.toDouble();
 } else if (pID == 220) {
 minDeg = pValue.toDouble();
 } else if (pID == 221) {
 maxDeg = pValue.toDouble();
 }
 }
 //分号后的数据代表结果
 QString str1 = l.at(1);
 QByteArray ba = myHelper::AsciiStrToByteArray(str1);
 QString str2 = myHelper::ByteArrayToHexStr(ba);
 //保存获取到的角度对角度数据
 if (isSaveDeg) {
 QString fileName = QString("%1/save/Deg_%2.txt").arg(App::AppPath)
 .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd-HH-mm-ss"));
 QFile file(fileName);
 file.open(QFile::WriteOnly | QFile::Text);
 file.write(str2.toLatin1());
 file.close();
 }
 QStringList tempList = str2.split(" ");
 int currentCount = tempList.count();
 //如果不是2的倍数则长度要减去1
 if ( currentCount % 2 != 0) {
 currentCount = (currentCount - 1);
 }
 //逐个取出角度值
 for (int i = 0; i < currentCount; i = i + 2) {
 qint16 value = myHelper::StrHexToShort(QString("%1%2").arg(tempList.at(i)).arg(tempList.at(i + 1)));
 double r = (double)(value * fenzi) / fenmu;
 //传过来的值放大了100倍,所以真实显示的值要除以100
 double re = r / 100;
 result.append(re);
 }
 emit ReceiveResultDegTimePlot(psetID, id, strDate, num, interval, targetDeg, minDeg, maxDeg, result);
 qDebug() << TIMEMS << "命令解析:" << "psetID:" << psetID << "结果编号:" << id << "时间:" << strDate << "工具系列号:" << num
 << "间隔:" << interval << "最终角度结果:" << targetDeg << "最终角度最小:" << minDeg << "最终角度最大:" << maxDeg
 << "结果集合:" << result;
 //将心跳重新置为真
 isHeart = true;
 qApp->processEvents();
 }
 //currentFlag = 255;
 //sleep = 50;
}

相关推荐

盲盒小程序背后的技术揭秘:如何打造个性化购物体验

在2025年的今天,盲盒小程序作为一种新兴的购物方式,正以其独特的魅力和个性化体验吸引着越来越多的消费者。这种将线上购物与盲盒概念相结合的应用,不仅为消费者带来了未知的惊喜,还通过一系列技术手段实现了...

小程序·云开发已支持单日亿级调用量,接口可用率高达99.99%

2019-10-1914:1210月19日,由腾讯云与微信小程序团队联合举办的“小程序·云开发”技术峰会在北京召开。会上,微信小程序团队相关负责人表示“小程序·云开发”系统架构已经支持每天亿级别的...

程序员副业开启模式:8个GitHub上可以赚钱的小程序

前言开源项目作者:JackonYang今天推荐的这个项目是「list-of-wechat-mini-program-list」,开源微信小程序列表的列表、有赚钱能力的小程序开源代码。这个项目分为两部分...

深度科普:盲盒小程序开发的底层逻辑

在当下的数字化浪潮中,盲盒小程序以其独特的趣味性和互动性,吸引着众多消费者的目光。无论是热衷于收集玩偶的年轻人,还是享受拆盒惊喜的上班族,都对盲盒小程序情有独钟。那么,这种备受欢迎的盲盒小程序,其开发...

微信小程序的制作步骤

SaaS小程序制作平台,作为数字化转型时代下的创新产物,不仅将易用性置于设计的核心位置,让非技术背景的用户也能轻松上手,快速制作出功能丰富、界面精美的小程序,更在性能和稳定性方面投入了大量精力,以确保...

携程开源--小程序构建工具,三分钟搞定

前言今天推荐的这个项目是「wean」,一个小程序构建打包工具。在wean之前,大量小程序工具使用webpack进行打包,各种loader、plugin导致整个开发链路变长。wean旨在解...

校园小程序的搭建以及营收模式校园外卖程序校园跑腿校园圈子系统

校园小程序的架构设计主要包括云端架构和本地架构两部分。云端架构方面,采用Serverless架构可以降低技术门槛,通过阿里云、腾讯云等平台提供的云服务,可以实现弹性扩容和快速部署。例如,使用云数据库、...

盲盒小程序开发揭秘:技术架构与实现原理全解析

在2025年的今天,盲盒小程序作为一种结合了线上购物与趣味性的创新应用,正受到越来越多用户的喜爱。其背后的技术架构与实现原理,对于想要了解或涉足这一领域的人来说,无疑充满了神秘与吸引力。本文将为大家科...

月活百万的小程序架构设计:流量暴增秘籍

从小程序到"大"程序的蜕变之路当你的小程序用户量从几千跃升至百万级别时,原有的架构就像一件不合身的衣服,处处紧绷。这个阶段最常遇到的噩梦就是服务器崩溃、接口超时、数据丢失。想象一下,在...

认知智能如何与产业结合?专家学者共探理论框架与落地实践

当前,以大模型为代表的生成式人工智能等前沿技术加速迭代,如何将认知智能与产业结合,成为摆在各行各业面前的一个问题。论坛现场。主办方供图7月4日,2024世界人工智能大会暨人工智能全球治理高级别会议在...

现代中医理论框架

...

认知行为(CBT)中的ABC情绪理论

情绪ABC理论是由美国心理学家阿尔伯特·艾利斯(AlbertEllis1913-2007)创建的理论,A表示诱发性事件(Activatingevent),B表示个体针对此诱发性事件产生的一些信...

说说卡伦霍妮的理论框架,对你调整性格和人际关系,价值很大

01自在今天我主要想说下霍妮的理论框架。主要说三本书,第一本是《我们时代的神经症人格》,第二本是《我们内心的冲突》,第三本是《神经症与人的成长》。根据我的经验,三本书价值巨大,但并不是每个人都能读进去...

供应链管理-理论框架

一个最佳价值的供应链,应该是一个具有敏捷性、适应性和联盟功能(3A)的供应链,其基本要素包括战略资源、物流管理、关系管理以及信息系统,目标是实现速度、质量、成本、柔性的竞争优势。篇幅有...

微信WeUI设计规范文件下载及使用方法

来人人都是产品经理【起点学院】,BAT实战派产品总监手把手系统带你学产品、学运营。WeUI是一套同微信原生视觉体验一致的基础样式库,由微信官方设计团队为微信Web开发量身设计,可以令用户的使用感知...

取消回复欢迎 发表评论: