一、准备工作:明确需要安装的工具

需要安装 5 个核心工具,全部安装到非中文、无空格的目录(比如 D:\EmbeddedTools),避免后续出现各种路径错误,工具清单:

  1. CMake:生成 Makefile 的构建工具
  2. MinGW64:提供 Windows 下的 make 命令环境
  3. arm-none-eabi-gcc:ARM 芯片的交叉编译器(含 GDB 调试器)
  4. OpenOCD:片上调试器,用于固件下载和调试
  5. VSCode:代码编辑器,安装插件后实现开发 / 调试一体化
  6. clangd:基于Clang的C/C++语言服务器,提供代码补全、错误检测、跳转、格式化等智能功能

硬件准备(以示例为例):STM32F103xB(stm32f103c8t6)开发板、DAP-Link 仿真器(ST-Link/J-Link 也可,后续配置稍改)。

二、工具下载与安装(含环境变量配置)

步骤 1:安装 CMake

  1. 下载地址:https://cmake.org/download/选择cmake-xxx-windows-x86_64.msi(xxx 为版本号,比如 3.24.1,最新版即可)
  2. 安装:双击安装包,一路下一步,记得勾选 “Add CMake to the system PATH for all users”(自动加环境变量,小白必选);若没勾选,后续手动加:找到 CMake 安装目录的bin 文件夹(比如 D:\EmbeddedTools\CMake\bin),添加到系统环境变量 Path。
  3. 验证安装:按下Win+R输入cmd打开终端,输入cmake,出现Usage相关提示即安装成功。

步骤 2:安装 MinGW64

  1. 下载地址:https://www.winlibs.com/。解压到指定目录(比如D:\EmbeddedTools\mingw64)。

  1. 配置环境变量:将解压目录下的bin 文件夹(D:\EmbeddedTools\mingw64\bin)添加到系统 Path。
  2. 关键修改:进入 mingw64\bin 目录,找到mingw32-make.exe复制一份并重命名为 make.exe(否则 Windows 识别不了 make 命令)。
  3. 验证安装:终端输入make -v,出现GNU Make 4.2.1类似版本信息即成功。

步骤 3:安装 arm-none-eabi-gcc(ARM 交叉编译器)

  1. 下载地址:https://developer.arm.com/downloads/-/gnu-rm选择gcc-arm-none-eabi-xxx-win32.exe(安装包)或 zip 压缩包,安装 / 解压到指定目录(比如 D:\EmbeddedTools\gcc_arm_none_eabi)。这部分可能出现空格,一定要注意

  1. 配置环境变量:将目录下的bin 文件夹添加到系统 Path。
  2. 验证安装:终端输入arm-none-eabi-gcc,出现fatal error: no input files即成功(提示无输入文件是正常的,说明编译器能被调用)。

步骤 4:安装 OpenOCD

  1. 下载地址:https://gnutoolchains.com/arm-eabi/openocd/选择openocd-xxx.7z压缩包,解压到指定目录(比如 D:\EmbeddedTools\OpenOCD)。

  1. 配置环境变量:将目录下的bin 文件夹添加到系统 Path。
  2. 验证安装:终端输入openocd,出现Open On-Chip Debugger 0.11.0+ 一些错误提示(提示找不到 cfg 文件)即成功,错误是正常的,因为没指定调试器和芯片。

所有工具安装后,打开此电脑→属性→高级系统设置→环境变量→系统变量→Path,确认以下路径都已添加(替换为你的实际安装路径):

  • D:\EmbeddedTools\CMake\bin
  • D:\EmbeddedTools\mingw64\bin
  • D:\EmbeddedTools\gcc_arm_none_eabi\bin
  • D:\EmbeddedTools\OpenOCD\bin

三、VSCode 配置:安装插件 + 基础设置

步骤 1:安装必备插件

打开 VSCode,点击左侧扩展图标(四个方块),在搜索框输入插件名,点击安装,共 2 个核心插件:

  1. C/C++(微软官方):实现代码高亮、自动补全、跳转,必装。
  2. Cortex-Debug(marus25 开发):实现 ARM Cortex-M 芯片的调试,调用 OpenOCD,必装。
  3. clangd:代码补全、错误检测.....

安装完成后重启 VSCode,让插件生效。

步骤 2:配置 C/C++ 插件(适配 ARM 开发)

  1. 打开 VSCode,按下F1键,在弹出的输入框中输入C/C++: 编辑配置 (UI),点击进入配置页面。
  2. 关键配置项修改:
    • 编译器路径:选择你的 arm-none-eabi-gcc 路径(比如 D:\EmbeddedTools\gcc_arm_none_eabi\bin\arm-none-eabi-gcc.exe)。
    • IntelliSense 模式:选择gcc-arm (legacy)(适配 ARM 芯片)。
    • C 标准:选择gnu17(或 c11,按需)。
    • C++ 标准:选择gnu++14(或 c++11,按需)。
  3. 配置完成后,VSCode 会在当前工作目录自动生成 **.vscode 文件夹c_cpp_properties.json** 文件,无需手动修改。

四、搭建 STM32 工程(核心:CMakeLists.txt + 目录组织)

工程搭建的核心是编写 CMakeLists.txt(CMake 的工程文件,替代 Keil 的工程配置),并按规范组织文件目录,这里直接用示例模板,小白直接复制修改即可。

步骤 1:创建工程目录结构

在电脑任意位置创建工程根目录(比如 D:\STM32_Project\firmware),按以下结构创建文件夹,严格对应名称(方便后续复用 CMake 模板):

firmware/  # 工程根目录
├── .vscode/  # VSCode配置文件夹(自动生成,无需手动建)
├── build/  # 编译输出目录(手动建,空文件夹即可)
├── drivers/  # 驱动文件夹,放STM32固件库
│   ├── CMSIS/  # 放CMSIS核心库文件
│   └── STM32F1xx_HAL_Driver/  # 放STM32F1 HAL库文件
└── main/  # 自己的源码文件夹
    ├── main.c  # 主函数文件
    └── main.h  # 头文件

固件库获取:第一个方法

从 ST 官网https://www.st.com/en/embedded-software/stm32cubef1.html#get-software下载 STM32F1xx HAL 库,解压后将对应的 CMSIS、STM32F1xx_HAL_Driver 文件夹复制到 drivers 目录。

第二个方法:在stm32cubemx里面下载

选择版本

找到仓库

复制里面的cmsis和STM32F1xx_HAL_Driver复制到drivers文件夹内。

步骤 2:编写 CMakeLists.txt(直接用模板)

工程根目录 firmware下,新建一个文本文档,重命名为CMakeLists.txt(无后缀,注意大小写),将以下模板代码复制进去,仅需修改芯片相关宏定义(比如 STM32F103xB,按你的芯片型号改,stm32f103c8t6属于xB)

# 强制指定交叉编译目标系统,不依赖Windows/VS
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_SYSTEM_VERSION 1)

# 禁用VS相关检测
set(CMAKE_GENERATOR "MinGW Makefiles" CACHE INTERNAL "" FORCE)
set(CMAKE_MAKE_PROGRAM "make" CACHE FILEPATH "Make program path" FORCE)

# 明确指定ARM交叉编译器路径(如果环境变量生效,直接写文件名即可)
set(TOOLCHAIN_PREFIX arm-none-eabi-)
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}gcc)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}g++)
set(CMAKE_ASM_COMPILER ${TOOLCHAIN_PREFIX}gcc)
set(CMAKE_AR ${TOOLCHAIN_PREFIX}ar)
set(CMAKE_OBJCOPY ${TOOLCHAIN_PREFIX}objcopy)
set(CMAKE_OBJDUMP ${TOOLCHAIN_PREFIX}objdump)
set(SIZE ${TOOLCHAIN_PREFIX}size)

# 跳过编译器可执行程序检测(嵌入式必加)
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)

# CMake最低版本要求
cmake_minimum_required(VERSION 3.21)

# 项目名称:可修改(比如MySTM32),支持C/C++/汇编
project(Mystm32)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_C_STANDARD 11)

# 编译选项:Cortex-M3内核(STM32F103是M3,其他芯片改对应内核,比如M4加-mfpu=fpv4-sp-d16)
add_compile_options(-mcpu=cortex-m3 -mthumb -mthumb-interwork)
add_compile_options(-ffunction-sections -fdata-sections -fno-common -fmessage-length=0)
add_compile_options($<$<COMPILE_LANGUAGE:ASM>:-x$<SEMICOLON>assembler-with-cpp>) # 汇编文件预处理

# 编译模式:Debug/Release,Debug带调试信息,Release优化速度
if ("${CMAKE_BUILD_TYPE}" STREQUAL "Release")
    message(STATUS "Maximum optimization for speed")
    add_compile_options(-Ofast)
else ()
    message(STATUS "Minimal optimization, debug info included")
    add_compile_options(-Og -g)
endif ()

# 头文件目录:无需修改,对应我们的目录结构
include_directories(
    ./
    ${CMAKE_SOURCE_DIR}/drivers/CMSIS/Include
    ${CMAKE_SOURCE_DIR}/drivers/CMSIS/Device/ST/STM32F1xx/Include
    ${CMAKE_SOURCE_DIR}/drivers/STM32F1xx_HAL_Driver/Inc
    ${CMAKE_SOURCE_DIR}/drivers/STM32F1xx_HAL_Driver/Inc/Legacy
    ${CMAKE_SOURCE_DIR}/main
)

# 宏定义:关键!按你的芯片修改,STM32F103xB对应F103C8/T8/RB等,F103xE对应F103ZE/VE等
add_definitions(-DUSE_HAL_DRIVER -D__MICROLIB -DSTM32F1 -DSTM32F1xx -DSTM32F103xB)

# 源文件自动扫描:无需修改,对应目录结构
aux_source_directory(${CMAKE_SOURCE_DIR}/drivers/STM32F1xx_HAL_Driver/Src HAL_DRIVER)
aux_source_directory(${CMAKE_SOURCE_DIR}/drivers/CMSIS/Device/ST/STM32F1xx/Source/Templates SYSTEM)
aux_source_directory(${CMAKE_SOURCE_DIR}/main MAIN)

# 启动文件和链接脚本:关键!必须是GCC版本(不能用Keil版本),按芯片改
set(STARTUP       ${CMAKE_SOURCE_DIR}/drivers/CMSIS/Device/ST/STM32F1xx/Source/Templates/gcc/startup_stm32f103xb.s)
set(LINKER_SCRIPT ${CMAKE_SOURCE_DIR}/drivers/CMSIS/Device/ST/STM32F1xx/Source/Templates/gcc/linker/STM32F103XB_FLASH.ld)

# 链接选项
add_link_options(-Wl,-gc-sections,--print-memory-usage,-Map=${PROJECT_BINARY_DIR}/${PROJECT_NAME}.map)
add_link_options(-mcpu=cortex-m3 -mthumb -mthumb-interwork)
add_link_options(-T ${LINKER_SCRIPT})

# 生成可执行文件(.elf)
add_executable(${PROJECT_NAME}.elf ${HAL_DRIVER} ${SYSTEM} ${MAIN} ${STARTUP} ${LINKER_SCRIPT})

# 生成hex和bin固件(下载用)
set(HEX_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.hex)
set(BIN_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.bin)
add_custom_command(TARGET ${PROJECT_NAME}.elf POST_BUILD
        COMMAND ${CMAKE_OBJCOPY} -Oihex $<TARGET_FILE:${PROJECT_NAME}.elf> ${HEX_FILE}
        COMMAND ${CMAKE_OBJCOPY} -Obinary $<TARGET_FILE:${PROJECT_NAME}.elf> ${BIN_FILE}
        COMMENT "Building ${HEX_FILE} && ${BIN_FILE}")

关键注意点

  • 启动文件(.s)和链接脚本(.ld)必须是 GCC 版本,HAL 库中 gcc 文件夹下的文件,不能用 Keil 的 armclang 版本。
  • 宏定义STM32F103xB按你的芯片型号改,比如 STM32F103RC 改STM32F103xB,STM32F103ZE 改STM32F103xE

步骤 3:用 CMake 生成 Makefile

  1. 打开 CMake 图形界面(安装后桌面有快捷方式,或终端输入cmake-gui)。
  2. 配置 CMake 路径:
    • Where is the source code:选择工程根目录 firmware(比如 D:\STM32_Project\firmware)。
    • Where to build the binaries:选择工程下的 build 文件夹(比如 D:\STM32_Project\firmware\build)。
  3. 点击Configure(配置),弹出窗口选择MinGW Makefiles,然后选择Use default native compilers,点击Finish
  4. 等待配置完成,底部出现Configuring done即成功(红色条目无需修改,直接下一步)。
  5. 点击Generate(生成),底部出现Generating done,此时 build 文件夹下会生成Makefile等文件,CMake 的工作完成。

下一步操作

  1. 点击「Generate」按钮(在「Configure」右边,现在已经可以点击了)
  2. 等待日志底部出现 Generating done,这才是完整的生成流程。
  3. 之后去看你的 build 文件夹,里面就会出现:
    • Makefile(核心构建文件)
    • cmake_install.cmake
    • CTestTestfile.cmake
    • 以及其他编译相关文件

关于多项目管理:不用重头搭建!(复用环境 + 模板)

不需要为每个项目重新配置环境 / CMake,核心思路是复用已搭建好的工具链 + 工程模板,只需要复制模板改少量配置即可

  1. 创建工程模板文件夹:把你现在能正常编译的 firmware 文件夹复制一份,重命名为新项目名(比如 firmware_LED);
  2. 仅修改 3 处配置
    • CMakeLists.txtproject(MiniBot C CXX ASM) → 改为 project(LED_Blink C CXX ASM)(项目名,随意改);
    • 若芯片型号不变(还是 F103C8T6),启动文件 / 链接脚本 / 宏定义完全不用改
    • 若芯片型号变(比如 F4),仅改启动文件、链接脚本、宏定义(其余编译链配置不变);
  3. 删除旧编译文件:删除新项目的 build 文件夹,重新 CMake Configure → Generate → make 即可
  4. 请帮我编写基于 STM32F103C8T6 的 LED 闪烁业务代码,要求如下:
    1. 技术栈:STM32 HAL 库 + C 语言 + CMake 工程(已配置好 arm-none-eabi-gcc 工具链);
    2. 硬件配置:
       - LED 引脚:PC13(推挽输出,无上拉/下拉);
       - 系统时钟:72MHz(外部晶振 8MHz);
       - 延时方式:基于 TIM2 定时器 1ms 中断(自定义 HAL 时基,避免函数重复定义);
    3. 功能需求:
       - LED 以 500ms 间隔闪烁;
       - 包含完整的 main.c、stm32f1xx_hal_msp.c、stm32f1xx_it.c、stm32f1xx_hal_timebase_tim.c;
    4. 代码要求:
       - 符合 STM32 HAL 库编程规范,注释清晰;
       - 避免 HAL 库时基模板文件(timebase_tim/rtc)的函数重复定义;
       - 包含系统时钟配置(SystemClock_Config)、GPIO/TIM2 初始化函数;
    5. 输出格式:按文件分块给出完整代码,标注每个文件的存放路径(如 main/main.c)。

    请帮我生成适配 STM32F103C8T6 + CMake 工程的 VSCode 配置文件(tasks.json + launch.json),要求如下:
    1. 环境信息:
       - arm-none-eabi-gcc 路径:D:/EmbeddedTools/gcc_arm_none_eabi/10-2021.10/bin;
       - OpenOCD 路径:D:/EmbeddedTools/OpenOCD/OpenOCD-20260302-0.12.0;
       - CMake 路径:D:/EmbeddedTools/cmake/bin;
       - 工程根目录:D:/Users/adminstrator/Desktop/c/STM32_Project/firmware;
       - 固件输出路径:build/Mystm32.elf;
    2. 配置要求:
       - tasks.json:包含「CMake 生成 Makefile + 编译工程」「OpenOCD 烧录固件」两个任务;
       - launch.json:配置 Cortex-Debug 调试器,连接 ST-Link(SWD 模式),自动停在 main 函数;
       - OpenOCD 配置文件用 stlink.cfg(新版),目标配置用 stm32f1x.cfg;
    3. 避坑要求:
       - 避免 Ninja 生成器,强制使用 MinGW Makefiles;
       - 烧录命令包含 verify(校验固件)、reset(复位运行);
       - 调试配置包含 SVD 文件路径(可选,用于查看寄存器);
    4. 输出格式:分别给出 tasks.json 和 launch.json 的完整代码,标注存放路径(.vscode/ 下)。
     

  5. 在菜单栏中点击终端,在下拉菜单中点击 运行任务

  • CMake 编译工程

    • 作用:执行 cmake --build build,把已经配置好的工程编译成 .elf/.hex/.bin 固件文件
    • 本质:只做「编译」,不会往芯片里烧任何东西。
  • CMake 配置 (MinGW Makefiles)

    • 作用:执行 cmake -G "MinGW Makefiles" ..,重新生成 Makefile 构建规则。
    • 本质:只做「配置」,不编译、不烧录,适合改了 CMakeLists.txt 后刷新构建环境。
  • OpenOCD 烧录固件

    • 作用:调用 OpenOCD 把编译好的 .elf 文件写入芯片 Flash,也就是你说的「下载到板子」。
    • 本质:真正的烧录操作,会把程序写到芯片里。

6.点击运行进入main,再点击将执行并烧录

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐