QT综合示例:QT串口通信
- 0、界面:
- 1、代码:
如果用qt写程序作为上位机,然后通过和usb和下位机通信的时候,就需要用到qt中的串口通信了。
0、界面:
1、代码:
1).pro 添加:
QT +=serialport
2)主函数 main.cpp 添加:
#include "mywidget.h"
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);myWidget w;w.show();return a.exec();
}
3)myWidget.h 添加:
#ifdef WIN32
#pragma execution_character_set("utf-8")
#endif#ifndef MYWIDGET_H
#define MYWIDGET_H#include <QWidget>#include <QSerialPort>
#include <QSerialPortInfo>#include <QDebug>
#include <QMessageBox>namespace Ui {
class myWidget;
}class myWidget : public QWidget
{Q_OBJECTpublic:explicit myWidget(QWidget *parent = 0);~myWidget();void initUI();public slots:void receiveInfo();private slots:void on_m_OpenPortButton_clicked();void on_btn_Send_clicked();private:Ui::myWidget *ui;private:QStringList getPortNameList(); // 获取所有可用的串口列表QSerialPort* m_serialPort; // 串口类QStringList m_portNameList; // 端口名列表private:void sendInfo(char* info,int len);void sendInfo(QString &info);void convertStringToHex(const QString &str, QByteArray &byteData);char convertCharToHex(char ch);
};#endif // MYWIDGET_H
4)myWidget.cpp 添加:
#include "mywidget.h"
#include "ui_mywidget.h"myWidget::myWidget(QWidget *parent) :QWidget(parent),ui(new Ui::myWidget)
{ui->setupUi(this);m_serialPort = new QSerialPort();this->setWindowTitle("QSerialPort");// 设置默认选项ui->m_OpenPortButton->setText("打开串口");ui->cBox_PortName->addItems(getPortNameList());ui->cBox_DataBits->setCurrentIndex(1);ui->cBox_BaudRate->setCurrentIndex(2);
}myWidget::~myWidget()
{delete ui;m_serialPort->close();delete m_serialPort;
}// 1、获得有效串行端口
QStringList myWidget::getPortNameList()
{QStringList m_serialPortName;foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts()){m_serialPortName << info.portName();//QMessageBox::information(this,tr("提示"),tr("serialPortName: %1").arg(info.portName()),QMessageBox::Ok);//qDebug()<<"serialPortName:"<<info.portName();}return m_serialPortName;
}// 2、连接、断开
void myWidget::on_m_OpenPortButton_clicked()
{if(m_serialPort->isOpen())//如果串口已经打开了 先给他关闭了{
// m_serialPort->flush();
// m_serialPort->clear();m_serialPort->close();}else{//当前选择的串口名字m_serialPort->setPortName(ui->cBox_PortName->currentText());//用ReadWrite 的模式尝试打开串口if(!m_serialPort->open(QIODevice::ReadWrite)){QMessageBox::warning(this,tr("提示"),tr("串口打开失败!"),QMessageBox::Ok);return;}// 串口设置:m_serialPort->setFlowControl(QSerialPort::NoFlowControl); //无流控制// 1、波特率和读写方向switch(ui->cBox_BaudRate->currentIndex()){case 0:m_serialPort->setBaudRate(QSerialPort::Baud2400,QSerialPort::AllDirections);break;case 1:m_serialPort->setBaudRate(QSerialPort::Baud4800,QSerialPort::AllDirections);break;case 2:m_serialPort->setBaudRate(QSerialPort::Baud9600,QSerialPort::AllDirections);//9600 比特率break;case 3:m_serialPort->setBaudRate(QSerialPort::Baud19200,QSerialPort::AllDirections);break;case 4:m_serialPort->setBaudRate(QSerialPort::Baud57600,QSerialPort::AllDirections);break;case 5:m_serialPort->setBaudRate(QSerialPort::Baud115200,QSerialPort::AllDirections);break;default:break;}// 2、数据位switch(ui->cBox_DataBits->currentIndex()){case 0:m_serialPort->setDataBits(QSerialPort::Data6);//6 bit 数据位break;case 1:m_serialPort->setDataBits(QSerialPort::Data7);//7 bit 数据位break;case 2:m_serialPort->setDataBits(QSerialPort::Data8);//8 bit 数据位break;default:break;}// 3、停止位switch(ui->cBox_StopBits->currentIndex()){case 0:m_serialPort->setStopBits(QSerialPort::OneStop);//1 bit停止位break;case 1:m_serialPort->setStopBits(QSerialPort::OneAndHalfStop); //1.5 bit停止位break;case 2:m_serialPort->setStopBits(QSerialPort::TwoStop); //2 bitbreak;default:break;}// 4、校验位switch(ui->cBox_Parity->currentIndex()){case 0:m_serialPort->setParity(QSerialPort::EvenParity);break;case 1:m_serialPort->setParity(QSerialPort::OddParity);break;default:m_serialPort->setParity(QSerialPort::NoParity);break;}connect(m_serialPort,SIGNAL(readyRead()),this,SLOT(receiveInfo()));}ui->m_OpenPortButton->setText(m_serialPort->isOpen()?tr("关闭串口") : tr("连接串口"));ui->m_OpenPortButton->setStyleSheet(m_serialPort->isOpen()?"color: red;":"color: black;");
}// 3、信息接收
void myWidget::receiveInfo()
{QByteArray info = m_serialPort->readAll();//qDebug()<<"receive info:"<<info;if(!info.isEmpty()){QString str = ui->textEdit_receive->toPlainText();str+=tr(info);ui->textEdit_receive->clear();ui->textEdit_receive->append(str);}info.clear();// QByteArray hexData = info.toHex();
// //这里面的协议 你们自己定义就行 单片机发什么 代表什么 我们这里简单模拟一下
// if(hexData == "0x10000")
// {
// //do something
// }
// else if(hexData == "0x100001")
// {
// //do something
// }
}// 4、发送按钮
void myWidget::on_btn_Send_clicked()
{m_serialPort->write(ui->textEdit_send->toPlainText().toLatin1());
}//写两个函数 向单片机发送数据:
// 信息发送函数一:
void myWidget::sendInfo(char* info,int len)
{for(int i=0; i<len; ++i){printf("0x%x\n", info[i]);}m_serialPort->write(info,len);//这句是真正的给单片机发数据 用到的是QIODevice::write 具体可以看文档
}// 信息发送函数二:
void myWidget::sendInfo(QString &info)
{QByteArray sendBuf;if (info.contains(" ")){info.replace(QString(" "),QString(""));//我这里是把空格去掉,根据你们定的协议来}qDebug()<<"Write to serial: "<<info;convertStringToHex(info, sendBuf); //把QString 转换 为 hexm_serialPort->write(sendBuf); //这句是真正的给单片机发数据 用到的是QIODevice::write 具体可以看文档
}// 基本和单片机交互数据都是16进制的
// Qstring 转为16进制的函数
void myWidget::convertStringToHex(const QString &str, QByteArray &byteData)
{int hexdata,lowhexdata;int hexdatalen = 0;int len = str.length();byteData.resize(len/2);char lstr,hstr;for(int i=0; i<len; ){//char lstr,hstr=str[i].toLatin1();if(hstr == ' '){i++;continue;}i++;if(i >= len)break;lstr = str[i].toLatin1();hexdata = convertCharToHex(hstr);lowhexdata = convertCharToHex(lstr);if((hexdata == 16) || (lowhexdata == 16))break;elsehexdata = hexdata*16+lowhexdata;i++;byteData[hexdatalen] = (char)hexdata;hexdatalen++;}byteData.resize(hexdatalen);
}//另一个 函数 char 转为 16进制
char myWidget::convertCharToHex(char ch)
{/*0x30等于十进制的48,48也是0的ASCII值,,1-9的ASCII值是49-57,,所以某一个值-0x30,,就是将字符0-9转换为0-9*/if((ch >= '0') && (ch <= '9'))return ch-0x30;else if((ch >= 'A') && (ch <= 'F'))return ch-'A'+10;else if((ch >= 'a') && (ch <= 'f'))return ch-'a'+10;else return (-1);
}