最近使用了linux的串口,整理了一下应用程序调用的API,希望将来有用。
主要有两个文件SerDrive.h盒SerDrive.c
//=======================================================
SerDrive.h
#ifndef SERDRIVE_H
#define SERDRIVE_H
//=======================
//串口名字
#define TTY0_NAME "/dev/ttySAC0"
#define TTY1_NAME "/dev/ttySAC1"
#define TTY2_NAME "/dev/ttySAC2"
//串口
#define TTYS0 1
#define TTYS1 2
#define TTYS2 3
//波特率
#define BAUD_2400 2400
#define BAUD_4800 4800
#define BAUD_9600 9600
#define BAUD_115200 115200
#define BAUD_460800 460800
//奇偶校验位
#define PARITY_ODD 'O' //奇数
#define PARITY_EVEN 'E' //偶数
#define PARITY_NONE 'N' //无奇偶校验位
//停止位
#define STOP_BIT_1 1
#define STOP_BIT_2 2
//数据位
#define DATA_BIT_7 7
#define DATA_BIT_8 8
//========================================
//串口API
/*打开串口函数*/
int open_port(int fd,int comport);
//串口配置的函数
int set_opt(int fd,int nSpeed, int nBits,
char nEvent, int nStop);
//从串口中读取数据
int read_datas_tty(int fd,char *rcv_buf,int TimeOut,int Len);
//向串口传数据
int send_data_tty(int fd, char *send_buf,int Len);
//==============
#endif // SERDRIVE_H
//*****************************************************
SerDrive.c
#include "SerDrive.h"
//===========================================
#include <stdio.h> /*标准输入输出定义*/
#include <stdlib.h> /*标准函数库定义*/
#include <unistd.h> /*Unix 标准函数定义*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> /*文件控制定义*/
#include <termios.h> /*POSIX 终端控制定义*/
#include <errno.h> /*错误号定义*/
//=============================================
#define DEVICE_TTYS 1
//=============================================
/*打开串口函数*/
int open_port(int fd,int comport)
{
if (comport==1)//串口 1
{
fd = open( TTY0_NAME, O_RDWR|O_NOCTTY|O_NDELAY);
if (-1 == fd){
perror("Can't Open Serial Port");
return(-1);
}
}
else if(comport==2)//串口 2
{
fd = open( TTY1_NAME, O_RDWR|O_NOCTTY|O_NDELAY);
if (-1 == fd){
perror("Can't Open Serial Port");
return(-1);
}
}
else if (comport==3)//串口 3
{
fd = open( TTY2_NAME, O_RDWR|O_NOCTTY|O_NDELAY);
if (-1 == fd){
perror("Can't Open Serial Port");
return(-1);
}
}
/*恢复串口为阻塞状态*/
if(fcntl(fd, F_SETFL, 0)<0)
printf("fcntl failed!\n");
else
printf("fcntl=%d\n",fcntl(fd, F_SETFL,0));
/*测试是否为终端设备*/
if(isatty(STDIN_FILENO)==0)
printf("standard input is not a terminal device\n");
else
printf("isatty success!\n");
printf("fd-open=%d\n",fd);
return fd;
}
//串口配置的函数
int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
{
struct termios newtio,oldtio;
/*保存测试现有串口参数设置,在这里如果串口号等出错,会有相关的出错信息*/
if ( tcgetattr( fd,&oldtio) != 0) {
perror("SetupSerial 1");
return -1;
}
bzero( &newtio, sizeof( newtio ) );
/*步骤一,设置字符大小*/
newtio.c_cflag |= CLOCAL | CREAD;
newtio.c_cflag &= ~CSIZE;
/*设置停止位*/
switch( nBits )
{
case 7:
newtio.c_cflag |= CS7;
break;
case 8:
newtio.c_cflag |= CS8;
break;
}
/*设置奇偶校验位*/
switch( nEvent )
{
case 'O': //奇数
newtio.c_cflag |= PARENB;
newtio.c_cflag |= PARODD;
newtio.c_iflag |= (INPCK | ISTRIP);
break;
case 'E': //偶数
newtio.c_iflag |= (INPCK | ISTRIP);
newtio.c_cflag |= PARENB;
newtio.c_cflag &= ~PARODD;
break;
case 'N': //无奇偶校验位
newtio.c_cflag &= ~PARENB;
break;
}
/*设置波特率*/
switch( nSpeed )
{
case 2400:
cfsetispeed(&newtio, B2400);
cfsetospeed(&newtio, B2400);
break;
case 4800:
cfsetispeed(&newtio, B4800);
cfsetospeed(&newtio, B4800);
break;
case 9600:
cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
break;
case 115200:
cfsetispeed(&newtio, B115200);
cfsetospeed(&newtio, B115200);
break;
case 460800:
cfsetispeed(&newtio, B460800);
cfsetospeed(&newtio, B460800);
break;
default:
cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
break;
}
/*设置停止位*/
if( nStop == 1 )
newtio.c_cflag &= ~CSTOPB;
else if ( nStop == 2 )
newtio.c_cflag |= CSTOPB;
/*设置等待时间和最小接收字符*/
newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 0;
/*处理未接收字符*/
tcflush(fd,TCIFLUSH);
/*激活新配置*/
if((tcsetattr(fd,TCSANOW,&newtio))!=0)
{
perror("com set error");
return -1;
}
printf("set done!\n");
return 0;
}
//======================================================
//从串口中读取数据
int read_datas_tty(int fd,char *rcv_buf,int TimeOut,int Len)
{
int retval;
fd_set rfds;
struct timeval tv;
int ret,pos;
tv.tv_sec = TimeOut/1000;//set the rcv wait time
tv.tv_usec = TimeOut%1000*1000;//100000us = 0.1s
pos = 0;
while(1){
FD_ZERO(&rfds);
FD_SET(fd,&rfds);
retval = select(fd+1,&rfds,NULL,NULL,&tv);
if(retval ==-1)
{
perror("select()");
break;
}
else if(retval)
{
ret= read(fd,rcv_buf+pos,1);
if(-1 == ret){
break;
}
pos++;
if(Len <= pos){
break;
}
}
else
{
break;
}
}
return pos;
}
//向串口传数据
int send_data_tty(int fd, char *send_buf,int Len)
{
ssize_t ret;
ret = write(fd,send_buf,Len);
if (ret == -1)
{
printf ("write device %s error\n", DEVICE_TTYS);
return -1;
}
return 1;
}
//**********************************************************************
//调用例子
#include "SerDrive.h"
//======================================
int SerFd = -1;
void ProcessInit(int argc, char *argv[])
{
/*打开串口函数*/
SerFd = open_port(SerFd,TTYS1);
if(0 < SerFd){
set_opt(SerFd,BAUD_2400,
DATA_BIT_8, PARITY_NONE, STOP_BIT_1);
}else{
printf("open_port ERROR !\n");
}
}
int main ( int argc, char *argv[])
{
int nTmp = 0;
char Buf[1024];
ProcessInit(argc,argv);
while(1){
//从串口中读取数据
nTmp = read_datas_tty(SerFd, Buf,100,1024);
if(0<nTmp){
//printf("rcv len=%d,data:%s\n",nTmp,Buf);
//向串口传数据
send_data_tty(SerFd, Buf,nTmp);
}
}
}
//*********************************************************************************
参考:
Linux串口编程
http://www.cnblogs.com/feisky/archive/2010/05/21/1740893.html
linux 串口特别是接收
http://blog.youkuaiyun.com/xyyangkun/article/details/7333288
Linux 串口编程
http://archive.cnblogs.com/a/1864327/
linux read() 函数
http://blog.youkuaiyun.com/bnxf00000/article/details/6235071
linux串口的select读,Linux下用select查询串口数据
http://www.justwinit.cn/post/3446/