修改STM32CubeMX生成文件:在VSCode中安全调整Inc与Src的实践指南
1. 为什么 STM32CubeMX 重新生成后我的代码全没了如果你用 STM32CubeMX 生成过工程大概率经历过这个瞬间在 VSCode 里吭哧吭哧改了半天Inc和Src里的文件加了自己的业务逻辑、改了注释、调了初始化顺序结果回到 CubeMX 点了一下 GENERATE CODE再切回 VSCode 一看——改动全被覆盖了只剩下一堆英文注释和默认的/* USER CODE BEGIN */空壳。这个问题的根源在于STM32CubeMX 生成的工程是模板驱动的。它把每个文件分成两类区域——一类是它自己管理的、每次生成都会重写的部分比如外设初始化、时钟配置、中断向量表另一类是通过USER CODE BEGIN xxx/USER CODE END xxx标记出来的、它承诺不会动的部分。你只要把代码写在标记之间重新生成时就能保住写在标记外面下次生成必然被冲掉。但现实情况往往更复杂。有时候你想改的是main.c里MX_GPIO_Init()的调用顺序有时候你想在stm32f1xx_it.c里加一个自定义中断处理有时候你甚至想改Inc目录下某个头文件的宏定义。这些位置不一定都有现成的 USER CODE 区硬改又怕丢。所以真正要解决的问题不是能不能改而是怎么改才能既满足需求又不被 CubeMX 覆盖。这篇内容就是围绕这个场景展开的。我会把整个流程拆成可复制的步骤先讲清楚 CubeMX 的代码生成规则和.ioc文件里哪些配置项会影响生成行为再给出在 VSCode 中安全修改Inc与Src的具体做法包括 USER CODE 区的标注规范、自定义文件的挂载方式、以及重新生成后用 diff 验证改动是否保留的完整动作。适合正在用 STM32CubeMX VSCode 做嵌入式开发、被重新生成丢代码困扰的读者。下面直接进入操作。2. 动手前先把 TaoToken 的接入配置准备好在正式改代码之前我想先花点篇幅说一个容易被忽略的前置环节如果你在开发过程中需要调用大模型来辅助理解 CubeMX 生成的英文注释、生成外设驱动片段、或者排查编译报错那么一个稳定的 API 接入点是很有必要的。我自己的做法是在 VSCode 里装 Continue 或 Cline 这类插件把模型请求指向 TaoToken 的接口这样在改Inc/Src的时候遇到看不懂的寄存器配置可以直接在编辑器里问。TaoToken 的官网入口是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基址是 https://taotoken.net/api 。注意 API 地址后面不加 UTM 参数直接用它作为 Base URL 就行。下面给出在 VSCode 插件里配置的完整片段你可以直接复制。以 Continue 插件的config.json为例配置结构如下{ models: [ { title: TaoToken, provider: openai, model: claude-sonnet-4-20250514, apiBase: https://taotoken.net/api, apiKey: sk-你的Key } ] }如果你用的是 Cline配置项名称略有不同但核心三件套是一样的Base URL 填https://taotoken.net/apiAPI Key 填你在控制台生成的密钥Model ID 填你要用的模型标识。Cline 的 settings 片段大致长这样{ cline.apiProvider: openai, cline.openAiBaseUrl: https://taotoken.net/api, cline.openAiApiKey: sk-你的Key, cline.openAiModelId: claude-sonnet-4-20250514 }这里要强调一点Base URL、Key、Model ID 这三样必须同时正确缺一个都会报 401 或者 model not found。我见过不少人只填了 Base URL 和 KeyModel ID 留空或者填了个不存在的名字结果请求一直失败还以为是网络问题。实际上错误信息里会明确写invalid model或者model not found对着改就行。Key 的获取路径是登录后在控制台的 API Keys 页面生成地址是 https://taotoken.net/console/api-keys 。生成后复制保存因为它只显示一次。如果你需要看更详细的接入说明文档入口在 https://taotoken.net/doc 。配置好之后你可以在 VSCode 里新建一个测试文件写一段简单的请求代码验证连通性。比如用 Python 快速测一下import requests url https://taotoken.net/api/v1/chat/completions headers { Authorization: Bearer sk-你的Key, Content-Type: application/json } data { model: claude-sonnet-4-20250514, messages: [{role: user, content: 回复ok}] } resp requests.post(url, headersheaders, jsondata, timeout30) print(resp.status_code) print(resp.json())如果返回 200 并且内容里有正常的回复说明接入没问题。这一步做完后面改代码时遇到不懂的地方就能随时在编辑器里问效率会高很多。如果你更习惯用对话界面来验证模型是否可用也可以直接打开 https://taotoken.net/models 在网页里试一句。3. 在 VSCode 中安全修改 Inc 与 Src 的完整配置现在进入正题。STM32CubeMX 生成的工程目录结构通常是这样的根目录下有.ioc文件、Core/Inc、Core/Src、Drivers等文件夹。Inc放头文件Src放源文件。你要改的东西基本都在这两个目录里。第一步先理解 USER CODE 区的规则。CubeMX 在每个它管理的文件里都插入了成对的标记格式是/* USER CODE BEGIN 区域名 */ // 你写在这里的代码不会被覆盖 /* USER CODE END 区域名 */常见的区域名有Includes、PV私有变量、PFP私有函数原型、0、1、2、3、4、WHILE、MX_GPIO_Init等。你只要把代码写在BEGIN和END之间重新生成时 CubeMX 会原样保留。这是最基础也最可靠的做法。但有些需求没法靠 USER CODE 区满足。比如你想在main.c的MX_GPIO_Init()函数内部、在某个HAL_GPIO_Init()调用之前插入一行代码而那个位置没有 USER CODE 标记。这时候硬插进去下次生成就没了。解决办法有两个一是把这段逻辑挪到main()的 USER CODE 区里在MX_GPIO_Init()调用之后手动补上二是把整个初始化函数复制一份到自己的文件里在 USER CODE 区调用自己的版本。我更推荐第二种做法因为它更干净。具体操作是在Src目录下新建一个my_gpio.c在Inc目录下新建my_gpio.h把需要自定义的初始化逻辑写进去。然后在main.c的 USER CODE 区里 include 这个头文件并调用。这样 CubeMX 重新生成时它只会重写main.c里它自己的部分你的my_gpio.c和my_gpio.h完全不受影响。但这里有个坑CubeMX 重新生成时它可能会根据.ioc里的配置重新扫描Src目录如果你新建的文件没有被正确挂载编译时可能找不到。解决办法是在.ioc文件里做两件事。第一确保你的自定义文件放在 CubeMX 认识的目录下通常是Core/Src和Core/Inc。第二在.ioc里找到ProjectManager.UnderRoot这个配置项确认它是true这样生成的文件会放在工程根目录下路径不会乱。.ioc文件里还有几个关键配置项会影响生成行为我列个表对照一下配置项作用推荐值ProjectManager.UnderRoot生成文件是否放在工程根目录trueProjectManager.CoupleFile是否把外设初始化拆到独立文件falseProjectManager.KeepUserCode是否保留 USER CODE 区内容trueProjectManager.GenerateUnderRoot生成路径是否在根目录true其中KeepUserCode必须为true否则 USER CODE 区也会被清空。这个值默认就是 true但如果你手动改过.ioc要确认一下。另外如果你在 VSCode 里用 C/C 插件做代码跳转需要在c_cpp_properties.json里把Inc目录加进includePath否则头文件会标红。配置片段如下{ configurations: [ { name: STM32, includePath: [ ${workspaceFolder}/Core/Inc, ${workspaceFolder}/Drivers/STM32F1xx_HAL_Driver/Inc, ${workspaceFolder}/Drivers/CMSIS/Include ], defines: [USE_HAL_DRIVER, STM32F103xB], compilerPath: arm-none-eabi-gcc } ], version: 4 }把这段写进.vscode/c_cpp_properties.jsonVSCode 就能正确识别Inc里的头文件跳转和补全都会正常。注意defines里的芯片型号要和你实际用的保持一致否则 HAL 库的条件编译会走错分支。4. 重新生成后如何验证改动是否保留改完代码、配置好.ioc接下来最关键的一步是验证。很多人改完就直接编译结果发现行为不对回头查半天才发现是某处改动被覆盖了。正确的做法是在重新生成前后做一次 diff 对比。具体操作在 VSCode 里打开终端用git管理你的工程。如果你还没初始化仓库先执行cd 你的工程目录 git init git add . git commit -m before regenerate然后在 CubeMX 里点 GENERATE CODE回到 VSCode 终端执行git diff --stat这个命令会列出所有被修改的文件和改动行数。如果某个你改过的文件出现在列表里说明它被 CubeMX 重写了。这时候用git diff 文件名看具体改了什么确认你的 USER CODE 区内容是否还在。更精细的做法是用git diff配合--word-diff参数这样能看到具体哪些词被改了git diff --word-diff Core/Src/main.c如果发现 USER CODE 区的内容丢了检查.ioc里的KeepUserCode是否为 true。如果发现自定义文件被删了检查文件是否放在Core/Src下、以及.ioc里的路径配置是否正确。还有一种情况CubeMX 重新生成后Inc目录下某个头文件的宏定义被改了。比如你在main.h里加了个#define MY_FLAG 1结果生成后没了。这是因为main.h的宏定义区也有 USER CODE 标记你要把宏定义写在/* USER CODE BEGIN EM */和/* USER CODE END EM */之间。如果那个位置没有标记就把宏定义挪到自己的头文件里在main.h的 USER CODE 区 include 进来。验证通过后再执行一次提交git add . git commit -m after regenerate, user code kept这样你就有了一个可回溯的记录。下次再改代码重复这个流程就行。实测下来这套 diff 验证动作能挡住 90% 以上的改动丢失问题剩下的 10% 基本是.ioc配置项写错了对着表格改一下就好。5. 常见报错与排查401、local proxy failed、reading choices在配置和使用过程中有几个报错出现的频率特别高我逐个说一下排查思路。第一个是401 Unauthorized。这个基本就是 Key 的问题。可能的原因有三个Key 复制时多了空格、Key 已经过期或被删除、请求头里的Authorization格式写错了。正确的格式是Bearer sk-xxx注意Bearer和 Key 之间有一个空格。如果你用的是 Cline 或 Continue检查配置里的apiKey字段是否完整。排查方法是用 curl 直接测curl -X POST https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer sk-你的Key \ -H Content-Type: application/json \ -d {model:claude-sonnet-4-20250514,messages:[{role:user,content:hi}]}如果 curl 返回 200说明 Key 没问题是插件配置的问题如果 curl 也返回 401那就是 Key 本身的问题去控制台重新生成一个。第二个是local proxy failed或类似的连接错误。这个通常出现在你本地配了代理、但代理没有正确处理 API 请求的情况下。排查方法是先确认你的网络能直接访问https://taotoken.net/api可以用curl -I https://taotoken.net/api看返回头。如果返回 200 或 401说明网络通如果超时检查本地代理设置。注意不要在插件里同时配代理和直连二选一即可。第三个是reading choices相关的报错完整信息可能是cannot read property choices of undefined或者reading 0。这个说明请求发出去了但返回的 JSON 结构里没有choices字段。常见原因是 Model ID 填错了服务端返回了一个错误对象而不是正常的 completion 结果。解决办法是打印完整的响应体看error字段里写了什么。如果是model not found换成正确的 Model ID如果是invalid request检查messages数组的格式。第四个是 OAuth 相关的报错比如OAuth token expired或invalid_grant。如果你用的是 Claude Code 这类工具它可能走的是 OAuth 流程而不是 API Key。这时候需要重新走一遍授权或者在配置里改用 API Key 模式。Claude Code 的配置入口在 https://taotoken.net/claudecode 里面有详细的接入说明。如果你需要长期做编码和 Agent 任务也可以看看 Coding Plan 的方案地址是 https://taotoken.net/coding-plan 。排查的时候记住一个原则先看报错信息里的关键词再对照上面的分类定位。401 看 Key连接错误看网络choices 看 Model IDOAuth 看授权方式。大部分问题都能在几分钟内解决。6. 把流程固化下来让每次生成都可控最后说一个我自己的习惯把整个改代码—重新生成—验证的流程写成一个脚本放在工程根目录下。脚本内容很简单就是 git 提交、调用 CubeMX 命令行生成、再 git diff。这样每次改完代码跑一下脚本就知道有没有丢东西。CubeMX 支持命令行生成命令格式是STM32CubeMX -q 你的工程.ioc-q表示静默模式生成完自动退出。你可以把这个命令和 git 操作串起来#!/bin/bash git add . git commit -m before regen STM32CubeMX -q project.ioc git diff --stat跑完看 diff 输出如果只有 CubeMX 自己管理的文件在变USER CODE 区和自定义文件都没动那就说明配置是对的。如果发现异常git checkout .回滚改完.ioc再试。这套流程跑顺之后你就不用再怕点 GENERATE CODE 了。Inc 和 Src 里的改动该保留的保留该覆盖的覆盖边界清晰。遇到需要临时改 CubeMX 管理区域的情况就把它挪到 USER CODE 区或者自定义文件里别硬改。时间长了你会发现真正需要硬改的场景其实很少大部分需求都能通过合理的文件组织解决。

相关新闻

氢燃料储能技术实战:破解可再生能源间歇性的系统架构与运维指南

氢燃料储能技术实战:破解可再生能源间歇性的系统架构与运维指南

做新能源项目这几年,我越来越觉得“间歇性”这三个字是躲不开的:风一停、太阳一落山,出力曲线说断就断,电网调度看到风光场站的功率预报都得先深吸一口气。很多人跑来问我,氢燃料储能技术到底能不能把可再生能源这个“…

2026/10/9 5:23:28 阅读更多 →
【Jetpack Compose基础语法学与练】第8课 rememberSaveable,页面旋转/系统重建保留状态

【Jetpack Compose基础语法学与练】第8课 rememberSaveable,页面旋转/系统重建保留状态

前言 上一课学习了 if 条件渲染和 LazyColumn 懒加载列表,掌握动态UI与长列表渲染。 我们一直用 remember 保存状态,但它有一个致命缺陷:手机旋转屏幕、系统因内存不足重建Activity时,remember保存的数据会全部丢失,重…

2026/10/9 5:23:28 阅读更多 →
深入解析 Pod_ContainerCreating 云盘挂载超时或冲突:基于 chaosblade 技能库的 K8s 故障演练实战指南

深入解析 Pod_ContainerCreating 云盘挂载超时或冲突:基于 chaosblade 技能库的 K8s 故障演练实战指南

运维云原生SREAI Agent人工智能 【免费下载链接】chaosblade An easy to use and powerful chaos engineering experiment toolkit.(阿里巴巴开源的一款简单易用、功能强大的混沌实验注入工具) 项目地址: https://gitcode.com/gh_mirrors/ch/…

2026/10/9 5:22:27 阅读更多 →

最新新闻

洛谷P5732杨辉三角:二维数组递推、组合数陷阱与DP思维启蒙

洛谷P5732杨辉三角:二维数组递推、组合数陷阱与DP思维启蒙

1. 从一道入门题说起:为什么所有算法新手都绕不开杨辉三角洛谷P5732,题目全称是【深基5.习7】杨辉三角,属于洛谷"深入基础"系列第五章的练习题。这个系列是给刚学完语法、开始接触算法的人准备的,题目本身不难&#xff…

2026/10/9 5:53:55 阅读更多 →
网络排查不再靠感觉:掌握延迟丢包与DNS判断标准

网络排查不再靠感觉:掌握延迟丢包与DNS判断标准

干这行久了你会发现一个很残酷的事实:大家排查网络问题的时候,命令都会敲,工具都会用,但真正到了"判断结果"这一步,很多人是靠感觉的。ping一下网关通着,就觉得网络没事;tracert看到星…

2026/10/9 5:53:55 阅读更多 →
SpringBoot日志追踪实战:用MDC+拦截器实现全链路TraceId

SpringBoot日志追踪实战:用MDC+拦截器实现全链路TraceId

1. 从一次线上事故说起:为什么日志追踪非做不可今年年初我接手了一个“老带新”的SpringBoot电商项目,四个服务互相调用,平时开发联调问题不大,一上生产就乱了套。有一次商品库存扣减异常,用户反馈“明明支付成功但订单…

2026/10/9 5:53:55 阅读更多 →
MySQL、Redis、MQ、ES高可用方案选型与避坑实战

MySQL、Redis、MQ、ES高可用方案选型与避坑实战

1. 高可用不是“装个集群”就完事:四个组件的选型逻辑先理清很多人一提高可用,脑子里第一反应就是“上集群”。MySQL 搞个主从、Redis 弄个哨兵、MQ 搭个镜像队列、ES 配个副本分片,然后觉得万事大吉。我早期也这么干过,结果一次机…

2026/10/9 5:53:55 阅读更多 →
ASCII与Unicode编码详解:从原理到乱码排查实战

ASCII与Unicode编码详解:从原理到乱码排查实战

字符编码这东西,平时写代码时几乎感觉不到它的存在,可一旦出问题,那真是让人抓耳挠腮。乱码、问号、方块字、emoji显示成两个问号,这些场景我相信每个开发者都遇到过。我自己印象最深的一次,是帮朋友处理一个批量导入的…

2026/10/9 5:53:55 阅读更多 →
PS5折腾指南:Mesh Shader、DualSense驱动与双机端口转发解析

PS5折腾指南:Mesh Shader、DualSense驱动与双机端口转发解析

最近后台和社群里不少朋友都在搜 PS5 相关的折腾问题,从 GPU 架构、手柄驱动到路由器端口转发都有人问,而且问得越来越细。说实话,PS5 已经发售了这么多年,但真正把硬件规格、外设兼容、网络配置这几块讲透的内容反而不多——大部…

2026/10/9 5:52:54 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 10:10:36 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 13:34:55 阅读更多 →