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

linux串口设置操作封装

2013-05-29 18:52 435 查看
#ifndef _SERIAL_H_
#define _SERIAL_H_

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termio.h>
#include <errno.h>

extern int set_serial(int fd, speed_t speed,int data, int parity, int stop);

#endif


#include "serial.h"

/*
*
* 功能:设置串口用于数据传输
*
* 参数描述:
* fd:打开串口的文件描述符
* speed:波特率,直接使用相关头文件中定义的宏值,
*        如:B9600,B115200
* data:数据位个数,直接使相关头文件定义的值
*       如:CS5(数据位为5),CS6,CS7,CS8
* parity:检验模式, 0无校验,1奇校验,2偶校验
* stop: 停止位个数,1或者2
*
* 返回值:成功返回0,失败返回-1,必要时将设置erron为EINVAL参数非法
*/

int set_serial(int fd, speed_t speed,int data, int parity, int stop)
{
int ret;
struct termios opt;

//检测参数有效性
if( speed & ~0x0F )  //speed用低4位表示,高位不应有数据
{
fprintf(stderr,"speed invalid\n");
errno = EINVAL;
return -1;
}

if( data & ~CSIZE )
{
fprintf(stderr,"data bits invalid\n");
errno = EINVAL;
return -1;
}

if( parity < 0 || parity > 2 )
{
fprintf(stderr,"parity invalid\n");
errno = EINVAL;
return -1;
}

if( stop < 1 || stop > 2 )
{
fprintf(stderr,"stop bits invalid\n");
errno = EINVAL;
return -1;
}

if( parity > 0 && data == CS8 )
{
fprintf(stderr,"parity and data bits don't match\n");
errno = EINVAL;
return -1;
}

//获得串口属性
ret = tcgetattr( fd, &opt );
if( ret < 0 )
{
perror("tcgetattr()");
return -1;
}

//设置串口波特率,设置收发为同一波特率
//cfsetispeed( &opt, speed );
//cfsetospeed( &opt, speed );
ret = cfsetspeed( &opt, speed );
if( ret < 0 )
{
perror("cfsetspeed()");
return -1;
}

//设置数据位
opt.c_cflag &= ~CSIZE ; //先将表示数据位的两个位清0
opt.c_cflag |= data;    //CS8,CS7...

//设置校验
if( 0 == parity )
{
opt.c_cflag &= ~PARENB; //检验使能位清0
}
else
{
opt.c_cflag |= PARENB;     //使能校验
if( 1 == parity )
opt.c_cflag |= PARODD; //奇校验
else
opt.c_cflag &= ~PARODD;//偶校验
}

//设置停止位
if ( 1 == stop )
opt.c_cflag &= ~CSTOPB;  //清0,一个停止位
else
opt.c_cflag |=  CSTOPB;  //置1,两个停止位

//关闭硬件流控
opt.c_cflag &= ~CRTSCTS;

//设置原始模式
cfmakeraw( &opt );

//设置串口属性
ret = tcsetattr( fd, TCSANOW, &opt );
if( ret < 0 )
{
perror("tcsetattr()");
return -1;
}

return 0;
}


测试程序

#include "serial.h"
#include <string.h>
#include <poll.h>

int main(int argc, char * argv[])
{

int ret;
int sfd;
int send_buf[128] = {0};
int recv_buf[128] = {0};
struct pollfd fds[2];

if( argc < 2 )
{
printf("usage: cmd <serial port>\n");
return -1;
}
//打开串口
sfd = open(argv[1], O_RDWR | O_NDELAY | O_NOCTTY );
if( sfd < 0 )
{
perror("open()");
return -1;
}
//设置串口属性
ret = set_serial(sfd, B9600,CS8,0,1);
if( ret < 0 )
{
perror("set_serial()");
return -1;
}

fds[0].fd = STDIN_FILENO;
fds[1].fd = sfd;
fds[0].events = ( POLLIN );
fds[1].events = ( POLLIN );

while(1)
{
ret = poll(fds, 2, -1);
if( ret < 0 )
{
perror("poll()");
return -1;
}
if( ret ==0 )
continue;

//标准输入有数据可读
if( fds[0].revents & POLLIN )
{
memset(send_buf,0,128);
ret = read(STDIN_FILENO, send_buf, 127);
send_buf[ret] = '\0';
printf("发送%2d字节:%s\n", ret, send_buf);
write(sfd, send_buf, ret);
}

//串口有数据可读
if ( fds[1].revents & POLLIN )
{
memset(recv_buf,0,128);
ret = read(sfd, recv_buf, 127);
recv_buf[ret] = '\0';
printf("收到%2d字节:%s\n", ret, recv_buf);
}
}

close(sfd);
}


相关链接: http://digilander.libero.it/robang/rubrica/serial.htm#CONTENTS
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: