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[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 (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 = 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);   
}  

  • 3
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Ymodem是一种用于在计算机之间进行文件传输的协议。它是在Xmodem协议的基础上进行改进和扩展的,具有更高的传输效率和更好的可靠性。下面将介绍如何使用C语言实现Ymodem协议。 首先,Ymodem协议需要在底层通过串口进行数据传输。我们可以使用C语言的串口编程库来实现串口通信功能。通过打开串口并设置相应的参数,我们可以实现与另一台计算机之间的数据传输。 接下来,我们需要实现Ymodem协议的数据帧格式。Ymodem协议中,每个数据帧由一个帧头、数据部分、校验码和帧尾组成。帧头包含了帧的起始标识和文件信息,数据部分存储着待传输的文件数据,校验码用于检验数据的完整性,帧尾标识帧的结束。我们可以使用C语言的结构体来定义Ymodem数据帧的格式,并使用适当的函数来填充、发送和接收数据帧。 在发送方的实现中,我们需要读取待传输的文件,将其分割成数据块,并封装成Ymodem数据帧。发送方需要通过串口将数据帧发送给接收方,并等待接收方的确认。如果接收方正确接收到数据帧,它将发送一个确认帧给发送方;如果接收方接收出现错误,它将发送一个重传请求给发送方。根据接收方的回应,发送方可以继续发送下一个数据帧,或者重新发送当前的数据帧。 在接收方的实现中,我们需要等待并接收发送方发送的数据帧,并根据数据帧的内容进行相应的处理。接收方需要检查数据帧的完整性和校验码,并将接收到的数据块写入到接收缓冲区。接收方还需要根据接收到的数据帧发送一个确认帧给发送方,以告知发送方数据帧的接收情况。 总结:使用C语言实现Ymodem协议需要涉及串口编程和Ymodem协议的数据帧格式定义。在发送方和接收方的实现中,需要处理数据帧的发送、接收、校验和确认等操作。通过适当的逻辑和算法,我们可以实现一个基于Ymodem协议的可靠文件传输系统。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值