下面讲述原理,也可以下载完整实验源码: 源码下载
前言
QT没有提供串口类,使用的是linux提供的函数。
linux下设备和文件使用一样,用open函数打开串口,设置等都提供了函数的,需要自己组合一下,封装成你要的函数。
1.QT串口发送数据
要使用串口,需先打开串口,封装的函数如下:
int open_port(constchar* 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)
{
case2400:
speed = B2400;break;
case4800:
speed = B4800;break;
case9600:
speed = B9600;break;
case19200:
speed = B19200;break;
case38400:
speed = B38400;break;
default:
case115200:
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
{
case7:
new_cfg.c_cflag |= CS7;break;
default:
case8:
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:
case1:
new_cfg.c_cflag &=~CSTOPB;break;
case2:
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;
}
return0;
}发送数据:
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>
classReceiveThread:publicQThread
{
Q_OBJECT
public:
explicitReceiveThread(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_HvoidReceiveThread::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;
elsecontinue;
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线程参考资料: http://qimo601.iteye.com/blog/1287279
以下内容引用自参考资料:(begin到end)
<begin> 以上代码简单,没有必要做过多的讲解,但是其中的“thread->terminate(); ”有必要讲解下,terminate()函数的调用便不会立刻终止线程,因为线程的何时终止取决于系统的调度策略,所在在之后又调用了wait()函数是线程阻塞等待直到退出或者超时。 最后加以一点就是在.pro文件中加入一行代码才能成功运行: CONFIG+=thread <end>
版权声明:本文为lovenessless原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。