• Qt QSerialPort 類實現(xiàn)串口通信

    2021/3/16??????點擊:
    使用的時候在 pro 添加這句導(dǎo)入模塊 QT += serialport

    1.連接串口 . 要先獲取到 可連接的所有的串口的名字

    QSerialPortInfo::availablePorts()
    [static] QListQSerialPortInfo::availablePorts()
    Returns a list of available serial ports on the system.
    返回系統(tǒng)上可用串行端口的列表
    
    QStringList m_serialPortName;
    foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
    {
    m_serialPortName << info.portName();
    qDebug()<<"serialPortName:"<
    

    獲取到串口名字列表以后,我們需要選擇個需要連接的 (自行根據(jù)選擇)

    2.根據(jù)串口名字 打開串口

    #includeQSerialPort *m_serialPort = new QSerialPort();//實例化串口類個對象
    
    if(m_serialPort->isOpen())//如果串口已經(jīng)打開了 先給他關(guān)閉了
    {
    	m_serialPort->clear();
    	m_serialPort->close();
    }
    //設(shè)置串口名字 假設(shè)我們上面已經(jīng)成功獲取到了 并且使用個
    m_serialPort->setPortName(m_serialPortName[0]);
    if(!m_serialPort->open(QIODevice::ReadWrite))//用ReadWrite 的模式嘗試打開串口
    {
    	qDebug()<setBaudRate(QSerialPort::Baud115200,QSerialPort::AllDirections);//設(shè)置波率和讀寫方向
        m_serialPort->setDataBits(QSerialPort::Data8);		//數(shù)據(jù)位為8位
        m_serialPort->setFlowControl(QSerialPort::NoFlowControl);//無流控制
        m_serialPort->setParity(QSerialPort::NoParity);	//無校驗位
        m_serialPort->setStopBits(QSerialPort::OneStop); //位停止位
    	//連接信號槽 當下位機發(fā)送數(shù)據(jù)QSerialPortInfo 會發(fā)送個 readyRead 信號,我們定義個槽void receiveInfo()解析數(shù)據(jù)
    	connect(m_serialPort,SIGNAL(readyRead()),this,SLOT(receiveInfo()));

    3.收發(fā)發(fā)送交互數(shù)據(jù)

    //接收單片機的數(shù)據(jù)
    	void receiveInfo()
    	{
    		QByteArray info = m_serialPort->readAll();
    		QByteArray hexData = info.toHex();
    		//這里面的協(xié)議 你們自己定義就行  單片機發(fā)什么 代表什么 我們這里簡單模擬下
    		if(hexData == "0x10000")
    		{
    			//do something
    		}
    		else if(hexData  == "0x100001")	
    		{
    			//do something
    		}	
    	}
    	//向單片機發(fā)送數(shù)據(jù)
    	//基本和單片機交互 數(shù)據(jù) 都是16進制的 我們這里自己寫個 Qstring 轉(zhuǎn)為 16進制的函數(shù)	
    	void 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)
    	            break;
    	        lstr = str[i].toLatin1();
    	        hexdata = convertCharToHex(hstr);
    	        lowhexdata = convertCharToHex(lstr);
    	        if((hexdata == 16) || (lowhexdata == 16))
    	            break;
    	        else
    	            hexdata = hexdata*16+lowhexdata;
    	        i++;
    	        byteData[hexdatalen] = (char)hexdata;
    	        hexdatalen++;
    	    }
    	    byteData.resize(hexdatalen);
    	}
    	//另個 函數(shù) char 轉(zhuǎn)為 16進制
    	char SerialPort::convertCharToHex(char ch)
    	{
    	    /*
    	    0x30等于十進制的48,48也是0的ASCII值,,
    	    1-9的ASCII值是49-57,,所以某個值-0x30,,
    	    就是將字符0-9轉(zhuǎn)換為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);
    	}
    	//寫兩個函數(shù) 向單片機發(fā)送數(shù)據(jù) 
    	void sendInfo(char* info,int len){
    	
    		for(int i=0; iwrite(info,len);//這句是真正的給單片機發(fā)數(shù)據(jù) 用到的是QIODevice::write 具體可以看文檔 
    	}
    	void sendInfo(const QString &info){
    		QByteArray sendBuf;
    	    if (info.contains(" "))
    	    {
    	        info.replace(QString(" "),QString(""));//我這里是把空格去掉,根據(jù)你們定的協(xié)議來
    	    }
    	    qDebug()<<"Write to serial: "<write(sendBuf);這句是真正的給單片機發(fā)數(shù)據(jù) 用到的是QIODevice::write 具體可以看文檔
    	}
    4.析構(gòu)的時候 關(guān)閉串口
      if (m_serialPort->isOpen())
        {
            m_serialPort->close();
        }
        delete m_serialPort;
    #ifndef WIDGET_H
    #define WIDGET_H
    #include#include#include#include#includenamespace Ui {
    class Widget;
    }
    class Widget : public QWidget
    {
        Q_OBJECT
    public:
        explicit Widget(QWidget *parent = 0);
        ~Widget();
        void initUI();
        QStringList getPortNameList();//獲取所有可用的串口列表
        void openPort();//打開串口
    public slots:
        void receiveInfo();
    private:
        Ui::Widget *ui;
        QSerialPort* m_serialPort; //串口類
        QStringList m_portNameList;
        QComboBox* m_PortNameComboBox;
        QPushButton* m_OpenPortButton;
    };
    #endif // WIDGET_H
    #include "widget.h"
    #include "ui_widget.h"
    #include#includeWidget::Widget(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::Widget)
    {
        ui->setupUi(this);
        m_serialPort = new QSerialPort();
        initUI();
        m_portNameList = getPortNameList();
        m_PortNameComboBox->addItems(m_portNameList); connect(m_OpenPortButton,&QPushButton::clicked,this,&Widget::openPort);
    }
    Widget::~Widget()
    {
        if (m_serialPort->isOpen())
        {
            m_serialPort->close();
        }
        delete m_serialPort;
        delete ui;
    }
    void Widget::initUI()
    {
        this->setWindowTitle("碼農(nóng)小明 test QSerialPort");
        m_OpenPortButton = new QPushButton();
        m_OpenPortButton->setText("打開串口");
        m_PortNameComboBox  = new QComboBox();
        QHBoxLayout *m_layout = new QHBoxLayout();
        m_layout->addWidget(m_PortNameComboBox);
        m_layout->addWidget(m_OpenPortButton);
        this->setLayout(m_layout);
    }
    QStringList Widget::getPortNameList()
    {
        QStringList m_serialPortName;
        foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
        {
            m_serialPortName << info.portName();
            qDebug()<<"serialPortName:"<isOpen())//如果串口已經(jīng)打開了 先給他關(guān)閉了
        {
            m_serialPort->clear();
            m_serialPort->close();
        }
        m_serialPort->setPortName(m_PortNameComboBox->currentText());//當前選擇的串口名字
        if(!m_serialPort->open(QIODevice::ReadWrite))//用ReadWrite 的模式嘗試打開串口
        {
            qDebug()<<"打開失敗!";
            return;
        }
        qDebug()<<"串口打開成功!";
        m_serialPort->setBaudRate(QSerialPort::Baud115200,QSerialPort::AllDirections);//設(shè)置波率和讀寫方向
        m_serialPort->setDataBits(QSerialPort::Data8);      //數(shù)據(jù)位為8位
        m_serialPort->setFlowControl(QSerialPort::NoFlowControl);//無流控制
        m_serialPort->setParity(QSerialPort::NoParity); //無校驗位
        m_serialPort->setStopBits(QSerialPort::OneStop); //位停止位
        connect(m_serialPort,SIGNAL(readyRead()),this,SLOT(receiveInfo()));
    }
    //接收到單片機發(fā)送的數(shù)據(jù)進行解析
    void Widget::receiveInfo()
    {
        QByteArray info = m_serialPort->readAll();
        qDebug()<<"receive info:"<