OpenIPC开源FPV之Adaptive-Link天空端代码解析
OpenIPC开源FPV之Adaptive-Link天空端代码解析
- 1. 源由
- 2. 框架代码
- 3. 报文处理
- 3.1 special报文
- 3.2 普通报文
- 4. 工作流程
- 4.1 `Profile` 竞选
- 4.2 `Profile` 研判
- 4.3 `Profile` 应用
- 5. 总结
- 6. 参考资料
- 7. 补充资料
- 7.1 RSSI 和 SNR 的物理含义
- 7.2 信号质量加权的理论依据
- 7.3 实际应用中的加权方法
- 7.4 加权方法的优化
- 7.5 综合考虑信号质量的模型
- 7.6 8812EU WiFi模块
1. 源由
在《OpenIPC开源FPV之Adaptive-Link工程解析》中,已经有了整个工程的大体概念,接下来再对代码进行逐步分析。
首先,对天空端的代码进行分析:ALink42n.c
2. 框架代码
ALink42n.c
相对来说,代码量最少,也是最为基本的一份代码。
目前,尚不太清楚具体n/p/q之间的差异,逻辑上看应该是关于切换配置profile
的条件计算方式不太一样,对于稳定性、可靠性方面应该有所差异。
- The relationship between .c and binary files #7
注:感兴趣的朋友,可以跟下帖子,不过随着代码的深入了解,以及性能测试数据,也能慢慢明晰之间的差异。
- 加载配置 - “/etc/alink.conf”
- 加载Profile - “/etc/txprofiles.conf”
- majestic:80
- wfb-cli:8000
- Terminal:bash
- 绑定默认IP - 10.5.0.10:9999
n/p/q只有q写的是10.5.0.10,其他是10.5.0.2,应该有笔误。
- 接受两种UDP报文:special报文和普通报文
main├──> load_config(CONFIG_FILE); // "/etc/alink.conf"├──> load_profiles(PROFILE_FILE); // "/etc/txprofiles.conf"├──> bind DEFAULT_IP(10.5.0.10) DEFAULT_PORT(9999)├──>loop recvfrom│ ├──> <special:> special_command_message(message);│ └──> process_message(message);└──> close(sockfd);
3. 报文处理
+--------------+---------------+-------------+
| | special? (8B) | Msg content |
| Msg len (4B) |---------------+-------------|
| | RF Signal Estimated Values |
+--------------+---------------+-------------+
3.1 special报文
- 报文格式:
+--------------+---------------+-------------+
| Msg len (4B) | special? (8B) | Msg content |
+--------------+---------------+-------------+
- 代码流程:
处理pause_adaptive
/resume_adaptive
/request_keyframe
命令
special_command_message├──> "pause_adaptive"│ └──> paused = true├──> "resume_adaptive"│ └──> paused = false├──> "drop_gop"│ └──> // 已经注释掉,代码暂时保留├──> "request_keyframe"│ └──> < > request_keyframe_interval_ms> `idrCommand`└──> "Unknown"
3.2 普通报文
- 报文格式:
+--------------+------------------+-----------------+----------------+-----------+------+-------+-------+---------------+
| Msg len (4B) | transmitted_time | link_value_rssi | link_value_snr | recovered | lost | rssi1 | rssi2 | rssi3 | rssi4 |
+--------------+------------------+-----------------+----------------+-----------+------+-------+-------+---------------+
- 代码流程:
解析地面端报文反馈的RF信号参数,比如:RSSI/SNR等
process_message├──> [index/token parse]│ ├──> <0> transmitted_time = atoi(token);│ ├──> <1> link_value_rssi = atoi(token);│ ├──> <2> link_value_snr = atoi(token);│ ├──> <3> recovered = atoi(token);│ ├──> <4> lost = atoi(token);│ ├──> <5> rssi1 = atoi(token);│ ├──> <6> rssi2 = atoi(token);│ ├──> <7> rssi3 = atoi(token);│ ├──> <8> rssi4 = atoi(token);│ └──> <.> Ignore extra tokens├──> <!time_synced> settimeofday(&tv, NULL)└──> <!paused> start_selection(link_value_rssi, link_value_snr);
4. 工作流程
4.1 Profile
竞选
当 2.1
paused 为 false
时,满足触发条件则进行 start_selection
:
start_selection├──> <selection_busy> return├──> <rssi_score == 999> value_chooses_profile(999); // Default settings│ └──> return├──> int combined_value = floor(rssi_score * w_rssi + snr_score * w_snr);├──> constrain(1000, 2000, combined_value)├──> float percent_change = fabs((float)(value - baseline_value) / baseline_value) * 100;└──> <percent_change >= hysteresis_percent>└──> <time_diff_ms >= min_between_changes_ms> value_chooses_profile(value); // apply new settings
注:这里采用了 rssi
和 snr
权重方式。
4.2 Profile
研判
当 Profile
竞选成功后,在实际应用时,需要检查触发条件,比如:如果当前为需要切换的 Profile
则无需触发。
value_chooses_profile├──> Profile* selectedProfile = get_profile(input_value);├──> [Find the index of the selected profile]├──> <previousProfile == currentProfile> return // no changes├──> <previousProfile == 0 && timeElapsed <= hold_fallback_mode_s> return // first profile in fallback time├──> <(currentProfile - previousProfile == 1) && timeElapsed <= hold_modes_down_s> // just one step difference in hold time└──> apply_profile(selectedProfile)
无缝的触发场景判断,能够确保信号的稳定传输和平滑切换:
- what’s the difference between hold_fallback_mode_s and hold_modes_down_s? #9
4.3 Profile
应用
这里需要注意几个细节:
- 功率增加/减小其命令执行顺序不一致
- 综合信号质量来选择不同的GI/MCS/FecK/FecN/Bitrate/Gop/Power/ROIqp
apply_profile
├──> Local Variables Initialization
│ └──> Command Templates and Time Calculation
├──> Load Profile Variables into Local Variables
│ └── Copy values from `profile` into local variables
├──> Profile Comparison (currentProfile vs previousProfile)
│ ├──> If currentProfile > previousProfile:
│ │ ├──> Execute Power Command if changed // "iw dev wlan0 set txpower fixed %d"
│ │ ├──> Execute GOP Command if changed // "curl -s 'http://localhost/api/v1/set?video0.gopSize=%f'"
│ │ ├──> Execute MCS Command if changed // "wfb_tx_cmd 8000 set_radio -B 20 -G %s -S 1 -L 1 -M %d"
│ │ ├──> Execute FEC Command if changed // "wfb_tx_cmd 8000 set_fec -k %d -n %d"
│ │ ├──> Execute Bitrate Command if changed // "curl -s 'http://localhost/api/v1/set?video0.bitrate=%d'"
│ │ ├──> Execute ROI Command if changed // "curl -s 'http://localhost/api/v1/set?fpv.roiQp=%s'"
│ │ └──> Execute IDR Command if enabled // "curl localhost/request/idr"
│ └──> Else (if currentProfile <= previousProfile):
│ └──> Execute commands in different order
└──> Display Stats (msposdCommand)└──> Execute `msposdCommand` // "echo '%ld s %d M:%d %s F:%d/%d P:%d G:%.1f&L30&F28 CPU:&C &Tc %s' >/tmp/MSPOSD.msg"
rangeMin | rangeMax | setGI | setMCS | setFecK | setFecN | setBitrate | setGop | wfbPower | ROIqp |
---|---|---|---|---|---|---|---|---|---|
999 | 999 | long | 0 | 12 | 15 | 3332 | 1.0 | 61 | 0,0,0,0 |
1000 | 1150 | long | 0 | 12 | 15 | 3333 | 1.0 | 60 | 0,0,0,0 |
1151 | 1300 | long | 1 | 12 | 15 | 6667 | 1.0 | 59 | 12,12,12,12 |
1301 | 1700 | long | 2 | 12 | 15 | 10000 | 1.0 | 58 | 12,8,8,12 |
1701 | 1850 | long | 3 | 12 | 15 | 12500 | 1.0 | 56 | 8,0,0,8 |
1851 | 2001 | short | 3 | 12 | 15 | 14000 | 1.0 | 56 | 4,0,0,4 |
-
rangeMin: Starting value of the range.
-
rangeMax: Ending value of the range.
-
setGI: 是无线通信系统中的 保护间隔(GI,Guard Interval)。短GI(400 ns)和长GI(800 ns)是两种常见的保护间隔设置,用于管理OFDM(正交频分复用)符号之间的时间间隔。选择短GI或长GI会影响性能和抗干扰能力。它通常在无线通信协议的 物理层(PHY) 中进行设置,比如Wi-Fi(802.11标准)。
-
setMCS: 定义了用于数据传输的调制和编码方案。MCS决定了数据是如何编码的(调制类型),以及为错误纠正添加了多少冗余数据(编码率)。在Wi-Fi(802.11n/ac/ax)中,MCS值通常从0到9(或更高,取决于Wi-Fi版本)。MCS索引是802.11协议标准的一部分,并且可以根据链路质量和信号强度进行调整。
-
setFecK: 指的是前向错误纠正(FEC)方案,特别是表示在应用错误纠正之前的数据位数(K值)。FEC用于通过添加冗余数据来提高无线通信的可靠性,从而使接收方能够纠正噪声或干扰引起的错误。K值通常是Reed-Solomon编码或卷积编码中的一个参数。
-
setFecN: 表示应用FEC后的总位数(包括数据位和校验位)。 K/N的比率给出了编码率,这决定了为错误纠正添加的冗余程度。较低的FEC值(例如1/2)表示更多的冗余和错误纠正能力,而较高的值(如3/4或5/6)则提供更高的吞吐量,但错误纠正能力较弱。
-
setBitrate: 表示通过无线链路传输数据的速度,通常以Mbps(兆比特每秒)为单位。该值受到调制方案、编码率和信号强度的影响。在Wi-Fi网络中,通常会根据这些因素动态调整比特率,以优化吞吐量,同时保持稳定的连接。
-
setGop: GOP设置与视频编码相关,尤其是在像H.264或H.265这样的压缩方案中。定义了关键帧(I帧)之间的间隔。短GOP意味着更频繁的关键帧(更高的视频质量,较低的压缩),而长GOP意味着较少的关键帧(更高的压缩,较低的质量)。在无线通信中,这个设置对于视频流的传输有很大影响。
-
wfbPower: 指的是无线前端(WFB)硬件的发射功率。发射功率是无线通信中的一个关键参数,影响无线信号的范围和质量。在Wi-Fi设备中,功率通常可以根据法规限制、设备能力和网络状况进行调整。wfbPower值可能用于配置设备中射频(RF)部分的放大器。
-
ROIqp: ROI QP values as a comma-separated string (e.g.,
0,0,0,0
).
5. 总结
Profile
是一个经验值(测试值),依赖于具体场景应用。- 配置参数(如:
hold_fallback_mode_s
/hold_modes_down_s
) 也是一个经验参数,依赖于具体应用场景。 - RSSI SNR 权重 RF信号质量计算模型,也是一个经验方法,可以调整更优的算法。
基于上述逻辑,对于这些内容的优化,就能更好的将FPV视频无缝的应用于实际环境 - 取决于大量的测试和优化。
注:这里感觉缺少心跳报文丢失的处理,以应对极端情况。
6. 参考资料
【1】OpenIPC开源FPV之Adaptive-Link工程解析
7. 补充资料
RSSI(接收信号强度指示)和SNR(信噪比)是衡量信号质量的常用指标。
加权 RSSI 和 SNR 以综合评估信号质量的做法,基于以下几个理论依据:
- RSSI 反映信号强度,而 SNR 反映信号与噪声的比率,两者结合能够更全面地评估信号质量。
- 加权方式可以根据应用场景和环境的变化,动态调整各个参数的影响,优化信号质量的评估。
- 加权系数的调整通常是基于实际的应用需求和实验数据优化的。
通过加权结合这两个指标,可以更准确地反映无线通信中的实际信号质量,进而为系统做出更合理的决策(如选择最佳基站、调整发射功率、优化资源分配等)。
7.1 RSSI 和 SNR 的物理含义
-
RSSI:表示接收到的信号强度,是衡量信号功率强度的一个指标。通常情况下,RSSI 越高,表示信号接收的质量越好。然而,RSSI 只反映了信号的强度,并不直接考虑噪声的影响。
-
SNR:表示信号与噪声的比值,是衡量信号质量的一个重要指标。SNR 越高,意味着信号在噪声背景下越清晰,通信质量越高。高的 SNR 值通常意味着信号更容易被准确解码,而低的 SNR 值则容易导致误码或通信失败。
7.2 信号质量加权的理论依据
-
信号强度与噪声的相对重要性:
单独依赖 RSSI 来衡量信号质量可能会产生误导。因为高强度的信号也可能伴随着较强的噪声,而高噪声水平会影响信号的清晰度。因此,SNR 提供了一个更全面的衡量标准,考虑了信号的强度与噪声的关系。加权方式结合了这两个指标,能够更准确地反映实际信号质量。 -
加权的数学模型:
一种常见的做法是将 RSSI 和 SNR 作为输入参数,通过某种加权函数或线性组合来得到一个综合的信号质量指标。可以根据具体场景的需求调整权重值。例如:
Q = w 1 ⋅ RSSI + w 2 ⋅ SNR Q = w_1 \cdot \text{RSSI} + w_2 \cdot \text{SNR} Q=w1⋅RSSI+w2⋅SNR
其中,$ w_1 $ 和 $ w_2 $ 是 RSSI 和 SNR 的权重系数,表示它们在信号质量计算中的相对重要性。- 选择合适的权重系数:
权重的设置需要根据具体的应用需求和实验数据来优化。在一些应用中,SNR 可能更为关键,因为它直接影响到数据传输的错误率,而在其他场景中,RSSI 可能更重要,因为信号强度直接决定了通信的覆盖范围。
- 选择合适的权重系数:
7.3 实际应用中的加权方法
-
无线通信系统:在无线通信中,RSSI 和 SNR 都是评估信号质量的重要指标。将两者加权后,系统可以更好地判断信号的稳定性和传输质量。例如,在 Wi-Fi 或移动通信中,基站或接入点会同时考虑这两个参数,以确保数据传输的可靠性。
-
动态信号质量评估:无线环境通常是动态变化的,信号强度和噪声水平可能随时间和位置变化。通过加权方式,可以更灵活地反映当前信号的质量,特别是在复杂的多径传播和干扰环境中。
7.4 加权方法的优化
-
信道的特性:在不同的无线信道中,RSSI 和 SNR 对信号质量的影响可能不同。例如,在高干扰环境下,SNR 的作用更为突出,因此可以为 SNR 分配更大的权重。而在信号强度较好的环境中,RSSI 可能会更重要。
-
基于经验的调整:通过实际测试和仿真,可以根据不同的环境条件和通信需求,调整 RSSI 和 SNR 的权重。例如,在一个需要长距离传输的场景中,可能会更侧重于 RSSI;而在一个要求高数据速率和低错误率的场景中,可能会更关注 SNR。
7.5 综合考虑信号质量的模型
在一些高级的信号质量评估模型中,除了直接的 RSSI 和 SNR 之外,可能还会考虑其他因素,比如:
- 路径损耗:信号在传播过程中的衰减。
- 干扰:来自其他无线设备或环境的噪声。
- 调制方式:不同的调制方式对信号质量的敏感度不同。
这些因素也可能在加权过程中作为附加的输入,进一步提升信号质量评估的准确性。
7.6 8812EU WiFi模块
- M8812EU2 2T2R 802.11a/n/ac WiFi Module
- Using BL-M8812EU2 (or other RTL8812EU-based) Wi-Fi Module
功率设置两个方法: WIP: Add support for RTL8812EU-based Wi-Fi adapters for FPV firmware #1344
driver_txpower_override
in/etc/wfb.conf
. The range is0~63
iw dev <wlan0> set txpower fixed <mBm>
. The range is0~3150
, and can be set dynamically when transmitting.
相关文章:

OpenIPC开源FPV之Adaptive-Link天空端代码解析
OpenIPC开源FPV之Adaptive-Link天空端代码解析 1. 源由2. 框架代码3. 报文处理3.1 special报文3.2 普通报文 4. 工作流程4.1 Profile 竞选4.2 Profile 研判4.3 Profile 应用 5. 总结6. 参考资料7. 补充资料7.1 RSSI 和 SNR 的物理含义7.2 信号质量加权的理论依据7.3 实际应用中…...

Next.js流量教程:核心 Web Vitals的改善
更多有关Next.js教程,请查阅: 【目录】Next.js 独立开发系列教程-CSDN博客 目录 引言 1. 什么是 Core Web Vitals? 1.1 Largest Contentful Paint (LCP) 1.2 First Input Delay (FID) 1.3 Cumulative Layout Shift (CLS) 2. 如何优化 …...

百度智能云千帆AppBuilder升级,百度AI搜索组件上线,RAG支持无限容量向量存储!
百度智能云千帆 AppBuilder 发版升级! 进一步降低开发门槛,落地大模型到应用的最后一公里。在千帆 AppBuilder 最新升级的 V1.1版本中,企业级 RAG 和 Agent 能力再度提升,同时组件生态与应用集成分发更加优化。 • 企业级 RAG&am…...

构建树莓派温湿度监测系统:从硬件到软件的完整指南
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...

12.11数据结构-图
无向完全图:在无向图中,如果任意两个顶点之间都存在边,则称该图为无向完全图。 有向完全图:在有向图中,如果任意两个顶点之间都存在方向相反的两条弧,则称该图为有向完全图。 含有n个顶点的无向完全图有…...

BERT模型入门(2)BERT的工作原理
文章目录 如名称所示,BERT(来自Transformer的双向编码器表示)是基于Transformer模型。我们可以将BERT视为只有编码器部分的Transformer。 在上一个主题《Transformer入门》中,我们了解到将句子作为输入喂给Transformer的编码器&a…...

python3 中的成员运算符
一. 简介 在Python 3中,成员运算符用于测试序列(如字符串、列表、元组、集合或字典)中是否包含某个值。身份运算符用于比较两个对象的身份,即它们是否引用内存中的同一个对象。 本文简单学习一下 python3 中的成员运算符与身份运…...

【测试面试篇1】测试开发与开发|selenium实现自动化测试|设计测试用例|常见的测试方法|开发不认可提测试的bug该怎么办
目录 1.选择走测试为什么还要学这么多的开发知识? 2.为什么选择软件测试开发岗位而不是软件开发岗位? 3.个人的职业规划是什么? 4.测试中遇到的问题如何进行解决? 5.对自己的项目做过哪些测试工作? 6.描述selenium…...

人大金仓数据linux安装注意事项
人大金仓数据linux安装注意事项 本次是个人搭建虚拟机安装centos7的环境下进行安装。 1、安装流程参照https://help.kingbase.com.cn/v9/install-updata/install-linux/preface.html。 2、mount安装文件报错 操作手册提供mount的命令如下: mount KingbaseES_V009R0…...

【Maven】多模块项目的构建
项目构建 什么是构建? 项目构建指的是将源代码和资源文件转换为可执行或可分发的软件制品(如 JAR、WAR 文件)的过程。这个过程不仅包括编译代码,还包括运行测试、打包、部署等步骤。Maven 提供了一套标准化的方法来处理这些任务…...

大模型学习笔记------SAM模型详解与思考
大模型学习笔记------SAM模型详解与思考 1、SAM框架概述2、Segment Anything Task3、Segment Anything Model SAM模型是Meta 提出的分割一切模型(Segment Anything Model,SAM)突破了分割界限,极大地促进了计算机视觉基础模型的发展…...

crictl和ctr与docker的命令的对比
crictl是遵循CRI接口规范的一个命令行工具,通常用它来检查和管理kubelet节点上的容器运行时和镜像 ctr是containerd的一个客户端工具, 接下来就是crictl的的常见命令,其中能完全替代docker命令的参照下列表格 操作crictldocker查看运行容器…...

SQLite建表语句示例(含所有数据类型、索引、自增主键、唯一索引)
下面是一个示例,展示如何创建一个用户信息表。 包含 SQLite 支持的所有数据类型,同时设置主键为自增、一个字段为唯一索引,以及另一个字段为普通索引: -- 创建用户信息表 CREATE TABLE user_info (id INTEGER PRIMARY KEY AUTOI…...

探秘Redis哨兵模式:原理、运行与风险全解析
一、引言 Redis 概述 在当今的数据存储领域,Redis 占据着十分重要的地位。它是一个内存中的数据存储,凭借其出色的性能和丰富的功能,被数百万开发人员广泛应用于诸多场景之中,已然成为构建高性能、可扩展应用程序的得力工具。 从…...

.NET平台使用C#设置Excel单元格数值格式
设置Excel单元格的数字格式是创建、修改和格式化Excel文档的关键步骤之一,它不仅确保了数据的正确表示,还能够增强数据的可读性和专业性。正确的数字格式可以帮助用户更直观地理解数值的意义,减少误解,并且对于自动化报告生成、财…...

零基础学安全--wireshark简介
目录 主要功能 捕获网络数据包 协议解析 数据包分析 数据包重组 过滤功能 统计与图表功能 官网 Wireshark是一个开源的网络协议分析工具 主要功能 捕获网络数据包 能够实时捕获网络中传输的数据包,用户选择要监听的网络接口(如以太网、WiFi等…...

[Flutter] : Clipboard
import package:flutter/material.dart; import package:flutter/services.dart; setData Clipboard.setData(ClipboardData(text: "传入的文字内容")); getData Clipboard.getData(Clipboard.kTextPlain) 记录 | Flutter剪切板-刨根问底做一个可以在后台…...

ArcGIS MultiPatch数据转换Obj数据
文章目录 ArcGIS MultiPatch数据转换Obj数据1 效果2 技术路线2.1 Multipatch To Collada2.2 Collada To Obj3 代码实现4 附录4.1 环境4.2 一些坑ArcGIS MultiPatch数据转换Obj数据 1 效果 2 技术路线 MultiPatch --MultipatchToCollada–> Collada --Assimp–> Obj 2.…...

《开源数据:开启信息共享与创新的宝藏之门》
《开源数据:开启信息共享与创新的宝藏之门》 一、开源数据概述(一)开源数据的定义(二)开源数据的发展历程 二、开源数据的优势(一)成本效益优势(二)灵活性与可定制性&…...

如何评估基于TRIZ理论生成的方案的可行性和有效性?
在科技创新与问题解决的过程中,TRIZ理论(发明问题解决理论)以其系统性和高效性著称,为工程师和创新者提供了一套强大的工具和方法。然而,仅仅依靠TRIZ理论生成创新方案并不足以确保项目的成功,关键在于如何…...

sh-寡肽-78——头发护理多肽原料,改善头发外观
主要特征 人的头发纤维结构由角质层、皮质和髓质组成。角质层约占头发重量的 15%,由重叠的细胞层组成,类似于鳞片系统,半胱氨酸含量很高。它为头发纤维提供保护作用。皮质是头发的中间区域,负责头发的强度、弹性和颜色。它由多种细…...

metagpt 多智能体系统
metagpt 多智能体系统 代码1. 动作及角色定义2. 主函数 代码解释1. 导入模块:2. 环境设置:3. 定义行动(Action):4. 定义角色(Role):5. 学生和老师的行为:6. 主函数&#…...

下采样在点云处理中的关键作用——以PointNet++为例【初学者无门槛理解版!】
一、前言 随着3D传感器技术的快速发展,点云数据在计算机视觉、机器人导航、自动驾驶等领域中的应用日益广泛。点云作为一种高效的3D数据表示方式,能够精确地描述物体的几何形状和空间分布。然而,点云数据通常具有高维度和稀疏性的特点&#…...

pytorch ---- torch.linalg.norm()函数
torch.linalg.norm 是 PyTorch 中用于计算张量范数(Norm)的函数。范数是线性代数中的一个重要概念,用于量化向量或矩阵的大小或长度。这个函数可以处理任意形状的张量,支持多种类型的范数计算。 1.函数签名 torch.linalg.norm(…...

系列1:基于Centos-8.6部署Kubernetes (1.24-1.30)
每日禅语 “木末芙蓉花,山中发红萼,涧户寂无人,纷纷开自落。”这是王维的一首诗,名叫《辛夷坞》。这首诗写的是在辛夷坞这个幽深的山谷里,辛夷花自开自落,平淡得很,既没有生的喜悦ÿ…...

spring学习(spring-bean实例化(无参构造与有参构造方法实现)详解)
目录 一、spring容器之bean的实例化。 (1)"bean"基本概念。 (2)spring-bean实例化的几种方式。 二、spring容器使用"构造方法"的方式实例化bean。 (1)无参构造方法实例化bean。 &#…...

Arm Cortex-M处理器对比表
Arm Cortex-M处理器对比表 当前MCU处理器上主要流行RISC-V和ARM处理器,其他的内核相对比较少;在这两种内核中,又以Arm Cortex-M生态环境相对健全,大部分的厂家都在使用ARM的处理器。本文主要介绍Arm Cortex-M各个不同系列的参数对…...

【git、gerrit】特性分支合入主分支方法 git rebase 、git cherry-pick、git merge
文章目录 1. 场景描述1.1 分支状态 2. 推荐的操作方式方法 1:git merge(保留分支结构)方法 2:git rebase(线性合并提交历史)直接在master分支执行git merge br_feature,再 执行 git pull --reba…...

WPF 相比 winform 的优势
wpf 相比 winform 的一些优点,网上也是众说纷纭,总的来说包括下面几点: 丰富的视觉效果:能够创建更具吸引力和现代化的用户界面,支持更复杂的图形和动画效果。不需要像 winform 一样,稍微做一点效果&#x…...

PYQT5程序框架
pyqt5程序框架_哔哩哔哩_bilibili 1.UI代码 Qhkuja.py # -*- coding: utf-8 -*-# Form implementation generated from reading ui file Qhkuja.ui # # Created by: PyQt5 UI code generator 5.15.7 # # WARNING: Any manual changes made to this file will be lost when py…...