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也是可以的,并没有添加别的库文件

原文地址:https://www.cnblogs.com/YiYA-blog/p/12021238.html