使用VSCode开发STM32 (通用版本)

本文以启明欣欣的工控板举例,讲述如何使用VSCode来开发STM32。MCU是STM32F407ZGT6

一 准备

1. 交叉编译器

打开https://gitlab.arm.com/tooling/gnu-toolchains-for-arm,找到编译器列表,

选择一个合适的,这里选最新的15.3.rel1,点击进入后下拉,找到如下Windows hosted交叉编译器,

选择红框中的任意一个,第一个是安装版,第二个是免安装版,本人下载了第二个,下载后找个目录解压,然后把目录下的bin目录添加到系统环境变量PATH里,例如本人的解压路径是D:\SW\arm-gnu-toolchain-15.3.rel1,

然后把D:\SW\arm-gnu-toolchain-15.3.rel1\bin添加到系统环境变量Path里,

  • 右键 "此电脑" → "属性" → "高级系统设置" → "环境变量"
  • 在 "系统变量" 中找到 Path,点击 "编辑",添加:D:\SW\arm-gnu-toolchain-15.3.rel1\bin

2. ninja

ninja用来代替make做实际的编译工作。

打开https://github.com/ninja-build/ninja/releases/,在Assets里找到Windows版本,

下载后解压到一个目录,然后把这个目录地址添加到系统环境变量Path了

3. openocd

打开https://github.com/xpack-dev-tools/openocd-xpack/releases,在Assets里找到Windows版本,

解压后把bin目录添加到系统环境变量Path里

4. CMake

下载Windows版本并安装,也要添加系统环境变量Path里,不再赘述

5. VSCode插件

安装CMake Tools和Cortex-Debug这2个插件即可

6. CubeMX工程

可以参考https://blog.csdn.net/whahu1989/article/details/144226202来创建CubeMX工程,同时把PE3,PE4和PG9配置成输出的GPIO,可以操作板子上的灯

在生成项目时注意以下几点,

Toolchain / IDE选择Makefile,这样生成的启动汇编文件和链接器脚本可以直接复用,另外勾选如下,


二 移植到VSCode

创建个目录然后使用VSCode打开,然后创建如下目录和文件,

然后按照如下步骤进行拷贝,

  • CubeMX工程的Core目录里的东西拷贝到VSCode工程的Core目录里
  • CubeMX工程的Drivers目录里的东西拷贝到VSCode工程的Drivers目录里
  • CubeMX工程的STM32F407xx_FLASH.ld拷贝到VSCode工程的ld目录
  • CubeMX工程的startup_stm32f407xx.s拷贝到VSCode工程的startup目录

CMakeLists.txt的内容如下,

bash 复制代码
cmake_minimum_required(VERSION 3.20)


set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")

# 交叉编译器
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_OBJCOPY ${TOOLCHAIN_PREFIX}objcopy)
set(CMAKE_OBJDUMP ${TOOLCHAIN_PREFIX}objdump)

project(STM32F407_APP LANGUAGES C CXX ASM)

# ================= STM32F407 M4F 配置 =================
set(MCU_CORE cortex-m4)

# 编译标志:每个参数单独一项,禁止空格拼接长字符串
add_compile_options(
    -mcpu=${MCU_CORE}
    -mthumb
    -mfpu=fpv4-sp-d16
    -mfloat-abi=hard
    -Og
    -g3
    -Wall
    -ffunction-sections
    -fdata-sections
    -std=c99
)

# 汇编文件启用cpp预处理
add_compile_options($<$<COMPILE_LANGUAGE:ASM>:-xassembler-with-cpp>)

# 链接参数同样!拆成独立元素,不要长字符串
add_link_options(
    -mcpu=${MCU_CORE}
    -mthumb
    -mfpu=fpv4-sp-d16
    -mfloat-abi=hard
    -T${CMAKE_SOURCE_DIR}/ld/STM32F407xx_FLASH.ld
    -Wl,--gc-sections
    -Wl,-Map=${PROJECT_NAME}.map
    --specs=nano.specs
    --specs=nosys.specs
)

# ================= 文件列表 =================
file(GLOB_RECURSE USER_SOURCES
    Core/Src/*.c
    Drivers/STM32F4xx_HAL_Driver/Src/*.c
    Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c
)

# GCC启动汇编
set(ASM_SOURCES startup/startup_stm32f407xx.s)

# 头文件路径
include_directories(
    Core/Inc
    Drivers/STM32F4xx_HAL_Driver/Inc
    Drivers/CMSIS/Device/ST/STM32F4xx/Include
    Drivers/CMSIS/Include
)

# 预定义宏(和CubeMX保持一致)
add_definitions(
    -DSTM32F407xx
    -DUSE_HAL_DRIVER
)

add_executable(${PROJECT_NAME}.elf ${USER_SOURCES} ${ASM_SOURCES})

# 生成hex、bin、反汇编
add_custom_command(TARGET ${PROJECT_NAME}.elf POST_BUILD
    COMMAND ${CMAKE_OBJCOPY} -O ihex ${PROJECT_NAME}.elf ${PROJECT_NAME}.hex
    COMMAND ${CMAKE_OBJCOPY} -O binary ${PROJECT_NAME}.elf ${PROJECT_NAME}.bin
    COMMAND ${CMAKE_OBJDUMP} -d ${PROJECT_NAME}.elf > ${PROJECT_NAME}.lst
)

.vscode目录下创建settings.json和launch.json,

settings.json内容如下,

bash 复制代码
{
    "cmake.generator": "Ninja",
    "cmake.buildDirectory": "${workspaceFolder}/build",
    "C_Cpp.default.compilerPath": "arm-none-eabi-gcc",
    "C_Cpp.default.includePath": [
        "${workspaceFolder}/**"
    ],
    "C_Cpp.default.defines": [
        "STM32F407xx",
        "USE_HAL_DRIVER"
    ]
}

launch.json内容如下,

bash 复制代码
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Debug STM32F407 STLink",
            "type": "cortex-debug",
            "request": "launch",
            "servertype": "openocd",
            "executable": "${workspaceFolder}/build/STM32F407_APP.elf",
            "configFiles": [
                "interface/stlink.cfg",
                "target/stm32f4x.cfg"
            ],
            "runToEntryPoint": "main",
            "cwd": "${workspaceFolder}",
            "svdFile": "${workspaceFolder}/STM32F407.svd"
        }
    ]
}

注意:CMakeLists.txt里设定的输出目标名字是STM32F407_APP.elf,所以在launch.json里配置"executable"时也要使用相同的文件


三 编译

在工程目录下打开终端,然后执行下面的命令进行编译,

bash 复制代码
cmake -GNinja -B build -S .
cmake --build build

编译完成后可以在build目录下看到生成的elf,hex和bin文件,


四 下载和调试

launch.json里设定了下载和调试,此时打开左侧的"Run and Debug",可以看到在已经有一个调试配置,这个名字和launch.json里设定的是一样的

点击这个名字左侧的绿色三角调试按钮,就可以自动下载并开启调试,直接走到main函数里并停下。用户可以在main.c里加点操作GPIO的代码来验证效果。


五 小结

本文讲述了如何使用VSCode开发STM32,可能会问为什么不使用ST提供的VSCode插件?或者为什么不使用PlatformIO?本人是为了简化和通用性,ST的插件只能用在ST的芯片,如果有其它厂的芯片就用不了,PlatformIO感觉有点重而且它不是使用CMake的。

最重要的一点是,如果项目已经很成熟,MCU及其外设什么的都是固定的,那么这样做就会简单很多,降低维护成本。

相关推荐
周洲08302 小时前
STM32 串口底层深度解析|USART 中断标志、硬件 FIFO,乱码根源底层定位
stm32·单片机·嵌入式硬件
阿斌.com5 小时前
Visual Studio 2026安装全攻略
ide·visual studio
李日华大战鸡红7 小时前
IC-MU128编码器使用教程
stm32
周洲08307 小时前
STM32片内Flash读写深度详解|掉电参数保存、底层原理
linux·前端·stm32
WD1372980155712 小时前
WD5030K输入工作电压 7.5‑30V,适合12A 及以内量产项目
stm32·单片机·嵌入式硬件·51单片机
我要神龙摆尾12 小时前
IDEA 阅读插件
java·ide·intellij-idea·idea-plugs·plugs
光子物联单片机13 小时前
STM32传感器模块编程实践(二十二)DIY智能WIFI视频控制小车
c语言·stm32·单片机·嵌入式硬件·音视频
新晨单片机设计14 小时前
S010C-基于STM32单片机水温控制系统(OLED显示)【Proteus仿真+Keil程序+原理图】
stm32·单片机·proteus·水温控制系统
lhbweilai14 小时前
从底层了解STM32八大功能(下)
stm32·单片机
新晨单片机设计15 小时前
S009C-基于STM32单片机语音出租车计价器【Proteus仿真+Keil程序+原理图】
stm32·单片机·proteus·出租车计价器