zoukankan      html  css  js  c++  java
  • ymodem协议c实现(转)

    源: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 != '')   
                {   
                    *namptr++ = *bufptr++;   
                }   
                *namptr = '';   
                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!=''; 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);   
    }  
  • 相关阅读:
    华章IT图书书讯(2011年第8期)
    iPhone游戏开发实践指南
    【北京讲座】Android系统Framework层源码分析(2011.09.24)
    深入理解Android
    你学或不学,Java就在那里,不离不弃
    近百本精品图书全部免费赠送——仅面向学生
    极限编程(Extreme Programming, XP)
    对任何希望深入理解C#的程序员来说,这本书都是不容错过的经典书籍
    C# 文件操作(转)
    一些数据格式化Eval( " ")和DataBinder.Eval(Container.DataItem, " ")的区别及用法
  • 原文地址:https://www.cnblogs.com/LittleTiger/p/4503486.html
Copyright © 2011-2022 走看看