摘要:上位机软件程序通过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

最新文章

  1. win7快捷键
  2. byobu相关操作
  3. js 遇到问题
  4. BZOJ 2002 [Hnoi2010]Bounce 弹飞绵羊 ——Link-Cut Tree
  5. DNS域名解析
  6. HBase学习笔记
  7. python 列表 字典 读写文件:pickle模块的基本使用
  8. 下的生产环境was重新启动不同意,怎么做?
  9. Gink掉过的坑(一):将CCTableView导入到lua中
  10. CSS学习总结
  11. 使用Java编译思想
  12. Springboot配置文件解析器
  13. Linux动态库生成与使用指南
  14. Python数据采集分析告诉你为何上海二手房你都买不起
  15. go map的使用
  16. django错误笔记——TypeError: view must be a callable or a list/tuple in the case of include().解决办法
  17. Using promises
  18. 2018.07.08 NOIP模拟 第K小数(二分)
  19. HDU - 4420 2013icpc长春A 函数离散化 + st表
  20. Creating a Fragment: constructor vs newInstance()

热门文章

  1. MockBean 单元测试
  2. 链表实现比较高效的删除倒数第k项
  3. 关于读写APP.config文件能读却写不了的问题
  4. SpringBoot区块链之以太坊区块高度扫描(简洁版)
  5. 大白话讲解 BitSet
  6. tomcat设定shared lib共享同样的jar
  7. .Net Core 商城微服务项目系列(十一):MQ消费端独立为Window服务+消息处理服务
  8. Oracle 的 rownum 问题
  9. 快学Scala 第九课 (伴生对象和枚举)
  10. Laravel Entrust 权限管理扩展包的使用笔记