MCU升级固件合并和转换工具

一、项目背景与业务价值

嵌入式固件发布经常不是单个文件交付。Boot、App、参数区、资源区可能来自不同构建链路,也可能使用 BIN、Intel HEX、Motorola S-record 等不同格式。研发或生产人员在烧录前需要把这些文件放到正确 Flash 地址上,确认没有越界、没有非预期覆盖,再生成一个可以直接交付给烧录工具的完整固件。

"MCU升级固件合并工具"解决的就是这条链路中的手工风险。原始需求要求支持多 Boot、多 App、多数据区文件组合,实际合并以绝对地址为准,列表顺序主要用于管理和覆盖策略。当前实现把工具收敛成一个本地浏览器静态应用:用户在页面中导入固件、配置 Flash 范围、检查地址、执行合并、下载固件和 TXT 报告,文件内容不上传到服务端。

业务痛点 手工处理方式 当前项目方案 实际收益
多个固件区间容易放错地址 靠表格和脚本手工维护起始地址 src/lib/address.ts 统一解析地址并检查 Flash 范围 地址缺失、非法、越界能在合并前暴露
HEX/S19/BIN 地址来源不同 手工判断内部地址和偏移 src/lib/parsers.ts 分格式解析为 AddressSegment 合并引擎只处理统一地址段,降低格式耦合
空洞填充值和覆盖行为不透明 合并后再用外部工具排查 src/lib/merge.ts 用填充值生成连续镜像,并记录冲突 issue 输出结果和报告能追溯
生产或售后交付需要留档 只交付固件文件 src/lib/report.ts 生成 TXT 报告 可记录输入文件、范围、CRC16 和结果

当前版本是 0.1.6,交付形态是 Vite 构建出的静态浏览器工具,不是原生 Windows/macOS/Linux 安装包。这一点直接影响"打开输出目录""写入任意本地路径"等能力:浏览器版本只能通过 Blob 下载固件和报告。

资源下载:https://download.csdn.net/download/m0_38106923/92879996

二、需求分析与业务流程

项目的 MVP 主线可以压缩成一句话:把多个已知或可解析地址的固件文件,转换为统一地址模型,完成合法性检查后输出目标固件和报告。需求拆解中明确的 P0 能力包括文件导入、地址配置与校验、固件合并、报告输出和主界面交互。

功能模块 实现说明 目标用户 当前状态
文件导入 支持点击拖拽区、键盘 Enter/Space、拖拽导入 .bin/.hex/.s19/.srec/.mot 嵌入式研发、生产烧录人员 已实现
地址配置 Flash 起始地址、大小、填充值、输出范围、冲突策略、BIN 起始地址、HEX/S19 偏移 嵌入式研发 已实现
配置检查 校验格式、地址、Flash 越界、文件重叠、无启用文件和大 Flash 警告 研发、生产、售后 已实现
固件合并 支持 BIN、HEX、S19、SREC、MOT 输出,空洞按填充值填充 生产烧录人员 已实现
合并报告 生成 TXT 报告,记录输入文件、范围、状态、CRC16、issue 和结果 生产、售后 已实现
项目保存/加载 保存工程配置和最近项目 研发 未纳入当前版本
原生安装包 桌面壳、打开输出目录、直接写本地目录 生产、售后 未纳入当前版本

业务主流程如下:
缺失
已填写或非 BIN
越界
重叠且禁止覆盖
通过或仅警告
配置 Flash 起始地址、大小、填充值
导入 BIN/HEX/S19/SREC/MOT 文件
识别格式并解析为 AddressSegment
BIN 是否有起始地址
返回 BIN_START_REQUIRED
检查 Flash 范围和文件重叠
返回 RANGE_OUT_OF_FLASH
返回 ADDRESS_OVERLAP
按输出范围创建 Uint8Array
填充空洞并写入固件段
生成 BIN/HEX/S-record 固件
生成 TXT 合并报告
浏览器下载固件和报告

异常路径并没有被隐藏到"用户自行修正"里。validateProject 会把配置错误、无启用文件、越界、冲突和大 Flash 警告统一转成 ValidationIssuesrc/lib/logMessages.ts 在 ITER-006 中进一步把错误数量、错误码和具体消息写进日志。例如多个地址错误同时出现时,日志不再只显示"存在几个错误",而是逐条列出 ADDRESS_OVERLAPRANGE_OUT_OF_FLASH 等错误内容。

三、技术选型与环境说明

原始技术建议中出现过 Tauri + Vue + Rust、C# WPF 等桌面端方案,但实际落地时根据本机工具链和交付成本选择了 Vite + React + TypeScript。这个选择牺牲了原生文件系统能力,换来了更低的首版实现成本和更直接的构建交付方式。

层次 技术/框架 版本或配置 选型依据
前端框架 React ^19.2.3 单页工作台状态和组件拆分足够直接
构建工具 Vite ^7.3.0 静态构建产物小,预览和打包流程简单
语言 TypeScript ^5.9.3 地址、文件、校验结果和合并结果需要明确类型边界
图标 lucide-react ^0.561.0 用于按钮和状态提示
测试 Vitest ^4.0.16 覆盖解析、校验、合并、导出、报告和日志格式
后端 不适用 文件只在浏览器本地处理
数据库 不适用 当前没有持久化工程或历史记录

vite.config.ts 中的 build.outDir 指向 ../编译产物/mcu-firmware-merge-tool,说明构建结果是静态文件目录,而不是可执行安装包。package.json 的脚本也很克制:typecheck 执行 tsc --noEmittest 执行 Vitest,build 先做类型检查再运行 Vite 构建。

四、系统整体架构设计

当前架构不是前后端分离系统,而是一个"页面工作台 + 纯函数核心模块 + 浏览器文件能力"的本地工具。UI 只负责用户交互和状态编排,固件解析、地址校验、合并、导出和报告生成都沉淀在 src/lib 下,后续如果封装 Tauri/Electron,核心模块仍有复用空间。
用户
React 单页工作台 App.tsx
浏览器 File API 读取本地文件
parsers.ts 格式识别与解析
AddressSegment 统一地址段
address.ts 项目配置与冲突校验
logMessages.ts 检查日志
addressMap.ts Flash 分布展示模型
merge.ts 合并引擎
exporters.ts BIN/HEX/S-record 输出
report.ts TXT 报告
Blob URL 下载固件
Blob URL 下载报告

架构层 主要职责 典型文件 设计要点
表现层 配置表单、导入区、文件表格、地址分布、日志和下载按钮 src/App.tsxsrc/App.css 所有变更通过 markDirty 让检查结果失效
解析层 文件格式识别,BIN/HEX/S19 解析,CRC16 计算 src/lib/parsers.tssrc/lib/crc.ts 输出统一的 AddressSegment[]
校验层 Flash 配置解析、越界检查、重叠检查、性能警告 src/lib/address.ts 合并前必须通过 validateProject
合并层 创建输出镜像、填充空洞、写入固件段、生成合并 CRC16 src/lib/merge.ts 内部使用 Uint8Array
输出层 生成 BIN/HEX/S19/SREC/MOT 和 TXT 报告 src/lib/exporters.tssrc/lib/report.ts SREC/MOT 复用 S-record 编码
测试层 核心算法和回归用例 src/lib/firmware.test.ts 覆盖最终 11 个测试

五、项目目录结构解析

正式源码目录集中在 02_完整源代码,结构很小,但职责边界比较清楚:

text 复制代码
02_完整源代码/
├─ package.json
├─ package-lock.json
├─ tsconfig.json
├─ vite.config.ts
├─ index.html
└─ src/
   ├─ main.tsx
   ├─ App.tsx
   ├─ App.css
   ├─ index.css
   └─ lib/
      ├─ types.ts
      ├─ parsers.ts
      ├─ address.ts
      ├─ merge.ts
      ├─ exporters.ts
      ├─ report.ts
      ├─ crc.ts
      ├─ addressMap.ts
      ├─ logMessages.ts
      └─ firmware.test.ts

这套目录没有 apirouterstoreserversql 等常见业务系统目录。核心原因是当前工具没有路由页面、没有远程接口、没有数据库。App.tsx 承担页面编排和状态机角色,src/lib 承担所有可测试的领域逻辑。测试文件也放在 lib 下,说明测试重点不是组件快照,而是固件解析、地址校验、合并和输出这些不会随 UI 文案频繁变化的规则。

六、核心业务模块与流程设计

6.1 文件解析模块:把不同格式压成统一地址段

src/lib/parsers.ts 是固件输入的第一道边界。detectFormat(fileName, bytes) 先按扩展名识别 .bin/.hex/.s19/.srec/.mot,扩展名不可靠时再读取文件开头判断 :S[0-9]。这一层没有直接进入合并逻辑,而是返回 FirmwareFile 上的 segmentsvalidDataSizecrc16statusissues

BIN 的处理最简单,也最容易出错:它没有内部地址,必须由用户填写起始地址。parseBinstartAddressInput 为空或格式错误时返回 needs-address,并写入 BIN_START_REQUIRED。这正好对应需求中的"BIN 文件必须由用户指定起始地址"。

HEX 和 S19 的复杂度主要在记录校验。parseIntelHex 处理数据记录、EOF、扩展段地址和扩展线性地址,并检查每行 checksum;parseSrec 处理 S1/S2/S3 数据记录和 S7/S8/S9 结束记录,同样检查 count 和 checksum。两个解析器最终都调用 compactSegments 合并同一文件内连续地址段,再用 concatSegmentBytes 计算单文件 CRC16。

6.2 地址校验模块:所有错误先变成 issue

src/lib/address.ts 把地址相关规则集中处理。parseAddress 支持 0x 十六进制和十进制,并限制在 32 位地址范围;parseByte 进一步把填充值限制在 0x00 - 0xFFparseProjectConfigFlash 起始地址 + Flash 大小 - 1 计算 Flash 结束地址。

validateProject 的价值在于统一产出 ValidationIssue,而不是让 UI 在不同分支里散落错误判断。它会按顺序检查项目配置、启用文件、文件自身解析 issue、Flash 越界、大 Flash 警告和地址重叠。重叠检查时会根据 conflictPolicy 决定 issue 等级:禁止覆盖时是 error,允许后者覆盖前者时是 warning,报告仍会记录冲突区间。

6.3 合并引擎模块:先填充,再按绝对地址写入

合并核心在 src/lib/merge.ts。它不再关心输入来自 BIN、HEX 还是 S19,只消费已经通过解析和校验的 AddressSegment。输出范围由 ProjectConfig.outputRange 控制:flash 表示完整 Flash,used 表示有效数据覆盖区。

ts 复制代码
export function mergeFirmware(config: ProjectConfig, files: FirmwareFile[], validation?: ValidationResult): MergeResult {
  const parsedConfig = parseProjectConfig(config);
  const validationResult = validation ?? validateProject(config, files);
  if (validationResult.hasErrors) {
    const firstError = validationResult.issues.find((issue) => issue.level === 'error');
    throw new Error(firstError?.message ?? '配置检查未通过,无法合并');
  }

  const segments = files.filter((file) => file.enabled).flatMap((file) => file.segments);
  const usedStart = Math.min(...segments.map((segment) => segment.start));
  const usedEnd = Math.max(...segments.map((segment) => segment.end));
  const outputStart = parsedConfig.outputRange === 'flash' ? parsedConfig.flashStart : usedStart;
  const outputEnd = parsedConfig.outputRange === 'flash' ? parsedConfig.flashEnd : usedEnd;

  const image = new Uint8Array(outputEnd - outputStart + 1);
  image.fill(parsedConfig.fillValue);

  for (const segment of segments) {
    const offset = segment.start - outputStart;
    image.set(segment.bytes, offset);
  }

  return {
    image,
    start: outputStart,
    end: outputEnd,
    segments,
    issues: validationResult.issues,
    outputName: buildOutputName(parsedConfig.outputFormat),
    createdAt: new Date().toISOString(),
    crc16: calculateCrc16Ccitt(image)
  };
}

这段逻辑体现了当前项目最核心的工程判断:合并结果不是把文件简单拼接,而是先建立连续地址空间,再按绝对地址写入每个数据段。空洞区域由 fillValue 填充,默认是 0xFF。如果选择完整 Flash 输出,镜像会覆盖 flashStartflashEnd;如果选择有效范围输出,则只覆盖已启用固件段的最小到最大地址。

这里的关键点是,mergeFirmware 只是消费 validation,并不会重新实现一套重叠策略。默认禁止覆盖的情况下,重叠会在校验阶段阻断合并;允许覆盖时,Uint8Array.set 的写入顺序会让后处理的段覆盖前面的段,冲突记录仍保留在 issues 中。

6.4 地址分布模块:展示模型不能等同底层记录段

地址分布在迭代中暴露过一个典型 UI 建模问题:HEX/S19 文件内部可能有多个非连续记录段,如果直接按底层 segments 显示空洞,同一个 Boot 文件内部的记录间隙会被误标成 0xFF 填充。ITER-005 将展示层独立成 src/lib/addressMap.ts,先用 buildFirmwareMapRanges(files) 按文件聚合视觉范围,再用 buildInterFirmwareFillRanges 只计算不同固件文件之间的填充区。

这个修正保留了两个事实:合并算法仍按底层地址段工作,保证输出数据精确;UI 地址分布按文件整体范围展示,避免把同一固件内部的稀疏记录解释成文件间空洞。firmware.test.ts 中的稀疏 Boot S19 场景用例,就是为这个回归风险补上的测试。

七、数据模型与持久化边界

当前项目没有数据库,数据模型全部是 TypeScript 类型和浏览器内存状态。src/lib/types.ts 是理解系统的入口。

对象 关键字段 说明
ProjectConfig flashStartflashSizeKbfillValueoutputFormatoutputRangeconflictPolicy 用户在项目配置区维护的合并规则
FirmwareFile nameformatroleenabledrawBytesstartAddressInputoffsetInputsegmentsstatuscrc16 页面文件表格和解析结果的统一载体
AddressSegment fileIdfileNamerolestartendbytes 合并引擎真正消费的数据结构
ValidationIssue levelcodemessagefileIdsstartend 校验、日志、状态徽标和报告共用的错误模型
MergeResult imagestartendsegmentsissuesoutputNamecrc16 合并完成后的下载和报告输入

App.tsx 通过 useState 保存 configfilesstatusvalidationfirmwareArtifacttextReportmergedCrc16logs。这意味着页面刷新后工程状态会丢失,当前版本也没有实现项目保存/加载。这个边界符合最终交付说明中的"不包含内容",不是遗漏的后端能力。

八、交互入口与模块协作

没有 HTTP 接口时,前后端协作章节需要换一种写法。这个项目的"接口"是 UI 事件和 src/lib 纯函数之间的调用约定。

用户动作 App.tsx 入口 核心模块 结果
点击或拖拽导入文件 addFileshandleFileChangehandleDrop createFirmwareFiledetectFormat 新增 FirmwareFile,状态变为 dirty
修改 Flash 或文件配置 updateConfigupdateFile 暂不调用核心算法 清空旧校验、旧下载和旧 CRC16
检查配置 checkConfig parseFirmwareFilevalidateProjectbuildTextReport 状态进入 blockedready
开始合并 startMerge mergeFirmwarebuildFirmwareArtifactbuildTextReport 状态进入 done,生成下载对象
下载固件或报告 downloadArtifactdownloadTextReport artifactToBlob 浏览器触发下载

这种边界的好处是核心逻辑不依赖 React DOM。解析器、校验器、合并器、导出器和报告生成器都可以在 Vitest 中直接调用,这也是当前测试能覆盖核心算法而不需要浏览器自动化的原因。

九、关键技术点与实现难点

9.1 HEX/S19 校验不是格式识别那么简单

格式识别只解决"用哪个解析器"的问题,不能保证文件内容可靠。Intel HEX 每行都需要检查记录长度、记录类型、地址、数据和校验和;Motorola S-record 还要检查 count 字段和结束记录。parseIntelHex 对缺少 EOF 的文件直接报错,parseSrec 对缺少 S7/S8/S9 结束记录也会报错。这样做会让部分非标准文件更早暴露,但换来的是合并前的确定性。

9.2 地址冲突策略要同时影响校验和报告

需求允许"默认禁止覆盖,也可允许后面的文件覆盖前面的文件"。代码没有把覆盖策略藏在合并阶段,而是在 validateProject 中把重叠 issue 标成 error 或 warning。这样 UI、日志、报告和合并按钮能共享同一个判断结果:error 阻断合并,warning 允许合并但保留记录。

9.3 CRC16 是交付口径,不是泛化校验框架

当前 CRC16 采用 CRC-16/CCITT-FALSE:初值 0xFFFF,多项式 0x1021src/lib/crc.ts 提供 calculateCrc16CcittformatCrc16,单文件 CRC16 在解析后计算,合并文件 CRC16 在 mergeFirmware 生成完整镜像后计算。最终交付说明也明确了这个变体假设,避免和其他工具的 CRC16 口径混淆。

9.4 日志明细直接影响排障效率

ITER-006 的修改看似只是文案,但它改善的是排障链路。buildValidationFailureLog 会筛出 error,并输出"错误编号 + 错误码 + 消息";buildValidationWarningLog 同样处理 warning。对于地址冲突、越界、无启用文件这类可能同时出现的问题,用户不需要逐行点开表格才能知道哪里失败。

十、安全性、性能与稳定性设计

安全方面,当前工具只处理用户主动选择的本地文件,不上传、不执行固件内容,也没有远程 API。页脚外部链接使用 target="_blank"rel="noreferrer"。由于没有后端和数据库,传统的认证、授权、SQL 注入、会话管理在当前版本不适用。

性能方面,合并阶段使用 Uint8Array 创建连续镜像,典型 2 MB Flash 可以在浏览器内完成。validateProject 在 Flash 大小超过 16 MB 时会返回 FLASH_SIZE_LARGE warning,提醒用户浏览器内存占用可能较高。地址分布图也没有逐字节渲染,而是渲染固件段和填充区摘要。

稳定性主要靠三层防线:解析阶段阻断格式错误,校验阶段阻断越界和默认冲突,合并阶段再次检查输出范围。UI 上任何配置、地址、文件启用状态变化都会调用 markDirty,清空旧的校验结果、下载对象、报告和合并 CRC16,避免用户拿旧结果继续操作。

十一、工程化实践与开发规范

项目的工程化重点不在大型框架,而在边界清楚和可验证。

工程措施 证据 作用
TypeScript 严格模式 tsconfig.jsonstrict: truenoEmit: true 避免地址、文件状态和输出类型混用
构建前类型检查 package.jsonbuild: tsc --noEmit && vite build 构建产物前先阻断类型错误
纯函数核心模块 src/lib/*.ts 解析、校验、合并、导出可脱离 UI 测试
依赖审计 交付记录中 npm.cmd audit --audit-level=moderate 通过 控制前端依赖风险
单元测试防回归 src/lib/firmware.test.ts 覆盖解析、重叠、填充、CRC16、输出编码、报告、地址分布和日志

在 Windows PowerShell 环境中,资料记录了一个实际约束:直接执行 npm.ps1 会受策略限制,因此命令统一使用 npm.cmd。这不是业务功能,但会影响交付后的复现路径,最终运行说明也采用了 npm.cmd installnpm.cmd run typechecknpm.cmd test -- --runnpm.cmd run buildnpm.cmd run preview -- --port 4173

十二、项目运行、部署与发布

本地源码运行方式:

powershell 复制代码
npm.cmd install
npm.cmd run typecheck
npm.cmd test -- --run
npm.cmd run build
npm.cmd run preview -- --port 4173

访问地址:

text 复制代码
http://127.0.0.1:4173

正式构建产物位于 03_正式构建产物/mcu-firmware-merge-tool/,包含 index.html、构建后的 CSS 和 JS 文件。由于产物是静态浏览器应用,部署方式可以是本地静态服务、Vite preview,或后续再封装进桌面壳。当前版本不能承诺"直接打开输出目录",下载行为受浏览器策略控制。

十三、测试策略与质量保障

测试重点放在最容易影响固件正确性的核心算法上,而不是只验证页面是否渲染。

测试场景 覆盖点 证据
Intel HEX 解析 扩展线性地址、checksum、EOF parses Intel HEX with extended linear address and checksum
S-record 解析 S3 数据、结束记录、checksum parses Motorola S-record S3 data
BIN 地址缺失 BIN_START_REQUIRED requires a start address for BIN files
地址重叠 ADDRESS_OVERLAP detects overlapping enabled files
空洞填充 非连续文件合并后填充 0xFF merges non-contiguous files and fills gaps
CRC16 CRC-16/CCITT-FALSE 标准样例 123456789 -> 29B1
输出编码 Intel HEX 和 S-record 输出格式 encodes merged output as HEX and S-record aliases
报告 输入文件、CRC16、合并结果 builds a traceable text report
地址分布 同一固件稀疏记录聚合 groups sparse records from the same firmware before showing fill ranges
日志 多错误、多警告明细 includes concrete validation error contents in failure logs

最终交付记录显示,ITER-006 后 npm.cmd test -- --run 通过 1 个测试文件、11 个测试;npm.cmd run typechecknpm.cmd run buildnpm.cmd audit --audit-level=moderate 均通过。本地浏览器预览检查覆盖了页面标题、日志区、地址分布空态、作者信息和控制台错误 0。

剩余风险也比较明确:没有使用客户真实固件在浏览器中做完整上传下载回归;S19/HEX 厂商私有扩展记录可能需要后续样本驱动迭代;超大 Flash 场景目前是 warning 提醒,还没有分段输出实现。

十四、源码阅读路径建议

阅读这个项目可以按业务链路走,而不是从 CSS 或入口文件平均展开:
package.json / vite.config.ts
types.ts
parsers.ts
address.ts
merge.ts
exporters.ts / report.ts
App.tsx
firmware.test.ts

先看 types.ts,能快速建立 FirmwareFileAddressSegmentProjectConfigValidationIssueMergeResult 的关系。然后读 parsers.ts,理解不同格式如何被压成统一地址段。再看 address.tsmerge.ts,主流程就完整了。exporters.tsreport.ts 负责交付物格式,最后回到 App.tsx 看这些纯函数如何被 UI 状态机串起来。

十五、架构演进方向

当前版本已经完成本地浏览器合并闭环,但它不是一个"全功能生产线工具"。后续演进可以按业务价值拆分,而不是一次性堆满增强功能。

方向 可做内容 前置条件
桌面封装 Tauri/Electron,支持原生保存路径、打开输出目录 明确目标平台和安装包要求
项目配置管理 保存/加载工程、最近项目、配置模板 设计本地存储或工程文件格式
芯片模板库 STM32/NXP/GD32 常用 Flash 范围模板 收集真实芯片族参数
生产线能力 命令行批量合并、固定配置运行 把核心模块包装成 CLI
安全增强 固件签名、加密、CRC 自动追加 明确算法、密钥管理和烧录端验证方式
大文件优化 分段输出、Web Worker、进度反馈 获取大 Flash 或多文件压力样本

比较适合优先推进的是"桌面封装"和"项目配置管理"。前者补齐浏览器静态工具的文件系统限制,后者能提升研发和生产人员反复合并同一项目时的效率。

十六、常见问题与排障路径



BIN_START_REQUIRED
RANGE_OUT_OF_FLASH
ADDRESS_OVERLAP
CONFIG_INVALID


无法合并
是否已通过配置检查
查看日志中的错误码和文件状态
下载是否失败
错误码类型
为 BIN 文件填写起始地址
调整 Flash 范围或文件地址
调整地址、禁用文件或改为允许覆盖
检查 Flash 起始地址、大小和填充值
更换浏览器或重新触发下载
检查报告中的输出范围和 CRC16

遇到格式错误时,优先确认文件扩展名和内容是否匹配。HEX 文件应包含 EOF 记录,S-record 文件应包含结束记录;如果厂商工具生成了私有扩展记录,当前解析器可能需要按真实样本扩展。遇到地址分布和预期不一致时,要区分"底层记录段"和"文件级展示范围":合并算法按记录段精确写入,地址分布按导入文件聚合展示。

十七、收口判断

这个项目的价值不在于界面复杂,而在于把固件合并中最容易出错的几件事前置校验:格式是否可信、地址是否明确、Flash 是否越界、文件是否重叠、输出是否可追溯。src/lib/parsers.tssrc/lib/address.tssrc/lib/merge.ts 构成了主业务链路,src/lib/report.tssrc/lib/addressMap.tssrc/lib/logMessages.ts 则把结果解释给用户。

当前版本适合交付为轻量本地工具,用于研发、生产或售后在浏览器中完成单次固件合并和报告留档。它的边界同样清楚:没有原生安装包,没有后端服务,没有数据库持久化,也没有自动烧录和命令行批量模式。把这些边界写清楚,反而能让后续迭代更准确地围绕真实缺口推进。

相关推荐
qq_370773092 小时前
OpenOCD 嵌入式调试完全指南:从零开始调试 GD32/STM32 单片机
stm32·单片机·嵌入式硬件·openocd
LCG元2 小时前
STM32实战:基于STM32F103的迷迭香智慧种植系统(自动补光+滴灌)
stm32·单片机·嵌入式硬件
SDAU200511 小时前
CH32V103C8T6的时钟操作
单片机·嵌入式硬件
不做无法实现的梦~11 小时前
SBUS 接收机到 STM32:为什么要做硬件反相、如何解析数据、如何接线与实现代码
stm32·单片机·嵌入式硬件
一路往蓝-Anbo12 小时前
第二章:隔离硬件 —— 利用 CMock 伪造 GPIO 与定时器
stm32·单片机·嵌入式硬件·软件工程·信息与通信·tdd
刘延林.13 小时前
esp32 s3+micpython快速验证ML307R 是否能正常连接4G
单片机·嵌入式硬件
不做无法实现的梦~18 小时前
86步进电机和DM860H驱动器的使用方法和记录
单片机·嵌入式硬件
Aaron158819 小时前
RFSOC+VU13P/VU9P+GPU多通道同步一体化解决方案
人工智能·嵌入式硬件·算法·matlab·fpga开发·硬件架构·基带工程
所见即所得1111119 小时前
stm32烧录过程中串口问题(串口被占用无法使用)
stm32·单片机·嵌入式硬件