1.功能需求
通过QT,编写一个库。库的作用是上层直接调用库的函数,并且传参。库函数根据下位机的通信协议,将数据进行封装。通过串口将数据发送给下位机。下位机获得数据后,会对数据进行解析,再通过串口应答一帧数据。库函数再对数据进行解析,提取上层需要的数据,以返回值的形式传递给上层。
2.实现步骤
1.初始化并打开串口
2.根据下位机的通信协议,编写相对应的函数对数据进行封装。
3.库函数接收到一帧数据后,提取有效数据并返回给上层。
3.代码实现
3.1打开串口
/* 全局变量 */
QSerialPort *serial;
bool OpenCOM(const QString &name) { serial = new QSerialPort(); //port name serial->setPortName(name); //open serial->open(QIODevice::ReadWrite); if(serial->isOpen()) { serial->setBaudRate(115200); serial->setDataBits(QSerialPort::Data8); serial->setStopBits(QSerialPort::OneStop); serial->setFlowControl(QSerialPort::NoFlowControl); } else { return false; } return true; }
以上的程序就是实例化一个QSerialPort类的对象。上位机根据实际串口是COM几,以传参的形式传递进来。要先打开串口再对串口进行配置。
其中isOpen()用来检测设备是否打开。
3.2 关闭串口
void CloseCom(void) { serial->clear(); serial->close(); serial->deleteLater(); //因为之前new了serial这个对象,所以在关闭串口的时候要销毁这个对象。不然会造成内存泄露 }
clear()用来清除输入输出缓冲区里面的数据。调用这个函数之前,串口必须已经被打开。
close()用来关闭串口设备。跟open相对应。
由于我们之前使用new创建了一个对象,会调用构造函数。就必须调用delete来销毁这个对象。这个是C++的规则。QT作为C++的库,也是一样的道理。但是QT可以不用delete,还可以使用deleteLater。从字面上的意思就是后面再删除。 (delete 和 new 必须 配对使用(一 一对应):delete少了,则内存泄露,多了麻烦更大。)
deleteLater()并没有将对象立即销毁,而是向主消息循环发送了一个event,下一次主消息循环收到这个event之后才会销毁对象。 这样做的好处是可以在这些延迟删除的时间内完成一些操作,坏处就是内存释放会不及时。
3.3数据封装
void Open_Door(int addr, int which_door) { QByteArray tx_buf; tx_buf.append(0xAA); tx_buf.append(static_cast<char>(addr)); tx_buf.append(0x01); tx_buf.append(static_cast<char>(which_door)); tx_buf.append(zero); tx_buf.append(zero); tx_buf.append(zero); tx_buf.append(0xFF); SendCmd(tx_buf); }
3.4 通过串口下发数据
QByteArray SendCmd(QByteArray cmd) { serial->write(cmd); serial->waitForBytesWritten(50000); QByteArray data; while(serial->waitForReadyRead(5000)) { data = serial->readAll(); //读取串口数据 if(!data.isEmpty()) { //读到数据了,退出循环 return data; } } }
<QT学习>使用串口类QSerialPort类进行数据接收和发送并封装成库,当做中间件
原文:https://www.cnblogs.com/zhuangquan/p/12795729.html