LV16-04-STM32工程创建

本文主要是如何创建STM32工程的相关笔记,若笔记中有错误或者不合适的地方,欢迎批评指正😃。

点击查看使用工具及版本
Windows windows11
Ubuntu Ubuntu16.04的64位版本
VMware® Workstation 16 Pro 16.2.3 build-19376536
SecureCRT Version 8.7.2 (x64 build 2214) - 正式版-2020年5月14日
开发板 正点原子 i.MX6ULL Linux阿尔法开发板
uboot NXP官方提供的uboot,NXP提供的版本为uboot-imx-rel_imx_4.1.15_2.1.0_ga(使用的uboot版本为U-Boot 2016.03)
linux内核 linux-4.15(NXP官方提供)
STM32开发板 正点原子战舰V3(STM32F103ZET6)
点击查看本文参考资料
  • 通用
分类 网址说明
官方网站https://www.arm.com/ARM官方网站,在这里我们可以找到Cotex-Mx以及ARMVx的一些文档
https://www.st.com/content/st_com/zh.htmlST官方网站,在这里我们可以找到STM32的相关文档
https://www.stmcu.com.cn/意法半导体ST中文官方网站,在这里我们可以找到STM32的相关中文参考文档
http://elm-chan.org/fsw/ff/00index_e.htmlFatFs文件系统官网
教程书籍《ARM Cortex-M3权威指南》ARM公司专家Joseph Yiu(姚文祥)的力作,中文翻译是NXP的宋岩
《ARM Cortex-M0权威指南》
《ARM Cortex-M3与Cortex-M4权威指南》
开发论坛http://47.111.11.73/forum.php开源电子网,正点原子的资料下载及问题讨论论坛
https://www.firebbs.cn/forum.php国内Kinetis开发板-野火/秉火(刘火良)主持的论坛,现也做STM32和i.MX RT
https://www.amobbs.com/index.php阿莫(莫进明)主持的论坛,号称国内最早最火的电子论坛,以交流Atmel AVR系列单片机起家,现已拓展到嵌入式全平台,其STM32系列帖子有70W+。
http://download.100ask.net/index.html韦东山嵌入式资料中心,有些STM32和linux的相关资料也可以来这里找。
博客参考http://www.openedv.com/开源网-原子哥个人博客
http://blog.chinaaet.com/jihceng0622博主是原Freescale现NXP的现场应用工程师
cortex-m-resources这其实并不算是一个博客,这是ARM公司专家Joseph Yiu收集整理的所有对开发者有用的官方Cortex-M资料链接(也包含极少数外部资源链接)
  • STM32
STM32STM32 HAL库开发实战指南——基于F103系列开发板野火STM32开发教程在线文档
STM32库开发实战指南——基于野火霸道开发板野火STM32开发教程在线文档
  • SD卡
SD Association提供了SD存储卡和SDIO卡系统规范
点击查看相关文件下载
STM32F103xx英文数据手册STM32F103xC/D/E系列的英文数据手册
STM32F103xx中文数据手册STM32F103xC/D/E系列的中文数据手册
STM32F10xxx英文参考手册(RM0008)STM32F10xxx系列的英文参考手册
STM32F10xxx中文参考手册(RM0008)STM32F10xxx系列的中文参考手册
Arm Cortex-M3 处理器技术参考手册-英文版Cortex-M3技术参考手册-英文版
STM32F10xxx Cortex-M3编程手册-英文版(PM0056)STM32F10xxx/20xxx/21xxx/L1xxxx系列Cortex-M3编程手册-英文版
SD卡相关资料——最新版本有关SD卡的一些资料可以从这里下载
SD卡相关资料——历史版本有关SD卡的一些历史版本资料可以从这里下载,比如后边看的SD卡2.0协议
SD 2.0 协议标准完整版这是一篇关于SD卡2.0协议的中文文档,还是比较有参考价值的,可以一看

可以用于STM32开发的软件有Keil MDK5、IAR、STM32CubeMX等,我自己是觉得IAR有些不好用,所以也没研究过,主要还是使用MDK5和ATM32CubeMX来开发,但是后来发现STM32CubeMX软件创建的工程可以导出makefile文件,所以这样的话VScode也不失为一种好用的开发工具,后边会尝试VScode进行STM32的开发,毕竟VScode是真的好用啊,哈哈。

一、 MDK5

软件官网:Keil Embedded Development Tools for Arm, Cortex-M, Cortex-R4, 8051, C166, and 251 processor families.

1. MDK5简介

MDK 源自德国的 KEIL 公司,是 RealView MDK 的简称。在全球 MDK 被超过 10 万的嵌入式开发工程师使用。是目前针对 ARM 处理器,尤其是 Cortex M 内核处理器的最佳开发工具。

Keil MDK面向各种STM32微控制器产品的全面软件开发解决方案,提供创建、编译和调试嵌入式应用程序时所需的一切资源。MDK包括真正的Arm编译器和易于使用的Keil uVision IDE/调试器,可与STM32CubeMX和软件包连接。MDK还提供各种专业的中间件组件。

MDK5 向后兼容 MDK4 和 MDK3 等,以前的项目同样可以在 MDK5 上进行开发(但是头文件方面得全部自己添加), MDK5 同时加强了针对 Cortex-M 微控制器开发的支持,并且对传统的开发模式和界面进行升级, MDK5 由两个部分组成: MDK Core 和 Software Packs。其中,Software Packs 可以独立于工具链进行新芯片支持和中间库的升级。 如下图所示:

image-20230419224850008

从上图可以看出, MDK Core 又分成四个部分: uVision IDE with Editor(编辑器), ARM C/C++ Compiler(编译器), Pack Installer(包安装器),uVision Debugger with Trace(调试跟踪器)。 uVision IDE 从 MDK4.7 版本开始就加入了代码提示功能和语法动态检测等实用功能,相对于以往的 IDE 改进很大。Software Packs(包安装器)又分为: Device(芯片支持), CMSIS(ARM Cortex 微控制器软件接口标准) 和 Mdidleware(中间库)三个小部分,通过包安装器,我们可以安装最新的组件,从而支持新的器件、提供新的设备驱动库以及最新例程等,加速产品开发进度。

Software Packs(包安装器)又分为: Device(芯片支持), CMSIS(ARM Cortex 微控制器软件接口标准) 和 Mdidleware(中间库)三个小部分,通过包安装器,我们可以安装最新的组件,从而支持新的器件、提供新的设备驱动库以及最新例程等,加速产品开发进度。

同以往的 MDK 不同,以往的 MDK 把所有组件到包含到了一个安装包里面,显得十分“笨重”, MDK5 则不一样, MDK Core 是一个独立的安装包,它并不包含器件支持和设备驱动等组件,但是一般都会包括 CMSIS 组件,大小 350M 左右,相对于 MDK4.70A 的 500 多 M,瘦身不少, 器件支持、设备驱动、CMSIS 等组件, 则可以点击 MDK5 的 Build Toolbar 的最后一个图标调出 Pack Installer,来进行各种组件的安装。

2.  软件下载

image-20230421224753539 image-20230421224845733
  • 软件内下载组件包
image-20230421225207179

3. 工程模板文件准备

最开始学STM32的时候,用标准库,自己手动创建工程,当时创一个工程,能编译通过就很难的样子,后来发现其实知道需要哪些文件后也没什么难度,在实际开发过程中,多数情况不会自己去创建工程模版,大多都是复制一个,然后添加自己的业务逻辑代码。而且后边会提另一个工具,它是ST官方主推的图形化开发工具,可以自动生成多种类型的工程模板。

3.1 库文件准备

我们这里基于两种库来新建MDK工程:

  • 标准库

标准库的版本:STM32F10x_StdPeriph_Lib_V3.6.0

下载地址:STM32标准外设软件库 - 意法半导体STMicroelectronics

  • HAL库

HAL库的版本:STM32Cube_FW_F1_V1.8.0

下载地址:STM32CubeF1 - STM32Cube MCU包,用于STM32F1系列(HAL、底层API和CMSIS(CORE、DSP和RTOS)、USB、TCP/IP、File system、RTOS和Graphic - 附带在以下ST板上运行的示例:STM32 Nucleo、探索套件和评估板) - 意法半导体STMicroelectronics

3.2 工程目录准备

  • (1)创建工程目录,我们的工程文件一会可以放在这个目录下
image-20230422175908442
  • (2)创建目录,并拷贝相关文件

这里我为了偷懒,我写了一个shell脚本,上边我创建的目录是在在虚拟机的共享目录下,所以我们可以直接在虚拟机中通过执行脚本来创建和拷贝相关文件,最后再chuangjianMDK工程,所需要执行的脚本如下:

点击查看详情
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#!/bin/sh
# =====================================================
# Copyright © hk. 2022-2025. All rights reserved.
# File name : 1.sh
# Author : qidaink
# Date : 2023-04-22
# ======================================================
##

##======================================================
BLACK="\033[1;30m"
RED='\033[1;31m' # 红
GREEN='\033[1;32m' # 绿
YELLOW='\033[1;33m' # 黄
BLUE='\033[1;34m' # 蓝
PINK='\033[1;35m' # 紫
CYAN='\033[1;36m' # 青
WHITE='\033[1;37m' # 白
CLS='\033[0m' # 清除颜色
##======================================================
# 变量定义

STD_PROJECT_ROOT_NAME=StdPeriph_Lib_Template
STD_LIB_NAME=STM32F10x_StdPeriph_Lib_V3.6.0
STD_STARTUP_NAME=startup_stm32f10x_hd.s
HAL_PROJECT_ROOT_NAME=STM32Cube_FW_F1_Template
HAL_LIB_NAME=STM32Cube_FW_F1_V1.8.0
PROJECT_TYPE="xxx lib project"

STD_PROJECT_DRIVER_DIRNAME="STM32F10x_FWLib"
HAL_PROJECT_DRIVER_DIRNAME="HAL_lib"
PROJECT_DIR_NAME[0]="" # STM32F10x_FWLib/HAL_lib 存放 ST 官方提供的库函数源码文件
PROJECT_DIR_NAME[1]="CORE" # CORE 用来存放核心文件和启动文件
PROJECT_DIR_NAME[2]="USER" # USER 用来放我们的代码工程文件
PROJECT_DIR_NAME[3]="OBJ" # OBJ 用来存放编译过程文件以及 hex 文件
PROJECT_DIR_NAME[4]="HARDWARE" # HARDWARE 存放用户编写的外设驱动文件
declare -A PROJECT_DIR_PATH # 定义一个字典,后边组合生成键值对,字典必须先声明

CURRENT_PATH=$(pwd)
PROJECT_ROOT_PATH=${CURRENT_PATH}
LIB_PATH=${CURRENT_PATH}
##======================================================
# 提示信息打印函数
function echo_menu()
{
echo -e "${GREEN}================================================${CLS}"
echo -e ""
echo -e "${WHITE}# CURRENT_PATH : ${CURRENT_PATH}${CLS}"
echo -e "${WHITE}# STD_PROJECT_ROOT_NAME : ${STD_PROJECT_ROOT_NAME}${CLS}"
echo -e "${WHITE}# HAL_PROJECT_ROOT_NAME : ${HAL_PROJECT_ROOT_NAME}${CLS}"
echo -e "${WHITE}# STD_LIB_NAME : ${STD_LIB_NAME}${CLS}"
echo -e "${WHITE}# HAL_LIB_NAME : ${HAL_LIB_NAME}${CLS}"
echo -e ""
echo -e "${GREEN}* [0] 拷贝STM32工程所需标准库文件(标准库工程)"
echo -e "${GREEN}* [1] 拷贝STM32工程所需HAL库文件(HAL库工程)"
echo -e "${GREEN}================================================${CLS}"

read -p "选择功能,默认选择0:" choose
if [ "${choose}" == "0" ] || [ "${choose}" == "" ];then # [0] 拷贝STM32工程所需标准库文件
PROJECT_ROOT_PATH=${CURRENT_PATH}/${STD_PROJECT_ROOT_NAME}
LIB_PATH=${CURRENT_PATH}/${STD_LIB_NAME}
PROJECT_DIR_NAME[0]=${STD_PROJECT_DRIVER_DIRNAME}
PROJECT_TYPE="STD_lib_project"
elif [ "${choose}" == "1" ];then # [0] 拷贝STM32工程所需HAL库文件
PROJECT_ROOT_PATH=${CURRENT_PATH}/${HAL_PROJECT_ROOT_NAME}
LIB_PATH=${CURRENT_PATH}/${HAL_LIB_NAME}
PROJECT_DIR_NAME[0]=${HAL_PROJECT_DRIVER_DIRNAME}
PROJECT_TYPE="HAL_lib_project"
fi

echo -e "${GREEN}================================================${CLS}"
echo -e "${GREEN}相关动态参数如下:${CLS}"
echo -e "${PINK}# PROJECT_TYPE : ${PROJECT_TYPE}${CLS}"
echo -e "${PINK}# PROJECT_ROOT_PATH : ${PROJECT_ROOT_PATH}${CLS}"
echo -e "${PINK}# LIB_PATH : ${LIB_PATH}${CLS}"
echo -e "${PINK}# PROJECT_DIR_NAME : ${PROJECT_DIR_NAME[*]}${CLS}"
echo -e "${GREEN}================================================${CLS}"
}

function copy_hal_lib_files()
{
cp -pr ${LIB_PATH}/Drivers/STM32F1xx_HAL_Driver/Inc ${PROJECT_DIR_PATH[${PROJECT_DIR_NAME[0]}]}
cp -pr ${LIB_PATH}/Drivers/STM32F1xx_HAL_Driver/Src ${PROJECT_DIR_PATH[${PROJECT_DIR_NAME[0]}]}

cp -p ${LIB_PATH}/Drivers/CMSIS/Device/ST/STM32F1xx/Source/Templates/arm/startup_stm32f103xe.s ${PROJECT_DIR_PATH[${PROJECT_DIR_NAME[1]}]}
cp -p ${LIB_PATH}/Drivers/CMSIS/Include/cmsis_armcc.h ${PROJECT_DIR_PATH[${PROJECT_DIR_NAME[1]}]}
cp -p ${LIB_PATH}/Drivers/CMSIS/Include/cmsis_armclang.h ${PROJECT_DIR_PATH[${PROJECT_DIR_NAME[1]}]}
cp -p ${LIB_PATH}/Drivers/CMSIS/Include/cmsis_compiler.h ${PROJECT_DIR_PATH[${PROJECT_DIR_NAME[1]}]}
cp -p ${LIB_PATH}/Drivers/CMSIS/Include/cmsis_version.h ${PROJECT_DIR_PATH[${PROJECT_DIR_NAME[1]}]}
cp -p ${LIB_PATH}/Drivers/CMSIS/Include/core_cm3.h ${PROJECT_DIR_PATH[${PROJECT_DIR_NAME[1]}]}

cp -p ${LIB_PATH}/Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f1xx.h ${PROJECT_DIR_PATH[${PROJECT_DIR_NAME[2]}]}
cp -p ${LIB_PATH}/Drivers/CMSIS/Device/ST/STM32F1xx/Include/system_stm32f1xx.h ${PROJECT_DIR_PATH[${PROJECT_DIR_NAME[2]}]}
cp -p ${LIB_PATH}/Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f103xe.h ${PROJECT_DIR_PATH[${PROJECT_DIR_NAME[2]}]}

cp -p ${LIB_PATH}/Projects/STM3210E_EVAL/Templates/Inc/main.h ${PROJECT_DIR_PATH[${PROJECT_DIR_NAME[2]}]}
cp -p ${LIB_PATH}/Projects/STM3210E_EVAL/Templates/Inc/stm32f1xx_hal_conf.h ${PROJECT_DIR_PATH[${PROJECT_DIR_NAME[2]}]}
cp -p ${LIB_PATH}/Projects/STM3210E_EVAL/Templates/Inc/stm32f1xx_it.h ${PROJECT_DIR_PATH[${PROJECT_DIR_NAME[2]}]}

cp -p ${LIB_PATH}/Projects/STM3210E_EVAL/Templates/Src/main.c ${PROJECT_DIR_PATH[${PROJECT_DIR_NAME[2]}]}
cp -p ${LIB_PATH}/Projects/STM3210E_EVAL/Templates/Src/system_stm32f1xx.c ${PROJECT_DIR_PATH[${PROJECT_DIR_NAME[2]}]}
cp -p ${LIB_PATH}/Projects/STM3210E_EVAL/Templates/Src/stm32f1xx_it.c ${PROJECT_DIR_PATH[${PROJECT_DIR_NAME[2]}]}
cp -p ${LIB_PATH}/Projects/STM3210E_EVAL/Templates/Src/stm32f1xx_hal_msp.c ${PROJECT_DIR_PATH[${PROJECT_DIR_NAME[2]}]}
}

function copy_std_lib_files()
{
cp -pr ${LIB_PATH}/Libraries/STM32F10x_StdPeriph_Driver/src ${PROJECT_DIR_PATH[${PROJECT_DIR_NAME[0]}]} # STM32F10x_FWLib
cp -pr ${LIB_PATH}/Libraries/STM32F10x_StdPeriph_Driver/inc ${PROJECT_DIR_PATH[${PROJECT_DIR_NAME[0]}]} # STM32F10x_FWLib

cp -p ${LIB_PATH}/Libraries/CMSIS/CM3/CoreSupport/core_cm3.c ${PROJECT_DIR_PATH[${PROJECT_DIR_NAME[1]}]} # CORE
cp -p ${LIB_PATH}/Libraries/CMSIS/CM3/CoreSupport/core_cm3.h ${PROJECT_DIR_PATH[${PROJECT_DIR_NAME[1]}]} # CORE
cp -p ${LIB_PATH}/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/startup/arm/${STD_STARTUP_NAME} ${PROJECT_DIR_PATH[${PROJECT_DIR_NAME[1]}]} # CORE

cp -p ${LIB_PATH}/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/stm32f10x.h ${PROJECT_DIR_PATH[${PROJECT_DIR_NAME[2]}]} # USER
cp -p ${LIB_PATH}/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/system_stm32f10x.c ${PROJECT_DIR_PATH[${PROJECT_DIR_NAME[2]}]} # USER
cp -p ${LIB_PATH}/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/system_stm32f10x.h ${PROJECT_DIR_PATH[${PROJECT_DIR_NAME[2]}]} # USER

cp -p ${LIB_PATH}/Project/STM32F10x_StdPeriph_Template/main.c ${PROJECT_DIR_PATH[${PROJECT_DIR_NAME[2]}]} # USER
cp -p ${LIB_PATH}/Project/STM32F10x_StdPeriph_Template/stm32f10x_conf.h ${PROJECT_DIR_PATH[${PROJECT_DIR_NAME[2]}]} # USER
cp -p ${LIB_PATH}/Project/STM32F10x_StdPeriph_Template/stm32f10x_it.c ${PROJECT_DIR_PATH[${PROJECT_DIR_NAME[2]}]} # USER
cp -p ${LIB_PATH}/Project/STM32F10x_StdPeriph_Template/stm32f10x_it.h ${PROJECT_DIR_PATH[${PROJECT_DIR_NAME[2]}]} # USER

}

function copy_files_to_project()
{
cd ${PROJECT_ROOT_PATH}
echo -e "${WHITE}# CURRENT_PATH : $(pwd)${CLS}"

# 创建相关目录
for DIR_NAME in ${PROJECT_DIR_NAME[@]}
do
if [ ! -d "${PROJECT_ROOT_PATH}/${DIR_NAME}" ];then
mkdir -v ${PROJECT_ROOT_PATH}/${DIR_NAME}
else
echo -e "${YELLOW}[WARN]${DIR_NAME} 目录已存在!!!${CLS}"
fi
PROJECT_DIR_PATH[${DIR_NAME}]=${PROJECT_ROOT_PATH}/${DIR_NAME}
done
#打印所有key值
echo -e "${GREEN}[INFO]${!PROJECT_DIR_PATH[*]}${CLS}"
#打印所有value
echo -e "${GREEN}[INFO]${PROJECT_DIR_PATH[*]}${CLS}"
# 拷贝相关文件
if [ "${PROJECT_TYPE}" == "STD_lib_project" ];then
copy_std_lib_files
exit
elif [ "${PROJECT_TYPE}" == "HAL_lib_project" ];then
copy_hal_lib_files
exit
fi

}
##======================================================
# 功能实现
echo_menu
copy_files_to_project

使用脚本的话,我们需要的文件如下:

image-20230422193626656

反正这几个目录还有这个脚本放在同一级目录下就可以了,执行完脚本,目录结构如下:

image-20230422193850860

4. MDK工程创建

4.1 创建空工程

  • (1)创建工程

点击 MDK 的菜单 :【Project】 →【New Uvision Project】 ,然后将目录定位到刚才建立的文件夹”Template” 之下,我们的代码工程文件放在 USER 目录,这个目录就看个人喜好了,也可以命名成别的,注意在上一步创建目录的时候改掉就好了。

image-20230422194207858

然后定位到 USER 目录下面,我们的工程文件就都保存到 USER 文件夹下面。工程命名为Template,点击保存。

image-20230422194517713
  • (2)选择芯片型号

接下来会出现一个选择 CPU 的界面,就是选择我们的芯片型号。 因为我使用的 STM32 型号为 STM32F103ZET6,所以在这里我们选【STMicroelectronics】 →【STM32F1 Series】→【STM32F103】→【STM32F103ZET6】(如果使用的是其他系列的芯片,选择相应的型号就可以了,特别注意: 一定要安装对应的器件 pack 才会显示这些内容。

image-20230422194758191
  • (3)点击 OK, MDK 会弹出 Manage Run-Time Environment 对话框,
image-20230422194844337

这是 MDK5 新增的一个功能,在这个界面,我们可以添加自己需要的组件,从而方便构建开发环境,我们直接点击 Cancel 即可。然后工程框架就就创建好啦:

image-20230422194945952

4.2 添加文件到工程

我们按照之前拷贝文件的目录结构,来在工程中创建相应的文件夹来管理代码:

image-20230422193850860

这里以标准库工程为例:

image-20230422200342045

(1)Project Targets 一栏,我们将 Target 名字修改为 Template,然后在 Groups 一栏删掉一个 SourceGroup1,建立三个 Groups: USER,CORE,FWLIB。然后点击 OK,可以看到我们的 Target名字以及 Groups 情况。

(2)往 Group (USER,CORE,FWLIB)里面添加我们需要的文件。

STM32F10x_FWLib/src 下面,将里面所有的文件选中(Ctrl+A),然后点击 Add,然后 Close 。这里需要说明一下,对于我们写代码,如果我们只用到了其中的某个外设,我们就可以不用添加没有用到的外设的库文件。例如我只用 GPIO,我可以只用添加 stm32f10x_gpio.c 而其他的可以不用添加。这里我们全部加进来是为了后面方便,不用每次添加,当然这样的坏处是工程太大,编译起来速度慢,用户可以自行选择。

用同样的方法,将 Groups 定位到 CORE 和 USER 下面,添加需要的文件。这里我们的 CORE 下面需要添加的文件为 core_cm3.c, startup_stm32f10x_hd.s (注意,默认添加的时候文件类型为.c,也就是添加 startup_stm32f10x_hd.s 启动文件的时候,需要选择文件类型为 All files 才能看得到这个文件), USER 目录下面需要添加的文件为 main.c, stm32f10x_it.c,system_stm32f10x.c。

最终我们的工程目录就如下所示:

image-20230422201234276

右边的图有些文件为什么带个钥匙标记?因为这些文件是只读的。

4.3 编译中间文件位置

  • 设置编译中间文件编译后存放目录

方法是点击魔术棒,然后选择“Output”选项下面的“Select folder for objects…” ,然后选择目录为我们上面新建的 OBJ 目录。 这里大家注意,如果我们不设置 Output 路径,那么默认的编译中间文件存放目录就是 MDK 自动生成的 Objects 目录和 Listings 目录。

image-20230422201648391

如果我们没有设置的话,将会在工程文件所在的目录生成这个两个目录:

image-20230423120452381

4.4 头文件位置

接下来我们编译一下工程,我们会发现全是这种报错:

image-20230422201734069

这是因为编译的时候找不到头文件位置导致的,我们要注意对于任何一个工程,我们都需要把工程中引用到的所有头文件的路径都包含到进来。 回到工程主菜单,点击魔术棒图标,会弹出来一个菜单,然后点击 c/c++选项.然后点击Include Paths 右边的按钮。弹出一个添加 path 的对话框,然后我们将图上面的 3 个目录添加进去。记住, keil 只会在一级目录查找,所以如果目录下面还有子目录,记得 path一定要定位到最后一级子目录,然后点击 OK。

image-20230422202101155

对于HAL库工程也是一模一样的操作。

4.5 全局宏定义与报错解决

  • (1)标准库创建的工程

我们再编译程序,会发现还是有很多警告和报错:

image-20230422202608565

这是因为库函数在配置和选择外设的时候通过宏定义来选择的,所以我们需要配置一个全局的宏定义变量。 我们还是在添加头文件路径的选项卡中,我们定位到 c/c++界面,然后填写

1
STM32F10X_HD,USE_STDPERIPH_DRIVER

到 Define 输入框里面(请注意,两个标识符中间是逗号不是句号。如果用的是中容量那么STM32F10X_HD 修改为 STM32F10X_MD,小容量修改为 STM32F10X_LD,然后点击 OK。

image-20230422203009385

然后我们再编译,会发现,竟然还有一个错,这里明显是说打不开这个头文件,我们双击这个错误,MDK会自动定位到出错的地方。

image-20230422203051400

这个错误出现在main.c中,这是因为这个main.c使我们从标准库的模板中复制出来的,主函数中添加了一些对应的评估板的东西,而调用到了这个头文件,但实际上我们并不需要这些,我们吧main.c文件内容改成这样,以后添加自己的代码就好,之前的可以不要:

1
2
3
4
5
6
#include "stm32f10x.h"

int main(void)
{
return 0;
}

然后我们再编译就不会报错啦,这样我们就得到了一个没有error,没有warn的工程模板啦:

image-20230422203630724
  • (2)HAL库创建的工程

上边是标准库的一些问题和解决方法,那么HAL库呢? 首先对于HAL库的话在 c/c++界面 填写一下宏:

1
USE_HAL_DRIVER,STM32F103xE

然后我们编译,会看到如下情况:

image-20230422220056965

会发现有3个error,全都是打不开这个文件,这个跟标准库,我们其实并没有用到这个文件,这里的引用删掉就好啦,然后我们继续编译,神奇的事情发生了,报错更多了:

image-20230422220233554

这些都是在报一些个符号重定义,这几个报错涉及到以下三个文件:

stm32f1xx_hal_msp_template.c 文件内容是一些空函数,一般不需要引入到工程中,我们从工程中去掉这个文件。

stm32f1xx_hal_timebase_tim_template.c和stm32f1xx_hal_timebase_rtc_alarm_template.c里边的没有研究过,不过看命名,应该也是一些例子之类的,他们并不是我们需要的驱动文件,我们把这两个文件也去掉。

image-20230422220926951

我们将这三个文件从工程中删除,然后重新编译工程,然后我们就得到了一个0error 0warn的工程啦:

image-20230422221042807

5. MDK5使用技巧

5.1 文本美化

文本美化,主要是设置一些关键字、注释、数字等的颜色和字体。MDK 提供了我们自定义字体颜色的功能。我们可以在工具 条上点击扳手的图标,在该对话框中,先设置 Encoding 为:Chinese GB2312(Simplified),然后设置 Tab size 为: 4。以更好的支持简体中文(否则,拷贝到其他地方的时候,中文可能是一堆的问号),同时 TAB间隔设置为 4 个单位。

image-20230422221818922

然后我们来到Colors&Fonts 选项卡,在该选项卡内,我们就可以设置自己的代码的子体和颜色了。由于我们使用的是 C 语言,故在 Window 下面选择: C/C++ Editor Files在右边就可以看到相应的元素了。

image-20230422221856733

在这里我们也可以自定义关键字美化,比如我们有一个自定义数据类型 u8,我们首先添加用户关键字,然后设置用户关键字的颜色:

image-20230422222548096

然后就会有以下效果啦:

image-20230422222645726

5.2 语法检测&代码提示

MDK5 支持代码提示与动态语法检测功能,使得 MDK 的编辑器越来越好用了, 我们打开配置对话框,选择 Text Completion 选项卡 :

image-20230422222822521

Strut/Class Members,用于开启结构体/类成员提示功能。

Function Parameters,用于开启函数参数提示功能。

Symbols after xx characters,用于开启代码提示功能,即在输入多少个字符以后,提示匹配的内容(比如函数名字、结构体名字、变量名字等),这里默认设置 3 个字符以后,就开始提示。

Dynamic Syntax Checking,则用于开启动态语法检测,比如编写的代码存在语法错误的时候,会在对应行前面出现 × 图标,如出现警告,则会出现感叹号图标,将鼠标光标放图标上面,则会提示产生的错误/警告的原因,如下图 。

image-20230422223059197

这几个功能,对我们编写代码很有帮助,可以加快代码编写速度,并且及时发现各种问题。不过这里要注意,语法动态检测这个功能, 有的时候会误报,自己确定无关紧要的可以不用理会,只要能编译通过(0 错误, 0 警告),这样的语法误报,一般直接忽略即可。

二、 STM32CubeMX

1. STM32CubeMX简介

STM32CubeMX是ST意法半导体推出的STM32系列芯片图形可视化配置工具,用户可以通过图形化向导为Cortex-M系列MCU生成初始化代码工程模板。相较于Keil创建工程模板, STM32CubeMX步骤少、上手快,但生成的工程模板比较臃肿,此部分简单介绍下相关创建操作,其实我们也可以使用自己自定义创建工程模板。我们其实也无需纠结使用哪一种方法,以后熟悉后,自然知道修改哪些内容, 在两种方式之间任意转换。

image-20230419230755825

这个软件有哪些优势?

① 直观的选择 MCU 型号,可指定系列、封装、外设数量等条件;

② 微控制器图形化配置;

③ 自动处理引脚冲突;

④ 动态设置时钟树,生成系统时钟配置代码;

⑤ 可以动态设置外围和中间件模式和初始化;

⑥ 功耗预测;

⑦ C 代码工程生成器覆盖了 STM32 微控制器初始化编译软件,如 IAR, KEIL, GCC;

⑧ 可以独立使用或者作为 Eclipse 插件使用;

⑨ 可作为 ST 的固件包、芯片手册等的下载引擎;

对于 STM32CubeMX 和 STM32Cube 的关系这里我们还需要特别说明一下, STM32Cube 包含 STM32CubeMX 图形工具和 STM32Cube 库两个部分,使用 STM32CubeMX 配置生成的代码,是基于 STM32Cube 库的。也就是说,我们使用 STM32CubeMX 配置出来的初始化代码,和STM32Cube 库兼容,例如硬件抽象层代码就是使用的 STM32 的 HAL 库。不同的 STM32 系列芯片,会有不同的 STM32Cube 库支持,而 STM32CubeMX 图形工具只有一种。所以我们配置不同的 STM32 系列芯片,选择不同的 STM32Cube 库即可。两者的关系如下图:

image-20240113124546529

2. 软件下载安装

下边两个软件安装的话一直下一步就是了,没什么难度,需要注意的是安装目录最好不要有中文路径。

2.1 Java运行环境

这个软件好像是Java写的,所以要想运行还需要安装Java运行环境。下载地址:Download Java for Windows(尽量安装最新版 64 位的Java)

image-20240113124802764

安装完 Java 运行环境之后,为了检测是否正常安装,我们可以打开 Windows 的命令输入框,输入: java -version 命令,如果显示 Java 版本信息,则安装成功。提示信息如下图:

image-20240113125006061

2.2 STM32CubeMX

文档地址:STM32CubeMX - STM32Cube initialization code generator - STMicroelectronics

下载地址:STM32CubeMX - STM32Cube initialization code generator - STMicroelectronics

image-20230419231334830

3. 基本使用

3.1 加载芯片支持包

【Help】→【Manage embedded software packages】

image-20230419231808046

然后我们便会打开如下弹窗,然后我们按照图中提示安装相关的包即可:

image-20230419231948987

若是安装完毕,并且安装成功,前边会变成如下的小绿色方框:

image-20230419232108324

其实也可以离线下载支持包,然后离线加载,这里暂时还未尝试,后边需要的话再补充。

3.2 创建工程

  • (1)【File】→【New Project】
image-20230419232250397
  • (2)【选择芯片型号】→【Start Project】
image-20230419232522160
  • (3)【Project Manager】→【Project】
image-20230419232829564
  • (4)【Project Manager】→【Code Generator】
image-20230419233134342
  • (5)点击右上角的全大写的【GENERATE CODE】然后等待生成工程即可
image-20230419233340030

3.3 HAL库和支持包在哪?

后来偶然一次发现了HAL库的安装位置,包括前边在线安装的芯片支持包,他们在这里:

1
C:\Users\用户名\STM32Cube\Repository
image-20230521074440279 image-20230521074456274