串口读取的问题(问题解决高分相送 100分)

lzwwiner 2004-12-09 10:36:22
我写了一个读取串口的程序,但是每次读取的类容都是不完整的.
如果我让程序sleep(1)读取的内容又会多.
怎样控制读取才能取得自己想要的完整信息.
...全文
251 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
lzwwiner 2004-12-10
  • 打赏
  • 举报
回复
自己先顶住
core 2004-12-09
  • 打赏
  • 举报
回复
这是我的一段代码,用select的

if (FD_ISSET(conf.serial.fd, &r))
{
rc = read(conf.serial.fd, conf.serial.r.buffer + conf.serial.r.bytes, sizeof(conf.serial.r) - conf.serial.r.bytes - 1);
if (rc > 0)
core 2004-12-09
  • 打赏
  • 举报
回复
读取的时候,用循环去读,直到read返回字节是0,再进入等待状态。

-----------------------
真不知道你这句话从哪来的根据是什么
lzwwiner 2004-12-09
  • 打赏
  • 举报
回复
to: pacman2000(pacman)(影子传说)

读取串口的时候我是这样的:

while(!stopped)
{
if((RecvLen=PortRecv(fdcom,RecvBuf,1024,portinfo.baudrate))>0)
{
RecvBuf[RecvLen]='\0';
time (&timep);
cerr<<ctime(&timep);
for(i=0;i<RecvLen;i++)
{
CharToInt[i]=RecvBuf[i];
printf("%d|",CharToInt[i]);
}
printf("\n\n");
//emit myAlert();
}
//msleep(500);
}
close(fdcom);

这已经是循环读取了.
lzwwiner 2004-12-09
  • 打赏
  • 举报
回复
to: hoyt(hoyt)

[VMIN] = 0; 可以有哪些取值 //控制字符,
[VTIME] = 0;

pacman2000 2004-12-09
  • 打赏
  • 举报
回复
读取的时候,用循环去读,直到read返回字节是0,再进入等待状态。
NC 2004-12-09
  • 打赏
  • 举报
回复
# include <termio.h>
# include <fcntl.h>
# include <string.h>
# include <stdio.h>
# include <sys/types.h>
# include <stdlib.h>
# include "../incl/tools.h"

extern int comm_flag ;

char atcmd [ 20 ] = "ATB0E0M0N1S0=1\r" ;

/*
* AT Command :
*
* B : BELL / CCITT
0 -- CCITT
1 -- BELL
* E : Echo On / Off
* M : Sound volumn
* C : get "CONECT OK" or not
*
*/

int tty_open ( tty_name, fd )

char * tty_name;
int * fd;

{

int i, j;
int id;
struct termio arg;

if ( ( id = open ( tty_name , O_RDWR | O_NDELAY ) ) < 0 )
return ( 1 );

arg.c_iflag = IGNBRK;
arg.c_oflag = 0;

if ( comm_flag == 1 ) /* modem pool */
arg.c_cflag = CLOCAL | HUPCL | CREAD | CS8 | B1200;
else /* nac or rs232 */
arg.c_cflag = CLOCAL | HUPCL | CREAD | CS8 | B9600;

arg.c_lflag = 0;
arg.c_line = 0;

if ( comm_flag == 1 ) {

arg.c_cc [ VMIN ] = 0;
arg.c_cc [ VTIME ] = 10;

}
else {

arg.c_cc [ VMIN ] = 1;
arg.c_cc [ VTIME ] = 0;

}

i = ioctl ( id, TCSETA, &arg );

if ( i != 0 )
return ( 3 );
j = id;

if ( ( id = open ( tty_name, O_RDWR ) ) < 0 ) {

ErrorLog ( ERROR, " Can't Open %s Twice", tty_name );
return ( 2 );

}

close ( j );

* fd = id ;

if ( comm_flag == 1 )
write ( id, atcmd, strlen ( atcmd ) );

return ( 0 );

}
NC 2004-12-09
  • 打赏
  • 举报
回复
上面是接收和发送的代码,下面贴出打开串口的代码
hoyt 2004-12-09
  • 打赏
  • 举报
回复
你试着控制一下串口的VMIN,VTIME属性看看
可以参考一下
http://www.linuxforum.net/forum/gshowflat.php?Cat=&Board=program&Number=94205&page=0&view=collapsed&sb=5&o=all&fpart=

欢迎参观我的个人网站 http://www.linuxc.net
NC 2004-12-09
  • 打赏
  • 举报
回复
# include <fcntl.h>
# include <time.h>
# include <string.h>
# include <stdio.h>
# include <signal.h>
# include <setjmp.h>
# include <sys/types.h>
# include <stdlib.h>
# include "tools.h"

extern int comm_flag;
jmp_buf env_buf;
void timeout_handler ( int );

FILE * fppp;

int rcv ( fd_r, fd_w, buffer, max_count )

unsigned char * buffer;
unsigned max_count;
int fd_r, fd_w;

{

unsigned char * current, lrc;
unsigned int i, lenth , time_out_comm;
char filename [ 80 ];
char date [ 9 ] , time [ 9 ] , tmp [40];

signal ( SIGALRM, timeout_handler );
alarm ( 0 );
setjmp ( env_buf );

current = buffer;
* current = 0x00;

if ( comm_flag == 1 ) { /* modem pool need handshake */

while ( * current != 0x05 ) /** ENQ **/
read ( fd_r, current, 1 );

* current = 0x06; /** ACK **/
write ( fd_w, current, 1 );

for ( i = 0; i < 6; i ++ ) {

read ( fd_r, current, 1 );

if ( * current == 0x02 ) /**** STX ****/
break;
else {
* current = 0x06;
write ( fd_w, current, 1 );
}
}
if ( i >= 6 )
return ( -1 );
}
else { /* nac or rs232 */
while ( * current != 0x02 ) /**** STX ****/
read ( fd_r, current, 1 );
}

/*
* when recv time large 3 sec
* error and exit !
*/
time_out_comm = GetTimeOut ( "COMPOS" ) ;
alarm ( time_out_comm ) ;

current ++;
for ( i = 0; i < 2; i ++, current ++ )
read ( fd_r, current, 1 );

current --;
lenth = ( * current >> 4 ) * 10 + ( * current & 0x0f );
current --;
lenth += ( * current >> 4 ) * 1000 + ( * current & 0x0f ) * 100;

current += 2;

ErrorLog ( TRACE, "lenth = %d", lenth );

if ( lenth >= 512 ) {

* current = 0x0;

alarm ( 0 ) ;

return ( -1 ) ;
}

for ( i = 0; i < lenth + 2; i ++, current ++ ) {

read ( fd_r, current, 1 );
* current &= 0x000000ff ;

}

* current = 0x0;

alarm ( 0 );

if ( * ( current - 2 ) != 0x03 ) {

ErrorLog ( ERROR , "ETX ERROR!" ) ;
return ( -1 );

}

lrc = LRC ( buffer + 1, lenth + 3 );

if ( * ( current - 1 ) != lrc ) {
ErrorLog ( ERROR , "LRC ERROR![%02x],[%02x]" , lrc , * ( current - 1 ) ) ;
return ( -1 );
}

sgetdate ( date ) ;
sgettimef ( time , ":" ) ;

sprintf ( tmp , "/log/pos%s.in" , date ) ;

GetFullName ( WORKDIR, tmp , filename );

fppp = fopen ( filename, "a+" );
if ( fppp != NULL ) {
fprintf ( fppp , "%s\n" , time ) ;
fprintf ( fppp , "================================================\n" ) ;
for ( i = 0 ; i < lenth + 5 ; i ++ )
fprintf ( fppp , "%02x " , buffer[i] );
fprintf ( fppp , "\n" ) ;
fprintf ( fppp , "================================================\n" ) ;
fclose ( fppp );
}

return ( lenth + 5 ); /* stx + lenth ( 2 ) + tpdu + data ( lenth - 5 ) + etx + lrc */

}

/*
* buffer include tpdu + data
*/

int snd ( fd, buffer, max_count )

int fd;
unsigned char * buffer;
int max_count;

{

unsigned i;
unsigned char snd_buffer [ 512 ];
char filename [ 80 ];
char date [ 9 ] , time [ 9 ] , tmp [40];

snd_buffer [ 0 ] = 0x02; /**** STX ****/

snd_buffer [ 1 ] = ( max_count / 100 ) + ( max_count / 100 ) / 10 * 6;
snd_buffer [ 2 ] = ( max_count % 100 ) + ( max_count % 100 ) / 10 * 6;

for ( i = 0; i < max_count; i ++ )
snd_buffer [ 3 + i ] = buffer [ i ];

snd_buffer [ max_count + 3 ] = 0x03; /**** ETX ****/

snd_buffer [ max_count + 4 ] = LRC ( snd_buffer + 1, max_count + 3 );
i = write ( fd , snd_buffer , max_count + 5 );

sgetdate ( date ) ;
sgettimef ( time , ":" ) ;

sprintf ( tmp , "/log/pos%s.out" , date ) ;

GetFullName ( WORKDIR, tmp , filename );

fppp = fopen ( filename , "a+" ) ;
if ( fppp != NULL ) {
fprintf ( fppp , "%s\n" , time ) ;
fprintf ( fppp , "================================================\n" ) ;
for ( i = 0 ; i < max_count + 5 ; i ++ )
fprintf ( fppp , "%02x " , snd_buffer[i] );
fprintf ( fppp , "\n" ) ;
fprintf ( fppp , "================================================\n" ) ;
fclose ( fppp ) ;
}


return ( i ) ;

}

void timeout_handler (int wlg )

{

signal ( SIGALRM, timeout_handler );
alarm ( 0 );
longjmp ( env_buf, 1 );
return ;

}
lzwwiner 2004-12-09
  • 打赏
  • 举报
回复
自己先顶住
lzwwiner 2004-12-09
  • 打赏
  • 举报
回复
to: yuanlei1978113(小石头)

我对select这个函数还不太熟悉,可以就我下面的代给我写一个简单的例子吗?
谢谢了.

while(!stopped)
{
if((RecvLen=read(fdcom,RecvBuf,1024))>0)
{
RecvBuf[RecvLen]='\0';
time (&timep);
cerr<<ctime(&timep);
for(i=0;i<RecvLen;i++)
{
CharToInt[i]=RecvBuf[i];
printf("%d|",CharToInt[i]);
}
printf("\n\n");
//emit myAlert();
}
//msleep(500);
}
close(fdcom);

yuanlei1978113 2004-12-09
  • 打赏
  • 举报
回复
用select监听,一次读取一个直到read返回0即可.
lzwwiner 2004-12-09
  • 打赏
  • 举报
回复
其实我读取串口已经没有问题了,就是想知道能不能控制每次读取串口所
读取的类容刚好是我需要的类容.
而且串口每次发来的内容是按已经定好的协议发送过来的,只是有时候发送过来的
信息长短不一样了.
hoyt 2004-12-09
  • 打赏
  • 举报
回复
可以参考一下《unix环境高级编程》的第11章,下面是一个文本链接的地址
chianpub有电子书籍下载,可以去找一下
http://unix-cd.com/article/printpage.asp?ArticleID=592
pacman2000 2004-12-09
  • 打赏
  • 举报
回复
core:
我说的是一般的轮询方式啊,有什么不对?read是有可能一次读取不完的啊,跟fd代表的设备本身有关,比如最常见的就是socket。

23,110

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧