1. 程式人生 > 其它 >[轉]qt實現串列埠通訊 - 純潔de小學生 - 部落格園

[轉]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部落格文章一鍵轉載外掛