1.1.1 添加库,添加类
首先,QT5 是自带 QSerialPort(Qt5 封装的串口类)这个类的,使用时需要在 pro 文件里面添加一行:
QT += serialport
加入下面两个文件:
#include <QSerialPort> #include <QSerialPortInfo>
QT5 中,串口通信是借助一个 QSerialPort 的对象来实现的,在设置 QSerialPort 对象对串口的名称、波特率、 数据位、校验位、停止位等参数后,方能对串口进行读写。下面,我总结了一下借助 QSerailPort 对串口进行设 置、打开、读、写和关闭的过程。
1.1.2 定义串口
QSerialPort *uart; uart = new QSerialPort(this);
1.1.3 搜索串口
//availablePorts 是返回当前系统所有能用的串口,返回值是一个容器 //QList 是容器类,在此的容器里边装的是 QSerialPortInfo QList<QSerialPortInfo> info = QSerialPortInfo::availablePorts(); for(int i=0; i<info.size(); i++){ ui->uartNameCombo->addItem(info[i].portName()); //addItem 加入数据到下拉 菜单里 }
1.1.4 设置和打开串口
void UiMain::on_openBtn_clicked() { QString uartName; QSerialPort::BaudRate baudRate; QSerialPort::DataBits dataBit; QSerialPort::StopBits stopBit; QSerialPort::Parity parityBit; //currentText 是获取当前选中的名字 uartName = ui->uartNameCombo->currentText(); //波特率 if(ui->baudrateCombo->currentText() == "9600"){ baudRate = QSerialPort::Baud9600; }else if(ui->baudrateCombo->currentText() == "115200"){ baudRate = QSerialPort::Baud115200; } //数据位 if(ui->databitCombo->currentText() == "5"){ dataBit = QSerialPort::Data5; }else if(ui->databitCombo->currentText() == "6"){ dataBit = QSerialPort::Data6; }else if(ui->databitCombo->currentText() == "7"){ dataBit = QSerialPort::Data7; }else if(ui->databitCombo->currentText() == "8"){ dataBit = QSerialPort::Data8; } //停止位 if(ui->stopbitCombo->currentText() == "1"){ stopBit = QSerialPort::OneStop; }else if(ui->stopbitCombo->currentText() == "1.5"){ stopBit = QSerialPort::OneAndHalfStop; }else if(ui->stopbitCombo->currentText() == "2"){ stopBit = QSerialPort::TwoStop; } //校验位 if(ui->parityCombo->currentIndex() == 0){ parityBit = QSerialPort::OddParity; }else if(ui->parityCombo->currentIndex() == 1){ parityBit = QSerialPort::EvenParity; }else if(ui->parityCombo->currentIndex() == 2){ parityBit = QSerialPort::NoParity; } //把参数设置到 uart 里 uart->setPortName(uartName); uart->setBaudRate(baudRate); uart->setDataBits(dataBit); uart->setStopBits(stopBit); uart->setParity(parityBit); if(!uart->open(QIODevice::ReadWrite)){ QMessageBox::critical(this, "fbi warnning", "打开失败"); }else{ QMessageBox::information(this, "提示", "打开成功"); }
1.1.5 读取数据
串口在收到数据后,会将数据存入接收缓冲区。此时,我们可以通过 readAll()函数将接收缓冲区的数据读出 来。当串口的接收缓冲区有数据时,QSerilaPort 对象会发出一个 readyRead()的信号。因此,我们可以编写一个槽 函数来读数据。
connect(uart, SIGNAL(readyRead()), this, SLOT(slotUartReadyRead()));
QString uartBuf; //假如没收完断截的数据,就会一直触发槽函数,定时器会被一直重置,不会超时 //当断截数据发完了,定时器就没人重启了,就会超时,这个时候收到的数据就是完整的数据 //也就是说收到一个字节后,20ms 内没有再次收到数据,默认为一帧数据接收完成 void UiMain::slotUartReadyRead() { timer->start(20); //重启定时器 20ms uartBuf.append(uart->readAll()); //追加写入到 uartBuf 里 } //超时了,说明数据完成一帧数据 void UiMain::slotTimeout() { timer->stop(); QByteArray ba; ba = uartBuf.toUtf8(); //QString(nRecv)不是强制转换 //QString(nRecv)是会触发 QString 的构造函数,当然 QString(int)这种构造函数是没有 的,会报错 ui->recvEdit->appendPlainText(ba); }
1.1.6 发送数据
使用write函数便可以把字节数组中的字节发送出去。
uart->write(buf.toUtf8()); //QString 转 char *的方法: buf.toLocal8Bit().data()
1.1.7 关闭串口
串口不用时,可通过 close()函数将其关闭。
uart->close();