在工作时串口通信的过程中需要传输文件,这里就就需要使用通信协议,此时选择的是Xmodem协议作简要研究

1、什么是Xmodem协议

Xmodem协议是串口通信中广泛使用到的异步文件传输协议。以128字节块的形式传输数据,并且每个块都使用一个校验过程来进行错误检测。在校验过程中如果接收方关于一个块的检验和与它在发送方的检验相同时,接收方就向发送方发送一个确认字节<ACK>。如果有错则发送一个字节<NAK>要求重发。以保证传输过程中的正确性,但是由于需要对每个块都要进行检验,显得效率比较低。

2、Xmodem协议相关控制字符

SOH              0x01          //Xmodem数据头
STX              0x02           //1K-Xmodem数据头
EOT              0x04           //发送结束
ACK             0x06           //认可响应
NAK             0x15           //不认可响应
CAN             0x18           //撤销传送
CTRLZ         0x1A          //填充数据包

3、标准Xmodem协议(每个数据包含有128字节数据)帧格

Xmodem包格式

Byte1                         Byte2                           Byte3                     Byte4~131            Byte132~133

Start Of Header          Packet Number          ~(Packet Number)          Packet Data            16-Bit CRC

Xmodem协议的传输数据单位为信息包,包含一个标题开始字符<SOH>或者<STX>,一个单字节包序号,一个单字节包包序号的补码,128个字节数据和一个双字节的CRC16校验

4、数据包说明

对于标准Xmodem协议来说,如果传送的文件不是128的整数倍,那么最后一个数据包的有效内容肯定小于帧长,不足的部分需要用CTRL-Z(0x1A)来填充

5、如何启动传输

Xmodem协议的传输由接收方启动,接收方向发送方发送"C"或者NAK(这里的NAK是用来启动传输的。下面我们用到的NAK是用来对数据产生重传机制)。其中接收方发送NAK信号表示接收方打算用累加和校验;发送字符"C"则表示接收方打算使用CRC校验。

6、传输过程

当接收方发送的第一个"C"或者NAK到达发送方,发送方认为可以发送第一个数据包了,传输启动。发送方接着接着应该将数据以每次128字节的数据加上包头,包号,包号补码,末尾加上校验和,打包成帧格式传送。发送方发了第一个包后就等待接收方的确认字节<ACK>,收到接收方传来的<ACK>确认,就认为数据包被接收方正确接收,并且接收方要求发送方继续发送下一个包;如果发送方收到接收方传来的<NAK>(这里的表示重发),则表示接收方请求重发刚才的数据包;如果发送方收到接收方传来的<CAN>字节,则表示接收方请求无条件停止传输。

7、结束传输

如果发送方正常传输完全部数据,需要结束传输,正常结束需要发送方发送<EOT>通知接收方。接收方回以<ACK>进行确认。如果接收方发送<CAN>给发送方也可以强制停止传输,发送方受到<CAN>后不需要发送<EOT>确认,此时传输已经结束。

8、Xmodem协议代码:

#include "BA_UART_CONFIG.h"
#include "BA_XModem.h" #define SOH 0x01
#define STX 0x02
#define EOT 0x04
#define ACK 0x06
#define NAK 0x15
#define CAN 0x18
#define CTRLZ 0x1A
#define DLY_1S 1000
#define MAXRETRANS 25 static int last_error = ; void out_buff(unsigned char *buff, int size)
{
int arg = ;
UART_HANDLER uart = getUartHandler(); writeSysUart(uart, buff, size, &arg);
} struct sysUartWaitArgStruct sysXmodemUartArg =
{
OS_OPT_PEND_BLOCKING,
,
NULL,
};
int in_buff(unsigned char *buff, int time_out)
{
int arg = ;
int qSize = ;
int readSize = ;
UART_HANDLER uart = getUartHandler(); last_error = ; sysXmodemUartArg.timeout = time_out; if(RETURN_RESULT_ERROR_NOERR ==
ctrlSysUart(uart, DEVICE_CONTROL_WAIT_EVENT, (UART_ARG)(&sysXmodemUartArg)))
{
qSize = uart->recvDQ.q.curSize;
if(qSize > )
{
readSize = readSysUart(uart, buff, qSize, &arg);
}
} if(readSize == )
last_error = ; return (readSize);
}
int calcrc(const unsigned char *ptr, int count)
{
int crc;
char i; crc = ;
while (--count >= )
{
crc = crc ^ (int) *ptr++ << ;
i = ;
do
{
if (crc & 0x8000)
crc = crc << ^ 0x1021;
else
crc = crc << ;
} while (--i);
} return (crc);
}
static int check(int crc, const unsigned char *buf, int sz)
{
if(crc)
{
unsigned short crc = calcrc(buf, sz);
unsigned short tcrc = (buf[sz]<<)+buf[sz+]; if (crc == tcrc)
return ;
}
else
{
int i = ;
unsigned char cks = ; for(i = ; i < sz; i ++)
{
cks += buf[i];
} if (cks == buf[sz])
return ;
} return ; }
//recv_buff_size == 384
int xmodemReceive(unsigned char *dest, int destsz)
{
unsigned char xbuff[];
int bufsz = ;
int crc = ;
unsigned char trychar = 'C';
unsigned char packetno = ;
int c = ;
int len = ;
int retry = ;
int retrans = MAXRETRANS;
int recvSize = ; for(;;)
{
for(retry = ; retry < ; retry ++)
{
if(trychar)
{
xbuff[] = trychar;
out_buff(xbuff, );
} recvSize = in_buff(xbuff, (DLY_1S)<<);
c = xbuff[]; if (last_error == )
{
switch(c)
{
case SOH:
bufsz = ;
goto start_recv;
case STX: {
xbuff[] = CAN;
out_buff(xbuff, );
}
return -;
case EOT: {
xbuff[] = ACK;
out_buff(xbuff, );
}
return len;
case CAN: in_buff(xbuff, DLY_1S);
c = xbuff[];
if(c == CAN)
{
{
xbuff[] = ACK;
out_buff(xbuff, );
}
return -;
}
break;
default:
break;
}
}
} if (trychar == 'C')
{
trychar = NAK;
continue;
} {
xbuff[] = CAN;
out_buff(xbuff, );
out_buff(xbuff, );
out_buff(xbuff, );
} return -; start_recv:
if(trychar == 'C')
crc = ; trychar = ; if(recvSize != (bufsz + (crc ? : ) + ))
goto reject; if(xbuff[] == (unsigned char)(~xbuff[]) &&
(xbuff[] == packetno || xbuff[] == (unsigned char)packetno - ) &&
check(crc, &xbuff[], bufsz))
{
if(xbuff[] == packetno)
{
int count = destsz - len; if (count > bufsz)
count = bufsz; if (count > )
{
memcpy(&dest[len], &xbuff[], count);
len += count;
} packetno ++; retrans = MAXRETRANS+;
} if(-- retrans <= )
{
{
xbuff[] = CAN;
out_buff(xbuff, );
out_buff(xbuff, );
out_buff(xbuff, );
}
return -;
} {
xbuff[] = ACK;
out_buff(xbuff, );
} continue;
} reject:
{
xbuff[] = NAK;
out_buff(xbuff, );
} }
} //send_buff_size == 140
int xmodemTransmit(unsigned char *src, int srcsz)
{
unsigned char xbuff[];
int bufsz = ;
int crc = -;
unsigned char packetno = ;
int i = ;
int c = ;
int len = ;
int retry = ; for(;;)
{
for( retry = ; retry < ; ++retry)
{
in_buff(xbuff, (DLY_1S)<<);
c = xbuff[]; if(last_error == )
{
switch(c)
{
case 'C':
crc = ;
goto start_trans;
case NAK:
crc = ;
goto start_trans;
case CAN:
in_buff(xbuff, DLY_1S);
c = xbuff[];
if(c == CAN)
{
{
xbuff[] = ACK;
out_buff(xbuff, );
}
return -;
}
break;
default:
break;
}
}
} {
xbuff[] = CAN;
out_buff(xbuff, );
out_buff(xbuff, );
out_buff(xbuff, );
} return -; for(;;)
{
start_trans:
xbuff[] = SOH;
bufsz = ;
xbuff[] = packetno;
xbuff[] = ~packetno; c = srcsz - len;
if(c > bufsz)
c = bufsz; if(c >= )
{
memset(&xbuff[], , bufsz); if (c == )
{
xbuff[] = CTRLZ;
}
else
{
memcpy(&xbuff[], &src[len], c); if (c < bufsz)
xbuff[ + c] = CTRLZ;
} if(crc)
{
unsigned short ccrc = calcrc(&xbuff[], bufsz); xbuff[bufsz + ] = (ccrc>>) & 0xFF;
xbuff[bufsz + ] = ccrc & 0xFF;
}
else
{
unsigned char ccks = ; for(i = ; i < bufsz + ; i ++)
{
ccks += xbuff[i];
} xbuff[bufsz + ] = ccks;
} for(retry = ; retry < MAXRETRANS; retry ++)
{
out_buff(xbuff, bufsz + + (crc ? : )); in_buff(xbuff, DLY_1S);
c = xbuff[]; if(last_error == )
{
switch(c)
{
case ACK:
packetno ++;
len += bufsz;
goto start_trans;
case CAN:
in_buff(xbuff, DLY_1S);
c = xbuff[];
if(c == CAN)
{
{
xbuff[] = ACK;
out_buff(xbuff, );
} return -;
}
break;
case NAK:
break;
default:
break;
}
}
}
{
xbuff[] = CAN;
out_buff(xbuff, );
out_buff(xbuff, );
out_buff(xbuff, );
} return -;
}
else
{
for(retry = ; retry < ; retry ++)
{
{
xbuff[] = EOT;
out_buff(xbuff, );
} in_buff(xbuff, (DLY_1S)<<);
c = xbuff[]; if(c == ACK)
break;
} return ((c == ACK) ? len : -);
}
}
}
}

最新文章

  1. 关于sql中in 和 exists 的效率问题,in真的效率低吗
  2. java中获取路径的几种基本的方法
  3. oracle for循环查找结果
  4. 如何基于纯GDI实现alpha通道的矢量和文字绘制
  5. IOS开发之—— UITextView禁止Emoji输入
  6. 批量清除.svn 或 _svn
  7. oracle 游标笔记
  8. JS正则表达式简单总结
  9. careercup-C和C++ 13.6
  10. 成为Java GC专家(3)—如何优化Java垃圾回收机制
  11. poj 3177
  12. codeforces Round #259(div2) E解决报告
  13. Android动画(一)-视图动画与帧动画
  14. React Native搭建开发环境 之 --走过的坑
  15. 第十五节、韦伯局部描述符(WLD,附源码)
  16. 将 HPC 作业从本地计算机提交到部署在 Azure 中的 HPC Pack 群集
  17. windows文件共享 防火墙规则设置
  18. linux命令总结top命令
  19. 部署OpenStack问题汇总(七)--解决apache启动错误&quot;httpd:Could not reliably determine...&quot;
  20. 去除两端margin的方法

热门文章

  1. Shell编程之case条件
  2. INSPIRED启示录 读书笔记 - 第22章 原型测试
  3. INSPIRED启示录 读书笔记 - 第2章 产品管理与产品营销
  4. Ubuntu登陆不进去(已解决)【转】
  5. poj2528线段树解题报告,离散化+线段树
  6. 【bzoj3240 &amp;&amp; 洛谷P1397】矩阵游戏[NOI2013](矩阵乘法+卡常)
  7. apache实现http自动转为https
  8. Thinkpad个性化设置:F1~F12恢复正常按键,Fn与Ctrl按键互换
  9. css开发素材网址
  10. Ajax-快速上手前后端交互