串口通信类似于udp通信,是无连接的,所以也要考虑编写心跳等协议
实际开发中根据给定的数据协议和给定的显示功能进行开发,制定相应的数据解析
这里我用通用的串口通信讲解如何快速搭建一个显示单片机或者其他计算机的各种信息
1.设计协议包的操作类
#ifndef AGREEMENT_H
#define AGREEMENT_H
#include <QObject>
#include <qbytearray.h>
#include <QMap>
#include <QVector>
namespace 协议名{ //可用json读取进行配置
enum Function {
WAVE =0x01
....
};
}
#define Q_NOTZERO(x) ((x!=0))
typedef struct SendPage{ //发送包
qint16 initial1 = 0x55;//字头
qint16 initial2 = 0xbe;//字头
qint16 packetlength = 0x0c;//包长
qint16 expressCommand = 0x0;//表示命令
qint16 function = 0x0;//功能
....
qint16 checkH;//效验H
qint16 checkL;//效验L
public:
QString number(qint16 number);//QString::number
void setExpressCommand(qint16 expressCommand) {
this->expressCommand = expressCommand;
}
void setFunction(qint16 function) {
this->function = function;
}
void setData(QVariant data);
SendPage();
void commit( QByteArray & byte) {//根据校验方式进行校验 同样可用使用json配置
checkH = 0;
switch (checkL)
{
case 方法1:
case 方法2:
break;
default:
break;
}
QString _str = QString(number(initial1) + ' '+
number(initial2) + ' '+
number(packetlength) + ' ' +
number(expressCommand) + ' ' +
number(function) + ' ' +
......
number(fill[0]) + ' ' +
number(checkH) + ' ' +
number(checkL));
SerialPort::String2Hex(_str, byte); //转化为16进制
}
void setCheckL(qint16 checkL) {
this->checkL = checkL;
}
void setFill(QVector<qint16> data){
for(int i=0;i<6 && i<data.length();++i)
this->fill[i]=data.at(i);
}
qint16 getInitial2() const;
void setInitial2(const qint16 &value);
}SendPage;
namespace PageHelp //xx为默认校验
{
void set协议1(QByteArray & byte, qint16 type, QVariant data, qint16 expressCommand, qint16 checkL = xx);
void set协议2(QByteArray &byte,qint16 type, QVariant data, qint16 expressCommand , qint16 checkL = xx);
}
class Agreement :public QObject
{
Q_OBJECT
public:
explicit Agreement(){
}
explicit Agreement(QVector<qint16> &vector,QObject *parent = nullptr):QObject(parent) {
m_vector = vector;
}
explicit Agreement(QObject *parent = nullptr):QObject(parent) {
}
QVector<qint16> values() const;
void setVector(const QVector<qint16> &values);
void append(qint16 value);
Agreement(const Agreement & agreement){
this->setVector(agreement.values());
}
qint16 indexOf(quint16 index){
if(index>=this->m_vector.length() || index<0){
return 0;
}
return m_vector[index];
}
void setList(QVector<qint16> & list);
void set(qint16 index,QVariant value);
signals:
void setupSuccess(qint16 function,qint16 value);
private:
QVector<qint16> m_vector;
};
class 协议1:public Agreement
{
Q_OBJECT
public:
void onSet(QVector<qint16> data);
qint16 value(AMMONOX::Function function);
协议1命名空间::Function key(qint16 value);
协议1(QVector<qint16> &vector,QObject *parent = nullptr);
signals:
void sendPage(QByteArray page);
private:
QMap<协议1命名空间::Function,qint16> m_mapFunction;
};
class 协议2:public Agreement
{
Q_OBJECT
public:
void onSet(QVector<qint16> data);
协议2命名空间::Function key(qint16 value);
qint16 value(协议2::Function function);
协议2(QVector<qint16> &vector,QObject *parent = nullptr);
signals:
void sendPage(QByteArray page);
private:
QMap<协议2命名空间::Function,qint16> m_mapFunction;
};
#endif //
2.设计串口消息接受发送类
实际开发过程中,PC性能一般大于下位机所有接受并不是一次就接受所有数据,而是和udp一样分片发送,所以再收发的过程中注意收发频率.