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 != '\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);   
}  

 

posted @ 2015-05-14 15:33  酒醉的Tiger  阅读(2161)  评论(0编辑  收藏  举报