使用Vscode和STM32CubeMx进行STM32开发详解

目录

使用arm工具链+OpenOCD开发stm32

一、简单介绍一下需要使用的工具

(1) VSCode(代码编辑神器)

(2) STM32CubeMX(用于生成初始代码和makefile文件)

(3)   arm-none-eabi-gcc(交叉编译器)

(4)   MSYS2(我安装它的目的是方便安装和管理后续的make、cmake、openocd等工具,也可以直接在其官网安装,使用MSYS2会更加方便)

(5)Git(建议安装,非常好用,后续的操作也是基于Git终端的)

二、如何安装工具

(1)VSCode安装

(2)STM32CubeMX安装

(3)arm-none-eabi-gcc安装 

(4)MSYS2安装 

         下面将介绍如何通过MSYS2安装make和openocd:

 (5)安装Git

 三、环境配置

        (1)VSCode插件选择

        (2)将VSCode终端更改为Git Bash 

        (3)开始创建工程

1. c_cpp_properties.json配置

2.launch.json配置

3.settings.json配置

4.tasks.json配置

(4)编译下载项目

(5)代码调试 

 四、引入自己的库

五、使用printf输出浮点数 


使用arm工具链+OpenOCD开发stm32

        前言:想必大家打开这篇文章都是看腻了或者不习惯使用Keil的开发页面,都想使用更加简洁强大的VSCode开发,不过既然选择不再使用Keil那肯定是需要付出一些代价的,那就是下面的VSCode开发环境配置起来相当复杂与繁琐,并且对stm32底层不太了解的不太友好,不过这也恰恰利用这个机会去学习了解一下,这里主要分享一下我当时配置VSCode开发环境的过程,下面有些地方没有做更加详细的解释,若是有些地方不明白可以在网上自己查阅一些资料,后续我也会不断完善这篇文章,虽然此文章有点长,希望大家能耐心看完取得收获。

一、简单介绍一下需要使用的工具

(1) VSCode(代码编辑神器)
(2) STM32CubeMX(用于生成初始代码和makefile文件)
(3)   arm-none-eabi-gcc(交叉编译器)
(4)   MSYS2(我安装它的目的是方便安装和管理后续的make、cmake、openocd等工具,也可以直接在其官网安装,使用MSYS2会更加方便)
  • make
  • openocd
  • (5)Git(建议安装,非常好用,后续的操作也是基于Git终端的)

    二、如何安装工具

    (1)VSCode安装

            进入VSCode的官网之后直接点击下载安装即可,这个比较简单在这里不再详细介绍,

    安装完了之后要记得将bin文件添加到环境变量。

    (2)STM32CubeMX安装

            点击STM32CubeMX链接跳转至官网,点击“Get Software”。

            Windows系统点击“Get latest”。

            后续跟着它的提示下载安装就行。 

    (3)arm-none-eabi-gcc安装 

            点击arm-none-eabi-gcc链接跳转至官网,往下滑选择下图中的第一个下载即可。

            下载之后将其解压到自己合适的位置即可,随后将其中的bin文件添加到系统环境变量。

    (4)MSYS2安装 

            点击MSYS2链接跳转至官网,按着官网提示的步骤下载安装即可。

             下面将介绍如何通过MSYS2安装make和openocd:

    1.安装make、cmake:

            按下电脑“win”键输入“MSYS2 UCRT64”,点击进入终端:

             输入"pacman -S make cmake"即可安装make和cmake。

    2.安装OpenOCD:

            按上述步骤,在终端MSYS2 UCRT64终端中输入“pacman -S mingw-w64-x86_64-openocd”即可安装OpenOCD。

    3.将make和OpenOCD添加到环境变量:

            查看make的地址,按下win键输入“MSYS2 UCRT64”打开终端:(输入“where make”)。例:将图中对应位置添加到环境变量。

            查看openocd的地址, 按下win键输入“MSYS2 MINGW64”打开终端:(输入“where openocd”)。例:将图中对应位置添加到环境变量。

    将“E:\msys64\usr\bin”和“E:\msys64\mingw64\bin”添加到环境变量。

     (5)安装Git

            点击Git链接跳转至官网,点击“Download for Windows”后点击下图中的地方下载安装即可,

     安装完了之后它的bin文件也需要添加到环境变量。

     三、环境配置

            (1)VSCode插件选择

    说明:最后一个插件“Task Buttons”可以使任务简化为底部的按钮,非常方便建议安装。

            (2)将VSCode终端更改为Git Bash 

            在VSCode设置里搜索“default terminal”,将下图中改为“Git Bash”即可。

            (3)开始创建工程

            打开cubemx,创建一个makefile初始化代码,并使用VSCode打开。如果这里不会的可以去网上查一查。重点:工程名以及工程所在的地址都不能有中文,并且创建完了之后最好不要更改工程名,不然会编译失败。

     打开之后应该是下图这样的:

    接下来是最重要的,配置.json文件:

            首先安装下图创建文件夹(文件名称要一模一样,不能自己更改),分别是.vscode文件夹,其中包括c_cpp_properties.json、launch.json、settings.json和tasks.json四个json文件,下面我将会提供已经配置好的文件,可以直接复制到自己工程里,只需要做一些小小的修改就可以直接运行。

    1. c_cpp_properties.json配置
    {
        /* C/C++插件的配置参数数组 */
        "configurations": [
            {
                "name": "STM32F103C8T6",                           //配置名称(用于在VSCode底部状态栏切换配置)
                /* 头文件搜索路径(影响IntelliSense), "${workspaceFolder}/**"将搜索所有子目录 */
                "includePath": [                                  
                    "${workspaceFolder}/**"                        //递归包含工作区所有目录
                ],
                /* 预定义宏(影响IntelliSense) */
                "defines": [
                    "_DEBUG",                                      //启用调试模式
                    "UNICODE",                                     //启用Unicode字符集
                    "_UNICODE",                                    //启用Unicode字符集
                    /* 下面的从Makefile文件里的define处复制过来 */
                    "USE_HAL_DRIVER",                              //启用STM32 Hardware Abstraction Layer (HAL) 库
                    "STM32F103xB"                                  //芯片系列宏
                ],
                /* 编译器绝对路径(用于推断系统头文件路径) 需要提前安装arm-none-eabi-gcc并添加到环境变量 */
                "compilerPath": "D:\\arm-none-eabi-gcc\\arm-gnu-toolchain-14.2.rel1-mingw-w64-i686-arm-none-eabi\\bin\\arm-none-eabi-gcc.exe",
                /* 传递给编译器的额外参数(影响IntelliSense) */
                "compilerArgs": [
                    /* 下面从Makefile文件里的cpu、fpu、float-abi和mcu处复制过来 */
                    "-mcpu=cortex-m3",
                    "-mthumb"
                ],
                "cStandard": "c11",                                 //C语言标准(如 c11, c17)
                "cppStandard": "c++17",                             //C++语言标准(如 c++17, gnu++20)
                "intelliSenseMode": "gcc-arm"                       //IntelliSense 引擎模式(需与编译器匹配)	"gcc-arm"(针对ARM GCC)
            }
        ],
        "version": 4                                                //一般固定为最新支持的版本(如 4)
    }
    

    其中的“defines”处有些变量需要从makefile文件里复制过来:

     

     其中的“compilerPath”路径需要更改为自己的安装路径:

     /* 编译器绝对路径(用于推断系统头文件路径) 需要提前安装arm-none-eabi-gcc并添加到环境变量 */
     "compilerPath": "D:\\arm-none-eabi-gcc\\arm-gnu-toolchain-14.2.rel1-mingw-w64-i686-arm-none-eabi\\bin\\arm-none-eabi-gcc.exe"

     其中的“compilerArgs”变量也需要从makefile文件里复制过来:

    "compilerArgs": [
    /* 下面从Makefile文件里的cpu、fpu、float-abi和mcu处复制过来 */
     "-mcpu=cortex-m3",
     "-mthumb"]

     

    2.launch.json配置
    {
        /* configurations数组用于定义不同的调试配置 */
        "configurations": [
            {
                "name": "Debug",                                           //调试配置的名称(显示在 VS Code 调试下拉菜单中)
                "cwd": "${workspaceFolder}",                               //调试器启动时的工作目录
                "executable": "./build/${workspaceRootFolderName}.elf",    //要调试的可执行文件路径(.elf或.axf文件)
                "request": "launch",                                       //调试请求类型:启动调试("launch")或附加到进程("attach")
                "type": "cortex-debug",                                    //调试器类型:必须为"cortex-debug"(使用Cortex-Debug扩展,取决于安装的插件)
                "preLaunchTask": "build",                                  //调试前执行的任务(通常是编译任务)
                "servertype": "openocd",                                   //调试服务器类型:openocd/jlink/pyocd 等(此处使用 OpenOCD)
                "device": "STM32F103xB",                                   //目标芯片型号
                /* OpenOCD 配置文件列表(指定调试接口和芯片配置) */
                "configFiles": [
                    "interface/stlink.cfg",                                //ST-LINK 调试器接口配置
                    "target/stm32f1x.cfg"                                  //STM32 系列芯片配置
                ],
                "svdFile": "./STM32F103.svd",                              //SVD 文件(需从官网下载)路径(用于外设寄存器实时查看)
                /* 实时变量监视配置 */
                "liveWatch": {
                    "enabled": true,                                       //启用实时变量更新
                    "samplesPerSecond": 4                                  //每秒采样次数(过高可能影响性能)
                },
                "searchDir": [],                                           //OpenOCD 配置文件的额外搜索路径(留空表示默认路径)
                "runToEntryPoint": "main",                                 //调试启动后自动运行到 main 函数入口暂停(跳过启动代码)
                "showDevDebugOutput": "none"                               //调试输出详细程度:none(不显示)/raw(原始数据)/parsed(解析后)
            }
        ],
        "version": "2.0.0"                                                 //配置文件版本(固定为 2.0.0)
    }
    

     以下内容需要根据自己芯片进行更改:若是当前没有svd文件则把有关这一行的配置删去。

    "device": "STM32F103xB",       //目标芯片型号
    /* OpenOCD 配置文件列表(指定调试接口和芯片配置) */
    "configFiles": [
    "interface/stlink.cfg",       //ST-LINK 调试器接口配置
    "target/stm32f1x.cfg"         //STM32 系列芯片配置
    ],
    "svdFile": "./STM32F103.svd",    //SVD 文件(需从官网下载)路径(用于外设寄存器实时查看)
    

     如果使用的是dap下载器,将上面的interface/stlink.cfg改为interface/cmsis-dap.cfg

     使用stlink无需更改此项

    3.settings.json配置
    {
        /* 文件关联配置:指定特定文件扩展名使用 C 语言模式 */
        "files.associations": {
            "main.h": "c",                         //将 main.h 识别为 C 语言文件
        },
        /* VsCodeTaskButtons 扩展配置(需安装插件) */
        "VsCodeTaskButtons.showCounter": true,     //在按钮上显示任务执行次数
        /* 定义自定义任务按钮 */
        "VsCodeTaskButtons.tasks": [
        {
        "label": "$(tools) Build",                 //显示工具图标(VSCode内置图标) + "Build" 文本
        "task": "build",                           //关联 tasks.json 中的 "build" 任务
        "tooltip": "🛠️ build"                     //可选的提示信息框,在鼠标悬停于按钮上时会显示🛠️ build(默认显示内容为任务名称)
        },
        {
        "label": "$(trashcan) Clean",
        "task": "clean",
        "tooltip": "🗑️ clean"
        },
        {
        "label": "$(trashcan) & $(tools)",
        "task": "rebuild",
        "tooltip": "🗑️ & 🛠️"
        },
        {
        "label": "$(zap) Flash",
        "task": "flash",
        "tooltip": "⚡ flash"
        }
        ],
        /* 终端配置 */
        "terminal.integrated.defaultProfile.windows": "Git Bash",
    }
    
    4.tasks.json配置
    {
        /* tasks数组用于定义一组可执行的任务(如编译、清理、烧录等),每个任务通过不同参数控制其行为 */
        "tasks": [
            /* 到下一个注释之间为编译任务 */
            {
                "type": "shell",                                 //任务类型:shell(在终端中执行命令)或process(直接运行程序)
                "label": "build",                                //任务唯一标识符(用于在命令面板或dependsOn中引用)
                "command":"make",                                //要执行的命令(此处为 make)
                /* 传递给命令的参数列表 */
                "args": [
                    "-j",                                        //启用多线程编译
                    "16"                                         //使用16个线程(根据 CPU 核心数调整)
                ],
                /* 定义如何从输出中提取错误/警告信息(如 $gcc 匹配 GCC 错误) */
                "problemMatcher":[
                    "$gcc"                                       //使用内置的 GCC 错误匹配规则
                ],
                "group": "build"                                 //任务分组(归类到 "build" 组,可通过快捷键触发)
            },
            /* 到下一个注释之间为清理任务 */
            {                   
                "type": "shell",                                 //任务类型:shell(在终端中执行命令)或process(直接运行程序)
                "label": "clean",                                //任务唯一标识符(用于在命令面板或dependsOn中引用)
                "command":"make",                                //要执行的命令 执行 make clean
                /* 传递给命令的参数列表 */
                "args": [
                    "clean"                                      //make 的目标为 clean
                ],
                /* 定义如何从输出中提取错误/警告信息(如 $gcc 匹配 GCC 错误) */
                "problemMatcher":[
                    "$gcc"                                       //使用内置的 GCC 错误匹配规则
                ],
                "group": "build"                                 //同样属于 build 组
            },
            /* 到下一个注释之间为重新编译任务 */
            {
                "type": "shell",                                 //任务类型:shell(在终端中执行命令)或process(直接运行程序)
                "label": "rebuild",                              //任务唯一标识符(用于在命令面板或dependsOn中引用)
                "command":"make",                                //要执行的命令
                /* 传递给命令的参数列表 */
                "args": [
                    "-j",                                        //启用多线程编译
                    "16"                                         //使用16个线程(根据 CPU 核心数调整)
                ],
                /* 定义如何从输出中提取错误/警告信息(如 $gcc 匹配 GCC 错误) */
                "problemMatcher":[
                    "$gcc"                                       //使用内置的 GCC 错误匹配规则
                ],
                "group": "build",                                //任务分组(归类到 "build" 组,可通过快捷键触发)
                /* 任务依赖:执行前先运行此项 */
                "dependsOn": [
                    "clean"                                      //依赖的任务标签(label)
                ]
            },
            /* 到下一个注释之间为烧录任务 */
            { 
                "type": "shell",                                 //任务类型:shell(在终端中执行命令)或process(直接运行程序)
                "label": "flash",                                //任务唯一标识符(用于在命令面板或dependsOn中引用)
                "command":"openocd",                             //要执行的命令 使用 OpenOCD 工具
                /* 传递给命令的参数列表(配置OpenOCD烧录时的参数) */
                "args": [
                    "-f",                                        //指定配置文件
                    "interface/stlink.cfg",                      //ST-LINK 调试器接口配置
                    "-f",                                        //指定配置文件
                    "target/stm32f1x.cfg",                       //STM32 系列芯片配置
                    "-c",                                        //执行命令
                    "program build/${workspaceRootFolderName}.elf verify reset exit"// 烧录固件
                    /* program: 烧录固件
                       verify:  校验烧录内容
                       reset:   复位芯片
                       exit:    烧录完成后退出 OpenOCD */
                ],
                /* 定义如何从输出中提取错误/警告信息(如 $gcc 匹配 GCC 错误) */
                "problemMatcher":[
                    "$gcc"                                        //使用内置的 GCC 错误匹配规则
                ],
                "group": "build",                                 //任务分组(归类到 "build" 组,可通过快捷键触发)
                /* 任务依赖:执行前先运行此项 */
                "dependsOn": [
                    "build"                                       //烧录前需先编译生成 .elf 文件
                ]
            }
        ],
        "version": "2.0.0"                                        //配置文件版本(固定为 2.0.0)
    }
    

     此处参数中的16需要根据自己电脑的cpu进行更改:

    "args": [
     "-j",                                        //启用多线程编译
    "16"                                         //使用16个线程(根据 CPU 核心数调整)
    ],

    此处变量的参数“stm32f1x.cfg”需要根据自己芯片进行略微调整:若是F4则改为stm32f4x.cfg

    "args": [
    "-f",                                        //指定配置文件
     "interface/stlink.cfg",                      //ST-LINK 调试器接口配置
    "-f",                                        //指定配置文件
    "target/stm32f1x.cfg",                       //STM32 系列芯片配置
    "-c",                                        //执行命令
    "program build/${workspaceRootFolderName}.elf verify reset exit"// 烧录固件
    ],

     如果使用的是dap下载器,将上面的interface/stlink.cfg改为interface/cmsis-dap.cfg 

     使用stlink无需更改此项

    (4)编译下载项目

            若是按照我上面的配置完成后,这是在VSCode的底部会出现几个按钮:点击第一个Build便是编译,第二个Clean便是删除build的编译项,第三个是Rebuild重新编译,第四个Flash是下载。若是没有安装“Task Buttons”这个插件,也可以按下键盘“CTRL+SHIFT+B”也可以选择编译或是下载项目。

    (5)代码调试 

            若是前面按照我给的步骤去更改json文件,那么这一步将会非常简单:直接点击下图按钮即可进行调试。

     四、引入自己的库

            用make进行编译时,make是根据Makefile里的内容寻找宏,头文件和哪些文件需要编译。而这个Makefile是STM32CubeMX根据选择的外设等自动生成的,因此,Makefile里显然只会包含HAL库或HAL的部分(取决于用户自己在生成工程时的选择),如果要引入自己写的驱动,就需要对Makefile进行改动。

    1.添加.c源文件:

    # source
    ######################################
    # C sources
    C_SOURCES =  \
    Core/Src/main.c \
    Core/Src/gpio.c \
    Core/Src/stm32f1xx_it.c \
    Core/Src/stm32f1xx_hal_msp.c \
    Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio_ex.c \
    Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c \
    Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c \
    Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc_ex.c \
    Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.c \
    Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.c \
    Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cortex.c \
    Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.c \
    Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash.c \
    Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash_ex.c \
    Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_exti.c \
    Core/Src/system_stm32f1xx.c \
    Core/Src/sysmem.c \
    Core/Src/syscalls.c  \
    Core/Hardware/Key.c \

    2.添加.h头文件:

    # C includes
    C_INCLUDES =  \
    -ICore/Inc \
    -IDrivers/STM32F1xx_HAL_Driver/Inc/Legacy \
    -IDrivers/STM32F1xx_HAL_Driver/Inc \
    -IDrivers/CMSIS/Device/ST/STM32F1xx/Include \
    -IDrivers/CMSIS/Include \
    -ICore/Hardware

    五、使用printf输出浮点数 

            需要在Makefile里的LDFLAGS后面加上-u _printf_float-u _scanf_float否则无法输入输出浮点数:

    # libraries
    LIBS = -lc -lm -lnosys 
    LIBDIR = 
    LDFLAGS = $(MCU) -u _printf_float -u _scanf_float -specs=nano.specs -T$(LDSCRIPT) $(LIBDIR) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-sections
    

    作者:慕默七清

    物联沃分享整理
    物联沃-IOTWORD物联网 » 使用Vscode和STM32CubeMx进行STM32开发详解

    发表回复