STM32f407 网络接收 fpga 的 bin 文件并更新到 fpga series7(2)

news2024/11/25 4:28:14

STM32f407 网络接收 fpga 的 bin 文件并更新到 fpga series7(2)

简介

实验 2:在单片机搭建好 tcp 服务器后,编写传送文件的上位机。

整体实现

- 利用qt的tcpsocket简单封装
- 每次发送512字节,这样小的tcp包就不会自动分包。保证每一个512tcp包都有帧头。
- 每次发送完,等待服务器返回一个包,用来判断是否正确写入fpga

代码

tcpclient.h

#ifndef TCPCLIENT_H
#define TCPCLIENT_H

#include <QObject>
#include <QString>
#include <QTcpSocket>
#include <QHostAddress>


class TcpClient : public QObject {
    Q_OBJECT
public:
    explicit TcpClient(QObject *parent = nullptr);

    Q_INVOKABLE bool connect_server(QString ip, int port);
    Q_INVOKABLE void close_client();

    Q_INVOKABLE bool send_buffer(char *buf, size_t len);
    Q_INVOKABLE bool recv_buffer(char *pdata, uint32_t len);

private:
    QTcpSocket *socket_;
};

#endif  // TCPCLIENT_H

tcpclient.c


#include "tcpclient.h"

#include <QAbstractSocket>


TcpClient::TcpClient(QObject *parent) {
    socket_ = new QTcpSocket(this);
}

/// @brief 连接服务器
/// @param ip 
/// @param port 
/// @return 成功返回true,超时返回false
bool TcpClient::connect_server(QString ip, int port) {
    socket_->connectToHost(QHostAddress(ip), port);
    if (socket_->waitForConnected(3000)) {
        return true;
    } else {
        return false;
    }
}

void TcpClient::close_client() { socket_->close(); }


/// @brief 发送buffer
/// @param buf 
/// @param len 
/// @return 成功返回true,超时返回false
bool TcpClient::send_buffer(char *buf, size_t len) {
    socket_->write(buf, len);
    if (socket_->waitForBytesWritten(3000)) {
        return true;
    } else {
        return false;
    }
    socket_->flush();
}

/// @brief 接收buffer
/// @param pdata 
/// @param len 
/// @return 成功返回true,超时返回false
bool TcpClient::recv_buffer(char *pdata, uint32_t len) {
    if(!socket_->waitForReadyRead(10000)){
        return false;
    }
    socket_->read(pdata, len);
    return true;
}

main.c

// 文件: main.cpp
// 时间: 2024-08-21
// 来自: ccj
// 描述: 把fpga程序发送给STM32服务器
//          1. 自定义帧结构 512字节,其中24字节帧头。剩下都是数据
//          2. 发送一个512字节的帧,要接收一个24字节的帧,里面有判断是否写入fpga成功。
//          3. 整体流程
//              3.1 发送24字节的开始命令帧
//              3.2 发送512字节的数据帧
//              3.1 发送24字节的结束命令帧


#include <stdint.h>
#include <time.h>
#include <thread>

#include <QFile>
#include <QString>
#include <QFileInfo>

#include "tcpclient.h"

#define qdebug() qDebug() << "[" << __FILE__ << ":" << __LINE__ << "]"

// 帧信息
#define kbuffer_len  512
#define kheader_size 24
#define kdata_len    (kbuffer_len - kheader_size)
#define kmagic       0xaa5555aa
#define kmagic1      0x55aaaa55

// 发送帧头type字段定义
#define ksend_type_start 0xa
#define ksend_type_write 0xb
#define ksend_type_end   0xc

// 接收帧头offset定义
#define krecv_offset_success 0
#define krecv_offset_failed  1

/// @brief 帧头
struct tcp_package_header {
    uint32_t magic;
    uint32_t type;
    uint32_t data_offset;
    uint32_t data_len;
    uint32_t order;
    uint32_t magic1;
};

// 发送和接收缓冲区
char send_buffer[kbuffer_len];
char recv_buffer[kheader_size];

struct tcp_package_header *send_header = (struct tcp_package_header *)send_buffer;
struct tcp_package_header *recv_header = (struct tcp_package_header *)recv_buffer;

char *pdata = send_buffer + kheader_size;


// 接收校验
// 发送一个tcp包,就接收一个tcp包做校验
#define recv_verify()                                                                \
    do {                                                                             \
        ret = client.recv_buffer(recv_buffer, kheader_size);                         \
        if (!ret) {                                                                  \
            qdebug() << "recv buffer failed.";                                       \
            return 1;                                                                \
        }                                                                            \
        switch (recv_header->data_offset) {                                          \
            case krecv_offset_success: break;                                        \
            case krecv_offset_failed: qdebug() << "write to fpga failed."; return 1; \
            default: break;                                                          \
        }                                                                            \
    } while (0)


int main(int argc, char *argv[]) {
    // 0 读取命令行参数
    if (argc != 4) {
        qdebug() << "Usage: tcpclient {ip} {port} {file_full_path}";
        return 1;
    }
    QString server_ip = QString::fromLocal8Bit(argv[1]);
    int server_port = std::stoi(argv[2]);
    QString file_full_path = QString::fromLocal8Bit(argv[3]);
    // QString server_ip = "192.168.11.33";
    // int server_port = 7;
    // QString file_full_path = "qf_pciefmc_top.bin";


    // 1 判断参数是否有效
    // 1.1 判断是否可以连接服务器
    TcpClient client;
    bool ret = client.connect_server(server_ip, server_port);
    if (!ret) {
        qdebug() << "connect server failed.";
        return 1;
    }

    // 1.2 判断文件是否存在
    QFile file(file_full_path);
    if (!file.open(QIODevice::ReadOnly)) {
        qdebug() << "Cannot open file for reading:" << file.errorString();
        return 1;
    }


    clock_t start, end;
    start = clock();

    // 2 发送文件到服务器
    // 2.1 发送开始帧
    std::memset(send_header, 0, sizeof(struct tcp_package_header));
    send_header->magic = kmagic;
    send_header->data_offset = kheader_size;
    send_header->magic1 = kmagic1;
    send_header->type = ksend_type_start;
    ret = client.send_buffer(send_buffer, kheader_size);
    if (!ret) {
        qdebug() << "send buffer failed.";
        return 1;
    }
    recv_verify();


    // 2.2 循环文件发送每一个帧
    QFileInfo fileinfo(file_full_path);
    uint64_t total_file_size = fileinfo.size();
    uint64_t total_read_size = 0;
    uint64_t read_buf_size = 0;
    int order = 1;
    while (total_read_size < total_file_size) {
        // 2.2.1 读取一个帧
        read_buf_size = file.read(pdata, kdata_len);
        if (read_buf_size == -1) {
            qdebug() << "read file error." << file.errorString();
            return 1;
        }

        // 2.2.2 发送帧
        send_header->type = ksend_type_write;
        send_header->data_len = read_buf_size;
        send_header->order = order;
        ret = client.send_buffer(send_buffer, kbuffer_len);
        if (!ret) {
            qdebug() << "send buffer failed.";
            return 1;
        }
        recv_verify();

        // 2.2.3 继续循环
        total_read_size += read_buf_size;
        order++;

        // 打印发送进度
        if (order % 5 == 0)
            qdebug() << "total: " << total_file_size << ", send: " << total_read_size
                     << ", process: " << (double)total_read_size / total_file_size * 100 << "%";
    }


    // 2.3 发送结束帧
    send_header->type = ksend_type_end;
    ret = client.send_buffer(send_buffer, kheader_size);
    if (!ret) {
        qdebug() << "send buffer failed.";
        return 1;
    }
    recv_verify();

    end = clock();
    double cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
    qdebug() << "update success. cost time: " << cpu_time_used << "s.";
}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

多商户商品下单限购问题修复

问题: 当商品设置限购为 1 时,够买数量未超过限购,但是还是提示超出限购数量 修复方法: 修改代码路径: app\common\repositories\store\order\StoreOrderCreateRepository.php 修改代码一: i s p a y s a r r a y u n i q u e ( a r r a y c o l u m n ( is_pays array_un…

阿里一款非常不错的多级缓存框架如何使用?

目录 前言 1. jetcache简介 2. jetcache使用 2. jetcache使用 3. 测试 3.1 方式一测试 3.2 方式二测试 3.3 方式三测试 4.缺点优点 5. 常见报错 前言 大家好&#xff0c;我是月夜枫~~ 在很多大数据、高并发的业务中&#xff0c;像MySql等传统的关系型数据库已经不能适用…

C++ 设计模式(3. 抽象工厂模式)

抽象工厂模式也是一种创建型设计模式&#xff0c;提供了一个创建一系列相关或相互依赖对象的接口&#xff0c;而无需指定它们具体的类【引用自大话设计模式第15章】基本结构 抽象工厂模式包含多个抽象产品接口&#xff0c;多个具体产品类&#xff0c;一个抽象工厂接口和多个具体…

BMC下使用KVM远程启动java被阻止解决方案

Java程序被阻止 进笔记本控制面板-Java里 安全里把BMC IP地址添加进去 -------------------------------------------- “如有侵权&#xff0c;联系删除”

【2024版】最新JDK下载和安装=保姆级教程,Java环境配置和使用指南,收藏这一篇就够了

大纲 JDK介绍 JDK下载 在线下载 离线下载 JDK安装 验证安装 JDK介绍 JDK&#xff08;Java Development Kit&#xff09;是用于开发Java应用程序的软件开发工具包。它包括&#xff1a;Java虚拟机&#xff08;JVM&#xff09;、Java类库以及其他一些用于开发Java应用程序的工具…

uniapp 获取定位权限及问题解决

目录 步骤一&#xff1a;在manifest.json中配置步骤二&#xff1a;引用文件可多页面复用的处理逻辑代码注意&#xff1a;问题处理&#xff08;1&#xff09;报错信息1&#xff1a;getLocation:fail the api need to be declared in the requiredPrivateInfos fie&#xff08;2&…

本地Docker部署Navidrome音乐服务器与远程访问听歌详细教程

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

VueSeamlessScroll 无缝滚动点击事件不生效(需要给复制Dom加样式)

VueSeamlessScroll 无缝滚动点击事件不生效&#xff08;需要给复制Dom加样式&#xff09; 实现效果遇到问题具体实现扩展 实现效果 VueSeamlessScroll 列表无缝滚动&#xff0c;且可以选择某一项进行选中改变背景&#xff0c;并且将选中的数据传到其他接口中 遇到问题 问题…

AgentMD:通过大规模临床工具学习提升语言代理的风险预测能力

人工智能咨询培训老师叶梓 转载标明出处 临床计算器在医疗保健中扮演着至关重要的角色&#xff0c;它们通过提供准确的基于证据的预测来辅助临床医生进行诊断和预后评估。然而&#xff0c;由于可用性挑战、传播不畅和功能受限&#xff0c;这些工具的广泛应用常常受限。为了克服…

如何备份电脑所有数据?有哪些方法值得参考借鉴?

备份电脑所有数据是防护数据丢失和泄密的重要一项措施&#xff0c;备份数据也有不同的方式和工具&#xff0c;正确的工具能帮你省时省力&#xff0c;下面盘点了几个方法&#xff0c;来看哪一种最适合你。 一、使用专业备份软件 第三方服务器文件自动备份软件&#xff1a;如安企…

AI恶搞《黑神话:悟空》爆火!

黑神话简直太火了&#xff0c;各个热搜榜都有它的身影。 单 Steam 上的销量榜就是榜首&#xff0c;同时在线人数突破 200W。 估计周末在线人数更多&#xff0c;能不能破最高同时在线人数记录&#xff0c;拭目以待。 最近有不少人用清影 AI 生成鬼畜视频&#xff0c;我也用《黑…

【精选】基于大数据的___银行信用卡用户的数仓系统的设计与实现(全网独一无二,最新定制)

目录&#xff1a; 关键技术介绍 PYTHON语言简介 大数据介绍 MySql数据库 DJANGO框架 Hadoop介绍 Scrapy介绍 B/S架构 系统的设计 系统总功能模块设计 系统测试 系统测试的目的 软件测试过程 6.3测试用例 参考代码&#xff1a; 为什么选择我&#xff1a; 博主介绍&am…

Ciallo~(∠・ω・ )⌒☆第二十三篇 python 可迭代,迭代器,生成器,装饰器

Python中的可迭代对象&#xff08;iterable&#xff09;是指可以被迭代的对象&#xff0c;例如列表、元组、字符串等。可迭代对象可以通过循环来访问其元素。 迭代器&#xff08;iterator&#xff09;是一种能够逐个访问元素的对象&#xff0c;它实现了__iter__()和__next__()方…

C++ TinyWebServer项目总结(1. 配置安装)

语雀文档 项目记录会先更新在我的语雀文档 &#xff1a;Webserver 然后再同步发送到CSDN上&#xff0c;有些格式问题实在是懒得改了&#xff0c;可能会导致大家看的不舒服&#xff0c;建议有需要的大家可以看看我的原文。 安装环境 Ubuntu 20.04 mysql Ver 8.0.39-0ubuntu0…

活动策划必备:活动页面设计全攻略

活动页面是营销策略中的重要环节&#xff0c;它不仅传递活动信息&#xff0c;更是吸引用户参与和转化的关键。设计师需要深入理解活动的核心价值和目标受众的需求&#xff0c;确保设计能够准确传达活动信息&#xff0c;同时激发用户的参与欲望。通过这样的设计&#xff0c;活动…

【AI Agent极限挑战赛】三大赛题揭晓

由AIGC开放社区联合联想拯救者、英特尔共同主办的【2024 AI Agent极限挑战赛】于8月17日在上海中庚聚龙酒店成功举办。赛事全面考察参赛者将AI技术应用于实际问题的能力。比赛内容包括对大语言模型的理解、提示词&#xff08;Prompt&#xff09;的结构化调优技术、个人助理Agen…

做谷歌seo如何确保网站的速度快?

想做谷歌seo&#xff0c;网站的快慢也是一个重要因素&#xff0c;至少不能慢的让客户等得不耐烦&#xff0c;以下是一些实用的小建议&#xff0c;帮助你提高页面加载速度&#xff0c;确保用户体验的顺畅。 压缩图片文件大小&#xff1a;图片通常是网页上最占用带宽的资源之一&a…

记一次:Datawhale AI夏令营-第五期-CV-Task01

前言&#xff1a;前面参加了第四期AIGC算是入门了&#xff0c;第五期我又来了&#xff0c;这期我参加了两个&#xff0c;计算机视觉CV所以按照惯例写一个笔记。 学习任务 一、计算机视觉CV的了解 1.1、什么是计算机视觉&#xff1f; 1.2、什么是YOLO&#xff1f;什么是物体…

SAP赋能消费品行业:创新与效率的双重驱动

在快速消费品行业&#xff0c;市场变化如同潮水般汹涌&#xff0c;消费者需求日益个性化&#xff0c;竞争愈发激烈。SAP系统以其先进的企业资源规划技术&#xff0c;为消费品行业提供了强大的数字化解决方案&#xff0c;助力企业在创新与效率的双重驱动下&#xff0c;实现业务的…

上位机图像处理和嵌入式模块部署(linux Qt程序的编译)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 linux上位机写程序&#xff0c;大家都喜欢用designer设计界面&#xff0c;用qt creator编写程序。这样其实也无可厚非。但是从效率和快速开发的角度…