[转]qt实现串口通讯 - 纯洁de小学生 - 博客园

 

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

 

 主要实现的功能:

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

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

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

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

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

6.实时显示时间

 

代码实现:

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

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

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

 

注意:

1 QString("%1").arg(ui>lineEdit_S_num>text().toInt(),8,16,QChar('0'))2 3 第一个参数 : 将Qstring转换为int型4 第二个参数 : 需要将几个字符串转换成十六进制的,5 如char型   :需要两个字符6    short型  : 需要四个字符7    int/long : 需要八个字符8 第三个参数:  转换为多少进制9 第四个参数:  不足位数的用0补齐
 1 //QByteArray里面的数据按照对应的通讯协议进行调整 2 void Widget::int_adjust(QByteArray  &str,qint8 startcount) 3 { 4     qint8 temp1; 5     qint8 temp2; 6     temp1 = str[startcount]; 7     temp2 = str[startcount+1]; 8     str[startcount] = str[startcount+3]; 9     str[startcount+1] = str[startcount+2];10     str[startcount+2] =temp2;11     str[startcount+3] =temp1;12 }13 void Widget::short_adjust(QByteArray  &str,qint8 startcount)14 {15     qint8 temp1;16     temp1 = str[startcount];17     str[startcount] = str[startcount+1];18     str[startcount+1] = temp1;19 }
 1 //字符串转成十六进制实现 2 void Widget::StringToHex(QString str, QByteArray &senddata) 3 { 4  5     int hexdata,lowhexdata; 6  7     int hexdatalen = 0; 8  9     int len = str.length();10 11     senddata.resize(len/2);12 13     char lstr,hstr;14 15     for(int i=0; i<len; )16     {17         //char lstr,18         hstr=str[i].toLatin1();19         if(hstr == ' ')20         {21             i++;22             continue;23         }24         i++;25         if(i >= len)26            break;27         lstr = str[i].toLatin1();28         hexdata = ConvertHexChar(hstr);29         lowhexdata = ConvertHexChar(lstr);30         if((hexdata == 16) || (lowhexdata == 16))31             break;32         else33             hexdata = hexdata*16+lowhexdata;34         i++;35         senddata[hexdatalen] = (char)hexdata;36         hexdatalen++;37     }38     senddata.resize(hexdatalen);39 }40 41 42 char Widget::ConvertHexChar(char ch)43 {44    if((ch >= '0') && (ch <= '9'))45             return ch-0x30;46         else if((ch >= 'A') && (ch <= 'F'))47            return ch-'A'+10;48         else if((ch >= 'a') && (ch <= 'f'))49             return ch-'a'+10;50         else return (-1);51 52 53 }

 

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

  1 #include "widget.h"  2 #include "ui_widget.h"  3 #include <QTimer>  4 #include <QDateTime>  5 #include <QMessageBox>  6 static int CountBase = 0;  7 static int SENDNUMSIZE = 20;  8 static int recvCount = 0;  9 Widget::Widget(QWidget *parent) : 10     QWidget(parent), 11     ui(new Ui::Widget) 12 { 13     ui->setupUi(this); 14     serial = new QSerialPort; 15     /* regester software timer*/ 16     atimer = new QTimer(); 17     atimer->setInterval(1000); 18     atimer->start(); 19  20     cycletime = new QTimer(); 21     cycletime->setInterval(ui->lineEdit_cycletime->text().toInt()); 22  23     QObject::connect(atimer,&QTimer::timeout,this,&Widget::timer_handle); 24  25         //查找可用的串口 26            foreach (const QSerialPortInfo &info,QSerialPortInfo::availablePorts()) 27            { 28                QSerialPort serial; 29                serial.setPort(info); 30                if(serial.open(QIODevice::ReadWrite)) 31                { 32                    ui->comBox->addItem(serial.portName()); 33                    serial.close(); 34                } 35            } 36            //设置波特率下拉菜单默认显示第0项 37            ui->baudBox->setCurrentIndex(0); 38            ui->baudBox->setEnabled(false); 39            ui->stopbitBox->setEnabled(false); 40            ui->databitBox->setEnabled(false); 41            ui->checkBox->setEnabled(false); 42            ui->comBox->setEnabled(false); 43 } 44  45 Widget::~Widget() 46 { 47     delete ui; 48 } 49 void Widget::timer_handle(void) 50 { 51  52     QDateTime current_date_time =QDateTime::currentDateTime(); 53     QString current_date =current_date_time.toString("yyyy.MM.dd hh:mm:ss ddd"); 54    // ui->textBrowser_date 55     ui->label_date->setText(current_date); 56  57 } 58  59 void Widget::on_pushButton_oprea_clicked() 60 { 61     if(ui->pushButton_oprea->text() == tr("串口已关闭")) 62         { 63             serial = new QSerialPort; 64             //设置串口名 65             serial->setPortName(ui->comBox->currentText()); 66             //打开串口 67             serial->open(QIODevice::ReadWrite); 68             //设置波特率 69             serial->setBaudRate(QSerialPort::Baud115200);//设置波特率为115200 70             //设置数据位数 71             switch (ui->databitBox->currentIndex()) 72             { 73             case 0: 74                 serial->setDataBits(QSerialPort::Data8);//设置数据位8 75                 break; 76             default: 77                 break; 78             } 79             //设置校验位 80             switch (ui->checkBox->currentIndex()) 81             { 82             case 0: 83                 serial->setParity(QSerialPort::NoParity); 84                 break; 85             default: 86                 break; 87             } 88             //设置停止位 89             switch (ui->stopbitBox->currentIndex()) 90             { 91             case 0: 92                 serial->setStopBits(QSerialPort::OneStop);//停止位设置为1 93                 break; 94             case 1: 95                 serial->setStopBits(QSerialPort::TwoStop); 96             default: 97                 break; 98             } 99             //设置流控制100             serial->setFlowControl(QSerialPort::NoFlowControl);//设置为无流控制101 102             //关闭设置菜单使能103             ui->baudBox->setEnabled(true);104             ui->stopbitBox->setEnabled(true);105             ui->databitBox->setEnabled(true);106             ui->checkBox->setEnabled(true);107             ui->comBox->setEnabled(true);108             ui->pushButton_oprea->setText(tr("串口已打开"));109 110             //连接信号槽111             QObject::connect(serial,&QSerialPort::readyRead,this,&Widget::ReadData);112         }113         else114         {115             cycletime->stop();116             //关闭串口117             serial->clear();118             serial->close();119             serial->deleteLater();120 121             //恢复设置使能122             ui->baudBox->setEnabled(false);123             ui->stopbitBox->setEnabled(false);124             ui->databitBox->setEnabled(false);125             ui->checkBox->setEnabled(false);126             ui->comBox->setEnabled(false);127             ui->pushButton_oprea->setText(tr("串口已关闭"));128         }129 }130 //读取接收到的信息131 void Widget::ReadData()132 {133      QByteArray temp;134     if(ui->HEX_SHOW->isChecked())135     {136        SENDNUMSIZE = ui->lineEdit_duiqi->text().toInt();137        temp = serial->readAll();138         QDataStream out(&temp,QIODevice::ReadWrite);    //将字节数组读入139             while(!out.atEnd())140             {141                 qint8 outChar = 0;142                 static qint8 datacount = 1;143                 recvCount++;144                 out>>outChar;   //每字节填充一次,直到结束145                 datacount++;146                 //十六进制的转换147                 QString str = QString(" %1").arg(outChar&0xFF,2,16,QLatin1Char('0'));148                 ui->textBrowser->insertPlainText(str);149                 ui->label_recvvalue->setNum(recvCount);150                 if(SENDNUMSIZE+2 == datacount)151                 {152                     datacount = 1;153                     ui->textBrowser->insertPlainText("\n");154                      ui->textBrowser->moveCursor(QTextCursor::End);155                 }156             }157     }158     else159     {160 161         temp += serial->readAll();162         if(!temp.isEmpty())163         {164             ui->textBrowser->append(temp);165             ui->textBrowser->moveCursor(QTextCursor::End);166         }167         temp.clear();168     }169 170 }171  short Widget::checksum(QByteArray ba)172 {173     short i = 0,sumValue = 0;174 175     for(i=2;i<(ba.length());i++)176     {177         sumValue+=ba.at(i);178     }179     return sumValue;180 }181 182 void Widget::on_send_clicked()183 {184     short checkValue = 0;185     QString str;186     QByteArray senddata;187     if(ui->pushButton_oprea->text() == tr("串口已关闭"))188     {189         QMessageBox::information(this, "warning", "串口没打开", QMessageBox::Yes);190 191     }192     if(ui->radio_dash->isChecked())193     {194          str =  ui->lineEdit_head->text()195                 + QString("%1").arg(ui->lineEdit_infopage->text().toShort(),2,16,QChar('0'))196                 + QString("%1").arg(ui->lineEdit_menu->text().toShort(),2,16,QChar('0'))197                 + QString("%1").arg(ui->lineEdit_speed->text().toShort(),2,16,QChar('0'))198                 + QString("%1").arg(ui->lineEdit_FP->text().toShort(),2,16,QChar('0'))199                 + QString("%1").arg(ui->lineEdit_BP->text().toShort(),2,16,QChar('0'))200                 + QString("%1").arg(ui->lineEdit_gear->text().toShort(),2,16,QChar('0'))201                 + QString("%1").arg(ui->lineEdit_hour->text().toShort(),2,16,QChar('0'))202                 + QString("%1").arg(ui->lineEdit_minute->text().toShort(),2,16,QChar('0'))203                 + QString("%1").arg(ui->lineEdit_TemP->text().toShort(),4,16,QChar('0'))//10204                 + QString("%1").arg(ui->lineEdit_trip->text().toShort(),4,16,QChar('0'))//12205                 + QString("%1").arg(ui->lineEdit_C_Trip->text().toShort(),4,16,QChar('0'))//14206                 + QString("%1").arg(ui->lineEdit_odo->text().toInt(),8,16,QChar('0'))//16207                 + QString("%1").arg(ui->lineEdit_LF_Press->text().toShort(),4,16,QChar('0'))//20208                 + QString("%1").arg(ui->lineEdit_LB_Press->text().toShort(),4,16,QChar('0'))//22209                 + QString("%1").arg(ui->lineEdit_RF_Press->text().toShort(),4,16,QChar('0'))//24210                 + QString("%1").arg(ui->lineEdit_RB_Press->text().toShort(),4,16,QChar('0'))//26211                 + QString("%1").arg(ui->lineEdit_oil_cost->text().toInt(),8,16,QChar('0'))//28212                 + QString("%1").arg(ui->lineEdit_C_oilcost->text().toShort(),2,16,QChar('0'))213                 + QString("%1").arg(ui->lineEdit_AV_oil_cost->text().toShort(),2,16,QChar('0'))214                 + QString("%1").arg(ui->lineEdit_can_warning->text().toShort(),2,16,QChar('0'))215                 + QString("%1").arg(ui->lineEdit_icon->text().toShort(),4,16,QChar('0'))//35216                 + QString("%1").arg(ui->lineEdit_backlight->text().toShort(),2,16,QChar('0'));217                  /*************** 调整short 和 init 数据类型字节发送顺序 ****************/218                  StringToHex(str,senddata);//将str字符串转换为16进制的形式219                  short_adjust(senddata,10);220                  short_adjust(senddata,12);221                  short_adjust(senddata,14);222                  int_adjust(senddata,16);223                  short_adjust(senddata,20);224                  short_adjust(senddata,22);225                  short_adjust(senddata,24);226                  short_adjust(senddata,26);227                  int_adjust(senddata,28);228                  short_adjust(senddata,35);229          }230     else{231          str =  ui->lineEdit_head->text()232                 + QString("%1").arg(ui->lineEdit_ST_Page->text().toShort(),2,16,QChar('0'))233                 + QString("%1").arg(ui->lineEdit_menu_level->text().toShort(),2,16,QChar('0'))234                 + QString("%1").arg(ui->lineEdit_cursor->text().toShort(),2,16,QChar('0'))235                 + QString("%1").arg(ui->lineEdit_C_selcet->text().toShort(),2,16,QChar('0'))236                 + QString("%1").arg(ui->lineEdit_num->text().toShort(),2,16,QChar('0'))237                 + QString("%1").arg(ui->lineEdit_S_num->text().toInt(),8,16,QChar('0'))238                 + QString("%1").arg(ui->lineEdit_S_hour->text().toShort(),2,16,QChar('0'))239                 + QString("%1").arg(ui->lineEdit_S_minute->text().toShort(),2,16,QChar('0'))240                 + QString("%1").arg(ui->lineEdit_S_year->text().toShort(),4,16,QChar('0'))241                 + QString("%1").arg(ui->lineEdit_S_month->text().toShort(),2,16,QChar('0'))242                 + QString("%1").arg(ui->lineEdit_S_day->text().toShort(),2,16,QChar('0'))243                 + QString("%1").arg(ui->lineEdit_S_backlight->text().toShort(),2,16,QChar('0'));244                  /*************** 调整short 和 init 数据类型字节发送顺序 ****************/245                  StringToHex(str,senddata);//将str字符串转换为16进制的形式246                  int_adjust(senddata,7);247                  short_adjust(senddata,13);248     }249 250 251     checkValue = checksum(senddata);252     senddata.append((char)(checkValue));253     serial->write(senddata);//发送到串口254     CountBase+=senddata.length();255 256     ui->label_sendvalue->setNum(CountBase);257  }258 void Widget::int_adjust(QByteArray  &str,qint8 startcount)259 {260     qint8 temp1;261     qint8 temp2;262     temp1 = str[startcount];263     temp2 = str[startcount+1];264     str[startcount] = str[startcount+3];265     str[startcount+1] = str[startcount+2];266     str[startcount+2] =temp2;267     str[startcount+3] =temp1;268 }269 void Widget::short_adjust(QByteArray  &str,qint8 startcount)270 {271     qint8 temp1;272     temp1 = str[startcount];273     str[startcount] = str[startcount+1];274     str[startcount+1] = temp1;275 }276 277 void Widget::StringToHex(QString str, QByteArray &senddata)278 {279 280     int hexdata,lowhexdata;281 282     int hexdatalen = 0;283 284     int len = str.length();285 286     senddata.resize(len/2);287 288     char lstr,hstr;289 290     for(int i=0; i<len; )291     {292         //char lstr,293         hstr=str[i].toLatin1();294         if(hstr == ' ')295         {296             i++;297             continue;298         }299         i++;300         if(i >= len)301            break;302         lstr = str[i].toLatin1();303         hexdata = ConvertHexChar(hstr);304         lowhexdata = ConvertHexChar(lstr);305         if((hexdata == 16) || (lowhexdata == 16))306             break;307         else308             hexdata = hexdata*16+lowhexdata;309         i++;310         senddata[hexdatalen] = (char)hexdata;311         hexdatalen++;312     }313     senddata.resize(hexdatalen);314 }315 316 317 char Widget::ConvertHexChar(char ch)318 {319    if((ch >= '0') && (ch <= '9'))320             return ch-0x30;321         else if((ch >= 'A') && (ch <= 'F'))322            return ch-'A'+10;323         else if((ch >= 'a') && (ch <= 'f'))324             return ch-'a'+10;325         else return (-1);326 327 328 }329 330 331 void Widget::on_pushButton_clicked()332 {333     ui->textBrowser->clear();334     CountBase = 0;335     ui->label_sendvalue->setNum(0);336     recvCount = 0;337      ui->label_recvvalue->setNum(0);338 }339 void  Widget::cycletime_handle(void)340 {341     on_send_clicked();342 }343 void Widget::on_lineEdit_duiqi_editingFinished()344 {345     SENDNUMSIZE = ui->lineEdit_duiqi->text().toInt();346 }347 348 void Widget::on_checkBox_TIMER_stateChanged(int arg1)349 {350     if(ui->checkBox_TIMER->isChecked())351     {352         cycletime->start();353         QObject::connect(cycletime,&QTimer::timeout,this,&Widget::cycletime_handle);354     }355     else356     {357         cycletime->stop();358     }359 360 }
all code

 


---------------------
作者:纯洁de小学生
来源:CNBLOGS
原文:https://www.cnblogs.com/st-home/p/10929020.html
版权声明:本文为作者原创文章,转载请附上博文链接!
内容解析By:CSDN,CNBLOG博客文章一键转载插件

posted @ 2021-09-15 18:18  decrement  阅读(143)  评论(0编辑  收藏  举报