liunx C 串口接收缓存区不够时 接收数据方法

 主要思路:飞快的从缓存区取数据(完).

1.将堵塞接收改为超时接收

/*
 * serial.h
 *
 *  Created on: 2021年11月22日
 *      Author: dell
 */
#include <asm/termios.h>
#ifndef SERIAL_H_
#define SERIAL_H_

static void set_baudrate (struct termios *opt, unsigned int baudrate)
{
    switch(baudrate)
    {
        case 460800:
            baudrate = B460800;
            break;
        case 115200:
            baudrate = B115200;
            break;
        case 19200:
            baudrate = B19200;
            break;
        case 9600:
            baudrate = B9600;
            break;
        case 2400:
            baudrate = B2400;
            break;
        default :
            baudrate = B9600;
            break;
    }
    speed_t speed = baudrate;
    cfsetispeed(opt, speed);
    cfsetospeed(opt, speed);
}
static void set_data_bit (struct termios *opt, unsigned int databit)
{
    opt->c_cflag &= ~CSIZE;
    switch (databit)
    {
        case 8:
        opt->c_cflag |= CS8;
        break;
        case 7:
        opt->c_cflag |= CS7;
        break;
        case 6:
        opt->c_cflag |= CS6;
        break;
        case 5:
        opt->c_cflag |= CS5;
        break;
        default:
        opt->c_cflag |= CS8;
        break;
    }
}
static void set_parity (struct termios *opt, char parity)
{
    switch (parity)
    {
        case 'N': /* 无校验 */
        case 'n':
            opt->c_cflag &= ~PARENB;
        break;
        case 'E': /* 偶校验 */
        case 'e':
            opt->c_cflag |= PARENB;
            opt->c_cflag &= ~PARODD;
        break;
        case 'O': /* 奇校验 */
        case 'o':
            opt->c_cflag |= PARENB;
            opt->c_cflag |= ~PARODD;
        break;
        default: /* 其它选择为无校验 */
            opt->c_cflag &= ~PARENB;
        break;
    }
}
static void set_stopbit (struct termios *opt, const char *stopbit)
{
     if (0 == strcmp (stopbit, "1"))
     {
         opt->c_cflag &= ~CSTOPB; /* 1 位停止位 t */
     }
     else if (0 == strcmp (stopbit, "1.5"))
     {
         opt->c_cflag &= ~CSTOPB; /* 1.5 位停止位 */
     }
     else if (0 == strcmp (stopbit, "2"))
     {
         opt->c_cflag |= CSTOPB; /* 2 位停止位 */
     }
     else
     {
         opt->c_cflag &= ~CSTOPB; /* 1 位停止位 */
     }
}

int set_port_attr ( int fd,struct termios *opt, int baudrate, int databit, const char *stopbit, char parity, int vtime, int vmin )
{
//    struct termios opt;

    tcgetattr(fd, opt);  // 读取串口设置
    set_baudrate(opt, baudrate);    // 设置波特率
    opt->c_cflag &= ~(CSIZE | PARENB);    // 输出标志 /* | CRTSCTS */
    set_data_bit(opt, databit);    // 数据位
    set_parity(opt, parity);        // 奇偶校验
    set_stopbit(opt, stopbit);        // 停止位

    opt->c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); //禁止将输入的CR转换为NL
    opt->c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);                // 本地标志
    opt->c_oflag &= ~OPOST;            // 输出标志
    opt->c_cc[VTIME] = vtime;        // 超时时间
    opt->c_cc[VMIN] = vmin;            // 最小字节数
    tcflush (fd, TCIFLUSH);
    return (int)tcsetattr (fd, TCSANOW, opt);// 设置串口设置

}

/*******************************************
 *  receive data
 *  返回实际读入的字节数
 *
********************************************/
int PortRecv(int fdcom, char *data, int datalen)
{
    int readlen, fs_sel;
    fd_set  fs_read;
    struct timeval tv_timeout;

    FD_ZERO(&fs_read);
    FD_SET(fdcom, &fs_read);
    tv_timeout.tv_sec = 0;
    tv_timeout.tv_usec = 10000;

    fs_sel = select(fdcom+1, &fs_read, NULL, NULL, &tv_timeout);
    if(fs_sel)
    {
        readlen = read(fdcom, data, datalen);
        return(readlen);
    }
    else{
        return(-1);
    }

    return (readlen);
}

#endif /* SERIAL_H_ */

函数调用

   // 打开串口
   fd= open(serial_address,O_RDWR | O_NOCTTY);// O_NOCTTY 告诉liunx本程序不作为串口控制终端 if(fd<0) { perror("open error"); return -1; }
  // 设置串口 res
= set_port_attr (fd,&opt, baudrate, 8, "1", 'N', 1, 1 ); if(res < 0) { perror("set uart arrt failed \n"); exit(-1); }
  // 接收数据
int buf_count = PortRecv(p->fd, tt, 255); /* 在串口读入字符串 */

2. 飞快从缓存区取数据,同时对报文进行区分

void *serial_read(struct thread_parameter *p)
{
    int i;
    char tt[255];
    int count;

    while(1)
    {
        char buf[1024];
        count=0;
        while(1)
        {
       // 每隔1毫秒就从缓存区取出所有数据,
       // 取出字节数为0时代表你这一帧接收完了 usleep(
1); int buf_count = PortRecv(p->fd, tt, 255); /* 在串口读入字符串 */ if(buf_count>0) { for(i=0;i<buf_count;i++) { buf[count] = tt[i]; count++; } } else { break; } } if(count > 0) { pthread_mutex_lock(p->lock); AddList_T(p->data,buf,count); pthread_mutex_unlock(p->lock); fflush(stdout); } usleep(1); } pthread_exit(NULL); }

 

posted @ 2022-06-21 17:31  妖言惑众'  阅读(407)  评论(0编辑  收藏  举报