qt实现串口通讯
摘要:上位机软件程序通过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实现串口通讯的更多相关文章
- 树莓派中QT实现串口通讯
树莓派中QT实现串口通讯 开发平台为QT 此博客QT使用的为WiringPi驱动 我使用的串口调试助手为 cutecom 先简单说一些开发过程中需要注意的问题 Linux 下设备为 tty ,对应在 ...
- QSerialPort-Qt串口通讯
版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QSerialPort-Qt串口通讯 本文地址:http://techieliang. ...
- 嵌入式Linux学习笔记(六) 上位机QT界面实现和串口通讯实现
目录 (1).参考资料 (2).QT界面布局实现 (3).数据和操作逻辑 在上一章我们实现了下位机的协议制定,并通过串口通讯工具完成了对设备内外设(LED)的状态修改,下面就要进行上位机软件的实现了( ...
- Qt之先用了再说系列-串口通讯(单串口单线程)
QT 串口通讯(单串口单线程) 串口通讯在我们写程序的时候或多或少会用到,借此在这记录一下QT是如何使用串口来通讯的.本次先侃侃在单线程下使用1个串口来通讯过程.好了,废话不多说,直接看步骤,我们的宗 ...
- Qt实现串口通信总结
Qt实现串口通信总结 注意: Qt5发布之前,Qt实现串口通信一般是采用第三方类库qextserialport.Qt5发布后自带了QtSerialPort 能够支持串口通信. 1.Qextserial ...
- Qt 编写串口调试助手
一.成品图展示 成品图如下所示: 二.串口通讯步骤 1.在工程文件(.pro)中添加串口通信相关运行库:QT += serialport 2.在头文件中添加: #include <QSerial ...
- C#串口通讯实例
本文参考<C#网络通信程序设计>(张晓明 编著) 程序界面如下图: 参数设置界面代码如下: using System; using System.Collections.Generic; ...
- delphi之动态库调用和串口通讯
串口通讯: Spcomm 控件属性: CommName :表示COM1,COM2等串口的名字: BaudRate:设定波特率9600,4800等 StartComm StopComm 函数Write ...
- 用SPCOMM 在 Delphi中实现串口通讯 转
用Delphi 实现串口通讯,常用的几种方法为:使用控件如MSCOMM和SPCOMM,使用API函数或者在Delphi 中调用其它串口通讯程序.利用API编写串口通信程序较为复杂,需要掌握大量通信 ...
随机推荐
- HTML 框架导航
初次学习HTML,在www.w3school.com.cn看到了框架导航,上面的例子没有看懂所以搜了一下相应的问题,最后弄懂了怎么实现同一界面下的框架导航. 首先是www.w3school.com.c ...
- 前端 页面加载完成事件 - onload,五种写法
在js和jquery使用中,经常使用到页面加载完成后执行某一方法.通过整理,大概是五种方式(其中有的只是书写方式不一样). 1:使用jQuery的$(function){}; 2:使用jquery的$ ...
- 世界地图展开图,来自 Simon's World Map
Simon's World Map 软件下载地址:https://www.dit-dit-dit.com/Blog/PostId/42/simons-world-map
- Servlet实现用户登录
1.登录过程分析: 通过表单收集用户的数据,Servlet通过request对象获得用户提交的数据,服务器还需要从数据库中通过sql语句查询有没有表单提交的数据中的用户.有则登录成功,否则,登录失败. ...
- JS 防抖和节流
防抖和节流 在处理高频事件,类似于window的resize或者scorll,或者input输入校验等操作时.如果直接执行事件处理器,会增大浏览器的负担,严重的直接卡死,用户体验非常不好. 面对这种情 ...
- 使用T2表中的值替换T1表的值
描述:现在有两张表,T1由Key和Value两个字段,T2也有Key和Value两个字段 当T1中的Key在T2表中存在时,更新使用T2表中对用的Value 值替换T1中的VAlue update A ...
- RDDs基本操作之Transformations
逐元素Transformation map() map()接收函数,把函数应用到RDD的每个元素,返回新的RDD 举例: val lines = sc.parallelize(Array(" ...
- svn新建文件不能提交的解决方法
svn新建文件不能提交的解决方法 在当前新建文件的目录下,右键空白处: 选择Properties 找到所有有ignore字眼的属性,查看这个属性的继承目录(inherited from),入我的是cl ...
- css3不定宽高水平垂直居中
1 justify-content:center;//子元素水平居中 2 align-items:center;//子元素垂直居中 3 display:-webkit-flex; 在父级元素上面加上上 ...
- 数据分析--numpy的基本使用
一.numpy概述 NumPy是高性能科学计算和数据分析的基础包.它是pandas等其他各种工具的基础. NumPy的主要功能: ndarray,一个多维数组结构,高效且节省空间 无需循环对整组数据进 ...