QT线程编程

编程入门 行业动态 更新时间:2024-10-19 22:40:56

QT<a href=https://www.elefans.com/category/jswz/34/1771240.html style=线程编程"/>

QT线程编程

转自: /
下面讲述原理,也可以下载完整实验源码: 源码下载
前言 QT没有提供串口类,使用的是linux提供的函数。 linux下设备和文件使用一样,用open函数打开串口,设置等都提供了函数的,需要自己组合一下,封装成你要的函数。
1.QT串口发送数据 要使用串口,需先打开串口,封装的函数如下:

int open_port(const char* dev_path)
{
int fd;

//open uart
fd = open(dev_path, O_RDWR|O_NOCTTY|O_NDELAY);
if(fd < 0)
{
perror("open serial port");
return -1;
}
if(fcntl(fd, F_SETFL, 0) < 0)//设置为阻塞模式,后面启动的线程会阻塞,串口有数据才读
perror("fcntl F_SETFL\n");
/*if(isatty(STDIN_FILENO) == 0)//再次验证是否为终端设备,我用的刷卡器,屏蔽了这个,不然会失败
{
perror("standard inpput is not a terminal device");
}*/

return fd;
}

接下来需要设置串口的波特率、校验、结束位等,封装的函数如下:

int set_com_config(int fd, int baud_rate, int data_bits, char parity, int stop_bits)
{
struct termios new_cfg, old_cfg;
int speed;
int returnvalue;

returnvalue = tcgetattr(fd, &old_cfg);//save current uart configure
if(returnvalue < 0)
{
perror("tcgetattr:tcsetattr()1");
return -1;
}

new_cfg = old_cfg;//直接获取串口的所有数据到新配置,省去了一些参数的手动设置
cfmakeraw(&new_cfg);//config as orignal mode: recevice byte one by one
new_cfg.c_cflag &= ~CSIZE;//clear c_cflag

switch(baud_rate)
{
case 2400:
speed = B2400;break;
case 4800:
speed = B4800;break;
case 9600:
speed = B9600;break;
case 19200:
speed = B19200;break;
case 38400:
speed = B38400;break; 
default:
case 115200:
speed = B115200;break;
}
cfsetispeed(&new_cfg, speed);//set in baud_rate
cfsetospeed(&new_cfg, speed);//set out baud_rate;

switch(data_bits)//set data bits
{
case 7:
new_cfg.c_cflag |= CS7;break;
default:
case 8:
new_cfg.c_cflag |= CS8;break;
}

switch(parity)//set parity
{
default:
case 's':
case 'S':
{
new_cfg.c_cflag &= ~PARENB;
new_cfg.c_cflag &= ~INPCK;
}break;

case 'o':
case 'O':
{
new_cfg.c_cflag |= (PARODD | PARENB);
new_cfg.c_cflag |= INPCK;
}break;

case 'e':
case 'E':
{
new_cfg.c_cflag |= PARENB;
new_cfg.c_cflag &= ~PARODD;
new_cfg.c_cflag |= INPCK;
}break;

case 'n':
case 'N':
{
new_cfg.c_cflag &= ~PARENB;
new_cfg.c_cflag &= ~CSTOPB;
}break;

}

switch(stop_bits)//set stop bits
{
default:
case 1:
new_cfg.c_cflag &= ~CSTOPB;break;
case 2:
new_cfg.c_cflag |= CSTOPB;break;
}

//set wait time and min recevice byte
new_cfg.c_cc[VTIME] = 0;
new_cfg.c_cc[VMIN] = 1;

tcflush(fd, TCIFLUSH);//清除数据

returnvalue = tcsetattr(fd, TCSANOW, &new_cfg);//激活配置
if(returnvalue < 0)
{
perror("tcsetattr:tcsetattr()2");
return -1;
}

return 0;
}


发送数据:

write(fd_com, buff, strlen(buff));//发送



2.QT线程编程 接收数据需要用一个线程,比较方便。 新建一个类,继承于QThread, 实现其中的 run 虚函数就大功告成, 用的时候创建该类的实例,调用它的 start 方法即可。但是 run 函数使用时有一点需要注意,即在其中不能创建任何 gui 线程(诸如新建一个 QWidget 或者 QDialog )。如果要想通过新建的线程实现一个 gui 的功能,那么就需要通过使用线程间的通信来实现。 自己实现run函数,start()函数不用自己写了哈。
.h文件如下:

#ifndef RECEIVETHREAD_H
#define RECEIVETHREAD_H

#include <QThread>

class ReceiveThread : public QThread
{
Q_OBJECT
public:
explicit ReceiveThread(QObject *parent = 0);
void run();
void enStopFlag();
void enBaudChanged_flag();

int fd;
int stop_flag;
char buff[100];
int baudChanged_flag;

signals:
void sendbuff(QString );

public slots:

};

#endif // RECEIVETHREAD_H



run函数如下:

void ReceiveThread::run()
{
qDebug()<<"Receive thread started";

int count_receive=0, c=0;
QString data;

memset(buff, 0, 100);
data.clear();

while(stop_flag)
{
c = read(fd, buff, 100);

if(baudChanged_flag)
{
data.clear();
memset(buff, 0, 100);
count_receive = 0;
baudChanged_flag = 0;
continue ;
}

if(c >= 0)
data += buff;
else continue;

memset(buff, 0, 100);
count_receive += c;
if(count_receive < 14)
continue;

data = data.mid(1, 10);
emit sendbuff(data);

data.clear();
count_receive = 0;
memset(buff, 0, 100);
}

qDebug()<<"Receive thread exited";
}


在mainwindow里面申请一个线程对象,thread->start(),线程就开始监听串口了。
3.QT串口接收数据 上面的线程开始监听了,只要串口设置对了,就可以读串口的数据了,上面程序是收到14个才发送给我的程序用。 我用来读卡的,所以有一些处理。
4.ARM串口收发方便调试的接法 ID读卡器波特率9600,无校验码,停止位1,出口只有TXD和RXD和GND。
读卡器用PC的USB供电 将ARM的GND和PC的GND连接,全部共地; 将读卡器的TXD接到ARM的RXD,读卡器将读到的卡号发给ARM; 将ARM的TXD接到PC的RXD,ARM将你设置的内容发给PC; 这样就可以在ARM上显示读取的卡号,在PC上显示ARM给出的调试信息,主要是同时验证程序的收发是否正确。
下载完整实验源码: 源码下载
接法如图:

5.线程的结束 有时候需要结束线程,但是如果设置为读串口数据为阻塞模式,则不能立即结束线程,要换个方法,如下: kill线程 某线程->terminate();
kill线程参考资料:  

以下内容引用自参考资料:(begin到end)

以上代码简单,没有必要做过多的讲解,但是其中的“thread->terminate(); ”有必要讲解下,terminate()函数的调用便不会立刻终止线程,因为线程的何时终止取决于系统的调度策略,所在在之后又调用了wait()函数是线程阻塞等待直到退出或者超时。

最后加以一点就是在.pro文件中加入一行代码才能成功运行:

CONFIG+=thread


更多推荐

QT线程编程

本文发布于:2024-03-06 01:29:23,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1713996.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:线程   QT

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!