摘要:上位机软件程序通过QT实现,采集输入信息,根据实际需要做出合适的串口通讯协议,实现效果如下图所示:

主要实现的功能:

1.串口基本参数可选,可调

2.显示区域可选择十六进制/asicii码显示,可根据自己的需求调整多少字节对齐,显示的比较工整,有利于解析协议

3.可自己制定协议头,其他子项内容都是以十进制输入,内置checksum自动计算

4.实时显示发送/接收字节数

5.可自己定制时间周期定时发送

6.实时显示时间

代码实现:

实现过程较为简单,主要是协议处理:

串口设备:新建串口对象 -> 寻找可用串口设置 -> 设置串口基本参数 -> 打开串口 ->监听串口

串口协议:LineEdit的内容是大端格式,所以使用的时候要将变量转换成大端,默认是小端

注意:

 QString("%1").arg(ui>lineEdit_S_num>text().toInt(),,,QChar(''))

 第一个参数 : 将Qstring转换为int型 第二个参数 : 需要将几个字符串转换成十六进制的,
如char型 :需要两个字符
short型 : 需要四个字符
int/long : 需要八个字符
第三个参数: 转换为多少进制
第四个参数: 不足位数的用0补齐
 //QByteArray里面的数据按照对应的通讯协议进行调整
void Widget::int_adjust(QByteArray &str,qint8 startcount)
{
qint8 temp1;
qint8 temp2;
temp1 = str[startcount];
temp2 = str[startcount+];
str[startcount] = str[startcount+];
str[startcount+] = str[startcount+];
str[startcount+] =temp2;
str[startcount+] =temp1;
}
void Widget::short_adjust(QByteArray &str,qint8 startcount)
{
qint8 temp1;
temp1 = str[startcount];
str[startcount] = str[startcount+];
str[startcount+] = temp1;
}
 //字符串转成十六进制实现
void Widget::StringToHex(QString str, QByteArray &senddata)
{ int hexdata,lowhexdata; int hexdatalen = ; int len = str.length(); senddata.resize(len/); char lstr,hstr; for(int i=; i<len; )
{
//char lstr,
hstr=str[i].toLatin1();
if(hstr == ' ')
{
i++;
continue;
}
i++;
if(i >= len)
break;
lstr = str[i].toLatin1();
hexdata = ConvertHexChar(hstr);
lowhexdata = ConvertHexChar(lstr);
if((hexdata == ) || (lowhexdata == ))
break;
else
hexdata = hexdata*+lowhexdata;
i++;
senddata[hexdatalen] = (char)hexdata;
hexdatalen++;
}
senddata.resize(hexdatalen);
} char Widget::ConvertHexChar(char ch)
{
if((ch >= '') && (ch <= ''))
return ch-0x30;
else if((ch >= 'A') && (ch <= 'F'))
return ch-'A'+;
else if((ch >= 'a') && (ch <= 'f'))
return ch-'a'+;
else return (-); }

要点,易错点基本已经指出,其他的比较简单,这里不再赘叙

 #include "widget.h"
#include "ui_widget.h"
#include <QTimer>
#include <QDateTime>
#include <QMessageBox>
static int CountBase = ;
static int SENDNUMSIZE = ;
static int recvCount = ;
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
serial = new QSerialPort;
/* regester software timer*/
atimer = new QTimer();
atimer->setInterval();
atimer->start(); cycletime = new QTimer();
cycletime->setInterval(ui->lineEdit_cycletime->text().toInt()); QObject::connect(atimer,&QTimer::timeout,this,&Widget::timer_handle); //查找可用的串口
foreach (const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
{
QSerialPort serial;
serial.setPort(info);
if(serial.open(QIODevice::ReadWrite))
{
ui->comBox->addItem(serial.portName());
serial.close();
}
}
//设置波特率下拉菜单默认显示第0项
ui->baudBox->setCurrentIndex();
ui->baudBox->setEnabled(false);
ui->stopbitBox->setEnabled(false);
ui->databitBox->setEnabled(false);
ui->checkBox->setEnabled(false);
ui->comBox->setEnabled(false);
} Widget::~Widget()
{
delete ui;
}
void Widget::timer_handle(void)
{ QDateTime current_date_time =QDateTime::currentDateTime();
QString current_date =current_date_time.toString("yyyy.MM.dd hh:mm:ss ddd");
// ui->textBrowser_date
ui->label_date->setText(current_date); } void Widget::on_pushButton_oprea_clicked()
{
if(ui->pushButton_oprea->text() == tr("串口已关闭"))
{
serial = new QSerialPort;
//设置串口名
serial->setPortName(ui->comBox->currentText());
//打开串口
serial->open(QIODevice::ReadWrite);
//设置波特率
serial->setBaudRate(QSerialPort::Baud115200);//设置波特率为115200
//设置数据位数
switch (ui->databitBox->currentIndex())
{
case :
serial->setDataBits(QSerialPort::Data8);//设置数据位8
break;
default:
break;
}
//设置校验位
switch (ui->checkBox->currentIndex())
{
case :
serial->setParity(QSerialPort::NoParity);
break;
default:
break;
}
//设置停止位
switch (ui->stopbitBox->currentIndex())
{
case :
serial->setStopBits(QSerialPort::OneStop);//停止位设置为1
break;
case :
serial->setStopBits(QSerialPort::TwoStop);
default:
break;
}
//设置流控制
serial->setFlowControl(QSerialPort::NoFlowControl);//设置为无流控制 //关闭设置菜单使能
ui->baudBox->setEnabled(true);
ui->stopbitBox->setEnabled(true);
ui->databitBox->setEnabled(true);
ui->checkBox->setEnabled(true);
ui->comBox->setEnabled(true);
ui->pushButton_oprea->setText(tr("串口已打开")); //连接信号槽
QObject::connect(serial,&QSerialPort::readyRead,this,&Widget::ReadData);
}
else
{
cycletime->stop();
//关闭串口
serial->clear();
serial->close();
serial->deleteLater(); //恢复设置使能
ui->baudBox->setEnabled(false);
ui->stopbitBox->setEnabled(false);
ui->databitBox->setEnabled(false);
ui->checkBox->setEnabled(false);
ui->comBox->setEnabled(false);
ui->pushButton_oprea->setText(tr("串口已关闭"));
}
}
//读取接收到的信息
void Widget::ReadData()
{
QByteArray temp;
if(ui->HEX_SHOW->isChecked())
{
SENDNUMSIZE = ui->lineEdit_duiqi->text().toInt();
temp = serial->readAll();
QDataStream out(&temp,QIODevice::ReadWrite); //将字节数组读入
while(!out.atEnd())
{
qint8 outChar = ;
static qint8 datacount = ;
recvCount++;
out>>outChar; //每字节填充一次,直到结束
datacount++;
//十六进制的转换
QString str = QString(" %1").arg(outChar&0xFF,,,QLatin1Char(''));
ui->textBrowser->insertPlainText(str);
ui->label_recvvalue->setNum(recvCount);
if(SENDNUMSIZE+ == datacount)
{
datacount = ;
ui->textBrowser->insertPlainText("\n");
ui->textBrowser->moveCursor(QTextCursor::End);
}
}
}
else
{ temp += serial->readAll();
if(!temp.isEmpty())
{
ui->textBrowser->append(temp);
ui->textBrowser->moveCursor(QTextCursor::End);
}
temp.clear();
} }
short Widget::checksum(QByteArray ba)
{
short i = ,sumValue = ; for(i=;i<(ba.length());i++)
{
sumValue+=ba.at(i);
}
return sumValue;
} void Widget::on_send_clicked()
{
short checkValue = ;
QString str;
QByteArray senddata;
if(ui->pushButton_oprea->text() == tr("串口已关闭"))
{
QMessageBox::information(this, "warning", "串口没打开", QMessageBox::Yes); }
if(ui->radio_dash->isChecked())
{
str = ui->lineEdit_head->text()
+ QString("%1").arg(ui->lineEdit_infopage->text().toShort(),,,QChar(''))
+ QString("%1").arg(ui->lineEdit_menu->text().toShort(),,,QChar(''))
+ QString("%1").arg(ui->lineEdit_speed->text().toShort(),,,QChar(''))
+ QString("%1").arg(ui->lineEdit_FP->text().toShort(),,,QChar(''))
+ QString("%1").arg(ui->lineEdit_BP->text().toShort(),,,QChar(''))
+ QString("%1").arg(ui->lineEdit_gear->text().toShort(),,,QChar(''))
+ QString("%1").arg(ui->lineEdit_hour->text().toShort(),,,QChar(''))
+ QString("%1").arg(ui->lineEdit_minute->text().toShort(),,,QChar(''))
+ QString("%1").arg(ui->lineEdit_TemP->text().toShort(),,,QChar(''))//
+ QString("%1").arg(ui->lineEdit_trip->text().toShort(),,,QChar(''))//
+ QString("%1").arg(ui->lineEdit_C_Trip->text().toShort(),,,QChar(''))//
+ QString("%1").arg(ui->lineEdit_odo->text().toInt(),,,QChar(''))//
+ QString("%1").arg(ui->lineEdit_LF_Press->text().toShort(),,,QChar(''))//
+ QString("%1").arg(ui->lineEdit_LB_Press->text().toShort(),,,QChar(''))//
+ QString("%1").arg(ui->lineEdit_RF_Press->text().toShort(),,,QChar(''))//
+ QString("%1").arg(ui->lineEdit_RB_Press->text().toShort(),,,QChar(''))//
+ QString("%1").arg(ui->lineEdit_oil_cost->text().toInt(),,,QChar(''))//
+ QString("%1").arg(ui->lineEdit_C_oilcost->text().toShort(),,,QChar(''))
+ QString("%1").arg(ui->lineEdit_AV_oil_cost->text().toShort(),,,QChar(''))
+ QString("%1").arg(ui->lineEdit_can_warning->text().toShort(),,,QChar(''))
+ QString("%1").arg(ui->lineEdit_icon->text().toShort(),,,QChar(''))//
+ QString("%1").arg(ui->lineEdit_backlight->text().toShort(),,,QChar(''));
/*************** 调整short 和 init 数据类型字节发送顺序 ****************/
StringToHex(str,senddata);//将str字符串转换为16进制的形式
short_adjust(senddata,);
short_adjust(senddata,);
short_adjust(senddata,);
int_adjust(senddata,);
short_adjust(senddata,);
short_adjust(senddata,);
short_adjust(senddata,);
short_adjust(senddata,);
int_adjust(senddata,);
short_adjust(senddata,);
}
else{
str = ui->lineEdit_head->text()
+ QString("%1").arg(ui->lineEdit_ST_Page->text().toShort(),,,QChar(''))
+ QString("%1").arg(ui->lineEdit_menu_level->text().toShort(),,,QChar(''))
+ QString("%1").arg(ui->lineEdit_cursor->text().toShort(),,,QChar(''))
+ QString("%1").arg(ui->lineEdit_C_selcet->text().toShort(),,,QChar(''))
+ QString("%1").arg(ui->lineEdit_num->text().toShort(),,,QChar(''))
+ QString("%1").arg(ui->lineEdit_S_num->text().toInt(),,,QChar(''))
+ QString("%1").arg(ui->lineEdit_S_hour->text().toShort(),,,QChar(''))
+ QString("%1").arg(ui->lineEdit_S_minute->text().toShort(),,,QChar(''))
+ QString("%1").arg(ui->lineEdit_S_year->text().toShort(),,,QChar(''))
+ QString("%1").arg(ui->lineEdit_S_month->text().toShort(),,,QChar(''))
+ QString("%1").arg(ui->lineEdit_S_day->text().toShort(),,,QChar(''))
+ QString("%1").arg(ui->lineEdit_S_backlight->text().toShort(),,,QChar(''));
/*************** 调整short 和 init 数据类型字节发送顺序 ****************/
StringToHex(str,senddata);//将str字符串转换为16进制的形式
int_adjust(senddata,);
short_adjust(senddata,);
} checkValue = checksum(senddata);
senddata.append((char)(checkValue));
serial->write(senddata);//发送到串口
CountBase+=senddata.length(); ui->label_sendvalue->setNum(CountBase);
}
void Widget::int_adjust(QByteArray &str,qint8 startcount)
{
qint8 temp1;
qint8 temp2;
temp1 = str[startcount];
temp2 = str[startcount+];
str[startcount] = str[startcount+];
str[startcount+] = str[startcount+];
str[startcount+] =temp2;
str[startcount+] =temp1;
}
void Widget::short_adjust(QByteArray &str,qint8 startcount)
{
qint8 temp1;
temp1 = str[startcount];
str[startcount] = str[startcount+];
str[startcount+] = temp1;
} void Widget::StringToHex(QString str, QByteArray &senddata)
{ int hexdata,lowhexdata; int hexdatalen = ; int len = str.length(); senddata.resize(len/); char lstr,hstr; for(int i=; i<len; )
{
//char lstr,
hstr=str[i].toLatin1();
if(hstr == ' ')
{
i++;
continue;
}
i++;
if(i >= len)
break;
lstr = str[i].toLatin1();
hexdata = ConvertHexChar(hstr);
lowhexdata = ConvertHexChar(lstr);
if((hexdata == ) || (lowhexdata == ))
break;
else
hexdata = hexdata*+lowhexdata;
i++;
senddata[hexdatalen] = (char)hexdata;
hexdatalen++;
}
senddata.resize(hexdatalen);
} char Widget::ConvertHexChar(char ch)
{
if((ch >= '') && (ch <= ''))
return ch-0x30;
else if((ch >= 'A') && (ch <= 'F'))
return ch-'A'+;
else if((ch >= 'a') && (ch <= 'f'))
return ch-'a'+;
else return (-); } void Widget::on_pushButton_clicked()
{
ui->textBrowser->clear();
CountBase = ;
ui->label_sendvalue->setNum();
recvCount = ;
ui->label_recvvalue->setNum();
}
void Widget::cycletime_handle(void)
{
on_send_clicked();
}
void Widget::on_lineEdit_duiqi_editingFinished()
{
SENDNUMSIZE = ui->lineEdit_duiqi->text().toInt();
} void Widget::on_checkBox_TIMER_stateChanged(int arg1)
{
if(ui->checkBox_TIMER->isChecked())
{
cycletime->start();
QObject::connect(cycletime,&QTimer::timeout,this,&Widget::cycletime_handle);
}
else
{
cycletime->stop();
} }

all code

qt实现串口通讯的更多相关文章

  1. 树莓派中QT实现串口通讯

    树莓派中QT实现串口通讯 开发平台为QT 此博客QT使用的为WiringPi驱动 我使用的串口调试助手为 cutecom 先简单说一些开发过程中需要注意的问题 Linux 下设备为 tty ,对应在 ...

  2. QSerialPort-Qt串口通讯

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QSerialPort-Qt串口通讯     本文地址:http://techieliang. ...

  3. 嵌入式Linux学习笔记(六) 上位机QT界面实现和串口通讯实现

    目录 (1).参考资料 (2).QT界面布局实现 (3).数据和操作逻辑 在上一章我们实现了下位机的协议制定,并通过串口通讯工具完成了对设备内外设(LED)的状态修改,下面就要进行上位机软件的实现了( ...

  4. Qt之先用了再说系列-串口通讯(单串口单线程)

    QT 串口通讯(单串口单线程) 串口通讯在我们写程序的时候或多或少会用到,借此在这记录一下QT是如何使用串口来通讯的.本次先侃侃在单线程下使用1个串口来通讯过程.好了,废话不多说,直接看步骤,我们的宗 ...

  5. Qt实现串口通信总结

    Qt实现串口通信总结 注意: Qt5发布之前,Qt实现串口通信一般是采用第三方类库qextserialport.Qt5发布后自带了QtSerialPort 能够支持串口通信. 1.Qextserial ...

  6. Qt 编写串口调试助手

    一.成品图展示 成品图如下所示: 二.串口通讯步骤 1.在工程文件(.pro)中添加串口通信相关运行库:QT += serialport 2.在头文件中添加: #include <QSerial ...

  7. C#串口通讯实例

    本文参考<C#网络通信程序设计>(张晓明  编著) 程序界面如下图: 参数设置界面代码如下: using System; using System.Collections.Generic; ...

  8. delphi之动态库调用和串口通讯

    串口通讯: Spcomm 控件属性: CommName  :表示COM1,COM2等串口的名字: BaudRate:设定波特率9600,4800等 StartComm StopComm 函数Write ...

  9. 用SPCOMM 在 Delphi中实现串口通讯 转

      用Delphi 实现串口通讯,常用的几种方法为:使用控件如MSCOMM和SPCOMM,使用API函数或者在Delphi 中调用其它串口通讯程序.利用API编写串口通信程序较为复杂,需要掌握大量通信 ...

随机推荐

  1. Hibernate 框架简单解说

  2. 跟我学SpringCloud | 第十八篇:微服务 Docker 化之基础环境

    1. 容器化 Docker 的横空出世,给了容器技术带来了质的飞跃,Docker 标准化了服务的基础设施,统一了应用的打包分发,部署以及操作系统相关类库等,解决了测试生产部署时环境差异的问题.对于运维 ...

  3. [Algorithm] Heap & Priority queue

    这里只是简单的了解,具体内容详见推荐的原链接 注意堆和树的区别 堆就是优先级队列的实现形式 堆排序 排序过程 Ref: 排序算法之堆排序(Heapsort)解析 第一步(构造初始堆): {7, 5, ...

  4. 网络编程之多线程——GIL全局解释器锁

    网络编程之多线程--GIL全局解释器锁 一.引子 定义: In CPython, the global interpreter lock, or GIL, is a mutex that preven ...

  5. Scrapy项目 - 实现腾讯网站社会招聘信息爬取的爬虫设计

    通过使Scrapy框架,进行数据挖掘和对web站点页面提取结构化数据,掌握如何使用Twisted异步网络框架来处理网络通讯的问题,可以加快我们的下载速度,也可深入接触各种中间件接口,灵活的完成各种需求 ...

  6. ASP.NET 服务端接收Multipart/form-data文件

    在网络编程过程中需要向服务器上传文件. Multipart/form-data是上传文件的一种方式. /// <summary> /// 上传工程文件 /// </summary&g ...

  7. Spring Boot 2.x基础教程:JSR-303实现请求参数校验

    请求参数的校验是很多新手开发非常容易犯错,或存在较多改进点的常见场景.比较常见的问题主要表现在以下几个方面: 仅依靠前端框架解决参数校验,缺失服务端的校验.这种情况常见于需要同时开发前后端的时候,虽然 ...

  8. 从零开始入门 K8s | 应用存储和持久化数据卷:核心知识

    作者 | 至天 阿里巴巴高级研发工程师 一.Volumes 介绍 Pod Volumes 首先来看一下 Pod Volumes 的使用场景: 场景一:如果 pod 中的某一个容器在运行时异常退出,被 ...

  9. Mysql高手系列 - 第19篇:mysql游标详解,此技能可用于救火

    Mysql系列的目标是:通过这个系列从入门到全面掌握一个高级开发所需要的全部技能. 这是Mysql系列第19篇. 环境:mysql5.7.25,cmd命令中进行演示. 代码中被[]包含的表示可选,|符 ...

  10. centos7.x 部署主、从DNS服务器

    1.准备 例:两台192.168.219.146(主), 192.168.219.147(从), 域名www.panyangduola.com 主.从DNS服务器均需要安装bind.bind-chro ...