|
本帖最后由 catch2000 于 2012-4-17 16:16 编辑
在基于AT91的嵌入式linux中接收串口数据时,发现对于接收的数据经常出现接收不完整的现象。一帧的数据可能会被当做两帧接收,导致对于一帧数据接收出现问题。虽然这种情况在一般情况下,并不是经常出现,但是只要数据量稍微大一些,情况就会出现。
根据APUE可知由VTIME,VMIN的设置共可以有四种选择
A:VTIME > 0, VMIN > 0
B: VTIME = 0, VMIN > 0
C: VTIME > 0, VMIN = 0
D: VTIME = 0, VMIN = 0
结合APUE中的示例程序,发现APUE中将终端设置为原始模式(raw modle)与这里的设置较为相似,于是想采用APUE中的部分参数设置,来修改此处的程序。
======APUE中 put terminal into a raw modle =====================
int
tty_raw(int fd) /* put terminal into a raw mode */
{
int err;
struct termios buf;
if (ttystate != RESET) {
errno = EINVAL;
return(-1);
}
if (tcgetattr(fd, &buf) < 0)
return(-1);
save_termios = buf; /* structure copy */
/*
* Echo off, canonical mode off, extended input
* processing off, signal chars off.
*/
buf.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
/*
* No SIGINT on BREAK, CR-to-NL off, input parity
* check off, don't strip 8th bit on input, output
* flow control off.
*/
buf.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
/*
* Clear size bits, parity checking off.
*/
buf.c_cflag &= ~(CSIZE | PARENB);
/*
* Set 8 bits/char.
*/
buf.c_cflag |= CS8;
/*
* Output processing off.
*/
buf.c_oflag &= ~(OPOST);
/*
* Case B: 1 byte at a time, no timer.
*/
buf.c_cc[VMIN] = 1;
buf.c_cc[VTIME] = 0;
if (tcsetattr(fd, TCSAFLUSH, &buf) < 0)
return(-1);
/*
* Verify that the changes stuck. tcsetattr can return 0 on
* partial success.
*/
if (tcgetattr(fd, &buf) < 0) {
err = errno;
tcsetattr(fd, TCSAFLUSH, &save_termios);
errno = err;
return(-1);
}
if ((buf.c_lflag & (ECHO | ICANON | IEXTEN | ISIG)) ||
(buf.c_iflag & (BRKINT | ICRNL | INPCK | ISTRIP | IXON)) ||
(buf.c_cflag & (CSIZE | PARENB | CS8)) != CS8 ||
(buf.c_oflag & OPOST) || buf.c_cc[VMIN] != 1 ||
buf.c_cc[VTIME] != 0) {
/*
* Only some of the changes were made. Restore the
* original settings.
*/
tcsetattr(fd, TCSAFLUSH, &save_termios);
errno = EINVAL;
return(-1);
}
ttystate = RAW;
ttysavefd = fd;
return(0);
}
从英文注释,可以了解到,各个参数的具体意义,
同时参考博客http://blog.csdn.net/awei_xu/article/details/3725329 [size=12.0000pt]中的红色标记部分设置来补充,
if((fd = open(dev,O_RDWR | O_NOCTTY | O_NDELAY)) == -1)
/*---------------------- 重要----------------------*/
//保证本程序不会成为端口的所有者,从而妨碍控制工作和挂起信号.
opt.c_cflag |= (CLOCAL | CREAD);
//选择原始输入方式: 原始输入方式是不经处理的.
opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
//输出不经处理
opt.c_oflag &= ~OPOST;
//取消软件流控制(不设置可能存在丢码)
opt.c_iflag &= ~(IXON | IXOFF | IXANY); /*----------------------------------------------------*/
最终的串口设置程序:
int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
{
struct termios oldtio;
struct termios newtio;
if( tcgetattr(fd, &oldtio) != 0) {
perror("SetupSerial 1");
return -1;
}
newtio = oldtio;
/*************Debug*******************/
newtio.c_cflag |= CLOCAL | CREAD;
newtio.c_cflag &= ~(CSIZE | PARENB);
newtio.c_lflag &= ~(ICANON | ISIG | ECHO | ECHOE | IEXTEN);
newtio.c_oflag &= ~OPOST;
newtio.c_iflag &= ~(IXON | IXOFF | IXANY | ICRNL | BRKINT
| INPCK | ISTRIP);
/***************************************/
.......
newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 1;
tcflush(fd,TCIFLUSH);
if((tcsetattr(fd,TCSANOW,&newtio))!=0)
{
perror("com set error");
return -1;
}
tcflush(fd,TCIFLUSH);
return 0;
}
修改完的初步测试中发现有时候也有数据接收不完整的情况。
请问这里会因为什么样的缘故导致数据接收不完整呢?
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
阿莫论坛20周年了!感谢大家的支持与爱护!!
你熬了10碗粥,别人一桶水倒进去,淘走90碗,剩下10碗给你,你看似没亏,其实你那10碗已经没有之前的裹腹了,人家的一桶水换90碗,继续卖。说白了,通货膨胀就是,你的钱是挣来的,他的钱是印来的,掺和在一起,你的钱就贬值了。
|