VxWorks 6.8下基于QT的串口编程

文章简要记录了VxWorks 6.8下基于Qt实现的串口编程。

相关的VxWorks串口,请参阅 VxWorks下的串口测试程序设计和源码

VxWorks简介

VxWorks 操作系统是美国WindRiver公司于1983年设计开发的一种嵌入式实时操作系统(RTOS),是嵌入式开发环境的关键组成部分。良好的持续发展能力、高性能的内核以及友好的用户开发环境,在嵌入式实时操作系统领域占据一席之地。它以其良好的可靠性和卓越的实时性被广泛地应用在通信、军事、航空、航天等高精尖技术及实时性要求极高的领域中,如卫星通讯、军事演习、弹道制导、飞机导航等。在美国的 F-16、FA-18战斗机、B-2 隐形轰炸机和爱国者导弹上,甚至连1997年4月在火星表面登陆的火星探测器、2008年5月登陆的凤凰号,和2012年8月登陆的好奇号也都使用到了VxWorks。

串口简介

串行接口(Serial Interface) 简称串口,也称串行通信接口或串行通讯接口(通常指COM接口),是采用串行通信方式的扩展接口,指数据一位一位地顺序传送。

串行接口的特点是通信线路简单,只要一对传输线就可以实现双向通信(可以直接利用电话线作为传输线),从而大大降低了成本,特别适用于远距离通信,但传送速度较慢。常见的有一般计算机应用的RS-232(使用 25 针或 9 针连接器)和工业计算机应用的半双工RS-485与全双工RS-422。

我这里使用了232和422传输方式,在我本人理解这两种方式根据需求硬件已经做好的传输方式(也可以在BIOS设置),我们知道是什么传输方式,做到心中有数和如何搭建测试环境,今天在这里教大家个简单的232-9针连接器的接线方式,一般没接触过的拿过来一脸懵逼,好家伙9跟针都不知道是干嘛的,那么我告诉你如果是 232-9针,什么也别管直接找到第2针和第3针用杜邦线回连,这时你就具备环境自己检测板卡串口模块是否好用,如果测试程序一定记得把第5跟针要连接上,否则会出现数据不精准的情况(文章底部有贴图)。

在软件层面上只需要关注数据位、停止位、奇偶效验、读取方式和效率即可;

232串口接线说明

RS232串口接线方法:直连和交叉接法

一般情况下,设备和电脑的连接通讯,需用到RS232串口线直连线;而设备和设备的连接通讯,就会用到RS232串口线的交叉线。用户在选择的时候,应根据两个设备之间连接的实际情况,选择不同接法的RS232串口线。

代码实例

VxWorks串口所需要包含的头文件

#include "vxWorks.h"
#include "stdIo.h"
#include "ioLib.h"
#include "sysLib.h"
#include "string.h"
#include "taskLib.h"

VxWorks串口配置函数

ioctl(m_SeriPort,SIO_HW_OPTS_SET, CLOCAL | CS8 | PARODD | PARENB);	//8位数据位|1位停止位|偶效验
ioctl(m_SeriPort,FIOBAUDRATE,9600);					//波特率9600
ioctl(m_SeriPort,FIOSETOPTIONS,OPT_RAW);				//设置串口raw模式                         
ioctl(m_SeriPort,FIOFLUSH,0);						//清空输入输出的缓冲区

open函数

#define SERI_NAME "/tyCo/0"
int m_SeriPort = open(SERI_NAME ,O_RDWR,0);  
int m_SeriPort = open(SERI_NAME ,O_WRONLY,0);  

write函数

char* sendData;
int writeCom = write(m_SeriPort, sendData,strlen(sendData));

read函数

char data;
int readCom = read(m_SeriPort,&data,1);

Seri_Demo_Qt_Vx

#ifndef THREAD_H
#define THREAD_H
#include <QThread>
#include <QDebug>
#include "vxWorks.h"
#include "stdIo.h"
#include "ioLib.h"
#include "sysLib.h"
#include "string.h"
#include "taskLib.h"
class Thread : public QThread
{
    Q_OBJECT
public:
    explicit Thread(QObject *parent = 0);
    ~Thread();
    void run();    												//重写run函数                                             
public:
    bool openSeri(QString comPort,int baudRate);                //打开串口
    void closeSeri();                                           //关闭串口
    void writeSeri(char* sendData);                             //发送数据
    void setFlag(bool flag = true);                             //线程数据标志位
signals:
	void RecvData(char data);
private:
    bool seriStop;      //读取数据标志位  true读取数据  false退出循环
    int m_SeriPort;     //串口文件描述符
    QString m_SeriName; //串口名
    int m_baud;         //波特率
};
#endif //THREAD_H
#include "thread.h"

Thread::Thread(QObject *parent) : QThread(parent)
{
}

Thread::~Thread()
{
}

void Thread::run()
{
	sysClkRateSet(1000);
	char rData;
	while(1)
	{
		int readCom = read(m_SeriPort,&rData,1);
		if(readCom > 0)
		{
			printf("%c\n",rData);
			emit RecvData(rData);
			if(seriStop == false)
			{
				qDebug()<< "isStop == false break";
				break;
			}
		}
		else
		{
			taskDelay(10);
		}
	}
}

bool Thread::openSeri(QString comPort, int baudRate)
{
	this->m_SeriName = comPort;
	this->m_baud = baudRate;
	qDebug()<< "Thread::openSeri" << comPort.toUtf8().data() << baudRate;
	m_SeriPort = open(comPort.toUtf8().data(),O_RDWR,0);               
	if(m_SeriPort == ERROR)
	{
		qDebug()<< "open :" << comPort.toUtf8().data() << " = " <<m_SeriPort << "failed !";
		return false;
	}
	ioctl(m_SeriPort,SIO_HW_OPTS_SET, CLOCAL | CS8 | PARODD | PARENB);  
	ioctl(m_SeriPort,FIOBAUDRATE,baudRate);                             
	ioctl(m_SeriPort,FIOSETOPTIONS,OPT_RAW);                           
	ioctl(m_SeriPort,FIOFLUSH,0);
	qDebug()<<  "open :" << comPort.toUtf8().data() << " = " << m_SeriPort << "succeeded !";
	return true;
}

void Thread::closeSeri()
{
	if(seriStop == false)
	{
		qDebug()<< "Thread::closeSeri";
		close(m_SeriPort);
	}
}

void Thread::writeSeri(char* sendData)
{
	if(m_SeriPort == ERROR)                                             
	{
		openSeri(m_SeriName,m_baud);
	}
	int writeCom = write(m_SeriPort, sendData,strlen(sendData));       
	qDebug()<< sendData << writeCom;
}

void Thread::setFlag(bool flag)
{
	this->seriStop = flag;   
	qDebug()<< "Thread::setFlag" << flag;
}

TestSeri_Demo_Qt_Vx_Demo

#ifndef SERI_H
#define SERI_H

#include <QObject>
#include <QDebug>
#include "thread.h"

class Seri : public QObject
{
    Q_OBJECT
public:
    explicit Seri(QObject *parent = 0);
    ~Seri();
public:
    /*	open_Seri	打开串口
     * 	comName		串口名
     * 	comBaud		串口波特率
     *	return 		成功 true 失败 false
     */
    bool open_Seri(QString comName,int comBaud);
    /* 	write_Seri	发送数据
     * 	comData		发送数据内容
     */
    void write_Seri(QByteArray comData);
    /*	
     * 	close_Seri	关闭串口
     */  
     void close_Seri();           
signals:
	send_Seri(char data);
private:
    Thread* m_pThread;

};
#endif // SERI_H
#include "Seri.h"

Seri::Seri(QObject *parent) : QObject(parent)
{
	m_pThread = new Thread;
}
Seri::~Seri()
{
	if(m_pThread){
		delete m_pThread;
		m_pThread=NULL;
	}
}
bool Seri::open_Seri(QString comName,int comBaud)
{
	if(m_pThread->openSeri(comName,comBaud))//如果打开成功
	{
		m_pThread->setFlag(true);
		m_pThread->start();
	}
	return false;
}
void Seri::write_Seri(QByteArray comData)
{
	m_pThread->writeSeri(comData.data());
}
void Seri::close_Seri()
{
	if(m_pThread->isRunning())//如果线程还在运行 --> 退出循环接收数据 --> 关闭串口 --> 退出线程 --> 回收线程
	{
		m_pThread->setFlag(false);
		m_pThread->closeSeri();
		m_pThread->quit();
		m_pThread->wait();
	}
}

程序代码说明:

  • thread类为配置串口类
  • seri类为外部使用类
  • 接收到的数据是利用信号槽为接口把数据传输出去