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

news/2024/9/20 7:36:19/ 标签: stm32, 网络, qt

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.ppmy.cn/news/1514337.html

相关文章

无人驾驶,并非无人之地

图片&#xff5c;Photo by 萝卜快跑 ©自象限原创 作者丨罗辑 老司机又双叒叕被“抢”了&#xff1f; 随着武汉无人驾驶的Robotaxi在各社交媒体平台出圈&#xff0c;自动驾驶安全员的职业从幕后走向台前&#xff0c;近期&#xff0c;招聘平台信息也显示&#xff0c;萝卜…

React Native中好用的UI组件库

文章目录 前言1.React Native ElementsStar数超24K地址 2.React Native UI KittenStar数超20K地址 3.NativeBaseStar数超20K地址 前言 下面是React Native中一些常用的UI库 1.React Native Elements Star数超24K 官方介绍 React Native Elements 的目标是提供一套用于在 Rea…

wpf DataTemplate 和 ControlTemplate 区别,应用举例

在WPF中&#xff0c;模版&#xff08;ControlTemplate &#xff09; ControlTemplate用于定义控件的内部结构和外观&#xff0c;它决定了控件的“长成什么样子”&#xff0c;并允许开发者在控件原有的内部逻辑基础上扩展自己的逻辑。DataTemplate则专注于数据内容的展示方式&am…

Parallels Desktop 19 for Mac 安装虚拟机需要激活吗

Parallels Desktop 19 for Mac 乃是一款适配于 Mac 的虚拟化软件。它能让您在 Mac 计算机上同时运行多个操作系统。您可借此创建虚拟机&#xff0c;并于其中装设不同的操作系统&#xff0c;如 Windows、Linux 或 macOS。使用 Parallels Desktop 19 mac 版时&#xff0c;您可在 …

【Docker】gitea的ssh容器直通

本文首发于 ❄️慕雪的寒舍 1.跟着文档走 gitea的安装比较简单&#xff0c;直接使用官方文档中的docker-compose文件即可。如果想实现ssh容器直通&#xff0c;需要对这个docker-compose文件做一定修改。 如果你还没有安装docker&#xff0c;参考本站教程 linux安装docker&…

手机麻将APP开发违法吗,有哪些注意的地方呢?

在我的职业生涯中&#xff0c;我处理过许多因开发或运营手机游戏而遭遇法律处罚的案例。游戏作为一种传统的娱乐形式&#xff0c;在中国拥有广泛的受众。然而&#xff0c;随着智能手机的普及&#xff0c;手机游戏的开发和运营逐渐成为热门领域&#xff0c;但其中也存在不少法律…

c++链表(list)

前言 链表作为一个常见的数据结构&#xff0c;在高频插入删除的场景下有独特的优势&#xff0c;在内存的使用上也极少有浪费可以按需申请。今天我们就来简单的学习一下这种数据结构&#xff0c;链表也有很多不同的实现&#xff0c;我们这里和标准库保持一致&#xff0c;实现带…

docker手动部署django项目Dockerfile编排-后端发布

1、首先创建一个桥接网络 docker network create auto 2、部署redis,提供celery的消息队列服务 docker run --name redis --restartalways -d --network auto -v redis:/data redis:alpine3、部署数据库 注意数据库账号密码 docker run --name mariadb --restartalways -d…

远程消息传递的艺术:NSDistantObject在Objective-C中的妙用

标题&#xff1a;远程消息传递的艺术&#xff1a;NSDistantObject在Objective-C中的妙用 引言 在Objective-C的丰富生态中&#xff0c;NSDistantObject扮演着至关重要的角色&#xff0c;特别是在处理分布式系统中的远程消息传递。它允许对象之间跨越不同地址空间进行通信&…

基于矢量控制器的PMSM永磁同步电机速度控制系统simulink建模与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 基于矢量控制器的PMSM永磁同步电机速度控制系统simulink建模与仿真&#xff0c;仿真输出电机转速跟踪曲线&#xff0c;PID控制器输出曲线以及Te输出曲线。 2.系统仿真结果 &…

通过访存地址获取主存数据的过程

目录 1.根据访存地址在Cache中查找数据 2.如果在Cache中命中 3.如果没有命中 4.数据送CPU 5.做几道题&#xff1a; 主要厘清思路&#xff0c;中间细节需自行补充! 1.根据访存地址在Cache中查找数据 ① 访存地址的结构会根据Cache和主存之间的映射方式不同而改变。映射方式…

【C++ 面试 - 面向对象】每日 3 题(七)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/fYaBd &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏&…

centos7.9系统安装cloudpods并使用ceph存储(二)

1.ceph安装 1.1 环境准备 配置hosts&#xff1a; $ vim /etc/hosts 10.121.x.x node01设置ssh无密码登录&#xff1a; # ssh-keygen -t rsa # ssh-copy-id -i /root/.ssh/id_rsa node01关闭selinux、firewalld # setenforce 0 # sed -i "s#SELINUXenforcing#SELINUXd…

5步掌握Python Django+Vue二手房项目,实现房价预测与知识图谱系统

&#x1f34a;作者&#xff1a;计算机毕设匠心工作室 &#x1f34a;简介&#xff1a;毕业后就一直专业从事计算机软件程序开发&#xff0c;至今也有8年工作经验。擅长Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等。 擅长&#xff1a;按照需求定制化开发项目…

基于SpringBoot的在线笔记网站的设计与实现

目录 项目技术和环境 页面展示 登录注册 管理员页面 用户页面 在线网址 源代码 本系统由十大核心模块构成&#xff0c;包括用户登录与注册模块、个人中心模块、笔记分类与笔记管理模块、笔记详情展示模块、分享协作与收藏管理模块、回收站与用户管理模块&#xff0c;以及…

深入探讨量子计算领域在发展过程中所遇到的难题及其解决方案。

一、引言 量子计算作为未来科技的重要方向&#xff0c;其潜力巨大&#xff0c;但同时也面临着诸多技术挑战。这些挑战不仅制约了量子计算的进一步发展&#xff0c;也考验着科学家和工程师们的智慧和毅力。本文将探讨量子计算面临的主要技术挑战&#xff0c;并分析其可能的解决…

自己做的一个用于生成DICOM文件的服务器

框架: .ner core web api .net8.0 Program.cs代码如下 using Microsoft.AspNetCore.HttpsPolicy; using System.Diagnostics;namespace PacsServer {/* public class Program{public static void Main(string[] args){//配置服务var builder WebApplication.CreateBuilder(a…

表格滚动分页查询

1.给表格添加id&#xff0c;height"100%"是固定表头 <el-table id"attr-table-box" height"100%" :row-style"{ height: 66px }" style"width: 100%; height: 100%; " > 2.使用计算属性获取总页数 computed: { // 表…

go语言中map、slice、chan底层数据结构是怎样的

map&#xff1a;rutime包下的map中的hmap // A header for a Go map. type hmap struct {// Note: the format of the hmap is also encoded in cmd/compile/internal/reflectdata/reflect.go.// Make sure this stays in sync with the compilers definition.count int /…

信息学奥赛初赛天天练-72-NOIP2016普及组-基础题3-无向图、简单无向图、自环、平行边、顶点的度、握手定理、递归

NOIP 2016 普及组 基础题3 5 以下不是存储设备的是( ) A 光盘 B 磁盘 C 固态硬盘 D 鼠标 6 如果开始时计算机处于小写输入状态&#xff0c;现在有一只小老鼠反复按照 CapsLock、 字母键 A、字母键 S、字母键 D、字母键 F 的顺序循环按键&#xff0c;即 CapsLock、A、S、D、F、…