Linux串口编程

最近使用了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.csdn.net/xyyangkun/article/details/7333288
Linux 串口编程
http://archive.cnblogs.com/a/1864327/
linux read() 函数
http://blog.csdn.net/bnxf00000/article/details/6235071
linux串口的select读,Linux下用select查询串口数据
http://www.justwinit.cn/post/3446/




你可能感兴趣的:(编程,linux,struct,null,Terminal,终端)