news 2026/7/11 21:59:53

使用CLion开发STM32

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
使用CLion开发STM32

目录

  • 参考
  • 1.准备工作
    • 1.安装STM32CubeCLT
      • 1. 它里面包含了什么?
      • 2. 它解决什么痛点?
    • 2.安装CLion
  • 2.第一个项目
    • 1.新建项目
      • 生成CMake项目
    • 2.配置工具链
    • 3.添加调试服务器
    • 4.编译运行
      • 问题 1.提示调试器固件版本太低
  • 3. 文件结构解析
    • 1. 核心代码与驱动(文件夹)
    • 2. 编译与构建配置文件(核心纽带)
    • 3. 硬件与芯片个性的配置文件
    • 4. CubeMX 专用文件
  • 4.工具链解析
    • CMake
    • Ninja
      • 它和 Make 是什么关系?
    • arm-none-eabi-gcc
      • 命名解析
      • 为什么STM32不需要专用编译器?
      • 硬件的差异,交给“链接脚本”和“寄存器头文件”
    • 编译大小对比

参考

【爽!手把手教你用CLion开发STM32【大人,时代变啦!!!】】 https://www.bilibili.com/video/BV1pnjizYEAk/?share_source=copy_web&vd_source=76327fb2011d9dba418b60898e94496e

  • 建议主要参考B站视频,再结合本文。

1.准备工作

1.安装STM32CubeCLT

STM32CubeCLT(全称STM32Cube Command-Line Toolset,即 STM32Cube 命令行工具集)是意法半导体(ST)官方推出的一款纯命令行、轻量化的嵌入式开发工具链整合包

简单来说,它是把官方胖大臃肿的 STM32CubeIDE 剥掉图形界面(GUI)外壳后,剩下的纯粹底层核心工具。

如果你不想用 ST 官方那个基于 Eclipse 的 STM32CubeIDE,而是想用VSCode、CLion或者搭建自动化编译链,那么这个工具包就是为你量身定制的。

1. 它里面包含了什么?

作为一个“全家桶”,STM32CubeCLT 把原本散落在各处的编译和烧录工具打包在了一起,免去了你一个一个去单独下载、配环境变量的痛苦:

  • GNU Toolchain for STM32:官方魔改/优化过的arm-none-eabi-gcc编译器、链接器等。
  • GDB Debugger:调试器客户端(GDB Client)以及配合 ST-LINK 使用的 GDB 服务端(GDB Server)。
  • STM32CubeProgrammer (CLI 版本):ST 官方的烧录和内存管理工具。你可以通过命令行直接一键擦除、擦写芯片的 Flash 或外部存储。
  • 完整的 SVD 文件库 (System View Description):包含了整个 STM32 MCU 家族的芯片寄存器映射描述文件。CLion 或 VSCode 的调试插件(如 Cortex-Debug)必须要读取这类文件,才能在调试时让你直观地看到每个外设寄存器(如 GPIOA_ODR)的当前十六进制值。

2. 它解决什么痛点?

在 STM32CubeCLT 推出之前,如果你想用 VSCode 或 CLion 开发 STM32,你通常需要:

  1. 去 Arm 官网下载 GCC 工具链。
  2. 去 ST 官网下载单独的 STM32CubeProgrammer。
  3. 去一些开源社区或者把 CubeIDE 装上,强行把里面的.svd文件拷出来。
  4. 手动把这堆东西的路径一个一个配进环境变量。
    一旦工具版本更新,或者团队换了新电脑、甚至在 Linux 服务器上跑自动化 CI/CD 构建,这套环境就要重新配一遍,极其痛苦。
    STM32CubeCLT 实现了“一次安装,全部搞定”。它支持 Windows、macOS 和 Linux,提供标准化的安装路径和元数据,第三方 IDE(比如新版本的 CLion 或 VSCode 插件)能够非常轻松地自动检测到它。
+-----------------------------------+ | 1. 图形化配置 & 初始化代码生成 | --> STM32CubeMX (生成 CMake 项目) +-----------------------------------+ | v +-----------------------------------+ | 2. 代码编写、重构与语义分析 | --> CLion / VSCode (前端 IDE) +-----------------------------------+ | v +-----------------------------------+ | 3. 底层编译、烧录、GDB 调试和 SVD | --> STM32CubeCLT (后端工具链) +-----------------------------------+

2.安装CLion

CLion: A cross-platform IDE for C and C++
CLion对个人用户免费,直接去官网下载即可。

2.第一个项目

1.新建项目

生成CMake项目
  • 需要先由STM32CubeMx生成一个项目,再在CLion中指定文件夹。

2.配置工具链

  • 选择STM32CubeCLT中的各项工具即可

默认的Mingw同样可以编译运行,因为它会自己扫描,并选择合适的工具链。

3.添加调试服务器

  • 在调试服务器里面新增 ST-LINK调试服务器。

4.编译运行

  • 小锤子构建
  • 绿色的三角形运行
问题 1.提示调试器固件版本太低

  • 执行脚本,可能会提示 DFU mode问题。
  • 此时把STLink从电脑上移除,重新再插入即可。

  • 成功

3. 文件结构解析

  • Keil项目
  • CMake项目

1. 核心代码与驱动(文件夹)

  • Core/

    项目的核心应用层。这里存放的是你作为开发者需要频繁修改的业务代码。里面通常包含:
    • Src/main.c:程序的入口。
    • Src/stm32f1xx_it.c:中断服务函数(Interrupt Service Routines)。
    • Src/gpio.cusart.c等:由 CubeMX 自动生成的、对应你在图形界面配置的外设初始化代码。
  • Drivers/

    底层驱动库。这里是底层的基石,你一般不需要也不应该去修改里面的内容。它包含:
    • CMSIS:ARM 官方提供的 Cortex-M 核标准接口(提供底层寄存器定义和核心 CPU 控制指令)。
    • STM32F1xx_HAL_Driver:ST 官方的 HAL 库(硬件抽象层)。你代码里调用的HAL_GPIO_WritePin等函数实现都在这里。
    cmake/
    CMake 辅助脚本目录。这里通常存放着由 CubeMX 自动生成的特定工具链配置文件(比如corrosion.cmake或寻找 ARM 编译器的gcc-arm-none-eabi.cmake),用来辅助主 CMake 脚本找到你的编译器。

2. 编译与构建配置文件(核心纽带)

  • CMakeLists.txt

    整个项目的“总设计图”。这是 CLion 能识别并编译这个项目的核心。它用文本形式规定了:
    • 使用什么编译器(arm-none-eabi-gcc)。
    • 要编译哪些.c文件,包含哪些.h头文件路径。
    • 开启什么优化等级(如你的-OsRelease模式)以及定义了哪些全局宏(如USE_HAL_DRIVER)。
  • CMakePresets.json

    CMake 预设配置文件。这是现代化 CMake(CMake 3.19+)引入的标准。它为 CLion 等工具直接提供了“一键配置”的方案,里面记录了诸如DebugRelease的构建目录(如build/debug)应该怎么配置,让 IDE 打开项目时能自动识别并配置好编译环境。

3. 硬件与芯片个性的配置文件

  • startup_stm32f103xe.s

    汇编启动文件。单片机上电后执行的第一行代码就在这里(Reset_Handler)。它负责:
    1. 初始化堆栈指针(SP)。
    2. 把 FLASH 中的已初始化变量(RW-data)搬运到 RAM。
    3. 把未初始化变量区(ZI-data/BSS)清零。
    4. 最后跳转到你的main()函数。(注:文件名中的xe代表该芯片属于大容量产品,即 High-density,拥有 512KB FLASH,正符合你上一发问中的容量)

STM32F103VETx_FLASH.ld
链接脚本(Linker Script)。我们在前面提到的“内存地图”。它明明白白地告诉链接器,这颗STM32F103VET芯片的 FLASH 起始于0x08000000(大小 512K),RAM 起始于0x20000000(大小 64K)。GCC 链接时会严格按照这个规则来把代码摆放到固件对应的位置。

4. CubeMX 专用文件

  • LED.ioc

    CubeMX 图形化配置文件。双击它可以直接唤醒 STM32CubeMX 软件。如果你以后想修改引脚配置(比如再加个串口、改个时钟频率),直接在图形界面里改,改完后点击Generate Code,它会自动刷新上述的CMakeLists.txtCore/Drivers/,而不会破坏你自己写的代码。
  • .mxproject

    CubeMX 的内部描述文件。隐藏文件或系统文件,记录了生成这个工程时 CubeMX 所使用的库版本、MCU 型号等底层控制文本,供 CubeMX 自身再次读取时使用,开发者无需理会。

4.工具链解析

CMake

C/C++(无论是电脑程序还是 STM32 裸机)项目一旦变大,会有无数的.c文件、.h头文件、第三方库。如果直接去调用 GCC,你要写一长串长达几百个字符的疯狂命令。

  • CMake 的工作:人类写一个CMakeLists.txt。CMake 读取它,去检查你的电脑上有没有安装交叉编译器、头文件在哪里。
  • 它的输出物:自己不编译任何一行 C 代码。它唯一的任务,是把人类好理解的配置,翻译成构建工具(Make 或 Ninja)能看懂的“低级脚本”:
    • 如果你指定了 Make,它就生成Makefile
    • 如果你指定了 Ninja,它就生成build.ninja

Ninja

Ninja 是一个为“速度”而生的构建系统。它的核心目标只有一个:尽可能快地只构建那些需要重新构建的代码
可以把它理解成一个“超级高效的调度员”或“任务执行专家”。

它和 Make 是什么关系?

你可能知道make,Ninja 和make是同一类工具,但设计哲学完全不同:

特点MakeNinja
设计目标功能丰富,语法灵活,方便人直接编写极致的速度,尤其针对大型项目
可读性Makefile 语法相对友好,人可以写build.ninja 语法极简,但不适合人写
智能程度内置很多规则,会自动推导非常“笨”,几乎不做任何推导,完全听命于输入文件
并行编译支持 (-j),但效率一般原生优秀,能充分利用多核 CPU
典型用途中小型项目,或作为 CMake 的生成目标作为 CMake 的生成目标,用于大型项目

一句话总结:Make 像一把瑞士军刀,功能多但不够快;Ninja 像一把专门的手术刀,只做一件事——飞快地执行构建命令。

Ninja 的速度优势来自它的“笨”:

  • 不推导依赖:它不会自己去猜foo.c包含了哪个头文件。所有依赖关系都由 CMake 这样的“上级生成器”提前算好,写在build.ninja文件里。Ninja 只是照单执行。
  • 极简解析:它的配置文件语法非常简单,解析速度飞快。
  • 完美的并行:它天生被设计为并行运行,能毫无浪费地让你的 CPU 所有核心满负荷工作。
    对于一个大型项目(比如 Chromium 浏览器、LLVM 编译器,或一个庞大的 STM32 工程),使用 Ninja 比使用 Make 可以节省 30% - 70% 的编译时间

arm-none-eabi-gcc

命名解析
  1. arm-none-eabi-gcc
  • arm:目标芯片是 32 位的 ARM 架构(如 Cortex-M 系列)。
  • none:供应商(Vendor)未指定(或者是无意义的,因为不需要厂商定制的系统库)。
  • eabiEmbedded ABI(嵌入式应用程序二进制接口)。这意味着它使用的是针对资源受限环境的裸机标准,标准 C 库通常采用非常精简的newlib,而不是体积庞大的 Linuxglibc
  • 注意中间少了一段,因为没有操作系统,所以“操作系统”那一栏直接被跳过了。
  1. arm-linux-gnueabihf-gcc
  • arm:目标芯片是 32 位的 ARM 架构(如 Cortex-A7/A9 等支持运行 Linux 的全功能处理器)。
  • linux:明确指定目标操作系统是Linux。编译器在编译时会注入 Linux 的系统调用接口(System Calls),并且链接标准 Linux C 库(glibc)。
  • gnu:符合 GNU 规范。
  • eabihfEABI Hard-Float(硬浮点)。表示目标 CPU 带有硬件浮点运算单元(VFP/NEON),编译器会直接生成硬件浮点指令,运算速度极快。
为什么STM32不需要专用编译器?

其实,你的直觉非常敏锐:在过去很长一段时间里,单片机开发确实极度依赖“专用编译器”

如果你接触过 51 单片机,或者用过早期的 PIC、AVR 芯片,你会发现它们都有自己专属的、甚至需要高昂授权费的专用编译器(比如 Keil C51、IAR 等)。如果你把编译 51 的编译器拿去编译 AVR,那是绝对行不通的。

那为什么到了 STM32,一款开源、通用的 GCC 编译器就能包办一切呢?这里面主要有两个时代背景和底层架构的变革:

  1. 根本原因:ARM 公司改变了游戏规则(统一的架构)

在 STM32 诞生之前,单片机市场是一片“百家争鸣”的混战状态。每家芯片厂商都有自己独特的指令集架构(ISA)

  • 意法半导体(ST)早期有自己的单片机内核。
  • 微芯(Microchip)有 PIC 架构。
  • 爱特梅尔(Atmel)有 AVR 架构。

因为每个芯片的硬件电路和指令(比如怎么做加法、怎么跳转)完全不一样,所以编译器必须针对特定的芯片“私人订制”。
改变发生在这个男人手里:ARM。

ARM 自己不卖芯片,只卖授权。它设计出了大名鼎鼎的Cortex-M内核(STM32 的心脏)。ST(意法半导体)不需要自己设计 CPU 核心了,直接从 ARM 买来内核,外面包上自己的外设(如 GPIO、定时器、ADC),就组装成了 STM32。

由于市场上无数厂商(ST、GD、NXP、TI)都在用同一种 ARM Cortex-M 内核,这就意味着它们的底层指令集是完全统一的。这时候,开发一款通用的、支持 ARM 指令集的编译器,其性价比和受众群体就会变得无比巨大。

  1. GCC 的精妙设计:前端与后端的“解耦”

GCC(GNU Compiler Collection)之所以被称为“通用编译器”,并不是说它有一套魔法能直接把 C 语言变成所有芯片的机器码,而是因为它在架构设计上玩了极高明的模块化分工
GCC 的编译过程是分层的:

  • 编译器前端(Frontend):负责死抠 C/C++ 语法。它把你的 C 语言代码检查一遍(看看有没有少分号,变量有没有定义),然后把它翻译成一种与芯片无关的中间语言(称为 IR)。
  • 优化器(Optimizer):在中间语言的基础上进行代码优化(比如死代码消除、循环展开)。
  • 编译器后端(Backend):这是关键!后端专门负责把中间语言翻译成特定芯片的机器码。

开发一个新的芯片架构,GCC 官方或者芯片大厂(比如 ARM 官方的工程师)只需要重写 GCC 的后端代码,告诉它怎么把中间语言翻译成 ARM 汇编指令。
因此,arm-none-eabi-gcc并不是一个拍脑袋凭空出现的独立编译器,它本质上是“GCC 的通用前端 + ARM 官方贡献的 ARM 后端插件”

硬件的差异,交给“链接脚本”和“寄存器头文件”

你可能会问:“既然编译器是通用的,那它怎么知道我这款 STM32 有多少 Flash?怎么知道引脚寄存器的地址在哪?”
通用编译器只负责把 C 语言逻辑翻译成通用的 ARM 指令(比如寄存器 R0 和 R1 相加)。至于具体到某一款具体型号(比如STM32F103C8T6)的硬件个性,是通过两份文本文件塞给编译器的:


  1. 寄存器映射头文件(如stm32f103xb.h
    它用 C 语言的结构体和宏定义,把芯片手册上的物理硬件地址绑定到代码里的变量上。
// 告诉编译器,GPIOA 这个结构体指针,指向 0x40010800 这个物理地址 #define GPIOA ((GPIO_TypeDef *) 0x40010800)
  1. 链接脚本(.ld文件,Linker Script)
    这是通用的arm-none-eabi-ld(链接器)必须读取的文件。它用纯文本明确勾勒出这颗具体芯片的“内存地图”:
MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 64K RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K }

有了这两个东西,通用的 ARM 编译器就能完美适配成千上万种不同的 ARM 芯片,而不需要为每款芯片单独写一个编译器程序。

编译大小对比

Program Size: Code=2700 RO-data=372 RW-data=16 ZI-data=1632

Memory region Used Size Region Size %age Used
RAM: 1584 B 64 KB 2.42%
FLASH: 4920 B 512 KB 0.94%

物理资源Keil 编译结果CLion (Debug)CLion (Release) 🌟
FLASH 占用3088 B4920 B3988 B(缩减 932 字节)
RAM 占用1648 B1584 B1584 B

① 为什么 CLion (GCC) 的 FLASH 大了近 1.8 KB?

这里大概率是由两个原因引起的:

  1. C 标准库的实现体积差异(最主要原因):
    • Keil默认开启了Microlib(微库)。Microlib 是 ARM 专门为微控制器深度定制的精简标准库,它里面的printfmemcpy、数学函数等体积极其小巧。
    • CLion (GCC)默认使用的是newlibnewlib-nano。虽然newlib-nano已经做过裁剪,但它的体积(尤其是涉及格式化输出、底层桩函数_sbrk等系统调用逻辑时)依然会比 Keil 的 Microlib 稍微臃肿一些。
  2. 优化等级(Optimization Level)不同:
    • Keil 可能开启了针对代码体积的优化(如-O3-Os)。
    • CLion 默认的 CMake 配置文件如果是Debug模式(-O0),GCC 会生成大量冗余的调试指令和未优化的代码。如果是Release模式(-Os),这个差距会明显缩小。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/11 21:58:43

CompletableFuture 异常处理:5种策略对比与最佳实践指南

CompletableFuture 异常处理:5种策略对比与最佳实践指南在Java 8引入的CompletableFuture为异步编程带来了革命性的改变,但真正考验开发者功力的往往不是正常流程,而是异常处理。本文将深入剖析5种核心异常处理策略,结合真实业务场…

作者头像 李华
网站建设 2026/7/11 21:57:59

5步掌握猫抓浏览器扩展:新手也能快速上手的完整指南

5步掌握猫抓浏览器扩展:新手也能快速上手的完整指南 【免费下载链接】cat-catch 猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 还在为网页上的精彩视频无法保存而…

作者头像 李华
网站建设 2026/7/11 21:54:48

宝可梦存档管理神器PKSM:从第一世代到第八世代的终极解决方案

宝可梦存档管理神器PKSM:从第一世代到第八世代的终极解决方案 【免费下载链接】PKSM Gen I to GenVIII save manager. 项目地址: https://gitcode.com/gh_mirrors/pk/PKSM 对于热爱宝可梦系列的玩家来说,PKSM宝可梦存档管理器是一个改变游戏体验的…

作者头像 李华
网站建设 2026/7/11 21:54:24

NAS使用方法

NAS Network Attached Storage,网络附加存储,一台带独立系统、网口、硬盘阵列的专用文件服务器,直接插交换机 / 路由器内网,局域网所有电脑、手机统一存取文件内网电脑 A 通过 XTerminal 连接 NASNAS 插网线连内网交换机&#xf…

作者头像 李华