• Qt_Ymodem自己实现


    文章内容
    1. 简单介绍Ymodem协议
    2. 给出封装好的Ymodem的代码和调用

    概念

    协议发展
    • Xmodem、Ymodem和Zmodem协议是最常用的三种通信协议。
    • Xmodem协议是最早的,传输128字节信息块。
    • Ymodem是Xmodem的改进版协议,具有传输快速稳定的优点。它可以一次传输1024字节的信息块,同时还支持传输多个文件。
      平常所说的Ymodem协议是指的Ymodem-1K,除此还有Ymodem-g(没有CRC校验,不常用)。
    • YModem-1K用1024字节信息块传输取代标准的128字节传输,数据的发送回使用CRC校验,保证数据传输的正确性。它每传输一个信息块数据时,就会等待接收端回应ACK信号,接收到回应后,才会继续传输下一个信息块,保证数据已经全部接收。
    协议

    Ymodem协议分为起始帧,数据帧和结束帧。

    起始帧:
    • 作用:传输文件名与文件的大小。
    • 数据格式:3字节数据首部+128字节数据+2字节CRC16校验码=133字节。(SOH 00 FF filename filezise NUL CRCH CRCL)
      • SOH=0x01,表示这个数据帧中包含着128个字节的数据(STX表示1024字节,初始帧只有128个)
      • 00表示数据帧序号,初始是0,依次向下排,FF是帧序号的取反
      • filename是要传输的文件名,如USTB_V3_1.0.1.26_NMEA.Bin,它在数据帧中的格式为:55 53 54 42 5F 56 33 5F 31 2E 30 2E 31 2E 32 36 5F 4E 4D 45 41 2E 42 69 6E 00,也就是把ASCII码转成十六进制,但是最后一定要在文件名后加上00,表示文件名的结束;
      • filesize表示文件的大小,如上面的USTB_V3_1.0.1.26_NMEA.Bin大小是132KB,也就是135168Byte,转换成十六进制就是0x21000,它在数据帧中的格式就是32 31 30 30 30 00,也就是ASCII的“21000”,同样最后要加上00表示结束
      • NULL就是数据部分的128字节中除去文件名和文件大小占据的剩下的字节都用00填充,CRCH和CRCL分别表示16位CRC校验码的高8位与低8位。
    数据帧:

    2.数据帧的数据格式(STX 01 FEdata[1024] CRCH CRCL)

    • STX=0x02,表示这帧数据帧后面包含着1024字节的数据部分;
    • 01是表示帧序号,FE是它的取反,再下一帧数据就是02 FD,
    • data[1024]表示存放着1024字节的文件数据;CRCH与CRCL是CRC16检验码的高8位与低8位。
    • 如果文件数据的最后剩余的数据在128~1024之前,则还是使用STX的1024字节传输,但是剩余空间全部用0x1A填充(STX 01 FE data[1024] 1A 1A……… CRCH CRCL)
      有一种特殊的情况:如果文件大小小于等于128字节或者文件数据最后剩余的数据小于128字节,则YModem会选择SOH数据帧用128字节来传输数据,如果数据不满128字节,剩余的数据用0x1A填充这是数据帧的结构就变成了:
      文件大小小于128字节: SOH 01 FE data[ ] 1A …1A CRCH CRCL
      文件最后剩余数据小于128字节: SOH 01 FE data[ ] 1A…1A CRCH CRCL
    结束帧:

    数据结构(SOH 00 FF NUL[128] CRCH CRCL)
    结束帧同样以SOH开头,表示后面跟着128字节大小的数据;结束帧的帧序也认为是00 FF;结束帧的128字节的数据部分不存放任何信息,即全部用00填充。

    代码:
    调用:

    // 打开文件
    void ShowData::readBOOTFile()
    {
       
        QByteArray m_data_buf;
        m_num = 0;
        QString filename = QFileDialog::getOpenFileName(this, "打开", "C:\\Users\\fh\\Desktop\\file/", "*.*");
        // 文件信息
        QFileInfo fileInfo = QFileInfo(filename);
    
        QFile r_file(filename);
        if(r_file.open(QIODevice::ReadOnly))
        {
       
            m_data_buf = r_file.readAll();
            m_file_size = fileInfo.size();
            m_modem.setInfoData(fileInfo.fileName().toUtf8(), fileInfo.size(), m_data_buf.data());
        }
    }
    // 开始传输
    void ShowData::begin()
    {
       
        m_num = 0;
        onSendYmodeData();
    }
    
    void ShowData::onSendYmodeData()
    {
       
        if(m_num == 0)
        {
       
            char buf[133] = {
       0};
            m_modem.getBeginData(buf);
    
            // 第一包
            QByteArray array;
            array = QByteArray(buf, begin_end_buf_size);
            qDebug("first data");
            serialThread->SedToSerial(array.toHex(), true);
        }
        else
        {
       
            uint32_t send_size = (m_num - 1) * 1024;
            emit sigUpdata(send_size, m_file_size);
            if(m_file_size < send_size)
            {
       
                char end_buf[133] = {
       0};
                m_modem.getEndData
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
  • 相关阅读:
    2022!影响百万用户金融信用评分,Equifax被告上法庭,罪魁祸首——『数据漂移』!
    【数据结构】归并排序和计数排序(排序的总结)
    电工特种作业操作证登高作业等报名考试费用是怎么样的
    小程序关键词排名:优化你的应用在搜索中的地位
    搜索技术【深度优先搜索】 - 排列树
    《Python机器学习与可视化分析实战》简介
    【C#实战】控制台游戏 勇士斗恶龙(3)——营救公主以及结束界面
    new;getline();重载<<和>>
    Python爬虫实战第一例【一】
    Java岗八年多开发经验分享
  • 原文地址:https://blog.csdn.net/weixin_44248637/article/details/139056723