catch2000 发表于 2012-4-17 16:11:12

AT91嵌入式linux下的串口接收问题

本帖最后由 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 = 1;
buf.c_cc = 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 != 1 ||
buf.c_cc != 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 中的红色标记部分设置来补充,
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= 0;
    newtio.c_cc   = 1;
   
    tcflush(fd,TCIFLUSH);
    if((tcsetattr(fd,TCSANOW,&newtio))!=0)
    {
      perror("com set error");
      return -1;
    }
tcflush(fd,TCIFLUSH);
return 0;
}

修改完的初步测试中发现有时候也有数据接收不完整的情况。
请问这里会因为什么样的缘故导致数据接收不完整呢?

catch2000 发表于 2012-4-20 09:44:34

串口方面的接收问题,
应该很多人遇到过,
大家有什么好的解决之道呢?

catch2000 发表于 2012-4-24 15:21:31

关于这个问题,
现在自认为是解决了,
首先串口配置这里,
感觉很多是这个样子。

后来发现是,
串口接收的字节设置,
小于了串口接收的数据字节,
导致了,没有被读出的数据,
被tcflush掉了。
后来改正,并做了其他修正,
基本解决了串口数据接收问题。
页: [1]
查看完整版本: AT91嵌入式linux下的串口接收问题