问题现象:Keil收费,并且不可扩展
问题解决:改用VSCode开发STM32
一 思想准备。
过程简单但细节繁多,如果没有折腾的欲望,请出门左转找STM32CubeIDE,对于不喜欢麻烦的人来说也挺好用的。
二 安装。
1)VScode
官方下载地址:https://code.visualstudio.com/
微云下载:https://share.weiyun.com/3cJqYzhX
安装教程:(知乎作者:IT-cute)https://zhuanlan.zhihu.com/p/106357123
安装后可在设置界面选择语言为中文。
安装时记得把以上几个对号选中
2)mingw64
微云下载:https://share.weiyun.com/QSFlI3Tq
安装:解压后得到名为mingw64的文件夹,直接将整个文件夹剪切到C盘或其他盘后,打开下级文件夹bin,将其中的mingw32-make.exe重命名为make.exe 。
添加环境变量:
赋值重命名后的make.exe所在文件夹的地址(例:因为我把解压文件放在C盘里,在我电脑上为C:\mingw64\bin)。
在Windows左下角任务栏的搜索处输入 环境变量 ,点击 编辑系统环境变量。
在Windows左下角任务栏的搜索处输入 环境变量 ,点击 编辑系统环境变量
在弹出的窗口中点击 环境变量(N) 然后选中变量名为 path 那一栏,点击 编辑 按钮,在新弹出的窗口中点击 新建 ,输入刚才复制的文件夹地址,一路点击 确认 窗口自动关闭。切记一定要点击 确认 保存一下。
切记一定要点击 确认 保存一下
3)openocd (开源片上调试器:Open On-Chip Debugger)
微云下载:https://share.weiyun.com/t5h4HOQo
同上,将解压后的文件夹剪切到C盘或其他盘,并且将openocd-0.10.0文件夹下级中的bin和bin-x64两个文件夹的完整目录添加到环境变量(例:在我电脑上文件夹地址分别为C:\openocd-0.10.0\bin和C:\openocd-0.10.0\bin-x64)。
4) GNU Arm Embedded Toolchain(arm-none-eabi)
微云下载:https://share.weiyun.com/Ju3t6Z8C
这是一个可执行文件,下载后直接默认安装即可,建议安装到C盘。
安装后打开目录:C:\Program Files (x86)\GNU Tools Arm Embedded\9 2019-q4-major\bin ,可以看到里边有很多arm-none-eabi-***.exe,把这个bin文件夹的目录添加到环境变量并点击确定保存。
5)STM32CubeMX
STM32CubeMX依赖Java环境,因此需要先安装Java(Java官方下载链接):
https://www.java.com/en/download/manual.jsp
微云下载:https://share.weiyun.com/H62gNrLh
安装教程:https://blog.csdn.net/as480133937/article/details/98885316
6)STM32CubeProgrammer
使用ST-Link调试需要安装对应的驱动,在这里我们通过STM32CubeProgrammer安装ST-Link驱动,如果你的电脑已经安装ST-Link驱动可以忽略这一步。
查看是否已经安装ST-Link驱动的方法:打开设备管理器,插入ST-Link-V2调试器,查看 通用串行总线设备 选项中是否有 STM32 STLink 选项,如果有则安装成功。
微云下载:https://share.weiyun.com/wJJGBh21
按照默认配置安装即可。
三 验证是否安装成功。
回到电脑桌面,鼠标移至桌面空白处,按住键盘 Shift 键 同时点击鼠标右键,在右键窗口中出现了 在此处打开PowerShell窗口,左击确定,进而打开PowerShell终端。
下面介绍几个命令用以查看之前安装的开发环境的版本,在PowerShell窗口中输入对应命令并按下回车,如果你得到了窗口输出的版本号,证明你软件安装正确且环境变量配置成功:
make -v 查看make版本;
openocd -v 查看openocd版本;
arm-none-eabi-gcc -v 查看gcc-arm版本。
正确的输出结果演示(gcc输出结果太长,只截取最后两行)
四 配置VSCode
首先使用STM32CubeMX生成标准模板,STM32CubeMX使用教程已经很多了,请读者自行百度搜索。需要注意的一点是,最后在Project Manager选项卡中,Toolchain/IDE选项选择Makefile。
Project Manager选项卡中,Toolchain/IDE选项选择Makefile。
在生成的程序模板中,我的工程名为F103_BLINK,选中F103_BINK文件夹,通过右键 -> Open With Code 打开工程:
右键 -> Open With Code 打开工程
打开main.c ,可能会发现很多语法报错,别着急,先安装一下必要的插件。主要是下面长图中框选的三个插件。在应用商店中搜索并安装即可。
安装一下必要的插件
接下来我们开始配置各种细节设置,这里是重中之重,很多教程零零散散,这里都没有讲全,请按照步骤一点点来:
1)文件 -> 首选项 -> 设置 -> 搜索:intelli sense mode,在下拉选项中修改为gcc-arm。
文件 -> 首选项 -> 设置 -> 搜索:intelli sense mode,在下拉选项中修改为gcc-arm
2)按F1键或者ctrl+shift+P,
输入:编辑配置UI,然后选择下图选项:
按F1键、输入:编辑配置UI
在新打开的配置窗口主要做以下修改:
a.添加三个宏定义:
添加三个宏定义 __CC_ARM、USE_HAL_DRIVER、STM32F103xB
其中第一条宏定义是告诉代码提示引擎使用gcc-arm的语法规则和库文件,如果不添加这条宏定义会出现诸如“uint32_t未定义”等错误(需要注意,这条宏定义为:__CC_ARM 前边的短横线有两条且所有字母大写)。
后两条宏定义你可能已经不陌生了,在KEIL中我们也常常添加类似的两条宏定义。其实在STM32CubeMX为我们生成的模板Makefile中已经存在这个宏定义,但是VSCode检查语法的时候并不会去读Makefile,因此需要我们手动添加。但并不需要强行记忆,我们打开工程文件夹中的Makefile文件,在大约第102行有:
# C defines
C_DEFS = \
-DUSE_HAL_DRIVER \
-DSTM32F103xB
直接把USE_HAL_DRIVER和STM32F103xB复制到配置界面即可,注意复制时把宏定义前边的“-D”删除,那是Makefile特有的格式。
b. 添加头文件包含路径
头文件路径可以在makefile文件中找到并复制粘贴
对应的工程头文件路径可以在makefile文件中找到并复制粘贴,也可以自行添加。
c. 编译器路径选择gcc.exe
编译器路径选择gcc.exe
d.如果此时你的编辑器还是不能进行代码提示,请在设置界面搜索prevent,将搜索结果中的对号取消勾选:
将搜索结果中的对号取消勾选
3)到这里所有环境配置工作都结束了,关闭所有窗口,通过鼠标右键 -> open with code重新打开工程。
接下来检查所有插件是否正常运行:
写一个简单的闪灯程序,检查语法提示等功能是否正常
简单的闪灯程序
在下方 终端 中输入 make ,敲回车进行编译:
终端 中输入 make ,敲回车进行编译
将单片机通过ST-Link下载器与电脑连接,在下方 终端 中输入 openocd ,敲回车,若出现以下信息则证明与单片机通信成功:
若出现图中信息则证明与单片机通信成功
Openocd连接成功后会占用一个终端,我们可以点击窗口右边的+号新建一个PowerShell终端,然后切换回openocd终端并点击删除。
Openocd连接成功后会占用一个终端,可以删除
五 VSCode调试配置
1)配置launch.json:
a. 在工程文件夹里新建一个文件,命名为openocd.cfg。
新建一个文件,命名为openocd.cfg
b. 点击VSCode左侧运行图标(带有一个小虫子的三角形,老版本可能只有虫子图标没有三角形)
c. 继续点击 创建launch.json文件 ,在弹出窗口中选择 Cortex-Debug 。
创建launch.json文件、选择 Cortex-Debug
d. 在自动打开的launch.json文件中,我们可以看到默认的调试工具是Jlink,这里我们更改为openocd。
然后在executable后手动输入正确的.elf文件路径。(elf文件在工程文件夹/build/xxx.elf中找到),最后在新增一条configFiles,后面填写我们新建的openocd.cfg的完整路径。详见配置格式下图:
详细配置说明
e. 接下来打开我们之前新建好的openocd.cfg文件。现在他还是空白的,我们只需要添加两条简单的代码:
source [find interface/stlink-v2.cfg]
source [find target/stm32f1x.cfg]
其中第一行代码是指明调试工具为stlink-v2,这个取决于你的调试工具
第二行指明目标芯片为stm32f1x系列。
不要担心,这里也不需要强行记忆,只需要记住代码格式即可,具体使用什么工具或者怎么写目标芯片名称,请打开openocd的安装目录,在C:\openocd-0.10.0\scripts中有interface和target两个文件夹,里边就放着已经预先写好的文件和调试规则。
预先写好的文件和调试规则
现在我们可以愉快的开始调试了!首先在下方PowerShell终端中输入 make 命令进行编译以确保调试程序与代码一致,然后点击左侧运行图标(就是那个带小虫子的三角形,快捷键F5),选择cortex-debug,点击绿色三角形开始运行,就可以进行调试了。我们可以切换到main.c,添加几个断点,看一下调试效果。
六 一键编译、烧录
你会发现,每次开始调试前需要手动输入make命令进行编译,每次调试结束后,单片机不能自动复位,需要手动复位程序才能正常运行。而且只有调试功能,没有一键下载、编译功能,这实在太麻烦了,因此我们进行教程的最后一步:添加task命令实现一键编译、一键烧录(下载)、调试前自动编译、调试后自动复位:
首先打开makefile,在文件最后一行新建两个任务(update和reset):
update:
openocd -f openocd.cfg -c init -c halt \
-c "program $(BUILD_DIR)/$(TARGET).hex verify reset exit"
reset:
openocd -f openocd.cfg -c init -c halt -c reset -c shutdown
其中,update下边两行代码为烧录命令,openocd -f openocd.cfg代表通过openocd打开我们之前新建的openocd.cfg文件, init为初始化 halt为挂起命令 相当于暂停单片机运行 目的是为了下一步的烧录,program为烧录命令 后边跟随的是需要烧录的hex文件路径和地址 翻阅makefile可以发现,此处地址为build/F103_Blink.hex,verify代表烧录后验证,reset代表烧录后重启,exit为退出。
Reset命令更加简单,不再赘述,读者可以直接复制使用,具体命令含义请查阅openocd安装目录里自带的pdf说明文档,我也是查阅文档后自己编写的,值得一提的是,一些教程烧录hex文件使用的是 flash write_image erase 命令,但我使用该命令每两次总会失败一次,改用program后解决此问题,如果您知道原因请告诉我一声,万分感谢。
Makefile命令编写完成后,按下F1键,输入 配置任务 ,选择下面的待选项,然后选择shell:gcc.exe模板:
按下F1键,输入 配置任务 ,选择shell:gcc.exe
打开tasks.json后,默认为以下内容,先把label冒号后边的内容重命名为自己需要的名字,以编译任务为例,我们改为 Build ,然后对应的把command冒号后边的内容改为 make ,最后把图中框选的用不到的内容直接删除:
默认gcc模板
最终结果是不是清爽了很多:
label冒号后边的内容重命名为Build command冒号后边的内容改为 make
我们用同样的方法,除了已将添加的Build任务,再添加一个Update任务和一个Reset任务,这两个任务正好需要调用我们此前在makefile中编写的update命令和reset命令,我们只需要复制已经写好的Build任务,把command后边的内容输入新的命令就好了:
添加新的命令
make;make update ,表示先后执行make中的make(编译)命令,然后执行我们在makefile中编写的update命令,将代码烧录进单片机。
make reset , 表示执行我们编写的reset命令,将单片机复位。
至此,所有命令都编写完了。我们再完善一下launch.json,这个文件与调试功能息息相关。我们此前说过,每次调试都不能自动编译、自动复位,为了解决这个问题,在launch.json最后添加两行代码:
最后面添加两行代码:"preLaunchTask": "Build" 和"postDebugTask": "Reset"
其中 "preLaunchTask": "Build",表示调试活动开始前先执行tasks.json中的编译命令。
而"postDebugTask": "Reset" 表示调试活动完成后先执行tasks.json中的复位命令。
我们再次按F5进行调试,会发现系统已经自动帮我们执行make命令进行编译,编译完成后开始调试,我们点击停止,则单片机自动复位。
现在只剩一个问题,命令已经写好了,怎么一键编译、一键烧录呢?其实很简单了,在VSCode菜单栏点击 终端 -> 运行任务 ,就会有 Reset、Build、Update三个任务供你选择:(分别对应 重启单片机、仅编译、编译后上传)
终端 -> 运行任务