好记性不如烂笔头(linux的串口超时read的参数意义)

在实际对串口设备操作时,一般都需要超时read,关于read的第三个参数意义总是忘记。


1:open /dev/ttySP0 获取fd


2:write(fd,***,)向fd写数据


3:fd返回响应数据,并使用select+read进行超时读取未知、不定长度的数据:

read函数参数有三:int fd,char * p,int nbyte,前两个好理解,

最后一个nbyte指:如果缓存中有大于nbyte个数据那么只返回nbyte个数据,剩余的数据下次再去读时才能读到,

如果缓存中只有少于nbyte个数据,那么这时就要配合打开串口时的一个配置参数“options.c_cc[VTIME] ” 来看了,不足nbyte个时,串口驱动只会等待options.c_cc[VTIME](单位百毫秒)这么长时间,到时间通知read同样返回,并且读取少于nbyte的实际数量的数据,而不会去等到select的超时,才返回,这么看来,串口配置也是自带的似乎是"硬超时"。


//read样例

//////////////////////////////////////////////////////////////////////////////////////////////////////////

int serial_read(int fd,char * p,int desire_get_len,int time_out_ms)
{
int nfds;
int nread = 0 ;
char read_temp[256];
fd_set readfds;
struct timeval tv;

    tv.tv_sec = time_out_ms/1000;
    tv.tv_usec = time_out_ms%1000;
FD_ZERO(&readfds);
FD_SET(fd,&readfds);
bzero(read_temp,sizeof(read_temp));
nfds = select(fd+1,&readfds,NULL,NULL,&tv);

if(nfds == 0) 
{
printf("timeout!\r\n");
return 0;
}
else
{
nread = read(fd,read_temp,desire_get_len);//即使不满desire_get_len,也会返回实际读取到的数据量
if(nread<=0)
{
            printf("read get problem!\r\n");
}
}
memcpy(p,read_temp,nread);
return nread;  
}

///////////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////////

//串口配置样例

int usart_ttyS0_init(char * uart_name,char * uart_rate)
{
    int fd1=0;


    struct termios options;    //usart par struct
    fd1 = open(uart_name, O_RDWR|O_NOCTTY);
    //printf("open result is %d\n",fd1);
    //logmsg(INFO_NAME,"open result is %d\r\n",fd1);


    tcgetattr(fd1, &options);        //获取opt指针。

        cfsetispeed(&options, B9600);    //set bps in
        cfsetospeed(&options, B9600);    //set bps out
  
options.c_cflag |= (CLOCAL | CREAD);    //enable date receiver
options.c_cflag &= ~PARENB;      //没有校验
options.c_cflag &= ~CRTSCTS;     //没有数据流
options.c_cflag &= ~CSTOPB;   //关闭两位停止位,就是一位停止位
options.c_cflag &= ~CSIZE;    //设置数据位宽时打开掩码
options.c_cflag |= CS8;       //8位数据位


        //关闭ICRNL IXON 防止0x0d 0x11 0x13的过滤
options.c_iflag &=~(IXON | IXOFF | IXANY); 
options.c_iflag &= ~ (INLCR | ICRNL | IGNCR);
        options.c_oflag &= ~(ONLCR | OCRNL);
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);    
//options.c_oflag &= ~OPOST;term.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);


        //options.c_oflag  &= ~OPOST;
options.c_oflag &= ~OPOST;   //使用原始数据


        //只有阻塞时,下面两个才有效,且针对读。
options.c_cc[VMIN]  = 50;  //最小字节数(读)   4800  50  5     这个傻意思忘记了
options.c_cc[VTIME] = 5;     //等待时间,单位百毫秒(读)  115200 50 1


tcsetattr(fd1, TCSANOW, &options); //写入options


return fd1;
}

/////////////////////////////////////////////////////////////////////////////////////////////



猜你喜欢

转载自blog.csdn.net/aazhoukeaa/article/details/68484075
今日推荐