精华内容
下载资源
问答
  • 多线程串口通信
    2022-08-09 10:26:32

    目标:实现Qt程序在与esp8266进行收发数据的同时通过另一个线程与开发板进行串口通信。

    主线程:发送AT指令连接服务器,将子线程发来的温湿度数据通过串口发送给ESP8266模块。接收来自服务器发来的指令,处理后又发给子线程。(这里要先把esp8266设置成AP模式)

    子线程:接收开发板的温度数据并发给主线程;接收主线程传来的命令并通过串口发送给开发板。

    实现子线程:

    定义一个串口对象,然后用moveToThread()将该对象放在子线程。

    my_thread = new QThread();
    
        port = new QSerialPort();
        init_port();
        this->moveToThread(my_thread);
        port->moveToThread(my_thread);
        my_thread->start();  

    串口配置 :

    定义串口对象,配置波特率、数据位、停止位、奇偶校验等。

     port->setPortName("COM6");                          //串口名 
        port->setBaudRate(115200);                           //波特率
        port->setDataBits(QSerialPort::Data8);             //数据位
        port->setStopBits(QSerialPort::OneStop);           //停止位
        port->setParity(QSerialPort::NoParity);            //奇偶校验
        port->setFlowControl(QSerialPort::NoFlowControl);  //流控制

    主次线程数据传递: 

    通过信号和槽实现。

    connect(local_serial, &SerialPort ::receive_data, this, &MainWindow::on_receive, Qt::QueuedConnection);

    带参信号函数

    signals:
      //发送数据到主线程
      void receive_data(QByteArray tmp);

    接收槽函数

    void MainWindow::on_receive(QByteArray tmpdata)
    {
         QString a=tmpdata.data();
         ui->textEdit_recv->append("温度:"+a[0]+a[1]+"\r\n"+"湿度:"+a[2]+a[3]);
         qDebug()<<"data_to_wifi:"<<tmpdata;
         serial->write(tmpdata);
         serial->waitForBytesWritten(500);
    }

     旋转小风扇:

    通过定时器控制

    void MainWindow::paintEvent(QPaintEvent *e)
    {
        QPainter painter(this);
        painter.setRenderHint(QPainter::SmoothPixmapTransform);
        QImage image(":/a/image/shanye.PNG");
         painter.translate(475, 224);
               painter.rotate(m_nAngle);
             painter.translate(-475, -224); //将原点复位
            painter.drawImage(390,140,image);
    
    }
    void MainWindow::onTimeout()
    {
        if(m_nAngle == 360)
        {
            m_nAngle = 0;
        }
        m_nAngle += 90;
        update();
    }
    
    void MainWindow::startCircle()
    {
        m_pCircleTimer->start();
    }
    void MainWindow::stopCircle()
    {
        m_pCircleTimer->stop();
    }

     

    更多相关内容
  • 串口通信的实现,编程环境为C#,实现技术采用了多线程方式
  • QSerialPort类的串口通讯例程,与单片机通信少不了使用串口进行通信,Qt 也提供了串口通信的类,使用的时候在 pro 添加这句导入模块 QT += serialport
  • 多线程串口通信

    2020-03-10 19:04:55
    串口通信类似于udp通信,是无连接的,所以也要考虑编写心跳等协议 实际开发中根据给定的数据协议和给定的显示功能进行开发,制定相应的数据解析 这里我用通用的串口通信讲解如何快速搭建一个显示单片机或者其他...

    串口通信类似于udp通信,是无连接的,所以也要考虑编写心跳等协议

    实际开发中根据给定的数据协议和给定的显示功能进行开发,制定相应的数据解析

    这里我用通用的串口通信讲解如何快速搭建一个显示单片机或者其他计算机的各种信息


    1.设计协议包的操作类

    #ifndef AGREEMENT_H
    #define AGREEMENT_H
    
    #include <QObject>
    #include <qbytearray.h>
    #include <QMap>
    #include <QVector>
    
    
    
    namespace  协议名{ //可用json读取进行配置
    enum Function {
        WAVE =0x01
    ....
    };
    }
    #define Q_NOTZERO(x) ((x!=0))
    
    typedef struct SendPage{    //发送包
        qint16 initial1 = 0x55;//字头
        qint16 initial2 = 0xbe;//字头
        qint16 packetlength = 0x0c;//包长
        qint16 expressCommand = 0x0;//表示命令
        qint16 function = 0x0;//功能
        ....
        qint16 checkH;//效验H
        qint16 checkL;//效验L
    public:
        QString number(qint16 number);//QString::number
    
        void setExpressCommand(qint16 expressCommand) {
            this->expressCommand = expressCommand;
        }
    
        void  setFunction(qint16 function) {
            this->function = function;
        }
    
        void setData(QVariant data);
    
        SendPage(); 
        void commit( QByteArray & byte) {//根据校验方式进行校验 同样可用使用json配置
    
            checkH = 0;
    
            switch (checkL)
            {
            case 方法1:
                
            case 方法2:
    
                break;
            default:
    
                break;
            }
    
    
            QString _str = QString(number(initial1) + ' '+
                                   number(initial2) + ' '+
                                   number(packetlength) + ' ' +
                                   number(expressCommand) + ' ' +
                                   number(function) + ' ' +
                                    ......
                                   number(fill[0]) + ' ' +
                    number(checkH) + ' ' +
                    number(checkL));
    
    
            SerialPort::String2Hex(_str, byte); //转化为16进制
    
        }
    
    
        void setCheckL(qint16 checkL) {
            this->checkL = checkL;
        }
    
        void setFill(QVector<qint16> data){
            for(int i=0;i<6 && i<data.length();++i)
                this->fill[i]=data.at(i);
        }
    
    
    
    
        qint16 getInitial2() const;
        void setInitial2(const qint16 &value);
    }SendPage;
    
    
    namespace PageHelp //xx为默认校验
    {
    
    void set协议1(QByteArray & byte, qint16 type, QVariant data, qint16 expressCommand, qint16 checkL = xx);
    void set协议2(QByteArray &byte,qint16 type, QVariant data, qint16 expressCommand , qint16 checkL = xx);
    }
    
    
    
    class Agreement :public QObject
    {
        Q_OBJECT
    public:
        explicit  Agreement(){
    
        }
    
        explicit Agreement(QVector<qint16> &vector,QObject *parent = nullptr):QObject(parent) {
            m_vector = vector;
        }
        explicit  Agreement(QObject *parent = nullptr):QObject(parent) {
    
        }
        QVector<qint16> values() const;
        void setVector(const QVector<qint16> &values);
        void append(qint16 value);
    
        Agreement(const Agreement & agreement){
            this->setVector(agreement.values());
        }
        qint16 indexOf(quint16 index){
            if(index>=this->m_vector.length() || index<0){
                return 0;
            }
            return m_vector[index];
        }
    
        void setList(QVector<qint16> & list);
    
        void set(qint16 index,QVariant value);
    
    signals:
        void setupSuccess(qint16 function,qint16 value);
    private:
        QVector<qint16> m_vector;
    };
    
    class 协议1:public Agreement
    {
        Q_OBJECT
    public:
    
        void  onSet(QVector<qint16> data);
    
        qint16 value(AMMONOX::Function function);
        协议1命名空间::Function key(qint16 value);
        协议1(QVector<qint16> &vector,QObject *parent = nullptr);
    signals:
        void sendPage(QByteArray page);
    
    private:
    
        QMap<协议1命名空间::Function,qint16> m_mapFunction;
    };
    
    class 协议2:public Agreement
    {
        Q_OBJECT
    public:
    
        void onSet(QVector<qint16> data);
        协议2命名空间::Function key(qint16 value);
        qint16 value(协议2::Function function);
    
        协议2(QVector<qint16> &vector,QObject *parent = nullptr);
    signals:
        void sendPage(QByteArray page);
    
    private:
    
        QMap<协议2命名空间::Function,qint16> m_mapFunction;
    };
    
    #endif //
    
    

    2.设计串口消息接受发送类

    实际开发过程中,PC性能一般大于下位机所有接受并不是一次就接受所有数据,而是和udp一样分片发送,所以再收发的过程中注意收发频率.

     

    展开全文
  • 模块名称:VC 多线程串口通讯类(MultiThread Com class),说明:主要演示了(Main class):CComPort 串口类的使用,聚合一个CSerialPort类用于串口的操作,接收模式说明(Receive Mode):  1.ManualReceiveByQuery,手动...
  • 在开发串口通讯的时候一直用的微软的,顺序执行,后来找到一个可以用多线程的帮组类,共享给大家,本人测试过xmodel都可以使用 ,调试也很方便,
  • c#编写串口通讯代码多线程实现Prepare serial communication codes multithreading
  • GPS导航系统需要实时获取来自接收机串口的定位数据,在对串口实时监控的同时还可以在前台进行一些其他的操作,利用基于多线程串口通信编程思想方法可以很好地解决这一问题。介绍多线程的基本概念和串口通信编程...
  • [233]多线程串口通讯例子,vc#开发的例子。代码比较简洁。但是有参考价值.zip上位机开发VC串口学习资料源码下载[233]多线程串口通讯例子,vc#开发的例子。代码比较简洁。但是有参考价值.zip上位机开发VC串口学习资料...
  • 异步多线程串口通信

    2018-06-26 17:18:57
    VC实现的多线程实现的串口异步通信 VC实现的多线程实现的串口异步通信
  • 摘 要:GPS导航系统需要实时获取来自接收机串口的定位数据,在对串口实时监控的同时还可以在前台进行一些其他的操作,利用基于多线程串口通信编程思想方法可以很好地解决这一问题。介绍多线程的基本概念和串口通信...
  • 多线程串口通信编程源代码C语言C++Qt编写上位机程序 Thread 源码介绍: 采用Qt的多线程技术,实现了在子线程中进行串口数据收发,采用互斥量实现线程间共享数据的互锁同步,可避免通信数据量大时的界面卡顿问题。...

    多线程串口通信编程源代码C语言C++Qt编写上位机程序
    Thread

    源码介绍:
    采用Qt的多线程技术,实现了在子线程中进行串口数据收发,采用互斥量实现线程间共享数据的互锁同步,可避免通信数据量大时的界面卡顿问题。通信数据格式为带有长度字段的可变长接口协议,包括头部、长度、校验等基本功能。6725627049465235TB_68875679

    开发环境是Qt5,使用Qt自带的QSerialPort。源代码中包含注释,设计说明文档等。
    代码特点:
    1、尽量贴合实际应用,细节考虑周到。
    2、注释完善,注重讲解,为便于学习,还增加了扩展知识点介绍。
    3、提供代码设计文档,使用文档,环境配置文档等。
    功能如下:
    采用多线程技术,数据收发处理在子线程内,避免主界面卡顿;
    支持常间的自定义报文格式,包括定长和可变长;
    具备定时发送及无应答超时提示功能;
    请添加图片描述
    请添加图片描述
    请添加图片描述
    请添加图片描述
    请添加图片描述
    请添加图片描述
    请添加图片描述
    请添加图片描述

    展开全文
  • 基于MFC开发的串口通信,技术用到API,和多线程开发串口通信
  • 多线程串口通讯实例源码分析,主要是在windows下 用MFC编程 实现excel读数据
  • Qt多线程串口通信源码

    热门讨论 2010-08-14 00:18:47
    采用Qt4.6.2编写的linux系统下的开源串口通信程序。使用开源的posix_qextserialport类
  • 原生 PB9 通过 API 实现多线程串口 COM 通讯。 1、Powerbuilder9.0_8836的版本 2、采用API,支持串口信号事件 3、事件监听、读字符,写字符都是采用的是多线程 4、多线程用的是PB的shareobject方法,不会crash。 5、...
  • 多线程串口通信 MFC CSerialPort

    千次阅读 2016-09-12 18:15:13
    原文转载自... 以下全为转载: ... 晚上应该继续完成未写完的代码,但Chrome上打开的标签实在太了,约30个了,必须关掉一些,所以需要把自己看的整理一下然后关掉。本次主要写点MF

    原文转载自http://www.cnblogs.com/xingrun/p/3587144.html?utm_source=tuicool&utm_medium=referral。


    以下全为转载:

    写在前面:

             晚上应该继续完成未写完的代码,但Chrome上打开的标签实在太多了,约30个了,必须关掉一些,所以需要把自己看的整理一下然后关掉。本次主要写点MFC环境下多线程串口通信相关的东西,这包括线程创建及控制、串口同步异步操作、内存非法访问(或者说是线程同步)、线程通信、Windows消息响应过程等。

    遇到问题:

             项目中IO传感器通信模块之前直接写在了主线程中,UI代码和串口通信代码搅合在一起,不利于后期维护,而且有个非常严重的问题,IO通信太忙导致整个系统比较卡,特别是当系统接上超过3个摄像机之后,MFC模态对话框使用Domodal()直接无法打开,卡住了,然后用户就无法操作了,这个问题必须要解决。

    解决方案:

             单独开辟一个线程来处理所有的串口通信,该IO线程和主线程(负责UI部分)通信,从而更新状态,不能子线程中直接更新UI,参看《MFC最好不要在子线程中操控界面上的控件》。

    具体步骤:

    1.创立IO线程并完成消息响应

    1
    2
    HANDLE  hThread1 = CreateThread( NULL,0,IOControlProc,( LPVOID )(m_pCOMSerialPort),0,&m_dwIOControlThreadId ); //创建IO线程
    CloseHandle( hThread1 ); //关闭线程句柄

      其中

    1
    2
    CSerialPort  *m_pCOMSerialPort; //通信串口
    DWORD  m_dwIOControlThreadId; //线程ID

      IOControlProc线程函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    DWORD  WINAPI IOControlProc( LPVOID  lpParameter)
    {
         CSerialPort *pSerialPort = (CSerialPort*)lpParameter;
         UINT_PTR  nHUMITimer = 0;
         UINT_PTR  nIOTimer = 0;
         //::SetTimer(NULL,NULL,200,(TIMERPROC)TimerProc);
         nHUMITimer = ::SetTimer(NULL,TEMPHUMICOMM_TIMER,500,(TIMERPROC)OnIOTimer); //温湿度
         nIOTimer =::SetTimer(NULL,IOCOMM_TIMER,100,(TIMERPROC)OnIOTimer); //IO
         PIOTimerStru pHumiTimer=  new  IOTimerStru;
         pHumiTimer->nIdEvent = TEMPHUMICOMM_TIMER;
         pHumiTimer->pSerialPort = pSerialPort;
         PIOTimerStru pIoTimer =  new  IOTimerStru;
         pIoTimer->nIdEvent = IOCOMM_TIMER;
         pIoTimer->pSerialPort = pSerialPort;
         PIOTimerStru pIoControl =  new  IOTimerStru;
         pIoControl->nIdEvent = TEMPHUMICOMM_TIMER + IOCOMM_TIMER;
         pIoControl->pSerialPort = pSerialPort;
         LPARAM    lParam;
         MSG msg;
         while (GetMessage(&msg,NULL,0,0))
         {
             TranslateMessage(&msg);
             if  (WM_TIMER == msg.message)
             {
                 lParam = msg.lParam; //WM_TIMER回调函数的地址
                 if  (nHUMITimer == msg.wParam)
                 {
                     msg.wParam = ( WPARAM )pHumiTimer;
                 }
                 else  if  (nIOTimer == msg.wParam)
                 {
                     msg.wParam = ( WPARAM )pIoTimer;
                 }          
             }  
             else  if  (WM_IOCOMMDATA == msg.message)
             {
                 msg.message = WM_TIMER;
                 pIoControl->wParam = msg.wParam;
                 pIoControl->lParam = msg.lParam;
                 msg.wParam = ( WPARAM )pIoControl;
                 msg.lParam = lParam;
             }      
             DispatchMessage(&msg);
         }
         delete  pHumiTimer;
         delete  pIoTimer;
         delete  pIoControl;
         return  0;
    }

      这里,IO线程有自己的消息循环队列(虽然没有窗口),参看:《子线程里如何使用定时器》,把这里的代码改成死循环的(参看《是否在子线程内使用SetTimer?》),如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    VOID  CALLBACK TimerProc(           HWND  hwnd,
         UINT  uMsg,
         UINT_PTR  idEvent,
         DWORD  dwTime
    ){
              //do some thing
              return ;
    }
     
    DWORD  WINAPI ThreadProc( LPVOID  lpParameter)
    {
           
         ::SetTimer(NULL,NULL,200,(TIMERPROC)TimerProc);
         MSG msg;
         while (GetMessage(&msg,NULL,0,0))
         {
             TranslateMessage(&msg);
             DispatchMessage(&msg);
         }
         return  0;
         
    }

      我的消息响应函数写成如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    VOID  CALLBACK OnIOTimer( HWND  hwnd, UINT  uMsg, UINT_PTR  idEvent, DWORD  dwTime)
    {
         PIOTimerStru pStru = (PIOTimerStru)idEvent;
         if  (pStru->nIdEvent == TEMPHUMICOMM_TIMER) //温湿度模块
         {
             static  bool  bFlag =  true ;
             if  (bFlag)
             {
                 IOSendData(pStru->pSerialPort,2,0x0A,0,0x03);
             }
             else
             {
                 IOSendData(pStru->pSerialPort,2,0x0A,0,0x04);
             }
             bFlag = !bFlag;
         }
         else  if  (pStru->nIdEvent == IOCOMM_TIMER) //IO控制模块
         {
             IOSendData(pStru->pSerialPort,1,0x10,0,0x03);
         }
         else  if  (pStru->nIdEvent ==  TEMPHUMICOMM_TIMER + IOCOMM_TIMER) //别的线程发送的指令
         {      
             WORD  highDeviceIndex = HIWORD(pStru->wParam); //设备号
             WORD  lowPortIndex = LOWORD(pStru->wParam); //设备1端口号,设备2指定温度或湿度模块
             WORD  highParam = HIWORD(pStru->lParam); //设备1指定状态1或者0,设备2指定整数部分
             WORD  lowParam = LOWORD(pStru->lParam); //设备1为0,设备2指定小数部分
     
             IOSendData(pStru->pSerialPort,( int )highDeviceIndex,( BYTE )highParam,( BYTE )lowParam,( BYTE )lowPortIndex);
         }
         return ;
    }

      这里要注意一个问题,OnIOTimer中获得的idEvent并不是我们设置的IOCOMM_TIMER或者TEMPHUMICOMM_TIMER,究其原因,参看《SetTimer在无窗口和有窗口线程的使用》,文中关于原因的解释为“注:只有当hWnd参数为非空时,计时器的ID为设置的 nIDEvent, 系统为你自动生成一个计时器ID,可由返回时值获取.”,可由MSDN得知。

    那么我们的这个IOCOMM_TIMER或者TEMPHUMICOMM_TIMER,怎么传递过去呢?查看《怎么往SetTimer的回调函数传递参数》得知,我们可由msg.wParam传递。

    那么对于我们自定义的消息TEMPHUMICOMM_TIMER + IOCOMM_TIMER,我也想让OnIOTimer来处理怎么办?直接修改msg.message = WM_TIMER;就可以了嘛?答案是不行的!

    为什么呢?参看《消息循环中的TranslateMessage函数和DispatchMessage函数》,原来“如果参数lpmsg指向一个WM_TIMER消息,并且WM_TIMER消息的参数IParam不为NULL,则调用IParam指向的函数,而不是调用窗口程序。”,那么我们直接修改msg.lParam为OnIOTimer函数的地址就行了。这样,所有消息响应完成了。

    2.多线程访问冲突(线程冲突)
    遇到一个问题,系统有一个串口通信端口,IO线程直接使用了,然后我在主线程中也发送数据,然后问题出现了,有时候会出现非法访问,跟踪了一下,原来两个线程使用了同一个串口通信缓冲区,主线程往里面压入数据的时候,可能子线程已经释放了该缓冲区,查询文章《CSerialPort连续发送大量数据时出错原因分析》,而我使用的CSerialPort是同步的,我尝试修改类库代码,报错太多,此方法放弃。最终,我的解决方法是把所有的串口IO通信全部交给子线程来做,那么主线程要做的事,可以通过发送消息给子线程,再由子线程代劳,主线程怎么发送消息给子线程?使用API函数PostThreadMessage来完成,第一个参数就是子线程的Id。

    子线程收到数据后,进行验证,验证通过后,发消息给主线程,通知它更新界面。《主线程与子线程间通信解决办法 - VC/MFC

    3.主线程退出前,关闭子线程

    1
    2
    PostThreadMessage(m_dwIOControlThreadId,WM_QUIT,0,0);
    Sleep(100); //需要等待关闭掉

    GetMessage有消息时且消息不为WM_QUIT时返回TRUE,如果有消息且为WM_QUIT则返回FALSE,没有消息时不返回。  

    这里可参看《如何正确的关闭 MFC 线程》和《GetMessage和PeekMessage的联系与区别以及用法 TranslateMessage与DispatchMessage 

    至此,经测试问题全部解决,记录一下。


    展开全文
  • 多线程串口通信.pdf

    2021-10-20 06:29:55
    多线程串口通信.pdf
  • 多线程串口通信技术及应用.pdf
  • VC 多线程串口通讯源码,测试方法:选择本机可用的串口,可同进打开多个可用的串口,还可以设置数据位、停止位、校验、波特率,往指定端口发送接收数据等。在VC6.0环境下可顺利编译。
  • 多线程串口通讯

    2014-10-21 00:20:27
    * 模块名称:多线程串口通讯类(MultiThread Com class) * 主要类说明(Main class): * CComPort 串口类 内聚合一个CSerialPort类用于串口的操作 * 接收模式说明(Receive Mode): * 1.ManualReceiveByQuery, //手动...
  • 【转】Qt 多线程串口通信问题?

    千次阅读 2019-03-19 10:41:19
    现在我的项目关于线程串口通信这里出了很问题。思路现在就是我首先自己封装了QSerialport的open、read、write函数,然后在通信层中开了 一个线程,在这个线程的构造函数中new了我封的serialport,并且就在这里...
  • Qt练习:多线程串口通信

    千次阅读 2020-04-06 22:14:42
    最近在学习Qt编程,为了练手,想做一个串口通信的小软件为之后的项目做准备,经过几天的学习与练习初步搭建起了多线程串口通信的框架及较少的其他功能 功能简介 串口接收 主线程显示ui,子线程接收串口数据,数据...
  • 主要完成:根据特定的通信协议实现串口与PC上特定串口通信软件的通信。测试版,只是完成主要框架,没有完全将协议的所有通信方式方法做完。其中包含的测试功能有:监听主机(PC上的软件)发送的特定请求,能够识别...
  • C#基于事件驱动的多串口多线程串口通讯软件架构设计[归纳].pdf
  • 多线程串口通信技术在DNC系统中的应用.pdf
  • 多线程串口通信技术在GPS导航中的应用.pdf
  • QT_串口多线程通讯

    千次阅读 2022-02-18 08:36:16
    架构说明:UI主界面定时发送读写信号,触发逻辑线程执行串口读写操作,并返回处理后的数据,由UI界面显示。 特点: 1.创建一个逻辑工作类 2.用moveToThread方法将工作类放入到线程中 3.UI主界面与线程的一切沟通...
  • 多线程串口通信技术在北斗导航中的运用分析.pdf

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 15,761
精华内容 6,304
关键字:

多线程串口通信