精华内容
下载资源
问答
  • QT5串口编程

    千次阅读 2016-04-29 18:10:53
    QT5串口编程,   官方概述: #include 提供使用串口的功能。 你可以使用QSerialPoartInfo帮助类获取可用串口资源,(将会列举出系统中所有的口 对获取正确的串口号是很有帮助的,   使用 setPort()or ...

                                             QT5串口编程,

     

    官方概述:

    #include<QSerialPort>

    提供使用串口的功能。

    你可以使用QSerialPoartInfo帮助类获取可用串口资源,(将会列举出系统中所有的口

    对获取正确的串口号是很有帮助的,

     

    使用 setPort()or setPortName() 设置参数来设置所需的串口,设置完后使用 只读 只写或读写的方式用open()方法打开,

     

    串口具有独占性,已经被打开的串口,其他进程将无法获取该串口使用权

     

    成功打开一个串口后 QSerialPort 会尝试确定当前的串口配置并自我初始化,但可以使用 setBaudRate(), setDataBits(), setParity(),setStopBits(),and setFlowControl() 来重新配置自己想要的配置,

     

    当端口可以读写,可用  read()or write()   readLine()and readAll() 来操作。

    如果所有的数据不是一下读完,剩下的数据将被接下来的数据追加到 QSerialPort的内部缓存,可以用setReadBufferSize()来设置缓存的大小。

     

      用 close() 可将串口断开io通讯

     

     

    第一步:获取串口,实现打开,关闭

    1创建串口对象,2获取串口资源,3实现打开,关闭:

     

    新建qwidget项目

    qmake 加入QT += serialport ,(否则报错,找不到下面的头文件 )

    在mainwindow.h中加入串口类头文件

    #include<QSerialPort>

    #include<QSerialPortInfo>

     

    (1)创建一个空 串口对象,因为该对象还没有获的实际端口的关联,

     

               QSerialPort *myport= new QSerialPort;

       

     

    (2)搜索可用串口:QSerialPortInfo 中有两个可以返回串口资源的静态方法

              Static Public Members

    QList<QSerialPortInfo>

    availablePorts()

     QList<qint32>

    standardBaudRates()

     

      

    用上面的方法获取串口资源:

    重要问题:返回值QList<QSerialPortInfo> 是什么

     

    使用用静态方法获取串口资源, availablePorts() 的返回值 为链表,链表元素为QSerialPortInfo类型,计算机里有几个可用串口返回的链表就有几个元素

     每个QSerialPortInfo元素 里面包含了此串口的所有信息,如该串口的名字,产品ID,是否处于被占用状态,下面是QSerialPortInfo所包含信的息集合

      

    QSerialPortInfo(const QSerialPort &port)

     

    QSerialPortInfo()

    QSerialPortInfo(const QString &name)

    QSerialPortInfo(const QSerialPortInfo&other)

    ~QSerialPortInfo()

    在获得一个串口的所有信息后

    该信息里包含了下面的内容

    QString

    description() const

    bool

    hasProductIdentifier() const

    bool

    hasVendorIdentifier() const

    bool

    isBusy() const

    bool

    isNull() const

    QString

    manufacturer() const

    QString

    portName() const

    quint16

    productIdentifier() const

    QString

    serialNumber() const

    void

    swap(QSerialPortInfo &other)

    QString

    systemLocation() const

    quint16

    vendorIdentifier() const

    QSerialPortInfo &

    operator=(const QSerialPortInfo &other)

     

    实例获取串口资源:    

    初级例:我的计算机里当前有5个串口  (怎么知道计算的串口资源:计算机属性->设备管理器->端口(COM和LPT)  )

          QList<QSerialPortInfo> list_info= QSerialPortInfo::availablePorts() ;

        qDebug()<<list_info[0].portName();

        qDebug()<<list_info[1].portName();

        输出:

        COM1

        COM2

        因为我的计算机里有5个串口,所以QSerialPortInfo::availablePorts()返回当前所有串口放在 Qlist 里,共有5个元素,一个元素对应一个串口的QSerialPortInfo信息。

     


     新的问题:计算机有没有串口,不知道有几个串口,

                   有没有串口:

                    QList提供 boolempty() ,和 bool isEmpty() 检测是否为空,(list_info为空就是没有串口)

                    有几个串口:

                     QList提供 int count()计算元素个数

     

        升级例:检测计算机是否有可用串口,以及可用串口的个数

                QList<QSerialPortInfo>list_info=QSerialPortInfo::availablePorts() ;

               if(list_info.isEmpty())

                {qDebug()<< "计算机没有可用串口" ;}

               else

                {qDebug()<< "有"<< list_info.count()<<"个可用串口" ; }

     

     

     

    (3)QSerialPort 空白对象 与 串口资源关联起来,打开串口,关闭串口

     

          串口对象与 设备关联:

          只有QSerialPort 才能操作串口,而 QSerialPort myport 只是创建了一个空白对象,无法操作硬件

     

          与硬件关联setPortName(const QString &name), &name为引用,直接传入所需串口的QString名字,如CM0,CM1即可

     

          打开串口,关闭串口:

            QSerialPort   open(OpenMode mode), 和  close() 方法

             OpenMode: 一般为

    QIODevice::ReadOnly

    0x0001

    The device is open for reading.

    QIODevice::WriteOnly

    0x0002

    The device is open for writing. Note that this mode implies Truncate.

    QIODevice::ReadWrite

    ReadOnly | WriteOnly

    The device is open for reading and writing.

     

     

     

    实例获取并打开串口:

        

    //创建空白串口对象

    QSerialPort  myport;   

     

      //查询串口资源,并获取

    QList<QSerialPortInfo> list_info=QSerialPortInfo::availablePorts();

               if(list_info.isEmpty())

                {qDebug()<< "计算机没有可用串口" ;}

               else

                {qDebug()<< "有"<< list_info.count()<<"个可用串口" ; };

                                    

                //空白串口对象与 设备关联

                  mypory.setPorName( list_info[0]. portName()  );

                                     

                //打开,关闭串口

                  mypory.open(  QIODevice::ReadWrite  )

                 myport.close();

     

     

     

     

     

    第二步:读取串口数据:

             准备虚拟串口工具串口调试工具

                为了更好的忽略实际硬件带来的干扰,先不用单片机与电脑连接向电脑发送数据,

             这里采用虚拟串口的方法会更好,下面先介绍虚拟串口的配置,与使用:

                   百度虚拟串口:虚拟串口破解版|VSPD ,下载,安装,按教程破解,打开界面


            

            physical ports 物理端口,即实际可用的设备,如果单片机与电脑连接,其下面就会罗列出来

            virtual ports,虚拟串口,这就是我们用软件虚拟出来,但具有实际效果的串口

                 点击右边的 “添加端口”就会听到计算机发现新硬件的声音,同时可在上图中的virtual ports 看到,计算机的设备管理器也可以看到


                  串口工具1(占用COM2),我们的程序(占用COM1),或者 ,串口工具1(占用COM1),我们的程序(占用COM2)就可以在我们的程序可串口工具1之间来传递信                息,以此来测试我们的程序

     

     

     

    读取串口数据:

            重点:

             QSerialPort  里没有读取数据的直接可用的方法,只有一个阻塞读取的虚函数virtual boolwaitForReadyRead(int msecs)

           直接丢弃不要用,

                QSerialPort  继承于 QIODevice最重要的是 ,诸如网络,串口这样的设备,【当有新数据到来时Device会发射 readyRead()

           信号, 】 这才是读取数据的关键,我们只要将该信号与自己的读取函数(槽)连接,只要新数据到来便自动读取数据

     

     

           建立自动读取连接:

            connect (myport , SIGNAL (readyRead())  , this ,SLOT( read_serialport_data()   )    )

            一旦有数据到来,就会跳到read_serialport_data (),这里略过里面的实现过程

            注意,必须声明read_serialport_data ()为槽,放在 slots: 关键字后面

     

          

    重要问题:汉字的显示,  中文乱码!

                  1 在ui上,或者qDebug()<< ; 显示汉字,直接用QString ,但前提是要将文本格式转换为UTF-8格式

                   2   在传输过程中,各种格式间的转换  中文几乎都乱码!!!!,中文在 char*  QString QByteArray 间转换都几乎乱码

                        只有这种方法不会:

                       例: QTextStreamstream( myport /myfile等QioDivice );

                                  ui->textshow->setText(stream.readAll() );

                          数据传输中,中文在QTextStream中不会乱码,

    第三步:发送串口数据:略

                                          待续----------------------------------------

     

    展开全文
  • Qt5 串口编程 发送接收 简单入门资料 上手简单 代码清晰
  • 编写简单的上位机(QT5串口编程
  • QT5串口编程——编写简单的上位机

    万次阅读 多人点赞 2016-01-30 15:51:48
    注:更新自2018年12月13日(我回看了一年多前写的这篇...学习了前面部分,对QT有了大概的了解后,就开始在网上寻找串口编程的方法。通过好几天的学习,终于写出了一个用于串口通信的上位机。下面开始介绍串口类的...

    注:更新自2018年12月13日(我回看了一年多前写的这篇博客,觉得不是很好,故翻新了一遍。)

    最近在学习嵌入式,而上位机又是一个不可缺少的工具,于是就开始接触QT,学习编写上位机。刚开始的时候什么都不懂,发现《Qt 学习之路 2》有比较好的入门教程。学习了前面部分,对QT有了大概的了解后,就开始在网上寻找串口编程的方法。通过好几天的学习,终于写出了一个用于串口通信的上位机。下面开始介绍串口类的使用。

    首先,QT5是自带QSerialPort这个类的,使用时需要在pro文件里面添加一行:

    QT       += serialport

    然后直接引用头文件就可以了。

    #include <QSerialPort>        //提供访问串口的功能 
    #include <QSerialPortInfo>    //提供系统中存在的串口的信息

    在QT5中,串口通信是借助一个QSerialPort的对象来实现的,在设置QSerialPort对象对串口的名称、波特率、数据位、校验位、停止位等参数后,方能对串口进行读写。下面,我总结了一下借助QSerailPort对串口进行设置、打开、读、写和关闭的过程。


    一、设置和打开串口

    //创建串口对象
    QSerialPort serial;
    //设置串口名
    serial.setPortName("COM3");
    //设置波特率
    serial.setBaudRate(QSerialPort::Baud9600);
    //设置数据位数
    serial.setDataBits(QSerialPort::Data8);
    //设置奇偶校验
    serial.setParity(QSerialPort::NoParity); 
    //设置停止位
    serial.setStopBits(QSerialPort::OneStop);
    //设置流控制
    serial.setFlowControl(QSerialPort::NoFlowControl);
    //打开串口
    serial.open(QIODevice::ReadWrite);

    以上代码是QSerialPort对象的设置示例,作用是:

    • 设置串口名为 COM3 
    • 设置波特率为9600
    • 设置数据位为8位
    • 设置没有奇偶校验位
    • 设置停止位为1位
    • 设置没有流控制
    • 以可读写的方式打开串口

    设置完这些就能进行读写操作了。如果遇到不理解的地方,可以选择QT的类或函数,然后按F1查阅手册。举个例子,如果我们想查看QSerialPort的其它的属性,可以选择QSerialPort的类名成员函数,然后按F1。


    二、读取数据

    //从接收缓冲区中读取数据
    QByteArray buffer = serial.readAll();
    

    串口在收到数据后,会将数据存入接收缓冲区。此时,我们可以通过readAll()函数将接收缓冲区的数据读出来。当串口的接收缓冲区有数据时,QSerilaPort对象会发出一个readyRead()的信号。因此,我们可以编写一个槽函数来读数据,例如:

    //连接信号和槽
    QObject::connect(&serial, &QSerialPort::readyRead, this, &MainWindow::serialPort_readyRead);
    
    ……
    
    //编写的槽函数
    void MainWindow::serialPort_readyRead()
    {
        //从接收缓冲区中读取数据
        QByteArray buffer = serial.readAll();
        
        //处理数据
        //……
    }

    三、发送数据

    serial->write(data);

    使用write函数便可以把字节数组中的字节发送出去。

    四、关闭串口

    serial->close();

    串口不用时,可通过close()函数将其关闭。

     

    接下来是一个实例

    1、创建一个新的Widgets Appliaction工程

    2、使用QtCreator的ui文件来设计上位机的界面,设计如下:

    3、mainwindow.h文件内容如下:

    //mainwindow.h
    
    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <QSerialPort>
    #include <QSerialPortInfo>
    
    namespace Ui {
    class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
    
    private slots:
        void serialPort_readyRead();
    
        void on_searchButton_clicked();
    
        void on_openButton_clicked();
    
        void on_sendButton_clicked();
    
        void on_clearButton_clicked();
    
    private:
        Ui::MainWindow *ui;
        QSerialPort serial;
    };
    
    #endif // MAINWINDOW_H
    

    4、mainwindow.cpp文件内容如下:

    //mainwindow.cpp
    
    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <QMessageBox>
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        //连接信号和槽
        QObject::connect(&serial, &QSerialPort::readyRead, this, &MainWindow::serialPort_readyRead);
    
        //发送按键失能
        ui->sendButton->setEnabled(false);
        //波特率默认选择下拉第三项:9600
        ui->baudrateBox->setCurrentIndex(3);
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    void MainWindow::serialPort_readyRead()
    {
        //从接收缓冲区中读取数据
        QByteArray buffer = serial.readAll();
        //从界面中读取以前收到的数据
        QString recv = ui->recvTextEdit->toPlainText();
        recv += QString(buffer);
        //清空以前的显示
        ui->recvTextEdit->clear();
        //重新显示
        ui->recvTextEdit->append(recv);
    }
    
    
    void MainWindow::on_searchButton_clicked()
    {
        ui->portNameBox->clear();
        //通过QSerialPortInfo查找可用串口
        foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
        {
            ui->portNameBox->addItem(info.portName());
        }
    }
    
    void MainWindow::on_openButton_clicked()
    {
        if(ui->openButton->text()==QString("打开串口"))
        {
            //设置串口名
            serial.setPortName(ui->portNameBox->currentText());
            //设置波特率
            serial.setBaudRate(ui->baudrateBox->currentText().toInt());
            //设置数据位数
            switch(ui->dataBitsBox->currentIndex())
            {
            case 8: serial.setDataBits(QSerialPort::Data8); break;
            default: break;
            }
            //设置奇偶校验
            switch(ui->ParityBox->currentIndex())
            {
            case 0: serial.setParity(QSerialPort::NoParity); break;
            default: break;
            }
            //设置停止位
            switch(ui->stopBitsBox->currentIndex())
            {
            case 1: serial.setStopBits(QSerialPort::OneStop); break;
            case 2: serial.setStopBits(QSerialPort::TwoStop); break;
            default: break;
            }
            //设置流控制
            serial.setFlowControl(QSerialPort::NoFlowControl);
    
            //打开串口
            if(!serial.open(QIODevice::ReadWrite))
            {
                QMessageBox::about(NULL, "提示", "无法打开串口!");
                return;
            }
    
            //下拉菜单控件失能
            ui->portNameBox->setEnabled(false);
            ui->baudrateBox->setEnabled(false);
            ui->dataBitsBox->setEnabled(false);
            ui->ParityBox->setEnabled(false);
            ui->stopBitsBox->setEnabled(false);
    
            ui->openButton->setText(QString("关闭串口"));
            //发送按键使能
            ui->sendButton->setEnabled(true);
        }
        else
        {
            //关闭串口
            serial.close();
    
            //下拉菜单控件使能
            ui->portNameBox->setEnabled(true);
            ui->baudrateBox->setEnabled(true);
            ui->dataBitsBox->setEnabled(true);
            ui->ParityBox->setEnabled(true);
            ui->stopBitsBox->setEnabled(true);
    
            ui->openButton->setText(QString("打开串口"));
            //发送按键失能
            ui->sendButton->setEnabled(false);
        }
    }
    
    void MainWindow::on_sendButton_clicked()
    {
        //获取界面上的数据并转换成utf8格式的字节流
        QByteArray data = ui->sendTextEdit->toPlainText().toUtf8();
        serial.write(data);
    }
    
    void MainWindow::on_clearButton_clicked()
    {
        ui->recvTextEdit->clear();
    }
    

    5、main.cpp文件内容如下:

    #include "mainwindow.h"
    #include <QApplication>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();
    
        return a.exec();
    }
    

    4、测试(将USB转TTL模块发送和接收引脚短接,自己发自己收)

     

    新的工程已经上传至:https://download.csdn.net/download/u014695839/10881180 (2018年12月27日更新)

    以前的工程在这里可以下载:http://download.csdn.net/detail/u014695839/9763670

    以上内容若有问题,大家务必提醒,我定会马上更正!

    希望能与大家多多交流。

    展开全文
  • Qt5串口编程详解

    千次阅读 2014-10-21 14:32:52
    Qt5串口编程详解【新版】 分类: qt2014-05-17 11:31 520人阅读 评论(0) 收藏 举报 Qt5的串口比Qt4的好用得多,Qt4的貌似没有集成官方库。 之前我也写过Qt5的串口,不过有一些缺陷,这次试图改进...
     

    Qt5串口编程详解【新版】

    分类: qt 520人阅读 评论(0) 收藏 举报

    Qt5的串口比Qt4的好用得多,Qt4的貌似没有集成官方库。

    之前我也写过Qt5的串口,不过有一些缺陷,这次试图改进。转载请保留链接:http://blog.csdn.net/qq363692146/article/details/26049355

    本文发表于2014.5.17。


    如果在linux下,记得使用root权限,可以用root权限打开可执行文件,或者用root权限打开Qt Creator。(原因是串口常常需要特权,有些串口有特权也只能度而不能写,这个可能是Qt本身的问题)【至于安卓端,其实没试过。】【用root打开Qt Creator似乎是一个一劳永逸的方法,这样每次运行都以root权限,但是一些配置文件也会被改变为root权限。下一次再以普通权限打开Qt Creator就会提示错误,需要输入这样命令 sudo chmod 777 `find 对应目录`,这样能将目录的每个文件去掉权限限制】



    好了,准备开始。



    先建立Qt Widgets Application,只要注意尽量不用中文路径即可,一直下一步,直到完成。


    接着修改“项目名.pro”文件,增加这一单独行。(这个项目文件可以根据需要裁剪和增加,以增快编译效率和设置选项,而这一行表示“我想用到串口”)

    1. QT       += serialport  



    进入mainwindow.ui,给它一个Combo Box(用于选择哪一个串口,一台电脑常常有多个串口)、一个label(用于显示串口是否正常)、一个Text Edit(用于接收数据)、一个lineEdit(用于发送数据)、一个Push Button(当按下一次,就发送一次),这里为了方便读者理解,与博文统一,请读者先别急着修改它们的ObeectName,至于布局,请随意。

    给Combo Box一个槽,来改变串口(右键,转到槽,选择currentIndexChange(QString))。//当改变选择的选项则触发,可得到选项名

    给Push Button一个槽,用于发送(右键,选择槽,选择第一个函数)。//当按下触发




    在mainWindow.h文件中

    加入头文件:(这里QSerialPort是必须的,而QSerialPortInfo是可选的,它能提供本机可用串口列表(列表的每一个元素都自动获取了对应的端口号、波特率、校验位等信息!),如果不使用它则需要手动编码,设置对应的串口、波特率等信息,最后完成之后单独拿出来讲,见下面的黄色阴影字体部分)

    1. #include <QSerialPort>  
    2. #include <QSerialPortInfo>  
    接着,给它一个private变量(表示串口及其操作函数)、一个private函数(用于初始化)、一个连接槽,(用于接收串口过来的数据,发送是不需要槽的,原因是发送是主动、随时的,而接收是被动、等待的):

    private变量:

    1. QSerialPort serial;  

    一个private函数:

    1. void initSeialPort();  

    连接槽:

    1. private slots:  
    2.     void serialRead();  


    进入mainWindow.cpp中

    在构造函数中:

    在ui->setupUi(this);之后加入这一句:

    1. initSeialPort();  

    在析构函数中:

    在delete ui;之前加入这一句:

    1. serial.close();  


    接下来补齐这些没有函数体为空的函数,为了方便可以直接复制(仔细浏览,看看它们已经定义了没有,或者是否ui触发的槽选择错误,如果有问题,请投诉):

    initSerialPort函数

    先连接槽,然后获取可用的infos(所有本地存在串口信息),如果都不可用,提示“无效”,如果存在,则为Combo Box添加选项,第一项是“串口”(只是提示,由于combo Box的选项从无到有,将触发一次 on_comboBox_currentIndexChanged(const QString &arg1) 槽 ,见下面橙色阴影字体),这个选项之后是其他的串口的端口号作为选项。

    1. void MainWindow::initSeialPort()  
    2. {  
    3.   
    4.     connect(&serial,SIGNAL(readyRead()),this,SLOT(serialRead()));   //连接槽  
    5.   
    6.     //get name for choose  
    7.     QList<QSerialPortInfo>  infos = QSerialPortInfo::availablePorts();  
    8.     if(infos.isEmpty())  
    9.     {  
    10.         ui->comboBox->addItem("无效");  
    11.         return;  
    12.     }  
    13.     ui->comboBox->addItem("串口");  
    14.     foreach (QSerialPortInfo info, infos) {  
    15.         ui->comboBox->addItem(info.portName());  
    16.     }  
    17. }  



    当每次combo Box选项变化,将触发下面的函数:

    arg1为该选择的Combo Box选项名称(第一次触发为“串口”,之后被用户选择为需要的串口号,根据上面的addItem函数可以逆推)

    根据arg1查找可用的串口列表,如果找不到(例如arg1为“串口”这个字符串,当然找不到)则提示“[出错]”,否则打开并提示"[已开启]"。

    这里serial先关后开,防止先前的串口忘了关闭(因为每改变一次选项就要开启一次,那么当然要把上一次的串口给关了才行)。

    1. void MainWindow::on_comboBox_currentIndexChanged(const QString &arg1)  
    2. {  
    3.     QSerialPortInfo info;  
    4.     QList<QSerialPortInfo> infos = QSerialPortInfo::availablePorts();  
    5.     int i = 0;  
    6.     foreach (info, infos) {  
    7.         if(info.portName() == arg1) break;  
    8.         i++;  
    9.     }  
    10.     if(i != infos.size ()){//can find  
    11.         ui->label->setText("[已开启]");  
    12.         serial.close();  
    13.         serial.setPort(info);  
    14.         serial.open(QIODevice::ReadWrite);         //读写打开  
    15.     }  
    16.     else  
    17.     {  
    18.         serial.close();  
    19.         ui->label->setText("[出错]");  
    20.     }  
    21. }  



    下面两个函数便不详述:

    1. void MainWindow::serialRead()  
    2. {  
    3.     ui->textEdit->append(serial.readAll());  
    4. }  

    toLatin1可用转换QString到QByteArray类型:

    1. void MainWindow::on_pushButton_clicked()  
    2. {  
    3.     if(ui->lineEdit->text().isEmpty())  
    4.         return;  
    5.     serial.write(ui->lineEdit->text().toLatin1());  
    6. }  



    好已经完成全部工作,测试一下吧。




    补充一下自己摸索的其他方法,作为阅读即可:


    问题1:如何去掉QSerialPortInfo头文件,并手动设置串口信息,这里举个例子:

    1. //注意这里serial是指针形式,而且下面的顺序有一定要求:  
    2. //下面这些设置都是针对单片机11.0592的晶振的,请根据具体情况设置:  
    3.   
    4. serial = new QSerialPort("COM4");       //串口号,一定要对应好,大写!!!串口号一般要修改。  
    5.     serial->open(QIODevice::ReadWrite);      //读写打开    
    6.     serial->setBaudRate(QSerialPort::Baud9600);  //波特率    
    7.     serial->setDataBits(QSerialPort::Data8); //数据位    
    8.     serial->setParity(QSerialPort::NoParity);    //无奇偶校验    
    9.     serial->setStopBits(QSerialPort::OneStop);   //无停止位    
    10.     serial->setFlowControl(QSerialPort::NoFlowControl);  //无控制    


    问题2:如何解决传接收断断续续的问题(在某些情况串口无意地经常把一条数据拆成多条数据,这时候多次触发了serialRead槽,得到不想要的结果):

    解决方法:

    1.对于固定长度的数据,假如有数据长度不正确,就请求重发。

    2.对于不固定长度的,可以在数据后面加上特殊符号作为识别,这里将举例(当特殊符号为'~')【不过这个代码没考虑多线程:static变量存在着】:

    1. void MainWindow::serialRead()    
    2. {    
    3.     static QByteArray allData;         //静态变量!!在串口只得到一部分的时候用来累加数据    
    4.     QByteArray dataTemp;                //本次接收的数据,可能是前半部分数据或者后半部分数据(甚至是被分割为多段数据的其中一部分数据),或者也可能是完整数据。  
    5.     while (!serial->atEnd()) {    
    6.         QByteArray dataTemp = serial->readAll();                //因为串口是不稳定的,也许读到的是部分数据而已,但也可能是全部数据    
    7.         if( dataTemp.data()[dataTemp.length() - 1] == '~'){     //当临时数据最后一位是'~',代表一条数据读完了    
    8.             allData += dataTemp;                                //总数据加上本次数据    
    9.             allData.resize(allData.size() - 1);                 //删除结尾的~符号    
    10.             qCritical() << allData;                             //这时候allData将是你要的数据    
    11.             allData.clear();                                    //清除数据!!!!!    
    12.         }    
    13.         else                                                  //当最后一位数据不是'~',即未读完    
    14.             allData += dataTemp;                               //每次累加这部分数据,因为还没发完    
    15.     }    
    16. }    
    展开全文
  • Qt5串口编程详解【新版】

    万次阅读 多人点赞 2014-05-17 11:31:44
    Qt5串口编程详解【新版】

    Qt5的串口比Qt4的好用得多,Qt4的貌似没有集成官方库。

    之前我也写过Qt5的串口,不过有一些缺陷,这次试图改进。转载请保留链接:http://blog.csdn.net/qq363692146/article/details/26049355

    本文发表于2014.5.17。


    如果在linux下,记得使用root权限,可以用root权限打开可执行文件,或者用root权限打开Qt Creator。(原因是串口常常需要特权,有些串口有特权也只能度而不能写,这个可能是Qt本身的问题)【至于安卓端,其实没试过。】【用root打开Qt Creator似乎是一个一劳永逸的方法,这样每次运行都以root权限,但是一些配置文件也会被改变为root权限。下一次再以普通权限打开Qt Creator就会提示错误,需要输入这样命令 sudo chmod 777 `find 对应目录`,这样能将目录的每个文件去掉权限限制】



    好了,准备开始。



    先建立Qt Widgets Application,只要注意尽量不用中文路径即可,一直下一步,直到完成。


    接着修改“项目名.pro”文件,增加这一单独行。(这个项目文件可以根据需要裁剪和增加,以增快编译效率和设置选项,而这一行表示“我想用到串口”)

    QT       += serialport



    进入mainwindow.ui,给它一个Combo Box(用于选择哪一个串口,一台电脑常常有多个串口)、一个label(用于显示串口是否正常)、一个Text Edit(用于接收数据)、一个lineEdit(用于发送数据)、一个Push Button(当按下一次,就发送一次),这里为了方便读者理解,与博文统一,请读者先别急着修改它们的ObeectName,至于布局,请随意。

    给Combo Box一个槽,来改变串口(右键,转到槽,选择currentIndexChange(QString))。//当改变选择的选项则触发,可得到选项名

    给Push Button一个槽,用于发送(右键,选择槽,选择第一个函数)。//当按下触发




    在mainWindow.h文件中

    加入头文件:(这里QSerialPort是必须的,而QSerialPortInfo是可选的,它能提供本机可用串口列表(列表的每一个元素都自动获取了对应的端口号、波特率、校验位等信息!),如果不使用它则需要手动编码,设置对应的串口、波特率等信息,最后完成之后单独拿出来讲,见下面的黄色阴影字体部分)

    #include <QSerialPort>
    #include <QSerialPortInfo>
    接着,给它一个private变量(表示串口及其操作函数)、一个private函数(用于初始化)、一个连接槽,(用于接收串口过来的数据,发送是不需要槽的,原因是发送是主动、随时的,而接收是被动、等待的):

    private变量:

    QSerialPort serial;

    一个private函数:

    void initSeialPort();

    连接槽:

    private slots:
        void serialRead();


    进入mainWindow.cpp中

    在构造函数中:

    在ui->setupUi(this);之后加入这一句:

    initSeialPort();

    在析构函数中:

    在delete ui;之前加入这一句:

    serial.close();


    接下来补齐这些没有函数体为空的函数,为了方便可以直接复制(仔细浏览,看看它们已经定义了没有,或者是否ui触发的槽选择错误,如果有问题,请投诉):

    initSerialPort函数

    先连接槽,然后获取可用的infos(所有本地存在串口信息),如果都不可用,提示“无效”,如果存在,则为Combo Box添加选项,第一项是“串口”(只是提示,由于combo Box的选项从无到有,将触发一次 on_comboBox_currentIndexChanged(const QString &arg1) 槽 ,见下面橙色阴影字体),这个选项之后是其他的串口的端口号作为选项。

    void MainWindow::initSeialPort()
    {
    
        connect(&serial,SIGNAL(readyRead()),this,SLOT(serialRead()));	//连接槽
    
        //get name for choose
        QList<QSerialPortInfo>  infos = QSerialPortInfo::availablePorts();
        if(infos.isEmpty())
        {
            ui->comboBox->addItem("无效");
            return;
        }
        ui->comboBox->addItem("串口");
        foreach (QSerialPortInfo info, infos) {
            ui->comboBox->addItem(info.portName());
        }
    }



    当每次combo Box选项变化,将触发下面的函数:

    arg1为该选择的Combo Box选项名称(第一次触发为“串口”,之后被用户选择为需要的串口号,根据上面的addItem函数可以逆推)

    根据arg1查找可用的串口列表,如果找不到(例如arg1为“串口”这个字符串,当然找不到)则提示“[出错]”,否则打开并提示"[已开启]"。

    这里serial先关后开,防止先前的串口忘了关闭(因为每改变一次选项就要开启一次,那么当然要把上一次的串口给关了才行)。

    void MainWindow::on_comboBox_currentIndexChanged(const QString &arg1)
    {
        QSerialPortInfo info;
        QList<QSerialPortInfo> infos = QSerialPortInfo::availablePorts();
        int i = 0;
        foreach (info, infos) {
            if(info.portName() == arg1) break;
            i++;
        }
        if(i != infos.size ()){//can find
            ui->label->setText("[已开启]");
            serial.close();
            serial.setPort(info);
            serial.open(QIODevice::ReadWrite);         //读写打开
        }
        else
        {
            serial.close();
            ui->label->setText("[出错]");
        }
    }



    下面两个函数便不详述:

    void MainWindow::serialRead()
    {
        ui->textEdit->append(serial.readAll());
    }

    toLatin1可用转换QString到QByteArray类型:

    void MainWindow::on_pushButton_clicked()
    {
        if(ui->lineEdit->text().isEmpty())
            return;
        serial.write(ui->lineEdit->text().toLatin1());
    }



    好已经完成全部工作,测试一下吧。




    补充一下自己摸索的其他方法,作为阅读即可:


    问题1:如何去掉QSerialPortInfo头文件,并手动设置串口信息,这里举个例子:

    //注意这里serial是指针形式,而且下面的顺序有一定要求:
    //下面这些设置都是针对单片机11.0592的晶振的,请根据具体情况设置:
    
    serial = new QSerialPort("COM4");       //串口号,一定要对应好,大写!!!串口号一般要修改。
        serial->open(QIODevice::ReadWrite);      //读写打开  
        serial->setBaudRate(QSerialPort::Baud9600);  //波特率  
        serial->setDataBits(QSerialPort::Data8); //数据位  
        serial->setParity(QSerialPort::NoParity);    //无奇偶校验  
        serial->setStopBits(QSerialPort::OneStop);   //无停止位  
        serial->setFlowControl(QSerialPort::NoFlowControl);  //无控制  


    问题2:如何解决传接收断断续续的问题(在某些情况串口无意地经常把一条数据拆成多条数据,这时候多次触发了serialRead槽,得到不想要的结果):

    解决方法:

    1.对于固定长度的数据,假如有数据长度不正确,就请求重发。

    2.对于不固定长度的,可以在数据后面加上特殊符号作为识别,这里将举例(当特殊符号为'~')【不过这个代码没考虑多线程:static变量存在着】:

    void MainWindow::serialRead()  
    {  
        static QByteArray allData;         //静态变量!!在串口只得到一部分的时候用来累加数据  
        QByteArray dataTemp;            	//本次接收的数据,可能是前半部分数据或者后半部分数据(甚至是被分割为多段数据的其中一部分数据),或者也可能是完整数据。
        while (!serial->atEnd()) {  
            QByteArray dataTemp = serial->readAll();                //因为串口是不稳定的,也许读到的是部分数据而已,但也可能是全部数据  
            if( dataTemp.data()[dataTemp.length() - 1] == '~'){     //当临时数据最后一位是'~',代表一条数据读完了  
                allData += dataTemp;                                //总数据加上本次数据  
                allData.resize(allData.size() - 1);                 //删除结尾的~符号  
                qCritical() << allData;                             //这时候allData将是你要的数据  
                allData.clear();                                    //清除数据!!!!!  
            }  
            else                                                  //当最后一位数据不是'~',即未读完  
                allData += dataTemp;                               //每次累加这部分数据,因为还没发完  
        }  
    }  

    展开全文
  • QT5串口编程 发送返回数据

    千次阅读 2018-03-02 16:16:04
    Qt5 串口通信 发送接收 源码例程例程下载源码:源码下载 下面介绍源码:1. 添加到IntSertest.proQT += serialport;如图所示: 2. MainWindow函数中添加:initSeialPort();如图: 3.在析构函数中添加:serial....
  • 第一次接触Qt5中的串口编程,其中遇到了不少麻烦,其中一个就是QSerialPort::pinoutSignals ()。对于本就是Qt菜鸟的我来说,在阅读了很久官方文档后仍旧没明白该函数的用法,努力询问“度娘”也没有得到想要的回复,...
  • 今天想写一个QT5串口编程,能够循环发送数据,想具体到us级别,不需要设置ms发送。所以想用一个线程一直发送。 关键问题是碰到在线程循环发送竟然发不出去,见鬼了。。。最后找到问题是要在每次发送后要判断...
  • Qt5.7串口编程

    2018-07-09 16:22:19
    Qt5.7串口编程Qt5.7串口编程Qt5.7串口编程Qt5.7串口编程Qt5.7串口编程
  • QT4 串口编程

    2014-09-14 10:35:03
    本资料为在基于潜入式Linux操作系统的QT4串口编程,建立线程,实现收发。
  • Qt实现串口编程

    万次阅读 2013-12-08 21:54:08
    windows下Qt实现串口编程的例子,仅作参考(Qt 5.1.1环境下编译运行通过): 工程所需文件如图 所有文件源代码 /************mainwindow.h*************/ #ifndef MAINWINDOW_H #define MAINWINDOW_H #include #...
  • QT串口编程

    2014-08-19 11:15:09
    QT串口编程,实现qt的串口通信,内含源码

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,452
精华内容 1,780
关键字:

qt5串口编程