您的位置:首页 > 运维架构 > Linux

linux串口类

2016-01-29 15:42 519 查看
近几天需要用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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: