Qt开发串口

首先,在工程文件里面,

QT += serialport

在头文件里面,

#include <QSerialPort>

1、配置打开串口

QSerialPort* myserial = new QSerialPort();
this->myserial->setPortName("COM1");//待打开的串口号
this->myserial->setBaudRate(9600,QSerialPort::AllDirections);//设置波特率;QSerialPort::AllDirections:双工
this->myserial->setDataBits(QSerialPort::Data8);//数据位
this->myserial->setParity(QSerialPort::NoParity);//校验位
this->myserial->setStopBits(QSerialPort::OneStop);//停止位
this->myserial->setFlowControl(QSerialPort::NoFlowControl);//流控制
this->myserial->open(QIODevice::ReadWrite);//打开串口

 

 2、发送数据

char test[5] = {0x01,0x02,0x03,0x04,0x05};

myserial.write(test);//发送

3、接收数据

定义一个函数作为槽函数,当接收缓冲区有数据的时候回调此函数。

void ReadBuf()
{
  QByteArray dataArray;
  dataArray = myserial->readAll();//读取数据
  if(!dataArray.isEmpty())
  {
    QString str;
    str = dataArray.toHex();//把数据直接转化为16进制的字符串形式
    ui->textEdit->setText(str);
  }
}

 

 此外,在打开串口函数里面关联信号与槽。已知,当接收缓冲区有数据的时候,串口对象会发送readyRead信号。

QObject::connect(myserial,&QSerialPort::readyRead,this,&MainWindow::ReadBuf);

4、关闭串口

this->myserial->close();

备注一、自动获取可用串口号,并设置在QComboBox中

1、需要包含头文件

#include <QSettings>

#include <qt_windows.h>

2、自定义函数

QString getcomm(int index, QString keyorvalue)
{
   HKEY hKey;
    wchar_t keyname[256]; //键名数组
    char keyvalue[256];  //键值数组
    DWORD keysize,type,valuesize;
    int indexnum;
    QString commresult;
    if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, KEY_READ, &hKey) != 0)
    {
        QString error="Cannot open regedit!";
        return error;
    }
    QString keymessage;//键名
    QString message;
    QString valuemessage;//键值
    indexnum = index;//要读取键值的索引号
    keysize = sizeof(keyname);
    valuesize = sizeof(keyvalue);
    if (RegEnumValue(hKey, indexnum, keyname, &keysize, 0, &type, (BYTE*)keyvalue, &valuesize) == 0)
    {
        for (int i=0; i<(int)keysize; i++)
        {
            message = keyname[i];
            keymessage.append(message);
        }
        for (int j=0; j<(int)valuesize; j++)
        {
            if (keyvalue[j] != 0x00)
                valuemessage.append(keyvalue[j]);
        }
        if (keyorvalue == "key")
            commresult = keymessage;
        if (keyorvalue == "value")
            commresult=valuemessage;
    }
    else
        commresult = "nokey";
    RegCloseKey(hKey);//关闭注册表
    return commresult;
}

 

3、将可用串口放在QComboBox里面

void MainWindow::InitInterface()
{
    QString path = "HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\SERIALCOMM";
    QSettings *settings = new QSettings(path, QSettings::NativeFormat);
    QStringList key = settings->allKeys();
    QStringList comlist;
    comlist.clear();
    /* 取串口名 */
    for (int i=0; i<key.size(); i++)
        comlist << getcomm(i, "value");
    ui->comboBox->addItems(comlist);
}

 


PS:
1、波特率9600意思是每秒最多传输9600/8=1200个字节;
2、如何解决粘包:(以传输ascii为例)
1)、接收数据,如果数据长度刚好为协议那么长,则直接解析
2)、如果长度不正确就把此包追加到本地变量中,然后判断根据报文头的位置把本地变量去掉报文头前面的数据(QString::mid)
3)、判断长度是否足够(并且本地变量的头是协议头),如果足够则取本地变量前n个数据进行解析,并将本地变量去掉这个包;如果不是协议头则清空此变量,再次进行循环

PS:
1、开发流程

 

2、如果编译器是MSVC,可能会报错:

无法解析的外部符号:regclosekey

 

 


posted @ 2017-04-04 13:11  朱小勇  阅读(7174)  评论(0编辑  收藏  举报