ymodem协议c实现

/Copyright ©**********
** 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[1024]; //数据
unsigned int filelen; //Ymodem可有带文件名称和长度
unsigned char filename[32];
}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 ©**********
** 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 = 0;   
mblock->modemtype = 2;   
mblock->rec_err = 0;   
mblock->crc_mode = 1;   
   
while (max_tries-- > 0)   
{      
    stat = modem_recvdata(mblock);   
    if (0 == 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  0;   
    }   
    else if (2 == stat)         //取消传输   
    {   
        return 2;   
    }   
    else if (-3 == stat)   
    {   
        if (mblock->cur_num == 1)   
        {   
            mblock->modemtype = 1;   
            mblock->nxt_num = 2;   
            return 1;   
        }   
    }   
    else                   //超时或校验方式不对   
    {   
        if (crc_tries-- <= 0)   
        {   
            crc_tries = MODEM_CRC_RETRIES;   
            mblock->crc_mode = (mblock->crc_mode+1) & 1;   
        }   
    }   
}   
return -1;   

}

/*****************************************************************************************
** 函数名称:
** 函数功能:
** 入口参数:
** 返 回 值:0:成功接收数据 -1:接收超时 -2:帧错误
-3:帧序号序号错误(严重错误) 1:消息结束 2:取消发送
** 编 写: 日 期: 版 本 号:
** 修改历史:
******************************************************************************************/
int modem_recvdata(modem_struct *mblock)
{
int stat, hd_found=0, i;
int can_counter=0, eot_counter=0;
unsigned char *in_ptr = mblock->buf;
int cksum;
unsigned char ch, blk, cblk, crch, crcl;

Uart_RxEmpty();                         //接收缓冲区清空   
   
if (mblock->nxt_num == 0)   
{   
    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 == 1)   
        {   
            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 == 0)   
    {   
        switch (ch)   
        {   
            case MODEM_SOH :   
                hd_found = 1;   
                mblock->len = 128;   
                break;   
            case MODEM_STX :   
                hd_found = 1;   
                mblock->len = 1024;   
                break;   
            case MODEM_CAN :   
                if ((++can_counter) >= MODEM_CAN_COUNT)   
                {   
                    return 2;   
                }   
                break;   
            case MODEM_EOT :                                //文件传输结束   
                if ((++eot_counter) >= MODEM_EOT_COUNT)   
                {   
                    Uart_SendByte(MODEM_ACK);   
                    if (mblock->modemtype == 2)         //Ymodem协议为批文件传输协议   
                    {   
                        Uart_SendByte(MODEM_C);          //单个文件需 C ACK C后会自动停止传输   
                        Uart_SendByte(MODEM_ACK);   
                        Uart_SendByte(MODEM_C);   
                        modem_cancle();               //多个文件强制停止传输   
                    }   
                    return 1;   
                }   
                break;   
            default:   
                break;   
        }   
    }   
    else   
    {   
        return -1;   
    }   
}   
   
stat = Uart_RecvByteTimeout(&blk);           //数据块错误或超时   
if (stat != 0)   
{   
    return -1;   
}   

stat = Uart_RecvByteTimeout(&cblk);           //数块补码   
if (stat != 0)   
{   
   return -1;   
}   

for (i=0; i < mblock->len ; i++)   
{   
    stat = Uart_RecvByteTimeout(in_ptr++);   
    if (stat != 0)   
    {   
        return -1;   
    }   
}   
   
stat = Uart_RecvByteTimeout(&crch);         //CRC   
if (stat != 0)   
{   
    return -1;   
}   
   
if (mblock->crc_mode)   
{   
    stat = Uart_RecvByteTimeout(&crcl);                
    if (stat != 0)   
    {   
        return -1;   
    }   
}   

if (blk^cblk != 0xff)                          
{   
    return (-2);   
}   

if (mblock->crc_mode)   
{   
    in_ptr = mblock->buf;   
    cksum = 0;   
       
    for (stat=mblock->len ; stat>0; stat--)   
    {   
        cksum = cksum^(int)(*in_ptr++) << 8;   
        for (i=8; i!=0; i--)   
        {   
            if (cksum & 0x8000)   
                cksum = cksum << 1 ^ 0x1021;   
            else   
                cksum = cksum << 1;   
        }   
    }   
    cksum &= 0xffff;   
       
    if (cksum != (crch<<8 | crcl))   
    {   
        mblock->rec_err = 1;   
        return (-2);   
    }   
}   
else   
{   
    for (i=0; i<mblock->len; i++)                //和校验方式   
    {   
        cksum += mblock->buf[i];   
    }   
    if ((cksum&0xff)!=crch)   
    {   
        mblock->rec_err = 1;   
        return (-2);   
    }   
}   
   
mblock->cur_num = blk;   
if (blk != mblock->nxt_num)                      //blk检查   
{    
    return (-3);   
}   

mblock->nxt_num++;   
mblock->rec_err = 0;   
return 0;   

}

unsigned int buf_filelen(unsigned char *ptr)
{
int datatype=10, result=0;

if (ptr[0]=='0' && (ptr[1]=='x' && ptr[1]=='X'))   
{   
    datatype = 16;   
    ptr += 2;   
}   

for ( ; *ptr!='\0'; ptr++)   
{   
    if (*ptr>= '0' && *ptr<='9')   
    {   
        result =result*datatype+*ptr-'0';   
    }   
    else   
    {   
        if (datatype == 10)   
        {   
            return result;   
        }   
        else   
        {   
            if (*ptr>='A' && *ptr<='F')   
            {   
                result = result*16 + *ptr-55;             //55 = 'A'-10   
            }   
            else if (*ptr>='a' && *ptr<='f')   
            {   
                result = result*16 + *ptr-87;             //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);
}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值