串口設置,select和 signal 在linux編程中的使用實例

以下程序包括串口的波特率,數據位,停止位,奇偶校驗位的設置代碼,是封裝好的可以直接使用的,

還包括select和signal在監聽端口的使用方法,也是可以直接套用!



#include <stdio.h>

#include <stdlib.h>
#include <sys/time.h>   //get local time
#include     <unistd.h>     /*Unix標準函數定義*/
#include     <sys/types.h>  /**/
#include     <sys/stat.h>   /**/
#include     <fcntl.h>      /*文件控制定義*/
#include     <termios.h>    /*PPSIX終端控制定義*/
#include     <errno.h>      /*錯誤號定義*/
#include      <string.h>    // 提供bzero函數
#include     <linux/kernel.h>
#include     <sys/ioctl.h>
#include     <signal.h>
#include   <sys/mman.h>
#define  TRUE 0
#define  FALSE -1

static struct termios termios_old, termios_new;
static int    fd_ser;             //File descriptor for the serial  zigbee
static fd_set   fs_read;
static struct timeval tv_timeout={1,0};
static struct sigaction sigaction_io;   /* definition of signal action */




static int      set_port_sig ();


static void     setbaudrate (int);
static int    getbaudrate ();
static void     setdatabit (int databit);
static int   BAUDRATE (int baudrate);
static int    _BAUDRATE (int baudrate);
static int    setportattr (int baudrate, int databit,
                             const char *stopbit, char parity);
static void     setstopbit (const char *stopbit);
static void     setparitycheck (char parity);


int open_port (int comport, int baudrate, int databit,
                   const char *stopbit, char parity)
{
    char           *pcomport;
    int           retval;


    switch (comport) {
    case 0:
        pcomport = "/dev/ttySAC0";
        break;
    case 1:
        pcomport = "/dev/ttySAC1";
        break;
    case 2:
        pcomport = "/dev/ttySAC2";
        break;
    case 3:
        pcomport = "/dev/ttySAC3";
        break;
    default:
        pcomport = "/dev/ttySAC1";
        break;
    }


    fd_ser = open (pcomport, O_RDWR | O_NOCTTY | O_NONBLOCK);
    if (-1 == fd_ser) {
        return (-1);
    }
    tcgetattr (fd_ser, &termios_old);       /* save old termios value */
    /* 0 on success, -1 on failure */
    retval = setportattr (baudrate, databit, stopbit, parity);
    if (-1 == retval) {
      return (-1);
    }
    return (retval);
}


/* get serial port baudrate */
static int getbaudrate ()
{
    return (_BAUDRATE (cfgetospeed (&termios_new)));
}


/* set serial port baudrate by use of file descriptor fd_ser */
static void setbaudrate (int baudrate)
{
    termios_new.c_cflag = BAUDRATE (baudrate);  /* set baudrate */
}


static void setdatabit (int databit)
{
    termios_new.c_cflag &= ~CSIZE;
    switch (databit) {
    case 8:
        termios_new.c_cflag |= CS8;
        break;
    case 7:
        termios_new.c_cflag |= CS7;
        break;
    case 6:
        termios_new.c_cflag |= CS6;
        break;
    case 5:
        termios_new.c_cflag |= CS5;
        break;
    default:
        termios_new.c_cflag |= CS8;
        break;
    }
}


static void setstopbit (const char *stopbit)
{
    if (0 == strcmp (stopbit, "1")) {
        termios_new.c_cflag &= ~CSTOPB; /* 1 stop bit */
    }
    else if (0 == strcmp (stopbit, "1.5")) {
        termios_new.c_cflag &= ~CSTOPB; /* 1.5 stop bits */
    }
    else if (0 == strcmp (stopbit, "2")) {
        termios_new.c_cflag |= CSTOPB;  /* 2 stop bits */
    }
    else {
        termios_new.c_cflag &= ~CSTOPB; /* 1 stop bit */
    }
}


static void setparitycheck (char parity)
{
    switch (parity) {
    case 'N':                  /* no parity check */
        termios_new.c_cflag &= ~PARENB;
        break;
    case 'E':                  /* even */
        termios_new.c_cflag |= PARENB;
        termios_new.c_cflag &= ~PARODD;
        break;
    case 'O':                  /* odd */
        termios_new.c_cflag |= PARENB;
        termios_new.c_cflag |= ~PARODD;
        break;
    default:                   /* no parity check */
        termios_new.c_cflag &= ~PARENB;
        break;
    }
}


static int setportattr (int baudrate,
                          int databit, const char *stopbit, char parity)
{
    bzero (&termios_new, sizeof (termios_new));
    cfmakeraw (&termios_new);
    setbaudrate (baudrate);
    termios_new.c_cflag |= CLOCAL | CREAD;      /* | CRTSCTS */
    setdatabit (databit);
    setparitycheck (parity);
    setstopbit (stopbit);
    termios_new.c_oflag = 0;
    termios_new.c_lflag |= 0;
    termios_new.c_oflag &= ~OPOST;
    termios_new.c_cc[VTIME] = 10;        /* unit: 1/10 second. */
    termios_new.c_cc[VMIN] = 128;       /* minimal characters for reading */
    tcflush (fd_ser, TCIFLUSH);
    return (tcsetattr (fd_ser, TCSANOW, &termios_new));
}


static int BAUDRATE (int baudrate)
{
    switch (baudrate) {
    case 2400:
        return (B2400);
    case 9600:
        return (B9600);
    case 19200:
        return (B19200);
    case 38400:
        return (B38400);
    case 57600:
        return (B57600);
    case 115200:
        return (B115200);
    default:
        return (B9600);
    }
}


static int _BAUDRATE (int baudrate)
{
/* reverse baudrate */
    switch (baudrate) {
    case B2400:
        return (2400);
    case B9600:
        return (9600);
    case B19200:
        return (19200);
    case B38400:
        return (38400);
    case B57600:
        return (57600);
    case B115200:
        return (115200);
    default:
        return (9600);
    }
}


void  close_port()
{
  tcsetattr (fd_ser, TCSADRAIN, &termios_old);
    close (fd_ser);
}
/* *************************************************
 * name:insert_data_db()
 *brief: pick up parameter from recvbuf
 * return value:
*************************************************/


/*
static int insert_data_db(char *data)
{
if(*data==0xfe)
{
int temp;//存放提取後的數據,爲了區別於前面的定義所以使用了簡寫
int hum;
int  illum;
int carb;


temp=*(data+temperature);
hum=*(data+humidity);
illum=*(data+illumination);
carb=*(data+carbon);


temp=(temp/10)+(temp%10);
hum=(hum/10)+(hum%10);
illum=(illum/10)+(illum%10);
carb=(carb/10)+(carb%10);


 insert_db(temp,hum,illum,carbon);


}


}*/
/* *************************************************
 * name:read_port()
 *brief:read data from port
 * return value: all data of read
*************************************************/
static int read_port (char *data, int datalength)
{
    int           retval = 0;
    FD_ZERO (&fs_read);
    FD_SET (fd_ser, &fs_read);


    retval = select (fd_ser+1, &fs_read, NULL, NULL, &tv_timeout);        //Linux下用select查詢串口數據 
    if (retval>0) {
  if(FD_ISSET(fd_ser,&fs_read))
       { return(read(fd_ser,data,datalength));
          tcflush(fd_ser,TCIOFLUSH);
  }
    }
    else 
        return (-1);
}


/**************************************************************
name  :signal_handler_IO()
brief :execute the reaction of signal
*************************************************************/
static void signal_handler_IO ()
{printf(" break begin \r\n");
   
    int             i = 0, start = 0;
    int   status;


    char            recvbuf[256];
    int             numflag = 0;
    status=read_port(recvbuf, 128);
if(status>0)
{
//insert_data_db(recvbuf);
printf("status=%d\r\n",status);
printf("%s",recvbuf);
}
close_port();
if(open_port(1,115200,8,"1",'N')<0)
printf("open port erro!");
set_port_sig();


   printf(" break over\r\n");
 //bzero(recvbuf,sizeof(recvbuf));
}
/**************************************************************
name:set_port_sig()
brief:install the signal handler before making the device asynchronous 
*************************************************************/
static int set_port_sig ()
{
    sigaction_io.sa_handler = signal_handler_IO;
    sigemptyset (&(sigaction_io.sa_mask));
    sigaction_io.sa_flags = 0;
    sigaction_io.sa_restorer = NULL;
    sigaction (SIGIO, &sigaction_io, NULL);


    /* allow the process to receive SIGIO */
    if (-1 == fcntl (fd_ser, F_SETFL, O_ASYNC))
        return (-1);
    if (-1 == fcntl (fd_ser, F_SETOWN, getpid ()))
        return (-1);
    /* Make the file descriptor asynchronous (the manual page says only
       O_APPEND and O_NONBLOCK, will work with F_SETFL...) */
    return (0);
}






int main()
{
if(open_port(1,115200,8,"1",'N')<0)
printf("open port erro!");
set_port_sig();
while(1)
{usleep(20000);}


close_port();
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章