Qt实现XYModem协议(五)

1 概述

  XMODEM协议是一种使用拨号调制解调器的个人计算机通信中广泛使用的异步文件运输协议。这种协议以128字节块的形式传输数据,并且每个块都使用一个校验和过程来进行错误检测。使用循环冗余校验的与XMODEM相应的一种协议称为XMODEM-CRC。还有一种是XMODEM-1K,它以1024字节一块来传输数据。YMODEM也是一种XMODEM的实现。它包括XMODEM-1K的所有特征,另外在一次单一会话期间为发送一组文件,增加了批处理文件传输模式。

本文利用C++实现XYModem-1K协议,并利用Qt串口类QSerialPort实现数据读写。

3 实现

3.4 XYModemSendFile

该模块实现XYModem协议发送文件。

流程图:
流程图

3.4.1 XYModemSendFile定义

class QSerialPort;
class XYModemSendFile : public QObject, public YModem
{
    Q_OBJECT
public:
    explicit XYModemSendFile(QSerialPort *serial, QObject *parent = nullptr);

public slots:
    void startYModem(QString const& fileName);
    void startXModem(QString const& fileName);
    void stop() { { doSignal(); }}
    void cancel() { tx_cancle(); }
signals:
    void gotFileSize(quint64 filesize);
    void progressInfo(quint32 blockNumber, quint64 bytesOfSend);
    void error(QString const& e);
    void finished();

protected:
    uint32_t write(uint8_t const *data, uint32_t size) override;
    uint32_t read(uint8_t *data, uint32_t size) override;
    uint8_t get_code(bool isWait = true) override;
private:
    bool singled() { return signal_; }
    void doSignal() { signal_ = true; };
    void doError(QString const& text);
private:
     QSerialPort* serial_;
     volatile bool signal_;
};

公共接口:

  • startYModem 开始YModem协议发送文件
  • startXModem 开始XModem协议发送文件
  • stop 停止发送
  • cancel 取消发送

信号:

  • gotFileSize 文件大小信号
  • progressInfo 传输进度信号
  • error 出错信号
  • finished 传输结束信号

重载接口:

  • write 向串口写数据
  • read 从串口读取数据
  • get_code 读取操作码

3.4.2 XYModemSendFile实现

3.4.2.1 startYModem
void XYModemSendFile::startYModem(QString const& fileName)
{
    QFileInfo fileInfo(fileName);
    uint64_t fileSize = fileInfo.size();
    std::string filename = fileInfo.fileName().toStdString();
    std::string filesize = QString::number(fileSize).toStdString();
    if(filename.size() + filesize.size() + 2 > SIZE1)
    {
        doError("Filename too long!");
        return;
    }
    //Get Start flag
    if(get_code() != C)
    {
        doError("Can not get  C!");
        return;
    }
    //SOH first block

    emit gotFileSize(fileSize);
    if(!tx_start(filename, filesize))
    {
        doError("Can not get  ACK and C!");
        return;
    }
    //Send data of file
    QFile file(fileName);
    if(!file.open(QIODevice::ReadOnly))
    {
        doError(QString("%1 cannot be opened!").arg(fileName));
        return;
    }

    uint8_t data[SIZE2];
    quint64 bytesOfSend = 0;
    quint32 block = 0;
    bool is_end = false;

    while(!singled())
    {
        quint64 size = file.read((char *)data, sizeof(data));
        if(size == 0)
        {
            is_end = true;
            break;
        }
        if(tx_send(data, size))
        {
            block++;
            bytesOfSend += size;
            emit progressInfo(block, bytesOfSend);
        }
        else
        {
            emit error("send is error");
            break;
        }
    }

    //Send end
    if(is_end)
    {
        if(tx_eot())
        {
            if(tx_end())
            {
                //std::cout << "end is ok" << std::endl;
            }
        }
    }
    emit finished();
    serial_->moveToThread(QApplication::instance()->thread());
}

函数流程:

  • 获取文件名和文件大小字符串
  • 如果文件名和文件大小字符串大小大于Size1(128)则返回文件名称太长错误返回
  • 获取操作码
  • 获得非C操作码,失败返回
  • 发送文件大小信号gotFileSize
  • 发送开始包(包括文件名称和文件大小。YModem协议发送该包,XModem协议不发送该包)
  • 打开文件,如果失败则返回
  • 读取文件内容
  • 发送文件内容
  • 发送成功发送,发送进度信号progressInfo
  • 发送失败,则发送错误信号并返回
  • 重复上述4步,直到文件发送完毕或停止
  • 如果文件发送完毕包(tx_eot),发送文件结束标志
  • 发送通信结束包(tx_end),结束通信。(这里只发送一个文件所以发送tx_end, 如果是多个文件需要发送tx_start开始新文件发送)
  • 发送传输结束信号finished
3.4.2.2 startXModem
void XYModemSendFile::startXModem(QString const& fileName)
{
    QFileInfo fileInfo(fileName);
    uint64_t fileSize = fileInfo.size();
    //Get Start flag
    if(get_code() != C)
    {
        doError("Can not get  C!");
        return;
    }
    //SOH first block
    emit gotFileSize(fileSize);
    //Send data of file
    QFile file(fileName);
    if(!file.open(QIODevice::ReadOnly))
    {
        doError(QString("%1 cannot be opened!").arg(fileName));
        return;
    }

    uint8_t data[SIZE2];
    quint64 bytesOfSend = 0;
    quint32 block = 0;
    bool is_end = false;
    next_id();
    while(!singled())
    {
        quint64 size = file.read((char *)data, sizeof(data));
        if(size == 0)
        {
            is_end = true;
            break;
        }
        if(tx_send(data, size))
        {
            block++;
            bytesOfSend += size;
            emit progressInfo(block, bytesOfSend);
        }
        else
        {
            emit error("send is error");
            break;
        }
    }

    //Send end
    if(is_end)
    {
        if(tx_eot())
        {
            //std::cout << "end is ok" << std::endl;
        }
    }
    emit finished();
    serial_->moveToThread(QApplication::instance()->thread());
}

函数流程:

  • 获取文件大小
  • 获取操作码
  • 如果不是C码,失败返回
  • 发送文件大小信号gotFileSize
  • 打开文件,如果失败则返回
  • 发送文件内容
  • 发送成功发送,发送进度信号progressInfo
  • 发送失败,则发送错误信号并返回
  • 重复上述4步,直到文件发送完毕或停止
  • 如果文件发送完毕包(tx_eot),发送文件结束标志
  • 发送传输结束信号finished
3.4.2.3 write/read
uint32_t XYModemSendFile::write(uint8_t const *data, uint32_t size)
{
    return serial_->write((const char *)data, size);
}
uint32_t XYModemSendFile::read(uint8_t *data, uint32_t size)
{
    return serial_->read((char *)data, size);
}

函数说明:

  • 直接调用串口读写接口实现读写接口。
3.4.2.4 get_code
uint8_t XYModemSendFile::get_code(bool isWait)
{
    while(!singled())
    {
        if(serial_->waitForReadyRead(10))
        {
            uint8_t data[1] = { 0 };
            read(data, sizeof(data));
            return data[0];
        }
        if(!isWait)
            break;
    }
    return MAX;
}

函数流程:

  • 等待串口输入
  • 如果有输入则读取一字节做为code码并返回.
  • 如果一直没有输入直到调用stop后返回无效码MAX.
3.4.2.5 doError
void XYModemSendFile::doError(QString const& text)
{
    emit error(text);
    serial_->moveToThread(QApplication::instance()->thread());
    emit finished();
}

函数流程:

  • 发送错误信号
  • 发送结束信号

Qt实现XYModem协议(四) Qt实现XYModem协议(六)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/567858.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

4月23号总结

java实现发送邮件 在做聊天室项目的时候&#xff0c;由于需要发送邮箱验证码&#xff0c;所以自己查找了这方面的内容。 首先需要在Maven里面依赖 <dependency><groupId>com.sun.mail</groupId><artifactId>javax.mail</artifactId><versio…

英伟达AI系列免费公开课

英伟达公开课官网地址 Augment your LLM Using Retrieval Augmented Generation Building RAG Agents with LLMs langchain的workflow: ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/c90cb157c9c84bb5b3da380ec56f5c2a.png Generative AI Explained

Linux系统中安装MySQL

1、在电脑中安装虚拟机 2、df -h查看光盘是否挂载&#xff0c;没挂载用mount -o ro /dev/sr0 /media命令挂载 3、进入etc/yum.repos.d目录查看仓是否配置&#xff0c;若配置进行下一一步&#xff0c;未配置则进行配置 配置软件仓库 [rootlocalhost yum.repos.d]# vim rhle.r…

Linux中文件描述符与重定向的深入探索

目录 1. 理解C语言的文件操作函数 2. 操作系统的文件操作接口 3. 文件描述符详解和其内核本质 4. 如何理解Linux下一切皆文件 5. Linux中的重定向 5.1 输出重定向 5.2 追加重定向 5.3 输入重定向 6. 结合文件描述符理解重定向 7.重定向的系统调用 在Linux操作系统中&a…

springboot整合mybatis-plus模版

1.创建springboot项目 Maven类型Lombok依赖Spring Web 依赖MySQL Driver依赖pom.xml&#xff1a;<?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/…

上门废品回收小程序,互联网回收拥有哪些特点?

随着社会的进步&#xff0c;人们的生活水平不断提高&#xff0c;产生的可回收物也在不断上升&#xff0c;每年垃圾站都能产生大量的可回收物&#xff0c;这也造成了资源的浪费。 目前&#xff0c;加快发展回收模式&#xff0c;提高我国回收效率成为了当下回收市场发展的重要方…

[笔试强训day04]

文章目录 WY22 Fibonacci数列NC242 单词搜索BC140 杨辉三角 WY22 Fibonacci数列 WY22 Fibonacci数列 #include<iostream> #include<cmath>using namespace std;int n;int main() {cin>>n;int a0,b1,c1;while(n>c){ab;bc;cab;}int ansmin(n-b,c-n);cout&l…

windows mysql8 安装后 提示密码不对,修改下密码认证方式就可以了

Windows上安装MySQL8后提示密码不对的问题可以通过以下步骤解决&#xff1a; 安装MySQL8 首先&#xff0c;你需要下载并安装MySQL8。你可以从MySQL官方网站下载符合你操作系统版本的安装包。 安装地址是&#xff1a;MySQL :: Download MySQL Installer 安装过程中&#xff…

ACRN Intel推出的虚拟机是啥样的?

前言 ACRN作为Intel为工控领域推出的一个小型化的虚拟机&#xff0c;它的特点主要有这么几个&#xff1a; 1.针对Intel的芯片做了非常强的优化 2.RT-VM实时虚拟机的实时性很好 3.CACHE缓存技术发挥的好 4.TCC技术 / 当然不是所有intel的芯片都支持&#xff0c;&#xff0c…

鸿蒙(HarmonyOS)性能优化实战-多线程共享内存

概述 在应用开发中&#xff0c;为了避免主线程阻塞&#xff0c;提高应用性能&#xff0c;需要将一些耗时操作放在子线程中执行。此时&#xff0c;子线程就需要访问主线程中的数据。ArkTS采用了基于消息通信的Actor并发模型&#xff0c;具有内存隔离的特性&#xff0c;所以跨线…

产品规划|如何从0到1规划设计一款产品?

我们要如何从0到1规划设计一款产品?在前期工作我们需要做什么呢?下面这篇文章就是关于此的相关内容,大家一起往下看多多了解了解吧! 一、什么是产品规划? 产品规划是一种策略,它设定了产品的价值和目标,并确定实施方案以实现这些目标。它考虑了产品的整个生命周期,基于…

[RTOS 学习记录] 工程管理工具make及makefile

[RTOS 学习记录] 工程管理工具make及makefile 这篇文章是我阅读《嵌入式实时操作系统μCOS-II原理及应用》后的读书笔记&#xff0c;记录目的是为了个人后续回顾复习使用。 前置内容&#xff1a; 开发工具 Borland C/C 3.1 精简版 文章目录 1 make 工具2 makefile 的内容结构3…

【学习笔记二十四】EWM补货策略和自动补货配置

一、EWM补货策略概述 1.计划补货 ①以联机或批处理模式启动 ②根据最大和最小数量计算补货 ③仅当库存量低于最低数量时才开始 ④四舍五入至最小补货数量的倍数 2.自动补货 ①在WT确认期间启动 ②根据最大和最小数量计算补货 ③只有当库存量低于最低数量时才开始 ④四舍…

Linux thermal框架介绍

RK3568温控 cat /sys/class/thermal/thermal_zone0/temp cat /sys/class/thermal/thermal_zone1/temp cat /sys/class/thermal/cooling_device0/cur_state cat /sys/class/thermal/cooling_device1/cur_state cat /sys/class/thermal/cooling_device2/cur_state thermal_zone…

翻页电子图书制作小技巧分享给你

当今社会&#xff0c;二维码已经成为了信息传递的重要方式之一&#xff0c;其在电子商务、广告营销、活动推广等领域广泛应用。而如何将二维码巧妙地融入电子画册中&#xff0c;制作出高端、具有吸引力的作品&#xff0c;成为了许多设计师和营销人员关注的焦点 但是很多人却不知…

ABeam×StartUp丨蓝因机器人访问ABeam旗下德硕管理咨询(深圳)新创部门,展开合作交流

近日&#xff0c;深圳蓝因机器人科技有限公司&#xff08;以下简称“蓝因机器人”&#xff09;创始人陈卜铭先生来访ABeam旗下德硕管理咨询&#xff08;深圳&#xff09;有限公司&#xff08;以下简称“ABeam-SZ”&#xff09;&#xff0c;与新创部门展开合作交流。 交流中&am…

六西格玛管理培训:我的转变与成长之旅

4月初&#xff0c;我参与了天行健咨询的六西格玛管理培训&#xff0c;这次经历不仅极大地提升了我的工作效率&#xff0c;还帮助我在工作中实现了卓越。现在&#xff0c;我想分享一些我在这次培训中的学习心得和实践经验&#xff0c;希望能对正在寻求提升绩效和卓越之路的大家有…

【无线通信】OQPSK

调制 sps 8; RolloffFactor 0.2; FilterSpanInSymbols 10;bits randi([0, 1], 224*8, 1); % 1792symbols bits*2 - 1; % 1792 re -symbols(2:2:end); % 896 im -symbols(1:2:end); % 896pFilterTx comm.RaisedCosineTransmitFilter(...Shape, Square root, ...Rollo…

MySQL主从结构搭建

说明&#xff1a;本文介绍如何搭建MySQL主从结构&#xff1b; 原理 主从复制原理如下&#xff1a; &#xff08;1&#xff09;master数据写入&#xff0c;更新binlog&#xff1b; &#xff08;2&#xff09;master创建一个dump线程向slave推送binlog&#xff1b; &#xff…

GoJudge环境部署本地调用云服务器部署go-judge判题机详细部署教程go-judge多语言支持

前言 本文基于go-judge项目搭建&#xff0c;由于go-judge官网项目GitHub - criyle/go-judge: Sandbox Server in REST / gRPC API. Based on Linux container technologies.&#xff0c;资料太少&#xff0c;而且只给了C语言的调用样例&#xff0c;无法知道其他常见语言比如&am…