⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xymodem1.c

📁 一位朋友用C编的串口通讯中的ymodem的文件传输源码。
💻 C
字号:
/****************************************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);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -