Xmodem通信协议实例

您所在的位置:网站首页 xmodem被取消 Xmodem通信协议实例

Xmodem通信协议实例

2023-05-07 13:12| 来源: 网络整理| 查看: 265

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

1、什么是Xmodem协议

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

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

4、数据包说明

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

5、如何启动传输

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

6、传输过程

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

7、结束传输

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

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 = 0; void out_buff(unsigned char *buff, int size) { int arg = 0; UART_HANDLER uart = getUartHandler(5); writeSysUart(uart, buff, size, &arg); } struct sysUartWaitArgStruct sysXmodemUartArg = { OS_OPT_PEND_BLOCKING, 1000, NULL, }; int in_buff(unsigned char *buff, int time_out) { int arg = 0; int qSize = 0; int readSize = 0; UART_HANDLER uart = getUartHandler(5); last_error = 0; 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 > 0) { readSize = readSysUart(uart, buff, qSize, &arg); } } if(readSize == 0) last_error = 1; return (readSize); } int calcrc(const unsigned char *ptr, int count) { int crc; char i; crc = 0; while (--count >= 0) { crc = crc ^ (int) *ptr++ bufsz) count = bufsz; if (count > 0) { memcpy(&dest[len], &xbuff[3], count); len += count; } packetno ++; retrans = MAXRETRANS+1; } if(-- retrans 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 >8) & 0xFF; xbuff[bufsz + 4] = ccrc & 0xFF; } else { unsigned char ccks = 0; for(i = 3; i < bufsz + 3; i ++) { ccks += xbuff[i]; } xbuff[bufsz + 3] = ccks; } for(retry = 0; retry < MAXRETRANS; retry ++) { out_buff(xbuff, bufsz + 4 + (crc ? 1 : 0)); in_buff(xbuff, DLY_1S); c = xbuff[0]; if(last_error == 0) { switch(c) { case ACK: packetno ++; len += bufsz; goto start_trans; case CAN: in_buff(xbuff, DLY_1S); c = xbuff[0]; if(c == CAN) { { xbuff[0] = ACK; out_buff(xbuff, 1); } return -1; } break; case NAK: break; default: break; } } } { xbuff[0] = CAN; out_buff(xbuff, 1); out_buff(xbuff, 1); out_buff(xbuff, 1); } return -4; } else { for(retry = 0; retry < 10; retry ++) { { xbuff[0] = EOT; out_buff(xbuff, 1); } in_buff(xbuff, (DLY_1S)


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3