linux 串口 拼帧处理

串口每次read数据可能不是完整的数据,参照网上的代码,写了拼帧的代码#include <stdio.h>

#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <strings.h>
#include <sys/time.h>
#include <sys/types.h>


int speed_arr[] = { B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1200, B300};
int name_arr[] =  { 115200,  57600,  38400,  19200,  9600,  4800,  2400,  1200,  300};

/**
*@brief  Set Serial Port BitRate
*@param  fd     Type : int The File Description of Serial Port
*@param  speed  Type : int  Serial Speed
*@return  void
*/
void set_speed(int fd, int speed)
{
    int   i;
    int   status;
    struct termios   Opt;
    tcgetattr(fd, &Opt);
    for( i=0; i < (sizeof(speed_arr) / sizeof(int)); i++ )
    {
        if (speed == name_arr[i])
        {
            tcflush(fd, TCIOFLUSH);
            cfsetispeed(&Opt, speed_arr[i]);
            cfsetospeed(&Opt, speed_arr[i]);
            status = tcsetattr(fd, TCSANOW, &Opt);
            if (status != 0)
            {
                perror("tcsetattr fd");
                return;
            }
            tcflush(fd,TCIOFLUSH);
        }
    }
}

/**
*@brief   Set Serial Port Databits, Stopbits and Parity.
*@param  fd     Type:  int The File Description of Serial Port
*@param  databits Type:  int Databits 7 or 8
*@param  stopbits Type:  int Stopbits 1 or 2
*@param  parity  Type:  int  Parity Type: n,N,e,E,o,O,s,S
*/
int set_Parity(int fd, int databits, int parity, int stopbits)
{
    struct termios options;
    if ( tcgetattr( fd,&options)  !=  0)
    {
        perror("SetupSerial 1");
        return(-1);
    }
    options.c_cflag &= ~CSIZE;
    switch (databits)               /*Set Datebits*/
    {
    case 7:
        options.c_cflag |= CS7;
        break;
    case 8:
        options.c_cflag |= CS8;
        break;
    default:
        fprintf(stderr,"Unsupported data size
");
        return(-1);
    }

    switch (parity) /*Set Parity*/
    {
    case 'n':
    case 'N':
          options.c_cflag &= ~PARENB;   /* Clear parity enable */
          options.c_iflag &= ~INPCK;     /* Enable parity checking */
          break;
    case 'o':
    case 'O':
          options.c_cflag |= (PARODD | PARENB); /* Odd Checking*/
          options.c_iflag |= INPCK;             /* Disnable parity checking */
          break;
    case 'e':
    case 'E':
          options.c_cflag |= PARENB;     /* Enable parity */
          options.c_cflag &= ~PARODD;   /* Even Checking*/
          options.c_iflag |= INPCK;       /* Disnable parity checking */
          break;
    case 'S':
    case 's':  /*as no parity*/
          options.c_cflag &= ~PARENB;
          options.c_cflag &= ~CSTOPB;
          break;
    default:
          fprintf(stderr,"Unsupported parity
");
          return(-1);
    }

    switch (stopbits)               /*Set Stobits*/
    {
    case 1:
        options.c_cflag &= ~CSTOPB;
        break;
    case 2:
        options.c_cflag |= CSTOPB;
        break;
    default:
        fprintf(stderr,"Unsupported stop bits
");
        return(-1);
    }
    /* Set input parity option */
    if (parity != 'n')
      options.c_iflag |= INPCK;

    /*以下两句添加后发送方可以不加回车换行,但是read读取不完整*/
    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);     /*Input*/
    options.c_oflag &= ~OPOST;  /*Output*/

    //屏蔽功能: NL(换行)->CR(回车)、CR->NL、忽略输入回车
    options.c_iflag &= ~(INLCR | ICRNL | IGNCR);
    options.c_oflag &= ~(ONLCR | OCRNL);

    tcflush(fd,TCIFLUSH);
    //未设置O_NONBLOCK或O_NDELAY
    options.c_cc[VTIME] = 150; /* Timeout in 15 seconds*/
    options.c_cc[VMIN] = 0; /* Update the options and do it NOW */
    if (tcsetattr(fd,TCSANOW,&options) != 0)
    {
      perror("SetupSerial 3");
      return(-1);
    }
    return(0);
}



void print_frame(unsigned char *buf,int size)
{
    int i;
    for(i = 0; i < size; i++)
    {
        printf("0x%x ", buf[i]);
    }
    printf("
");
}


void getCompleteFrame(unsigned char *inBuf,int inCnt,unsigned char *outBuf,int *destCnt,int *readStatus)
{
    int i;
    for(i = 0; i < inCnt; i++)
    {
        if(inBuf[i] == 0x01 && inBuf[i+1] == 0x03)//header
        {
            outBuf[(*destCnt)++] = inBuf[i];
            *readStatus = 1;
            continue;
        }
        if(*readStatus == 1)//body
        {
            outBuf[(*destCnt)++] = inBuf[i];
        }
        if(*destCnt == outBuf[2] && *readStatus == 1)//tail
        {
            print_frame(outBuf,*destCnt);
            *readStatus = 0;
            *destCnt = 0;
            memset(outBuf, -1, sizeof(outBuf));
           // memset(inBuf,0,sizeof(inBuf));
            continue;
        }
    }
}


int main(void)
{
    unsigned char battery_msg[512];
    int fd;
    unsigned char read_buf[512] = {0};
    int nread = 0;
    fd = open("/dev/ttyS0", O_RDWR|O_NOCTTY);
    if (fd > 0)
    {
        printf("Open  Port Success!
");
    }
    else
    {
        printf("Can't Open port
");
        return(-1);
    }

    set_speed(fd, 115200);
    if(set_Parity(fd, 8, 'N', 1) == -1)
    {
        close(fd);
        return(-1);
    }
    int i = 0, rc = 0;
    int flag = 0;
    fd_set rset;
    struct timeval tv;
    int read_status = 0;
    int dest_cnt = 0;

    while (1) //循环读取数据
    {
        FD_ZERO(&rset);
        FD_SET(fd, &rset);

        tv.tv_sec = 5;
        tv.tv_usec = 0;

        rc = select(fd+1, &rset, NULL, NULL, &tv);

        if(rc > 0)
        {
      if(FD_ISSET(fd_485C2, &rset))
      {
memset(read_buf,
0, sizeof(read_buf)); usleep(100); nread = read(fd, read_buf, sizeof(read_buf)); // printf("read %d data ", nread); if(nread > 0) { getCompleteFrame(read_buf, nread, battery_msg,&dest_cnt,&read_status); }
      } } } close(fd);
return 0; }
原文地址:https://www.cnblogs.com/birdBull/p/12029933.html