参考博客:
- 博客园-菜头大大:QT串口通信
- CSDN-宗师之路:QT实现串口通信(附源码下载)
- CSDN-xz-c:C++将10进制字符串转为16进制字符串
本文改进
- 在前辈们的代码基础上进行改进,使操作更符合逻辑
- 优化代码结构,提高了代码的可移植性
QT实现串口通信
- 在工程文件(.pro)中添加串口通信相关运行库:
QT += serialport
- 在头文件中添加
#include <QtSerialPort/QSerialPort> #include <QtSerialPort/QSerialPortInfo>
- 在头文件中定义全局的串口对象:
QSerialPort *serial;
串口通讯步骤
- 设置串口名称
- 寻找可用串口
void control::scanPort() { this->ui->cb_port->clear(); int isHavePort = 0; foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) { QSerialPort serial; serial.setPort(info); //判断端口能否打开 if(serial.open(QIODevice::ReadWrite)) { this->ui->cb_port->addItem(serial.portName()); isHavePort ++; } if(isHavePort == 0){ QMessageBox::information(NULL, "警告", "没有可用串口"); } } }
- 设置串口名
serial = new QSerialPort; //设置串口名 serial->setPortName(this->ui->cb_port->currentText());
- 寻找可用串口
- 打开串口
serial->open(QIODevice::ReadWrite);
- 设置波特率
serial->setBaudRate(QSerialPort::Baud115200);//设置波特率为115200
- 设置数据位
serial->setDataBits(QSerialPort::Data8);//设置数据位8
- 设置校验位
serial->setParity(QSerialPort::NoParity); //无校验位
- 设置停止位
serial->setStopBits(QSerialPort::OneStop);//停止位设置为1
- 设置流控制
serial->setFlowControl(QSerialPort::NoFlowControl);//设置为无流控制
通过上述操作,串口的基本设置就设置好了,接下来需要实现数据的接收和发送:
- 在打开串口按钮中执行的操作中添加槽函数,当下位机中有数据发送过来时就会相应这个槽函数
connect(serial, SIGNAL(readyRead()), this, SLOT(readData()));
- 从上位机发送数据到下位机,发送内容位ASII码值或者为Hex格式;根据自身需求,我将数据进行了转换和格式化,此处为Hex格式。
serial->write(QString2Hex(formatInput(hexStr)));
进制转换及格式化
由于下位机需求,需要两帧将数据发送过去,经过多番考虑,最终决定将十进制转换为16进制,然后以Hex进行发送
- 十进制转换为16进制字符串
//将十进制int转换为十六进制字符串 QString control::decInt2HexStr(int dec) { //保证数据在两帧范围内 if(dec > 65535) { QMessageBox::information(NULL, "警告", "输入超出规定范围(input < 65535)"); return "0"; } QString hexStr; int temp = dec / 16; int left = dec % 16; if(temp > 0) hexStr += decInt2HexStr(temp); if(left < 10) hexStr += (left + '0'); else hexStr += ('A' + left - 10); return hexStr; }
- 将字符串转换为Hex格式
//字符串转Hex(QByteArray)类型 QByteArray control::QString2Hex(QString hexStr) { QByteArray senddata; int hexdata, lowhexdata; int hexdatalen = 0; int len = hexStr.length(); senddata.resize(len/2); char lstr, hstr; for(int i = 0; i < len; ) { //将第一个不为' '的字符赋给hstr; hstr = hexStr[i].toLatin1(); if(hstr == ' ') { i++; continue; } i++; //当i >= len时,跳出循环 if(i >= len) break; //当i < len时,将下一个字符赋值给lstr; lstr = hexStr[i].toLatin1(); //将hstr和lstr转换为0-15的对应数值 hexdata = ConvertHexChar(hstr); lowhexdata = ConvertHexChar(lstr); // if((hexdata == 16) || (lowhexdata == 16)) break; else hexdata = hexdata * 16 + lowhexdata; i++; senddata[hexdatalen] = (char)hexdata; hexdatalen++; } senddata.resize(hexdatalen); return senddata; } //将单个字符串转换为hex //0-F -> 0-15 char control::ConvertHexChar(char c) { if((c >= '0') && (c <= '9')) return c - 0x30; else if((c >= 'A') && (c <= 'F')) return c - 'A' + 10;//'A' = 65; else if((c >= 'a') && (c <= 'f')) return c - 'a' + 10; else return -1; }
- 输出形式格式化
//将输入格式化,补满四位:0XFFFF QString control::formatInput(QString hexStr) { int strlen = hexStr.length(); switch(strlen) { case 0: hexStr = "0000"; break; case 1: hexStr = "000" + hexStr; break; case 2: hexStr = "00" + hexStr; break; case 3: hexStr = "0" + hexStr; break; case 4: hexStr = hexStr; break; default: break; } return hexStr; }