在实际对串口设备操作时,一般都需要超时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;
}
/////////////////////////////////////////////////////////////////////////////////////////////