最近使用了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);
- }
- }
- }