linux串口类

近几天需要用linux的串口,在网上找了一些例子,随后又自己改成了一个类

可以发送,接收未测试。

头文件:

#ifndef MYSERIAL_H
#define MYSERIAL_H

class MySerial
{
	public:
		MySerial()
		{};
		int UART_open(const char *portName);
		int UART_open(int uartNum);
		int UART_set(int baud = 115200,int flow_ctrl = 0,int databits = 8,int stopbits = 1,int parity = 0);
		int UART_init(int baud = 115200,int flow_ctrl = 0,int databits = 8,int stopbits = 1,int parity = 0);
		int UART_recv(unsigned char *rcv_buf,int data_len);
		int UART_send(unsigned char *send_buf,int data_len);
		~MySerial();
	
	private:
		int fd;  //串口设备描述符
};
#endif
cpp:

/****************************************************************
* FileName:            mySerial.cpp
* Author:              sfy
* Description:         linux串口类  
****************************************************************/


#include <iostream>
#include <unistd.h> //Unix 标准函数定义
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <termios.h>
#include <string>
#include <vector>
#include <utility>
#include <sstream>
#include "mySerial.h"

using namespace std;


/***********************************************************************
* 名称:         UART_open
* 功能:         打开指定串口并返回状态
* 入口参数:     portName:串口号(ttyUSB0,ttyUSB1,ttyUSB2)
* 返回值:       正确打开返回0  错误返回-1
************************************************************************/

int MySerial::UART_open(const char *portName)
{
	fd = open(portName,O_RDWR|O_NOCTTY|O_NDELAY);//非阻塞模式打开
	if(fd == -1)
	{
		cout << "Can't open serial port" << *portName << endl;
		return -1;
	}
	//判断串口的状态是否为阻塞状态
	int BOOL = fcntl(fd,F_SETFL,0);
	if(BOOL < 0)
	{
		cout << "fcntl failed" << endl;
		return -1;
	}
	else
	{
		printf("fcntl=%d\n",BOOL);
	}
	//测试是否为终端设备
	if(!isatty(STDIN_FILENO))
	{
		cout << "standard input is not a terminal device" << endl;
		return -1;
	}
	else
	{
		cout << "isatty success!" << endl;
	}
	//cout << "fd->open" << fd << endl;
	
	return 0;
}
/***********************************************************************
* 名称:         UART_open
* 功能:         打开串口并返回状态
* 入口参数:     uartNum:串口号 自动打开0-uartNum之间的一个串口号
* 返回值:       正确返回0  错误返回-1
************************************************************************/
int MySerial::UART_open(int uartNum)
{
	stringstream stream;    
	string uartName = "/dev/ttyUSB";
	string str;
	bool BOOL;

	for(int i = 0;i <= uartNum; ++i)
	{
		stream.clear();
		stream << i;
		stream >> str;
		str = uartName + str;
		fd = open(str.c_str(),O_RDWR|O_NOCTTY|O_NDELAY);//非阻塞模式打开
		if(fd != -1)
		{
			cout << "open serial port " << str << " successed" << endl;
			break;
		}
		cout << "open serial port " << str << "  failed" << endl;
		if(i == uartNum)
		{
			return -1;
		}
	}	

	//判断串口的状态是否为阻塞状态
	BOOL = fcntl(fd,F_SETFL,0);
	if(BOOL < 0)
	{
		cout << "fcntl failed" << endl;
		return -1;
	}
	else
	{
		printf("fcntl=%d\n",BOOL);
	}
	//测试是否为终端设备
	if(!isatty(STDIN_FILENO))
	{
		cout << "standard input is not a terminal device" << endl;
		return -1;
	}
	else
	{
		cout << "isatty success!" << endl;
	}
	//cout << "fd->open" << fd << endl;
	
	return 0;
}

/***************************************************************************
* 名称:                       UART_set
* 功能:                       设置串口数据位,停止位,校验位
* 入口参数:                   baud               波特率 2400 4800 9600 115200
*                             flow_ctrl          数据流控制 0 1 2
*                             databits           数据位  7或8
*                             stopbits           停止位  1或2
*                             parity             校验类型  0 1 2
* 返回值:                    正确返回0        错误返回-1
*****************************************************************************/
int MySerial::UART_set(int baud ,int flow_ctrl ,int databits ,int stopbits ,int parity )
{	 
	typedef std::pair< int,int> Baud;
	vector<Baud> baud_list;
	baud_list.push_back(Baud(2400,B2400));
	baud_list.push_back(Baud(4800,B4800));
	baud_list.push_back(Baud(9600,B9600));
	baud_list.push_back(Baud(115200,B115200));

	struct termios options;
	
	/*tcgetattr(fd,&options)得到与fd指向对象的相关参数,并将他们保存与options,该函数还可以测试配置是否正确,
	  该串口是否可用等,若调用成功,函数返回0,若调用失败,返回-1    */
	if(tcgetattr(fd,&options) !=0)
	{
		cout << "设置串口失败" <<endl;
		return -1;
	}
	
	for(vector< Baud >::iterator iter=baud_list.begin();iter!=baud_list.end();++iter)
	{
		if(iter->first == baud)
		{
			cfsetispeed(&options,iter->second);
			cfsetospeed(&options,iter->second);
		}
	}
	//修改控制模式 保证程序不会占用串口
	options.c_cflag |= CLOCAL;
	//修改控制模式 使得能够从串口中读输入数据
	options.c_cflag |= CREAD;

	//设置数据流控制
	switch (flow_ctrl)
	{
		case 0 : //不使用流控制
				options.c_cflag &= ~CRTSCTS;
				break;
		case 1 : //使用硬件流控制
				options.c_cflag |= CRTSCTS;
				break;
		case 2 : //使用软件流控制
				options.c_cflag |= IXON |IXOFF |IXANY;
				break;
		default :
				cout << "数据流参数错误" << endl;
				return -1;
	}

	//设置数据位
	options.c_cflag &= ~CSIZE;   //屏蔽其他标志位
	switch(databits)
	{
		case 5 :
			options.c_cflag |= CS5;
			break;
		case 6 :
			options.c_cflag |= CS6;
			break;
		case 7 :
			options.c_cflag |= CS7;
			break;
		case 8 :
			options.c_cflag |= CS8;
			break;
		default :
			cout << "数据位参数错误" << endl;
			return -1;
	}
	
	//设置校验位
	switch(parity)
	{
		case 0 : //无奇偶校验位
			options.c_cflag &= ~PARENB;
			//options.c_iflag &= ~INPCK;
			break;
		case 1 : //奇校验
			options.c_cflag |= (PARODD | PARENB);
			//options.c_iflag |= INPCK;
			break;
		case 2 : //偶校验
			options.c_cflag &= ~PARENB;
			options.c_cflag &= ~PARODD;
			//options.c_iflag |= INPCK;
			break;
		case 3 : //设置为空格
			options.c_cflag &= ~PARENB;
			options.c_cflag &= ~CSTOPB;
			break;
		default :
			cout << "校验位参数错误" << endl;
			return -1;
	}
	
	//设置停止位
	switch(stopbits)
	{
		case 1 :
			options.c_cflag &= ~CSTOPB;
			break;
		case 2 :
			options.c_cflag |= CSTOPB;
			break;
		default :
			cout << "停止位参数错误" << endl;
			return -1;
	}
	
	//修改输出模式 原始数据输出
	options.c_oflag &= ~OPOST;

	//设置等待时间和最小接受字符
	options.c_cc[VTIME] = 1; // 读取一个字符等待1*(1/10)s 
	options.c_cc[VMIN ] = 1; // 读取字符的最小个数为1

	//如果发生数据溢出,接受数据,但是不再读取
	tcflush(fd,TCIFLUSH);

	//将修改后的数据设置写入串口
	if(tcsetattr(fd,TCSANOW,&options) != 0)  //立即生效
	{
		cout << "com set error" << endl;
		return -1;
	}
	
	return 0;
}

/**********************************************************
* 名称:                     USRT_init()
* 功能:                     串口初始化
* 入口参数:                 fd         文件描述符
*                           baud       串口波特率
*                           flow_ctrl  数据流控制
*                           databits   数据位   7或8
*                           stopbits   停止位   1或2
*                           parity     检验类型  N E O S
* 返回值:                  正确返回0 ,错误返回-1
*************************************************************/

int MySerial::UART_init(int baud ,int flow_ctrl ,int databits ,int stopbits ,int parity )
{
	//设置串口数据帧格式
	if(UART_set(baud,flow_ctrl,databits,stopbits,parity) != 0)
	{
		cout << "set uart error" << endl;
		return -1;
	}

	return 0;	
}

/**********************************************************************
* 名称:                                        UART_recv
* 功能:                                        接受串口数据
* 入口参数:                                     rcv_buf    数据缓存区
*                                               data_len   一帧数据的长度
* 返回值:                                       正确返回实际接受字符数   错误返回-1
*************************************************************************/

int MySerial::UART_recv(unsigned char *rcv_buf,int data_len)
{
	int len,fs_sel;
	fd_set fs_read;

	struct timeval time;

	FD_ZERO(&fs_read);
	FD_SET(fd,&fs_read);

	time.tv_sec = 10;
	time.tv_usec = 0;

	//使用select实现串口的多路通信
	fs_sel = select(fd+1,&fs_read,NULL,NULL,&time);
	if(fs_sel)
	{
		len = read(fd,rcv_buf,data_len);
		return len;
	}

	return -1;
}

/******************************************************************************
* 名称:                      UART_send
* 功能:                      发送数据
* 入口参数:                  send_buf 发送缓存区
*                            data_len 一帧数据个数
* 返回值:                   正确返回实际发送字符数   错误返回-1
*******************************************************************************/

int MySerial::UART_send(unsigned char *send_buf, int data_len)
{
	int len = 0;
	len = write(fd,send_buf,data_len);  //返回实际串口发送字符数
	if(len == data_len)
	{
		return len;
	}

	tcflush(fd,TCOFLUSH);
	return -1;
}



/********************************************************************************
* 名称:                    ~MySerial
* 功能:                    析构函数  关闭串口
* 入口参数:                void
* 返回值:                  void
*********************************************************************************/

MySerial::~MySerial()
{
	close(fd);
}
			

使用例子:

#include "mySerial.h"
#include <iostream>
#include <unistd.h>

using namespace std;

int main()
{
	unsigned char send_buf[20] = "1234567891";
	MySerial serial;
	bool BOOL =serial.UART_open(5);
	if(BOOL !=0)
	{
		return -1;
	}
	serial.UART_init(115200,0,8,1,0);

	while(1)
	{
		int len = serial.UART_send(send_buf,20);
		if(len > 0)
			cout << "send data successful" << endl;
		else
			cout << "send datafailed" << endl;
		sleep(1);
	}
	
    return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值