zoukankan      html  css  js  c++  java
  • CY7C68013_AD5933_上位机

    目录

    1、CreateEvent()

    2、OVERLAPPED结构体

    3、Qt多线程

         (1) 使用重写QTread类中的虚函数:run()

         (2)使用一个槽函数运行所有的线程代码

    4、Qt添加CyAPI.lib库

    1、CreateEvent()控制线程

    (1)CreateEvent()函数相关

    CreateEvent是一个Windows API函数。它用来创建或打开一个命名的或无名的事件对象。可以在一个线程的执行函数中创建一个事件对象,然后观察它的状态,“有信号”(触发,开,true),如果是”无信号”(未触发,关,false)就让该线程睡眠,这样该线程占用的CPU时间就比较少:

    HANDLE    CreateEvent
    (        
      LPSECURITY_ATTRIBUTES     lpEventAttributes,     // SD 一般为空        
      BOOL     bManualReset,                           //  reset   type 事件是自动复位(false)还是人工复位(true)        
      BOOL     bInitialState,                          //     initial state   初始状态,有信号(true),无信号(false)        
      LPCTSTR     lpName                           //     object  name   事件对象名称      );  
    
    ******

    代码中CreateEvent默认初始状态是true即有信号状态,当执行waitForSingleObject时不会等待。 并且是自动复位的,在执行waitForSingleObject之后会变成未触发(无信号)状态。

    bManualReset:TRUE,使用ResetEvent()手动重置为无信号状态;FALSE,当一个等待线程被释放时,自动重置状态为无信号状态。
    
    bInitialState:指定事件对象的初始状态,当TRUE,初始状态为有信号状态;当FALSE,初始状态为无信号状态。
     1 lpEventAttributes[输入]
     2 一个指向SECURITY_ATTRIBUTES结构的指针,确定返回的句柄是否可被子进程继承。如果lpEventAttributes是NULL,此句柄不能被继承。
     3 Windows NT/2000:lpEventAttributes的结构中的成员为新的事件指定了一个安全符。如果lpEventAttributes是NULL,事件将获得一个默认的安全符。
     4 bManualReset[输入]
     5 指定将事件对象创建成手动复原还是自动复原。如果是TRUE,那么必须用ResetEvent函数来手工将事件的状态复原到无信号状态。如果设置为FALSE,当一个等待线程被释放以后,系统将会自动将事件状态复原为无信号状态。
     6 bInitialState[输入]
     7 指定事件对象的初始状态。如果为TRUE,初始状态为有信号状态;否则为无信号状态。
     8 lpName[输入]
     9 指定事件的对象的名称,是一个以0结束的字符串指针。名称的字符格式限定在MAX_PATH之内。名字是对大小写敏感的。
    10 如果lpName指定的名字,与一个存在的命名的事件对象的名称相同,函数将请求EVENT_ALL_ACCESS来访问存在的对象。这时候,由于bManualReset和bInitialState参数已经在创建事件的进程中设置,这两个参数将被忽略。如果lpEventAttributes是参数不是NULL,它将确定此句柄是否可以被继承,但是其安全描述符成员将被忽略。
    11 如果lpName为NULL,将创建一个无名的事件对象。
    参数含义

    (2)Event相关

        一个Event被创建以后,可以用OpenEvent()来获得它的Handle,用CloseHandle()来关闭它(在主线程中使用CloseHandle()函数,很有可能导致子线程的Event对象信号控制机制失效,但需要将Event关闭,否则容易造成句柄泄漏问题,故合理使用关闭句柄函数);用SetEvent()或PulseEvent()来设置它使其有信号,用ResetEvent() 来使其无信号,用WaitForSingleObject()或WaitForMultipleObjects()来等待其变为有信号.
         SetEvent(HANDLE hEvent );   PulseEvent(HANDLE hEvent );   ResetEvent(HANDLE hEvent );

         PulseEvent()是一个比较有意思的使用方法,正如这个API的名字,它使一个Event 对象的状态发生一次脉冲变化,从无信号变成有信号再变成无信号,而整个操作是原子的.
    对自动复位的Event对象,它仅释放第一个等到该事件的thread(如果有),而对于人工复位的Event对象,它释放所有等待的thread.

         这里有两个API函数用来修改事件对象的信号状态:SetEvent和ResetEvent。前者把事件对象设为”有信号”状态,而后者正好相反。
         在事件对象生成后,必须调用WaitForSingleObject来让线程进入等待状态,该函数的语法如下:

      WaitForSingleObject(HANDLE hHandle,DWORD dwMilliseconds);

      hHandle-->指向同步对象的指针。事件对象其实是同步对象的一种。
      dwMilliseconds--> 等待同步对象变成”有信号”前等待的时间,以毫秒计。当等待的时间超过该值后无信号同步对象仍处于”无信号”状态,线程不再等待,                  WaitForSingleObject函数会返回WAIT_TIMEOUT。如果想要线程一直等待,请把该参数设为INFINITE(该值等于0xffffffff)为一直等待。

    参考博客:

    https://blog.csdn.net/richerg85/article/details/7471426  有具体例子

    https://blog.csdn.net/u011028345/article/details/78358324  定义

    2、OVERLAPPED结构体

    OVERLAPPED即OVERLAPPED是一个包含了用于异步输入输出的信息的结构体。

    I/O设备处理必然让主程序停下来干等I/O的完成,解决这个问题,可以使用OVERLAPPED。
    OVERLAPPED I/O是WIN32的一项技术, 你可以要求操作系统为你传送数据,并且在传送完毕时通知你。这项技术使你的程序在I/O进行过程中仍然能够继续处理事务。事实上,操作系统内部正是以线程来I/O完成OVERLAPPED I/O。你可以获得线程的所有利益,而不需付出什么痛苦的代价。也就是说,OVERLAPPED主要是设置异步I/O操作,异步I/O操作是指应用程序可以在后台读或者写数据,而在前台做其他事情。

    第一种声明:

    typedef struct _OVERLAPPED
     { 
      DWORD Internal; 
      DWORD InternalHigh; 
      DWORD Offset; 
      DWORD OffsetHigh; 
      HANDLE hEvent; 
    } OVERLAPPED
    1 Internal: 预留给操作系统使用。它指定一个独立于系统的状态,当GetOverlappedResult函数返回时没有设置扩展错误信息ERROR_IO_PENDING时有效。
    2 InternalHigh: 预留给操作系统使用。它指定长度的数据转移,当GetOverlappedResult函数返回TRUE时有效。
    3 Offset: 该文件的位置是从文件起始处的字节偏移量。调用进程设置这个成员之前调用ReadFile或WriteFile函数。当读取或写入命名管道和通信设备时这个成员被忽略设为零。
    4 OffsetHigh: 指定文件传送的字节偏移量的高位字。当读取或写入命名管道和通信设备时这个成员被忽略设为零。
    5 hEvent: 在转移完成时处理一个事件设置为有信号状态。调用进程集这个成员在调用ReadFile、 WriteFile、TransactNamedPipe、 ConnectNamedPipe函数之前。
    参数说明

    第二种声明:

    typedef struct _OVERLAPPED 
    {
        ULONG_PTR Internal; //操作系统保留,指出一个和系统相关的状态
        ULONG_PTR InternalHigh; //指出发送或接收的数据长度
        union 
        {
             struct 
            {
                DWORD Offset; //文件传送的字节偏移量的低位字
                DWORD OffsetHigh; //文件传送的字节偏移量的高位字
             };
             PVOID Pointer; //指针,指向文件传送位置
          };
        HANDLE hEvent; //指定一个I/O操作完成后触发的事件
    } OVERLAPPED, *LPOVERLAPPED;                                               

    3、Qt多线程

    (1) 使用重写QTread类中的虚函数:run()

    新建一个类并继承QThread,然后重新改写类QThread中的虚函数run()。当要开启新线程时,只需要实例该类(即创建该类的对象),然后调用函数start(),就可以开启一条多线程(执行run()中的代码)

    创建多线程步骤如下:

    a1新建一个类MyThread,基类为QThread。

    a2重写类MyThread的虚函数void run();,即新建一个函数protected void run(),然后对其进行定义。

    a3在类MyThread中定义方法clseThread(),并定义标志位isStop,在run()函数中判断isStop的状态,如果为ture则退出线程(即退出run()函数)

    a3在需要用到多线程的地方,实例MyThread,然后调用函数MyThread::start()后,则开启一条线程,即自动运行函数run()。

    a4当停止线程时,调用MyThread::wait()函数,等待线程结束,并且回收线程资源。

    1)创建一个Qt工程,并放入两个按钮进去;

    2)新建一个MyThread类,先新建一个mythread.h文件和mythread.cpp文件,自己定义run()和closeThread()方法,并定义线程结束或者是开始标志位isStop

     1 #ifndef MYTHREAD_H
     2 #define MYTHREAD_H
     3 
     4 #include <QThread>
     5 
     6 class MyThread : public QThread
     7 {
     8 private:
     9     volatile bool isStop;        //volatile关键字确保本条指令不会因为编译器的优化而省略
    10 protected:
    11     virtual void run();
    12 public:
    13     MyThread();         //构造函数
    14     void closeThread();
    15 };
    16 
    17 #endif // MYTHREAD_H
    mythread.h
     1 #include "mythread.h"
     2 #include <QDebug>
     3 #include <QMutex>
     4 
     5 //构造函数,对私有变量进行初始化
     6 MyThread::MyThread()
     7 {
     8     isStop=false;
     9 }
    10 
    11 void MyThread::run()
    12 {
    13     isStop=false;    //如果不加上这一句,在第二次运行时,isStop就保持了上一次等于true的状态,从进入run函数只有就退出了
    14     while(1)
    15     {
    16         if(isStop)
    17             return;  //退出run()函数
    18         qDebug()<<tr("mythread Qthread::currentThreadId()=")<<QThread::currentThreadId();
    19         sleep(1);
    20     }
    21 }
    22 
    23 void MyThread::closeThread()
    24 {
    25     isStop=true;
    26 }
    mythread.cpp

    3)编写widget.h和widget.cpp

     1 #ifndef WIDGET_H
     2 #define WIDGET_H
     3 
     4 #include <QWidget>
     5 #include "mythread.h"
     6 #include <QDebug>
     7 
     8 namespace Ui {
     9 class Widget;
    10 }
    11 
    12 class Widget : public QWidget
    13 {
    14     Q_OBJECT
    15 
    16 public:
    17     explicit Widget(QWidget *parent = 0);
    18     ~Widget();
    19 private slots:
    20     void openThreadBtnSlot();        //打开线程按钮对应的槽函数
    21     void closeThreadBtnSlot();       //关闭线程按钮对应的槽函数
    22     void finishedThreadBtnSlot();    //线程结束会发出一个finished()信号,该信号对应这个槽函数
    23 
    24 private:
    25     Ui::Widget *ui;
    26     MyThread *thread1;  //创建线程对象
    27 };
    28 
    29 #endif // WIDGET_H
    widget.h
     1 #include "widget.h"
     2 #include "ui_widget.h"
     3 
     4 
     5 Widget::Widget(QWidget *parent) :
     6     QWidget(parent),
     7     ui(new Ui::Widget)
     8 {
     9     ui->setupUi(this);
    10 
    11     thread1 = new MyThread;  //线程初始化
    12 
    13     connect(ui->StartThreadPushButton,SIGNAL(clicked(bool)),this,SLOT(openThreadBtnSlot()));  //关联线程打开按钮和开启线程的槽函数
    14     connect(ui->QuitThreadPushButton,SIGNAL(clicked(bool)),this,SLOT(closeThreadBtnSlot()));  //关联线程关闭按钮和关闭线程的槽函数
    15     connect(thread1,SIGNAL(finished()),this,SLOT(finishedThreadBtnSlot()));  //关联线程结束信号finished()和该信号对应的槽函数
    16 }
    17 
    18 //打开线程对应的槽函数
    19 void Widget::openThreadBtnSlot()
    20 {
    21     thread1->start();  //开启thread1对应的线程,执行类MyTread中的run()
    22     qDebug()<<tr("Main Thread id: ")<<QThread::currentThreadId();
    23 }
    24 
    25 //关闭线程对应的槽函数
    26 void Widget::closeThreadBtnSlot()
    27 {
    28     thread1->closeThread();  //关闭线程thread1,即不再执行MyThread类中的槽函数
    29     thread1->wait();
    30 }
    31 
    32 //关闭线程后会触发线程的一个finished()信号,该信号对应下面的这个槽函数
    33 void Widget::finishedThreadBtnSlot()
    34 {
    35     qDebug()<<tr("Thread End Signal finished() has benn touched");
    36 }
    37 
    38 Widget::~Widget()
    39 {
    40     delete ui;
    41 }
    widget.cpp

    运行结果:

     参考博客:

    https://blog.csdn.net/naibozhuan3744/article/details/81174681

    (2)使用一个槽函数运行所有的线程代码

    新建一个类Mythrea,并继承对象QObject,来实现多线程。

    利用继承QObject方法创建多线程,主要的步骤有一下几点:(注意:退出线程循环后,还要调用QThread::quit()函数,该线程才会触发QThread::finished()信号)

    a1:首先创建一个类MyThread,基类为QObject。

    a2:在类MyThread中创建一个槽函数,用于运行多线程里面的代码。所有耗时代码,全部在这个槽函数里面运行。在MyThread类中新建一个closeThread()共有函数,用于关闭线程(退出MyThread类中用于执行线程 代码的槽函数)

    a3:实例一个QThread线程对象(容器),将类MyThread的实例对象转到该容器中,用函数void QObject::moveToThread(QThread *thread);

    1 myThread->moveToThread(thread1);  //thread1是QThread类对象,myThread是MyThread类对象

    a4:用一个信号触发该多线程槽函数,比如用QThread::started()信号。

    1 connect(thread1,SIGNAL(started()),myThread,SLOT(startThreadSlot()));  //startThreadSlot()是MyThread类中用于执行线程代码的槽函数

    a5:用信号QThread::finished绑定槽函数QThread::deleteLatater(),在线程退出时,销毁该线程和相关资源。

    1 connect(thread1,SIGNAL(finished()),myThread,SLOT(deleteLater()));  //deleteLater()是QObject类中的一个函数

    a6:所有线程初始化完成后,启动函数QThread::start()开启多线程,然后自动触发多线程启动信号QThread::started()。

     1 #ifndef MYTHREAD_H
     2 #define MYTHREAD_H
     3 
     4 #include <QObject>
     5 
     6 class MyThread : public QObject
     7 {
     8     Q_OBJECT
     9 private:
    10     volatile bool isStop;                               //volatile关键字确保本条指令不会因为编译器的优化而省略
    11 
    12 public:
    13     explicit MyThread(QObject *parent = nullptr);      //构造函数
    14     void closeThread();  //关闭线程
    15 
    16 public slots:
    17     void startThreadSlot();                            //开启线程槽函数
    18 };
    19 
    20 #endif // MYTHREAD_H
    mythread.h
     1 #include "mythread.h"
     2 #include <QDebug>
     3 #include <QTHread>
     4 
     5 //构造函数,对私有变量进行初始化
     6 MyThread::MyThread(QObject *parent) : QObject(parent)
     7 {
     8     isStop=false;
     9 }
    10 
    11 void MyThread::startThreadSlot()
    12 {
    13     isStop=false;    //如果不加上这一句,在第二次运行时,isStop就保持了上一次等于true的状态,从进入run函数只有就退出了
    14     while(1)
    15     {
    16         if(isStop)
    17             return;  //退出run()函数
    18         qDebug()<<tr("mythread Qthread::currentThreadId()=")<<QThread::currentThreadId();
    19         QThread::sleep(1);
    20     }
    21 }
    22 
    23 //关闭线程
    24 void MyThread::closeThread()
    25 {
    26     isStop=true;
    27 }
    mythread.cpp
     1 #ifndef WIDGET_H
     2 #define WIDGET_H
     3 
     4 #include "mythread.h"
     5 #include <QWidget>
     6 #include <QThread>
     7 #include <QDebug>
     8 
     9 namespace Ui {
    10 class Widget;
    11 }
    12 
    13 class Widget : public QWidget
    14 {
    15     Q_OBJECT
    16 
    17 public:
    18     explicit Widget(QWidget *parent = 0);
    19     ~Widget();
    20 private slots:
    21     void openThreadBtnSlot();        //打开线程按钮对应的槽函数
    22     void closeThreadBtnSlot();       //关闭线程按钮对应的槽函数
    23     void finishedThreadBtnSlot();    //线程结束会发出一个finished()信号,该信号对应这个槽函数
    24 
    25 private:
    26     Ui::Widget *ui;
    27     QThread *thread1;
    28     MyThread *myThread;
    29 };
    30 
    31 #endif // WIDGET_H
    widget.h
     1 #include "widget.h"
     2 #include "ui_widget.h"
     3 #include <QThread>
     4 
     5 Widget::Widget(QWidget *parent) :
     6     QWidget(parent),
     7     ui(new Ui::Widget)
     8 {
     9     ui->setupUi(this);
    10 
    11     connect(ui->StartThreadPushButton,SIGNAL(clicked(bool)),this,SLOT(openThreadBtnSlot()));  //关联线程打开按钮和开启线程的槽函数
    12     connect(ui->QuitThreadPushButton,SIGNAL(clicked(bool)),this,SLOT(closeThreadBtnSlot()));  //关联线程关闭按钮和关闭线程的槽函数
    13 
    14 }
    15 
    16 //开始线程按钮对应的槽函数
    17 void Widget::openThreadBtnSlot()
    18 {
    19     qDebug()<<tr("statr thread");
    20     thread1 = new QThread;      //线程容器初始化
    21     myThread = new MyThread;    //初始化
    22 
    23     myThread->moveToThread(thread1);  //将创建的对象移到线程容器thread1中去
    24 
    25     connect(thread1,SIGNAL(finished()),myThread,SLOT(deleteLater()));  //线程终止时要调用deleteLater槽函数,deleteLater()是QObject类中的槽函数
    26     connect(thread1,SIGNAL(started()),myThread,SLOT(startThreadSlot()));  //关联线程thread1开始信号和myThread中的槽函数,startThreadSlot()是MyThread类中的槽函数
    27     connect(thread1,SIGNAL(finished()),this,SLOT(finishedThreadBtnSlot()));  //关联线程结束信号finished()和该信号对应的槽函数,finishedThreadBtnSlot()是Widget类中的槽函数
    28 
    29     thread1->start();    //开启线程,执行MyThread类中的槽函数startThreadSlot()
    30     qDebug()<<"mainWidget QThread::currentThreadId()="<<QThread::currentThreadId();
    31 }
    32 
    33 //关闭线程对应的槽函数
    34 void Widget::closeThreadBtnSlot()
    35 {
    36     qDebug()<<"close the thread";
    37     if(thread1->isRunning())
    38     {
    39         myThread->closeThread();  //关闭线程槽函数
    40         thread1->quit();          //退出循环事件
    41         thread1->wait();          //释放线程槽函数资源
    42     }
    43 }
    44 
    45 //关闭线程后会触发线程的一个finished()信号,该信号对应下面的这个槽函数
    46 void Widget::finishedThreadBtnSlot()
    47 {
    48     qDebug()<<tr("Thread End Signal finished() has benn touched");
    49 }
    50 
    51 Widget::~Widget()
    52 {
    53     delete ui;
    54 }
    widget.cpp

    运行结果:

     参考博客:

    https://blog.csdn.net/naibozhuan3744/article/details/81201502

    4、Qt添加CyAPI.lib库

    (1)在C:CypressCypress Suite USB 3.4.7CyAPIlibx64路径下找到CyAPI.lib文件放到工程路径下,后执行下面的操作:

    (2)添加步骤

            

    #pragma comment(lib,*User32.lib)

    上图还是把“为debug版本添加'd'作为后缀去掉吧”

    然后会报错:CyAPId.lib文件不存在,解决方法如下:

      -> ->

    错误即可消失,刚刚完成库添加之后可能执行qmake是灰色的的,但是等一会是可以的

    但是只是添加CyAPI.lib也是可以的,并没有添加别的库文件

  • 相关阅读:
    设计模式之工厂模式
    面向对象的五大原则
    抽象类和接口、类库
    静态
    面向对象三大特性
    JVM(Java虚拟机)优化大全和案例实战
    Java调用Lua脚本(LuaJava使用、安装及Linux安装编译)
    Java调用.dll文件
    linux yum命令详解
    linux nohup命令
  • 原文地址:https://www.cnblogs.com/YiYA-blog/p/12021238.html
Copyright © 2011-2022 走看看