1. 程式人生 > >QT串列埠通訊(1)

QT串列埠通訊(1)

       最近幫老師做的專案中使用到了QT串列埠,然後首先百度了一下,發現網上的QT串列埠程式碼都是同一個版本。而且沒有公開原始碼,遂自己寫了個簡單的串列埠通訊程式碼,並將它公佈出來,一方面供有需要的人蔘考,另一方面記錄下來,也可以防止自己忘記了。
       本專案沒有用到QT自帶的串列埠通訊模組,使用了第三方庫qextserialport,這個庫基本已經滿足了串列埠所有的功能,而且上手也快。好了。廢話不多說了,先來張效果圖吧。

50

       這是整體效果圖,主要實現的是開發板和下位機通訊,上位機通過串列埠傳送指令給下位機,下位機再執行相應的操作。本文主要講講串列埠通訊的部分吧。
       簡單來說,串列埠通訊分為三部分:1:設定埠號和波特率等等,資料位和校驗之類的一般的可以提前設定好,再程式碼中同樣也可以設定。2:將資料寫入串列埠,這個時候就要分發送的是多少進位制的資料了,雖然計算機在實際儲存時是不區分進位制的。3:讀串列埠資料,將串列埠接收到的資料讀出來,進行下一步處理。後面我會把全部程式碼貼出來,程式碼經過除錯已經可以運行了。本文中具體的控制元件佈局我就不講了,我只講講一些核心的程式碼,大家感興趣的話可以自己去跑跑我的程式碼,程式碼中註釋非常詳細,每一行都有註釋,看起來不費勁。

設定埠和波特率

 //開啟串列埠,波特率和埠號可以通過下拉選單進行選擇
void uwiCMonitorPC::on_openMyComBtn_clicked()
{
    QString portName = portNameComboBox->currentText(); //獲取串列埠名
    myCom = new Win_QextSerialPort(portName,QextSerialBase::EventDriven);
    //定義串列埠物件,並傳遞引數,在建構函式裡對其進行初始化
    myCom ->open(QIODevice::ReadWrite); //開啟串列埠
    if(baudRateComboBox->currentText()==tr("38400")) //根據下拉選單中內容對串列埠進行設定
    //設定波特率
    myCom->setBaudRate(BAUD38400);
    else if(baudRateComboBox->currentText()==tr("115200"))
    myCom->setBaudRate(BAUD115200);
    //設定資料位
    myCom->setDataBits(DATA_8);
    //設定奇偶校驗
    myCom->setParity(PAR_NONE);
    //設定停止位 
    myCom->setStopBits(STOP_1);    
    myCom->setFlowControl(FLOW_OFF);  //設定資料流控制,我們使用無資料流控制的預設設定
    myCom->setTimeout(500);  //設定延時
    connect(myCom,SIGNAL(readyRead()),this,SLOT(readMyCom()));
    //訊號和槽函式關聯,當串列埠緩衝區有資料時,進行讀串列埠操作
    openMyComBtn->setEnabled(false); //開啟串列埠後“開啟串列埠”按鈕不可用
    closeMyComBtn->setEnabled(true); //開啟串列埠後“關閉串列埠”按鈕可用
    sendMsgBtn->setEnabled(true); //開啟串列埠後“傳送資料”按鈕可用
	O2U1->setEnabled(true);
	O2U2->setEnabled(true);
	O2U3->setEnabled(true);
    baudRateComboBox->setEnabled(false); //設定各個組合框不可用
    portNameComboBox->setEnabled(false);
}

    在埠設定和波特率配置中,主要用到的控制元件有QComboBox,可以實現下拉選單功能,還沒用過這個控制元件的小夥伴可以自行百度下,很簡單的啦。

寫串列埠資料

//傳送訊息
void uwiCMonitorPC::on_sendMsgBtn_clicked()
{ 
if(O2U1->isChecked()||O2U2->isChecked()||O2U3->isChecked())//判斷選擇的是那種功能
{
	QString num;
	if(O2U1->isChecked())//配置查詢
	{
	  int table[20]={0x2e,0x2d,0x3d,0x3e,0x00,0x0d,0x01,0x00,0x00,0x00,0x00};
	  int *p=table;
	  int wCRC =CRC16(p,11);
	  table[11]=wCRC>>8;
	  table[12]=wCRC&0x00ff;
	  for(int i=0;i<13;i++)
		num+=table[i];
	 }	
	else if(O2U2->isChecked())//地址配置
	{
      int table[20]={0x2e,0x2d,0x3d,0x3e,0x00,0x11,0x02,0x00,0x00,0x00,0x00,0x00,0x0c,0x01,0x02};
	  table[11]=edit1->text().toInt();
	  int *p=table;
	  int wCRC =CRC16(p,15);
	  table[15]=wCRC>>8;
	  table[16]=wCRC&0x00ff;
	  for(int i=0;i<17;i++)
		num+=table[i];
	}
	else if(O2U3->isChecked())//功能配置
	{
       int table[20]={0x2e,0x2d,0x3d,0x3e,0x00,0x0e,0x03,0x00,0x00,0x00};
	   if(device->currentText()==tr("投料機"))           table[10]=0x01;
	   else if(device->currentText()==tr("增氧泵"))      table[10]=0x02;
	   else if(device->currentText()==tr("三合一"))      table[10]=0x03;
	   else if(device->currentText()==tr("氨  氮"))      table[10]=0x04;
	   else if(device->currentText()==tr("氣象站"))      table[10]=0x05;
	   else if(device->currentText()==tr("三合一和氨氮")) table[10]=0x06;
	   else                                             table[10]=0x07;
	   table[11]=edit5->text().toInt();
	   int *p=table;
	   int wCRC =CRC16(p,12);
	   table[12]=wCRC>>8;
	   table[13]=wCRC&0x00ff;
	   for(int i=0;i<14;i++)
		num+=table[i];
	 
	}
	QByteArray outData=num.toAscii();//將16進位制數轉化為可以傳送的QByteArray 資料
    myCom->write(outData);//將資料寫入串列埠
}

    資料格式轉換真心累啊,我在後面中會給大家介紹我在資料格式轉換中遇到的坑,大家可以參考,寫入資料部分,其實最主要的控制元件就是一個lineedit,也即文字框,將要傳送的資料輸入到文字框,然後讀取文字框中的內容即可 table[11]=edit1->text().toInt();將edit1中輸入的內容轉換成10進位制,並存貯在table中,然後就可以寫入串列埠了,當然怎麼寫入的我們就可以不用管了,你只要負責把資料準備好就可以了,直接送到函式 myCom->write(outData);中就可以了,呼叫了第三方庫,很多步驟我們都省了。

讀串列埠資料

if (myCom->bytesAvailable()<=0)
{return;}//如果沒有收到資料就返回
	Sleep(100);//延時100ms確保資料可以一次讀出
    QByteArray temp = myCom->readAll();//得到全部資料
	QString tempDataHex=uwiCMonitorPC::ByteArrayToHexStr(temp);//位元組陣列變為字串
    textBrowser->insertPlainText(tempDataHex+"\n");	//返回資料顯示

    讀串列埠部分也就是一個函式 myCom->readAll();讀之前需要延時一段時間以確保串列埠資料可以一次接受完成。將得到的資料轉換為QString型別,然後就可以送進去顯示了。

    串列埠通訊主要的核心部分大概就是這三部分了,呼叫第三方庫,主要難點就在於資料型別轉換,因為串列埠傳送和文字框接受顯示的資料型別是不一樣的,還有傳送16進位制資料時也得進行資料型別轉換。反正我在格式轉換上面花了很多時間,我在下篇部落格中會貼出各種格式轉換的程式碼,供大家參考。
    對串列埠通訊原理不瞭解的可以自己先去網上自行了解下原理,等了解原理後再寫串列埠程式就遊潤有餘了,整個程式碼我已經打包好了,只要用cmake編譯下就可以運行了(所有的控制元件都是用程式碼實現的,沒有基於qt caeater,控制元件不是拖拽來的,當然為了學習,為了提高程式碼能力,我建議不拖拽,如果在實際專案中那就不一樣了),我過會會將所有程式碼上傳,有問題的歡迎留言討論。


關於我自己

  • 一個正派但不正經的程式設計師

  • 18年計算機專業碩士畢業生,騰訊SNG部門實習生,現加盟快手科技 ,後端研發工程師一枚

  • 喜歡技術,喜歡網際網路

  • 民遙控 ,趙雷、陳粒、宋冬野

  • 公眾號:程式設計美學,時不時寫篇文章,偶爾數羊,其實說到底,只是想和你聊聊
    在這裡插入圖片描述