Qt 串口通信

  在Qt5之前,串口通信基本依赖于第三方库,下面是我曾接触过的串口通信类库:

名称

语言

平台

 

QextSerialPort

QT C++

Win/Linux

http://sourceforge.net/projects/qextserialport/files/

QSerialPort

QT C++

 

QT5已经集成

libserial

C++

Linux

 http://files.cnblogs.com/kyyblabla/libserial-0.5.2.gz.7z

 

  以上串口通信类库通信过程基本是一下步骤,即:打开串口 > 配置串口参数 > 收发数据。

  注意,串口参数(波特率、数据位、停止位、奇偶校验、流控等)必须在串口打开之后进行配置才有效。

  在使用串口接收数据时,会出现数据接收不完整的情况,这种情况很常见,尤其是在 QextSerialPort 和 QSerialPort 中,有一段时间我不得不怀疑是不是参数或者是硬件问题。后来发现这并不是异常,在通信中我依赖 readAll() 函数获取串口数据,但 readAll() 由 readyRead()信号触发,readyRead在串口读到起始标志时立即发送,并不一保证一定是当前所发数据的起始部分。因此串口通信双方通信前应制定好通信协议,规定好数据的起始于结尾标志,串口当读到完整的起始于结束标志之后,才认定读完一条完整的数据。

  下面分别就这三种串口通信类库进行实例代码的编写。

QextSerialPort使用小例

  QextSerialPort在Window平台下可用Win_QextSerialPort进行串口通信,下面对Win_QextSerialPort再一次封装的串口通信类SerialPort:

  头文件:serialport.h

  1 #ifndef SERIALPORT_H

  2 #define SERIALPORT_H

  3 

  4 #include <QObject>

  5 

  6 

  7 

  8 /**

  9  * @brief 串口参数

 10  */

 11 struct SerialConfig{

 12     int baudRate;        //波特率

 13     int characterSize;   //传输位

 14     int stopBits;        //停止位

 15     int parity;          //校验位 0无校验 1奇校验 2偶校验

 16     //char*serialPort[20];     //设备文件名

 17     int flowControl;     //流控

 18     long timeOut;        //超时时间

 19 };

 20 

 21 class Win_QextSerialPort;

 22 

 23 /**

 24  * @brief 串口通信类

 25  */

 26 class SerialPort : public QObject

 27 {

 28     Q_OBJECT

 29 public:

 30 

 31     explicit SerialPort(QString portName, QObject *parent = 0);

 32     //~SerialPort();

 33 

 34     /**

 35      * @brief 串口数据大发送格式

 36      */

 37     enum SerialDataType{

 38         ASCLL=0, //ascll方式

 39         HEX      //二进制方式

 40     };

 41     /**

 42      * @brief 配置串口参数

 43      * @param config

 44      */

 45     void setSerila(SerialConfig *config);

 46 

 47     /**

 48      * @brief 获取串口开启状态

 49      * @return

 50      */

 51     bool isOpend();

 52 

 53     /**

 54      * @brief 设置数据发送方式

 55      * @param type

 56      */

 57     void setSerialDataType(SerialDataType type);

 58 signals:

 59     /**

 60      * @brief 串口获取到数据

 61      */

 62     void strSerial(QString);

 63 public slots:

 64 

 65 

 66     /**

 67      * @brief  开启串口

 68      * @param  串口参数

 69      * @return 是否成功打开串口

 70      */

 71     bool openSerial(SerialConfig *config);

 72 

 73     /**

 74      * @brief 关闭串口

 75      */

 76     void closeSerial();

 77 

 78     /**

 79      * @brief 写入数据到串口,系统默认是ascll方式

 80      * @param str 待写入数据

 81      */

 82     void writeSerial(QString str);

 83 private slots:

 84     /**

 85      * @brief 读取数据

 86      */

 87     void readSerial();

 88 private:

 89     /**

 90      * @brief 基本串口通信类

 91      */

 92     Win_QextSerialPort*serial;

 93 

 94     /**

 95      * @brief 数据发送形式

 96      */

 97     SerialDataType serialDataType;

 98 

 99 

100 };

101 

102 #endif // SERIALPORT_H

  源文件:serialport.cpp

  1 #include "serialport.h"

  2 #include "serial_inc/win_qextserialport.h"

  3 

  4 #include <QDebug>

  5 

  6 SerialPort::SerialPort(QString portName,QObject *parent):QObject(parent),serialDataType(HEX)

  7 {

  8 

  9     this->serial=new Win_QextSerialPort(portName, QextSerialBase::EventDriven);

 10     connect(serial,SIGNAL(readyRead()),this,SLOT(readSerial()));

 11 

 12 }

 13 

 14 void SerialPort::setSerila(SerialConfig *config)

 15 {

 16 

 17     //波特率

 18     BaudRateType baudRate;

 19 

 20     switch (config->baudRate) {

 21     case 9600:

 22         baudRate=BAUD9600;

 23         break;

 24     case 115200:

 25         baudRate=BAUD115200;

 26         break;

 27     default:

 28         baudRate=BAUD4800;

 29         break;

 30     }

 31 

 32     //数据位

 33     DataBitsType dataBits;

 34     switch (config->characterSize) {

 35     case 7:

 36         dataBits=DATA_7;

 37         break;

 38     default:

 39         dataBits=DATA_8;

 40         break;

 41     }

 42 

 43     //停止位

 44     StopBitsType stopBits;

 45     switch (config->stopBits) {

 46     case 1:

 47         stopBits=STOP_1;

 48         break;

 49     case 2:

 50         stopBits=STOP_2;

 51         break;

 52     default:

 53         stopBits=STOP_1_5;

 54         break;

 55     }

 56 

 57     //奇偶校验

 58     ParityType parity;

 59     switch (config->parity) {

 60     case 0:

 61         parity=PAR_NONE;

 62         break;

 63     case 1:

 64         parity=PAR_ODD;

 65         break;

 66     default:

 67         parity=PAR_EVEN;

 68         break;

 69     }

 70 

 71     //数据流控

 72     FlowType flow=FLOW_OFF;

 73 

 74     serial->setBaudRate(baudRate);

 75     serial->setDataBits(dataBits);

 76     serial->setStopBits(stopBits);

 77     serial->setParity(parity);

 78     serial->setFlowControl(flow);

 79 

 80     serial->setDtr(false);

 81     serial->setRts(false);

 82 

 83 

 84 }

 85 

 86 bool SerialPort::isOpend()

 87 {

 88     return this->serial!=NULL?serial->isOpen():false;

 89 }

 90 

 91 void SerialPort::setSerialDataType(SerialPort::SerialDataType type)

 92 {

 93     this->serialDataType=type;

 94 }

 95 

 96 

 97 void SerialPort::writeSerial(QString str)

 98 {

 99 

100     if(this->serialDataType==this->ASCLL){

101         serial->write(str.toLocal8Bit());

102     }else{

103 

104         QByteArray b;

105         b=QByteArray::fromHex(str.toUtf8());

106         serial->write(b);

107     }

108 

109 }

110 

111 void SerialPort::readSerial()

112 {    

113 

114     qDebug()<<serial->bytesAvailable();

115 

116     QString str="";

117 

118     QByteArray array=serial->readAll();

119 

120     if(this->serialDataType==SerialPort::ASCLL){

121         str=QString::fromLocal8Bit(array.data());

122     }else{

123         array=array.toHex();

124         str=QString::fromUtf8(array.data());

125     }

126 

127     str=str.trimmed();

128 

129     qDebug()<<"serial get:"<<str;

130 

131     emit this->strSerial(str);

132 

133 

134 }

135 

136 

137 /**打开

138  * @brief SerialPort::openSerial

139  * @return

140  */

141 bool SerialPort::openSerial(SerialConfig*config)

142 {

143 

144     bool isOpen=serial->open(QIODevice::ReadWrite);

145 

146     qDebug()<<"isOpen:"<<isOpen;

147     //如果已经成功打开串口,则经行串口参数配置

148     //这里有一个概念:串口配置必须在串口设备成功打开后才有效!

149     if(isOpen){

150         this->setSerila(config);

151     }

152 

153     return isOpen;

154 }

155 

156 void SerialPort::closeSerial()

157 {

158     serial->close();

159 

160 }

 

QSerialPort 使用小例

  QSerialPort通信方式与 Win_QextSerialPort方式类似。

  串口初始化代码片段:

 1   QSerialPort serial=new QSerialPort(this);

 2 

 3     connect(serial, SIGNAL(readyRead()), this, SLOT(readData()));

 4 

 5     serial->setPortName("COM4");

 6     serial->setBaudRate(9600);

 7     serial->setDataBits(QSerialPort::Data8);

 8     serial->setParity(QSerialPort::NoParity);

 9     serial->setStopBits(QSerialPort::OneStop);

10     serial->setFlowControl(QSerialPort::NoFlowControl);

11     if (serial->open(QIODevice::ReadWrite)) {

12 

13         qDebug()<<"yes";

14 

15     } else {

16 

17         qDebug()<<"no";

18     }

  数据接收函数:

1 void QPort::readData()

2 {

3     QByteArray data = serial->readAll();

4     qDebug()<<data;

5    

6 }

libserial使用小例

  libserial只使用于Linux平台,下载源码后,进行编译和安装。下面是封装的串口通信类 Serial

  头文件:serial.h

 1 #ifndef SERIAL_H

 2 #define SERIAL_H

 3 

 4 #include "common.h"

 5 #include "SerialStream.h"

 6 #include "SerialStreamBuf.h"

 7 #include <QObject>

 8 

 9 using namespace std;

10 using namespace LibSerial;

11 

12 

13 typedef struct

14 {

15     int baudRate;        //!<波特率

16     int characterSize;   //!<传输位

17     int stopBits;        //!<停止位

18     int parity;          //!校验位 0无校验 1奇校验 2偶校验

19     char*serialPort; //!设备文件名

20 

21 }SerialConfig;

22 

23 

24 class Serial : public QObject

25 {

26     Q_OBJECT

27 public:

28     explicit Serial(QObject *parent = 0);

29 

30 signals:

31 

32     void message(QString msg);

33 public slots:

34     //打开串口

35     bool open(SerialConfig*config);

36     void work();

37     void close();

38     void sendMesg(QString msg);

39 private slots:

40 

41 private:

42     /**

43      * @brief 初始化串口数据

44      * @param config

45      */

46     void initSerialStream(SerialConfig*config);

47 

48     /**

49      * @brief 串口字节流

50      */

51     SerialStream serialStream;

52 

53     bool isRuning;

54 };

55 

56 #endif // SERIAL_H

  源文件:serial.cpp

  1 #include "serial.h"

  2 

  3 //数据开始标示

  4 #define SERIAL_DATA_START 2

  5 

  6 //数据结束标示

  7 #define SERIAL_DATA_END 3

  8 

  9 Serial::Serial(QObject *parent) :

 10     QObject(parent)

 11 {

 12 }

 13 

 14 bool Serial::open(SerialConfig *config){

 15 

 16 

 17     serialStream.Open(config->serialPort);

 18 

 19     if(!serialStream.IsOpen())

 20     {

 21         qDebug()<<"cannot open serial "<<config->serialPort;

 22         return false;

 23     }else{

 24 

 25         qDebug()<<"success open serial "<<config->serialPort;

 26     }

 27 

 28     initSerialStream(config);

 29 

 30     return true;

 31 

 32 }

 33 

 34 

 35 void Serial::work(){

 36 

 37     //缓存数据

 38     char *msg = new char[255];

 39     int index = 0;

 40     char next_byte ;    //串口接收到的下一个字节

 41     this->isRuning=true;

 42     forever{

 43         //

 44         if(this->isRuning==false){

 45             break;

 46         }

 47 

 48         serialStream.get( next_byte );

 49 

 50         int char_num=next_byte+0;

 51 

 52         if(char_num<30){

 53             qDebug()<<":"<<next_byte+0;

 54         }else{

 55             qDebug()<<next_byte;

 56         }

 57 

 58         if(char_num!=SERIAL_DATA_END)

 59         {

 60             if(char_num==SERIAL_DATA_START){

 61                 index=0;

 62                 continue;

 63             }

 64 

 65             msg[index] = next_byte;

 66             index++;

 67         }

 68         else

 69         {

 70             msg[index] = '\0';

 71             index = 0;

 72             qDebug("%s",msg);

 73             emit message(QString(msg).trimmed());

 74         }

 75     }

 76 }

 77 

 78 void Serial::close(){

 79 

 80     this->isRuning=false;

 81 }

 82 

 83 void Serial::sendMesg(QString msg)

 84 {

 85     msg.insert(0,2);

 86     msg.append(3);

 87 

 88     char*cmsg =msg.toUtf8().data();

 89     serialStream.write(cmsg,strlen(cmsg));

 90 

 91 }

 92 

 93 void Serial::initSerialStream(SerialConfig *config)

 94 {

 95 

 96     SerialStreamBuf::BaudRateEnum baudRate;

 97 

 98     switch (config->baudRate) {

 99     case 9600:

100         baudRate=SerialStreamBuf::BAUD_9600;

101         break;

102     case 115200:

103         baudRate=SerialStreamBuf::BAUD_115200;

104         break;

105     default:

106         baudRate=SerialStreamBuf::BAUD_4800;

107         break;

108     }

109 

110     SerialStreamBuf::CharSizeEnum characterSize;

111     switch (config->characterSize) {

112     case 7:

113         characterSize=SerialStreamBuf::CHAR_SIZE_7;

114         break;

115     default:

116         characterSize=SerialStreamBuf::CHAR_SIZE_8;

117         break;

118     }

119 

120 

121     SerialStreamBuf::ParityEnum parity;

122     switch (config->characterSize) {

123     case 0:

124         parity=SerialStreamBuf::PARITY_NONE;

125         break;

126     case 1:

127         parity=SerialStreamBuf::PARITY_ODD;

128         break;

129     default:

130         parity=SerialStreamBuf::PARITY_EVEN;

131         break;

132     }

133 

134 

135     serialStream.SetBaudRate(baudRate);

136     serialStream.SetCharSize(characterSize);

137     serialStream.SetNumOfStopBits(config->stopBits);

138     serialStream.SetParity(parity);

139 }

 

 

你可能感兴趣的:(qt)