关于嵌入式linux下的串口通讯问题---回车、换行、缓冲

嵌入式Linux串口通讯测试问题:
  经过实验,从Linux(PC)通过串口向嵌入式Linux开发板发送数据时,串口初始化完毕后遇到回车(0x0d)或换行(0x0a)才开始从串口接收数据,回车或换行前的数据接收不到,回车或换行后的数据接收正常.从嵌入式Linux开发板通过串口向Linux(PC)发送数据,接收正常.无丢字符现象.请问这是为什么?两台Linux(PC)经过串口通讯接收正常.
-----------------------------
应该是你初始化不完整造成的.不知道你是直接端口操作还是访问的 ttySX来完成的.
-----------------------------
=============================================================================
http://bbs.linuxpk.com/thread-33570-1-1.html
我现在编写了一个 linux串口接收程序, 接收时必须在发送信息的后面附带一个 回车符,要不然它只会存在接受缓存中而不 接收,我上网搜了,说是什么行缓冲的问题,但是不知道怎么去解决啊!
------------------------------------
linux串口中,默认的模式下只有但backspace按下的时候,才可以把缓冲区的数据提交给进程, linux提供了一个接口可以改变 串口的这种默认的行为,详细信息可以查看 man termios
============================================================================
 
http://www.lslnet.com/linux/dosc1/06/linux-137429.htm(注:这个程序就是我用的一个能够实现接收串口数据的程序,其中把信息分开接收是因为设置的最少接收的字节数的问题,可以设置成大一些的数据)
 
现在想用 串口接收数据,找了一个 串口程序,前一段用的每问题。现在发现了一个问题,各位高手帮忙看一下如何解决?
    接受程序是这样的:(之前的初始化就不写了,肯定没问题)
                     char buff[512];
                   while((nread = read(fd,buff,10))>0)//fd是端口文件
                   {
                              printf("Len %d\n",nread);
                              buff[nread]='\0';
                              printf("%s\n",buff);
                    }
     我把两台机器 串口连起来,一台 linux运行这个程序。另一台winxp运行 串口助手先前者发数据。比如发
两次“This is a test message!”这个字符串,[b]发现 linux端没有任何显示[/b]。这时,我在winxp的字符串后加一个 回车符再发一次, linux就接受到了,而且之前发的数据也打印数来了,如下
len=10
This is a 
len=10
test messa
len=10
ge!This is
len=10
a test me
len=10
ssage!This
len=10
is a test
len=10
message!

len=1

     (最后这应该是 回车符)
     我的理解是 串口发的数据 linux已经都受到了,都放在缓冲区里了,但是必须出现一个结束符read函数才能从缓冲区里读出数据来,所以最后加上 回车符发送消息后,之前发的也显示出来了,不知道这么理解对不对。

    但是,我现在是想只要winxp端发来数据, linux端就显示出来,而不必等待结束符。我想了好久也没有头绪,对缓冲区这里得知识不太了解。希望各位高手帮帮忙,要怎样解决这个问题?
----------------------------------------------
可以设置成不缓存的吧,google下
----------------------------------------------
怎么设呢?
是用setbuf吗?
setbuf(stdin,NULL);
我用这个不管用
----------------------------------------
你现在处理的是 串口fd,你把stdin setbuf肯定不行了
-----------------------------------------
这有个例子,先看看
http://astronomy.swin.edu.au/~pbourke/other/serial/tru64.c
还有个编程向导也可以看看
http://digilander.libero.it/robang/rubrica/serial.htm
==============================================================================
http://topic.csdn.net/u/20090730/15/9f78d601-8456-4071-9512-d218b7f229a9.html
我的程序是跑在linux下的串口通讯程序,通讯一方是我的LINUX程序,另一方是个单片机. 
  他给我发送数据的时候现在我必须让他在数据的末尾再另加发一个回车的ASIC码我才能收到,否则收不到,这是怎么回事情啊?
-----------------------
设计用回车做发送标志吧。
-----------------------
检查一下 单片机程序,是不是有缓冲机制?
-------------------------
查了查资料,好象是说需要设置为原始模式.可究竟怎么设置为原始模式,总也没个统一的说法.高手们谁有这方面经验啊?
-------------------------
首先要有一个协议,如果协议里没有回车就不用了,直接进行收发,还有就是可以的话在协议里增加一个报文长度,这样也很好判断结束. 
想想也不对呀,怎么会让对方加结束符你才能收到,你是怎么判断一帧数据结束的?查检一下
-------------------------
while(1) 
  { 
      nread = read(fd, buff, 127); 
  while((nread>0)) 
  { 
      buff[nread]='\0'; 
      printf("%s",buff); 
            nread = 0; 
  } 
  } 


这个是我的读串口程序,我没加任何判断,只要读到了就显示.可如果对方不发送回车我这边就怎么也显示不出来.无论对方之前发了多少东西,只要最后发个回车,前面发的就会全部显示出来.
---------------------------------
设置原始通信模式,串口不对接收到的数据进行处理而直接返回 
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); 
options.c_oflag &= ~OPOST;
---------------------------------
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); 
options.c_oflag &= ~OPOST; 
接受程序设置了,还是那样. 

应该不是发送方的问题.因为我用另外一个linux系统发送也是这样,发送完了必须发送个回车. 
这边才接到.
----------------------------------
设置原始模式可以通过cfmakeraw函数,同时可以添加超时和读取最小字符的设置。
======================================================================
 
http://topic.csdn.net/u/20071010/12/1f584805-f8f0-44f4-b6af-130401152ceb.html
linux与windows间进行简单的串行数据的发送 接收操作. linux下的程序源码如下,windows用使用 串口调试程序收发数据.结果 linux发往windows的数据能正常 接收,但windows发往 linux的数据 linux方却无法 接收,最奇怪的事是: windows发送的数据windows自己却收到了( linux没有转发收到的数据, 串口线的2,3脚也没有短接;在windows上开两个 串口调试程序,在COM1,COM2间发送数据进行试验,一切正常)!!请高人指点迷津. 
#include /* Standard input/output definitions */ 
#include /* String function definitions */ 
#include /* UNIX standard function definitions */ 
#include /* File control definitions */ 
#include /* Error number definitions */ 
#include /* POSIX terminal control definitions */ 
#include  
#include  
#include  
#include  
int main(void) 

int recnum,fd; 
char buf[1024]; 
recnum=0; 
recnumb=0; 
fd=open("/dev/ttyS0",O_RDWR|O_NONBLOCK) 
if(fd==-1) 

perror("failed to open com1:"); 
return 0; 

ia=write(fd,"the data come from  linux!",25); 
if(ia <0) 

fputs("failed to write data to com1!\n",stderr); 
return 0; 

while(1) 

recnum=read(fd,buf,255); 
if(recnum>0) 
break; 

printf("%s\n",buf); 
close(fd); 
return 0; 


--------------------------
你用 串口调试助手发送数据的时候加个“ 回车”, linux下就能收到了,是什么原因,我也不清楚,反正我以前用 串口发数据的时候就是这样,正奇怪着呢,就搞别的去了,这个问题一直没有解决。
--------------------------
非常感谢楼上的,加个" 回车"确实能够收到了,但很奇怪 linux在收到的时候还是会给windows回发数据,我觉得可能是 串口驱动的问题,我想把问题解决应该不难,甚至自己写个驱动,但现在的问题是不知道驱动放在哪里了。另外在setserial里有divisor选择驱动,默认是0,能改变这个吗?
---------------------------
默认文件是行缓冲的,没回车当然收不到 
要进行终端特性设置的,好好看看termio
---------------------------
谢谢指教,现在比较急,我在看termio.h这个文件,是不是定义这个结构体的时候需要设置,或者终端特性设置指什么?
---------------------------
终端设置就是指定义termio这个结构体吧,还有个问题,为什么windows给 linux串口信息,会自动返回信息呢?也是和终端设置有关系吗?还是驱动?
--------------------------
我好好看了下termio,受益非浅,确实是里面的设置问题,谢谢,问题已解决,准备结贴。
======================================================================
 
常用设置

9.1设置规范模式

规范模式是面向行的输入方式,输入字符被放入用于和用户交互可以编辑的缓冲区内,直接到读入回车或者换行符号时才结束。

可以通过如下方式来设置

option.c_lflag |= (ICANON | ECHO | ECHOE);

9.2设置原始输入模式

原始输入模式是没有处理过的,当接收数据时,输入的字符在它们被接收后立即被传送,使用原始输入模式时候,一般可以选择取消ICANON,ECHO,ECHOE和ISIG选项。

例如:

option.c_lflag &= ~(ICANON | ECHO | ECHOE);

=========================================================================

总结:上面的问题应该比较清楚了,就是在输入模式的设置上出了问题,默认的可能是行缓冲的,导致在接收串口的时候,串口会自行把数据存到缓冲里面,只有接收到回车、换行等结束标志后,才把数据一起送到内存,这样串口的read函数才能读到数据,也就会触发相应的标志(SIGIO)。所以,需要在对串口设置的时候,要设置为原始输入模式。

你可能感兴趣的:(嵌入式,Linux)