源:YModem协议

YModem协议:

YModem协议是由XModem协议演变而来的,每包数据可以达到1024字节,是一个非常高效的文件传输协议。

下面先看下YModem协议传输的完整的握手过程:先看下图

SENDER:发送方。

RECEIVER:接收方。

第一步先由接收方,发送一个字符'C'

发送方收到'C'后,发送第一帧数据包,内容如下:

SOH 00 FF Foo.c NUL[123] CRC CRC

第1字节SOH:表示本包数据区大小有128字节。如果头为STX表示本包数据区大小为1024

第2字节00: 编号,第一包为00,第二包为01,第三包为02依次累加。到FF后继续从0循环递增。

第3字节FF: 编号的反码。 编号为00 对应FF,为01对应FE,以此类推。

第4字节到最后两字节:若第1字节为SOH时有128字节,为STX时有1024字节,这部分为数据区。“Foo.c” 文件名, 超级终端下,在文件名后还有文件大小。官方dome也是因为使用了这个文件大小进行比对。这就是为什么用SecureCRT中的YMODEM协议而无法正确传输的原因。在文件名和文件大小之后,如果不满128字节,以0补满。

最后两字节:这里需要注意,只有数据部分参与了效CRC验,不包括头和编码部分。

16位CRC效验,高字节在前,低字节在后。

接收方收到第一帧数据包后,发送ACK正确应答。

然后再发送一个字符'C'。

发送方收到'C'后,开始发送第二帧,第二帧中的数据存放的是第一包数据。

接收方收到数据后,发送一个ACK然后等待下一包数据传送完毕,继续ACK应答。直到所有数据传输完毕。

数据传输完毕后,发送方发EOT,第一次接收方以NAK应答,进行二次确认。

发送方收到NAK后,重发EOT,接收方第二次收到结束符,就以ACK应答。

最后接收方再发送一个'C',发送方在没有第二个文件要传输的情况下,

发送如下数据

SOH 00 FF 00~00(共128个) CRCH CRCL

接收方应答ACK后,正式结束数据传输。

以上部分,为YMODEM协议的基本操作流程。

源:ymodem协议c实现

/****************************************Copyright (c)**************************************************
** Henan Star Hi-Tech CO.,LTD
** All rights reserved.
**
**----------------------------------------File Info-----------------------------------------------------
** 文件名称:
** 工程项目:
** 说 明:
**
** 作 者: 日 期:
** 建立版本:
**
**----------------------------------------modification--------------------------------------------------
** 作 者:
** 日 期:
** 版 本: 标 记:
** 说 明:
**
********************************************************************************************************/ #ifndef __XYMODEM_H_
#define __XYMODEM_H_ #define MODEM_MAX_RETRIES 50 //接收等待延时时间
#define MODEM_CRC_RETRIES 51 //>MODEM_MAX_RETRIES固定为CRC校验
#define MODEM_CAN_COUNT 3 //Wait for 3 times CAN before quiting
#define MODEM_EOT_COUNT 1 #define MODEM_SOH 0x01 //数据块起始字符
#define MODEM_STX 0x02
#define MODEM_EOT 0x04
#define MODEM_ACK 0x06
#define MODEM_NAK 0x15
#define MODEM_CAN 0x18
#define MODEM_C 0x43 typedef struct{
int modemtype;
int crc_mode;
int nxt_num; //下一数据块序号
int cur_num; //当块序号
int len;
int rec_err; //数据块接收状态
unsigned char buf[]; //数据
unsigned int filelen; //Ymodem可有带文件名称和长度
unsigned char filename[];
}modem_struct; #ifdef __cplusplus
extern "C"{
#endif int ymodem_init(modem_struct *mblock);
int modem_recvdata(modem_struct *mblock);
//int crc_16(unsigned char *buf, int len);
void modem_cancle(void);
#ifdef __cplusplus
}
#endif #endif
/****************************************Copyright (c)**************************************************
** Henan Star Hi-Tech CO.,LTD
** All rights reserved.
**
**----------------------------------------File Info-----------------------------------------------------
** 文件名称:
** 工程项目:
** 说 明:
**
** 作 者: 日 期:
** 建立版本:
**
**----------------------------------------modification--------------------------------------------------
** 作 者:
** 日 期:
** 版 本: 标 记:
** 说 明:
**
********************************************************************************************************/ #include "xymodem1.h"
#include "heads.h" unsigned int buf_filelen(unsigned char *ptr); /*****************************************************************************************
** 函数名称:
** 函数功能:
** 入口参数:
** 返 回 值:
** 编 写: 日 期: 版 本 号:
** 修改历史:
******************************************************************************************/
int ymodem_init(modem_struct *mblock)
{
int stat;
int max_tries = MODEM_MAX_RETRIES;
int crc_tries =MODEM_CRC_RETRIES;
unsigned char *bufptr = mblock->buf;
unsigned char *namptr = mblock->filename; mblock->nxt_num = ;
mblock->modemtype = ;
mblock->rec_err = ;
mblock->crc_mode = ; while (max_tries-- > )
{
stat = modem_recvdata(mblock);
if ( == stat) //接收成功
{
//file name
while (*bufptr != '\0')
{
*namptr++ = *bufptr++;
}
*namptr = '\0';
bufptr++;
while (*bufptr == ' ')
{
bufptr++;
}
//file length
mblock->filelen = buf_filelen(bufptr);
//other data;
Uart_SendByte(MODEM_ACK);
return ;
}
else if ( == stat) //取消传输
{
return ;
}
else if (- == stat)
{
if (mblock->cur_num == )
{
mblock->modemtype = ;
mblock->nxt_num = ;
return ;
}
}
else //超时或校验方式不对
{
if (crc_tries-- <= )
{
crc_tries = MODEM_CRC_RETRIES;
mblock->crc_mode = (mblock->crc_mode+) & ;
}
}
}
return -;
} /*****************************************************************************************
** 函数名称:
** 函数功能:
** 入口参数:
** 返 回 值:0:成功接收数据 -1:接收超时 -2:帧错误
-3:帧序号序号错误(严重错误) 1:消息结束 2:取消发送
** 编 写: 日 期: 版 本 号:
** 修改历史:
******************************************************************************************/
int modem_recvdata(modem_struct *mblock)
{
int stat, hd_found=, i;
int can_counter=, eot_counter=;
unsigned char *in_ptr = mblock->buf;
int cksum;
unsigned char ch, blk, cblk, crch, crcl; Uart_RxEmpty(); //接收缓冲区清空 if (mblock->nxt_num == )
{
if (mblock->crc_mode)
{
Uart_SendByte(MODEM_C);
}
else
{
Uart_SendByte(MODEM_NAK);
}
}
else
{
if (mblock->rec_err)
{
Uart_SendByte(MODEM_NAK);
}
else
{
if (mblock->nxt_num == )
{
if (mblock->crc_mode)
{
Uart_SendByte(MODEM_C);
}
else
{
Uart_SendByte(MODEM_NAK);
}
}
else
{
Uart_SendByte(MODEM_ACK);
}
}
}
while (!hd_found) //头字节
{
stat = Uart_RecvByteTimeout(&ch);
if (stat == )
{
switch (ch)
{
case MODEM_SOH :
hd_found = ;
mblock->len = ;
break;
case MODEM_STX :
hd_found = ;
mblock->len = ;
break;
case MODEM_CAN :
if ((++can_counter) >= MODEM_CAN_COUNT)
{
return ;
}
break;
case MODEM_EOT : //文件传输结束
if ((++eot_counter) >= MODEM_EOT_COUNT)
{
Uart_SendByte(MODEM_ACK);
if (mblock->modemtype == ) //Ymodem协议为批文件传输协议
{
Uart_SendByte(MODEM_C); //单个文件需 C ACK C后会自动停止传输
Uart_SendByte(MODEM_ACK);
Uart_SendByte(MODEM_C);
modem_cancle(); //多个文件强制停止传输
}
return ;
}
break;
default:
break;
}
}
else
{
return -;
}
} stat = Uart_RecvByteTimeout(&blk); //数据块错误或超时
if (stat != )
{
return -;
} stat = Uart_RecvByteTimeout(&cblk); //数块补码
if (stat != )
{
return -;
} for (i=; i < mblock->len ; i++)
{
stat = Uart_RecvByteTimeout(in_ptr++);
if (stat != )
{
return -;
}
} stat = Uart_RecvByteTimeout(&crch); //CRC
if (stat != )
{
return -;
} if (mblock->crc_mode)
{
stat = Uart_RecvByteTimeout(&crcl);
if (stat != )
{
return -;
}
} if (blk^cblk != 0xff)
{
return (-);
} if (mblock->crc_mode)
{
in_ptr = mblock->buf;
cksum = ; for (stat=mblock->len ; stat>; stat--)
{
cksum = cksum^(int)(*in_ptr++) << ;
for (i=; i!=; i--)
{
if (cksum & 0x8000)
cksum = cksum << ^ 0x1021;
else
cksum = cksum << ;
}
}
cksum &= 0xffff; if (cksum != (crch<< | crcl))
{
mblock->rec_err = ;
return (-);
}
}
else
{
for (i=; i<mblock->len; i++) //和校验方式
{
cksum += mblock->buf[i];
}
if ((cksum&0xff)!=crch)
{
mblock->rec_err = ;
return (-);
}
} mblock->cur_num = blk;
if (blk != mblock->nxt_num) //blk检查
{
return (-);
} mblock->nxt_num++;
mblock->rec_err = ;
return ;
} unsigned int buf_filelen(unsigned char *ptr)
{
int datatype=, result=; if (ptr[]=='' && (ptr[]=='x' && ptr[]=='X'))
{
datatype = ;
ptr += ;
} for ( ; *ptr!='\0'; ptr++)
{
if (*ptr>= '' && *ptr<='')
{
result =result*datatype+*ptr-'';
}
else
{
if (datatype == )
{
return result;
}
else
{
if (*ptr>='A' && *ptr<='F')
{
result = result* + *ptr-; //55 = 'A'-10
}
else if (*ptr>='a' && *ptr<='f')
{
result = result* + *ptr-; //87 = 'a'-10
}
else
{
return result;
}
}
}
}
return result;
} void modem_cancle(void)
{
Uart_SendByte(0x18);
Uart_SendByte(0x18);
Uart_SendByte(0x18);
Uart_SendByte(0x18);
Uart_SendByte(0x18);
}

YModem协议的更多相关文章

  1. stm32 Bootloader设计(YModem协议) (转)

    源:stm32 Bootloader设计(YModem协议) 相信很多人都希望,不开盖就可以对固件进行升级吧,就像手机那些.下文中的bootload就来实现这样的功能. 前段时间有项目关于Bootlo ...

  2. ymodem协议c实现(转)

    源:ymodem协议c实现 /****************************************Copyright (c)******************************** ...

  3. Ymodem协议说明

      模块的固件烧录过程,由Term(发送方)发送固件文件,模块(接收方)接收并写入MCU,期间使用的数据传输协议是ymodem协议. 一.概述 ymodem协议是一种发送并等待的协议,即发送方发送一个 ...

  4. Ymodem协议(参考STM32)

    相信很多人都希望,不开盖就可以对固件进行升级吧,就像手机那些.下文中的bootload就来实现这样的功能. 前段时间有项目关于Bootload设计.所以就仔细的去了研究了一翻.以前都是用的stm32官 ...

  5. ZYNQ使用ymodem协议传输文件

    SDK: V2014.4 协议: Ymodem 工具: USB转UART转接线.xshell6软件 可实现各种文件传输,大小不限,只是速度很慢 参考原代码如下: /****************** ...

  6. python调用Moxa PCOMM Lite通过串口Ymodem协议发送文件

    本文采用python 2.7编写. 经过长期搜寻,终于找到了Moxa PCOMM Lite.调用PCOMM.DLL可以非常方便的通过串口的Xmodem.Ymodem.Zmodem等协议传输文件,而无需 ...

  7. Kermit,Xmodem,1K-Xmodem,Ymodem,Zmodem传输协议小结

    来自:http://blog.163.com/czblaze_3333/blog/static/208996228201272295236713/ Kermit协议 报文格式: 1.       MA ...

  8. STM32 Bootloader基于ymodem传输协议串口IAP升级详解

    硬件:stm32f103cbt6 软件:STM32F10x_StdPeriph_Lib_V3.5.0 文章目录 1 预备知识 2 Bootloader 2.1 启动流程 2.2 校验跳转地址是否有效 ...

  9. STM32F103/429串口IAP+Ymodem升级

    起因: 串口IAP升级在正点原子的例程中有讲解,正点原子的方法是:在RAM中开辟一个120K的数据空间,用来存放bin文件,bin文件通过串口一次性发送到单片机,然后再实现程序的跳转.但是这种方法在实 ...

随机推荐

  1. android代码格式化方法小结

    转载:http://blog.csdn.net/androidzhaoxiaogang/article/details/7692526 Download the android-formatting. ...

  2. iostextField文本框基本使用

    (1)可以根据需要设置文本框的样式(包括形状.边框颜色.背景等). (2)可以根据需要设置文字显示样式(包括输入密码时的密文显示.文字横向居中.纵向居中上下.输入的文字是否首席木大写.文字超过后是否缩 ...

  3. SCANF SCANF_S

    今天在看C的教程的时候,用VS2013写了一小段代码 scanf("%f",&w); 提示需要在预编译器里添加 _CRT_SECURE_NO_WARNINGS,  百度了下 ...

  4. Struts2(result 流 )下载

    jsp: <body> <a href="stream.action?fileName=psb.jpg">psb</a> <br> ...

  5. HDU2504:又见GCD

    Problem Description 有三个正整数a,b,c(0<a,b,c<10^6),其中c不等于b.若a和c的最大公约数为b,现已知a和b,求满足条件的最小的c.   Input ...

  6. React和动态网站接口的经济学

    来自: React and the economics of dynamic web interfaces 自从2000开始我就一直在做web开发,曾见过很多以各种库和框架的起起落落,这些库和框架作为 ...

  7. win8上cmder文字重叠问题

    1.用过ubuntu上的bash,zsh后发现win自带的cmd弱爆了,在网上搜索后找到了代替品cmder,下载安装后好发现中文错位的问题, 状况如下: 修复方法:把设置里面的Monospace选项勾 ...

  8. C++中的基本数据类型

    C++中定义了一组表示整数.浮点数.单个字符和布尔值的算术类型(arithmetic type). 另外还定义了一种叫做void的特殊类型.void类型没有对应的值,仅用在有限的一些情况下,通常用作无 ...

  9. java synchronized 线程同步机制详解

    Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 一.当两个并发线程访问同一个对象object中的这个synchronized(this ...

  10. webservice(soap)接口的加密,SHA-1实现

    import java.io.UnsupportedEncodingException;import java.security.MessageDigest;import java.security. ...