首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 操作系统 > UNIXLINUX >

嵌入式linux下串口采用xmodem协议 接受不成功解决方法

2012-06-14 
嵌入式linux下串口采用xmodem协议 接受不成功接受时总是无法接受完整的包而超出最大次数,最后退出程序, 请

嵌入式linux下串口采用xmodem协议 接受不成功
接受时总是无法接受完整的包而超出最大次数,最后退出程序, 请问是什么原因? 怎么改?

int xmodemReceive(int fd, char *dest, int destsz)
{
  unsigned char xbuff[38]; /* 1024 for XModem 1k + 3 head chars + 2 crc + nul */
  //unsigned char *p;
  int bufsz, crc = 0;
  unsigned char c, trychar = 'C';
  unsigned char packetno = 1;
  int len = 0;
  int retry, retrans = MAXRETRANS;
  for(;;)
  {
  for( retry = 0; retry < 4; ++retry)
  {
  if (trychar)
  port_outbyte(fd, trychar);
  }
  while(c != SOH){
  c = port_inbyte(fd);
  if(c == EOT || c == CAN)
  break;
  }//(DLY_1S)<<1);
  if (last_error == 0)
  {
  switch (c)
  {
  case SOH:
  bufsz = 32;
  goto start_recv;
  case EOT:
  flushinput();
  port_outbyte(fd, ACK);
  return len; /* normal end */
  case CAN:
  c = port_inbyte(fd);//DLY_1S);
  if (c == CAN)
  {
  flushinput();
  port_outbyte(fd, ACK);
  return -1; /* canceled by remote */
  }
  break;
  default:
  break;
  }
  }

  if (trychar == 'C')
  {
  trychar = NAK;
  continue;
  }
  flushinput();
  port_outbyte(fd, CAN);
  port_outbyte(fd, CAN);
  port_outbyte(fd, CAN);
  return -2; /* sync error */
  start_recv:
  if (trychar == 'C') crc = 1;
  trychar = 0;
  usleep(10000);
  retry = read(fd, xbuff, 38);
  if (retry < 37)
  {
  printf("last_error2=%d\n", retry);
  goto reject;
  }
  if (xbuff[1] == (unsigned char)(~xbuff[2]) &&
  (xbuff[1] == packetno || xbuff[1] == (unsigned char)packetno-1) &&
  check(crc, &xbuff[3], bufsz))
  {
  if (xbuff[1] == packetno)
  {
  int count = destsz - len;
  if (count > bufsz)
  count = bufsz;


  if (count > 0)
  {
  memcpy (&dest[len], &xbuff[3], count);
  len += count;
  }
  ++packetno;
  printf("count=%d len=%d packetno=%d\n", count, len, packetno);
  retrans = MAXRETRANS+1;
  }
  if (--retrans <= 0)
  {
  flushinput();
  port_outbyte(fd, CAN);
  port_outbyte(fd, CAN);
  port_outbyte(fd, CAN);
  return -3; /* too many retry error */
  }
  port_outbyte(fd, ACK);
  continue;
  }
  reject:
  flushinput();
  c = port_inbyte(fd);
  printf("rej=%d\n", c);
  port_outbyte(fd, NAK);
  }
}

int xmodemTransmit(int fd, unsigned char *src, int srcsz)
{
unsigned char xbuff[38]; /* 1024 for XModem 1k + 3 head chars + 2 crc + nul */
int bufsz, crc = -1;
unsigned char packetno = 1;
int c, len = 0;
int retry;
for(;;)
{
//for( retry = 0; retry < 16; ++retry)
//{
while(c != 'C'){
c = port_inbyte(fd);
if(c == NAK || c == CAN)
break;
}//(DLY_1S)<<1);
if (last_error == 0) 
{
switch (c) 
{
case 'C':
crc = 1;
goto start_trans;
case NAK:
crc = 1;
goto start_trans;
case CAN:
c = port_inbyte(fd);//DLY_1S);
if (c == CAN)
{
port_outbyte(fd, ACK);
flushinput();
return -1; /* canceled by remote */
}
break;
default:
break;
}
}
//}
port_outbyte(fd, CAN);
port_outbyte(fd, CAN);
port_outbyte(fd, CAN);
flushinput();
return -2; /* no sync */
for(;;)
{
start_trans:
xbuff[0] = SOH; bufsz = 32;
xbuff[1] = packetno;
xbuff[2] = ~packetno;
c = srcsz - len;
printf("c1=%d \n", c);
if (c > bufsz) c = bufsz;
if (c >= 0) 
{
memset (&xbuff[3], 0, bufsz);
if (c == 0) 
{
xbuff[3] = CTRLZ;
}
else 
{
memcpy (&xbuff[3], &src[len], c);
if (c < bufsz) xbuff[3+c] = CTRLZ;
}
if (crc) 
{
unsigned short ccrc = crc16_ccitt(&xbuff[3], bufsz);
xbuff[bufsz+3] = (ccrc>>8) & 0xFF;
xbuff[bufsz+4] = ccrc & 0xFF;
}
for (retry = 0; retry < MAXRETRANS; ++retry)
{
usleep(100000);
write(fd, xbuff, 38);
usleep(10000);
c = port_inbyte(fd);//DLY_1S);
if (last_error == 0 )
{
switch (c)
{
case ACK:
printf("ACK=%d\n", c);
++packetno;
len += bufsz;
goto start_trans;
case CAN:
c = port_inbyte(fd);//DLY_1S);
if ( c == CAN)
{
port_outbyte(fd, ACK);
flushinput();
return -3; /* canceled by remote */
}
break;
case NAK:
printf("NAK=%d\n", c);


//break;
default:
break;
}
}
}
printf("C=%d\n", c);
port_outbyte(fd, CAN);
port_outbyte(fd, CAN);
port_outbyte(fd, CAN);
flushinput();
return -4; /* xmit error */
}
else 
{
for (retry = 0; retry < 10; ++retry) 
{
port_outbyte(fd, EOT);
c = port_inbyte(fd);//(DLY_1S)<<1);
if (c == ACK) break;
}
flushinput();
return (c == ACK)?len:-5;
}
}
}
}



[解决办法]
楼主 有完整的程序嘛 发份看下 linuxarmcom@163.com

热点排行