STM32 工程的创建 - 基于寄存器或标准库
目前 STM32 的开发方式有 3 个层次:
- 基于寄存器方式。极少的人使用这种形式。这种方式最底层、最直接、效率更高,但 STM32 寄存器十分复杂,一般不建议采取这种方式。
- 基于标准库(库函数)方式。使用 ST 官方提供封装好的函数,通过调用函数间接配置寄存器。这种方式对开发人员比较友好,有利于提高开发效率。
- 基于 HAL 库方式。HAL 库是 ST 公司目前主力推的开发方式,全称就是 Hardware Abstraction Layer(抽象印象层)。可以使用图形化界面快速配置 STM32,隐藏底层的逻辑。
这里介绍基于寄存器或标准库方式创建 STM32 工程(以 STM32F103C8T6 为例,其它型号大差不差),并通过点灯演示示例。基于 HAL 库方式请移步:STM32 工程的创建 - 基于 HAL 库
软件安装提示:阅读前请准备好 Keil uVision5 MDK 的安装(可以和 Keil C51 安在一起),软件需破解。安装和破解过程不再赘述。Keil 的一些使用技巧可以看这篇文章:Keil 的使用技巧与问题解决
LED 点灯实验工具准备:
- ST-LINK
- STM32(以 STM32F103C8T6 最小核心板为例)
- 杜邦线若干
固件库下载
进入官网: https://www.st.com/
右上角选择中文。根据菜单选择:工具与软件>嵌入式软件>STM32 微控制器软件。
选择标准外设软件库,选择 F1 系列。
点击获取最新版本进行下载。
解压后得到固件库文件夹:
1 | STM32F10x_StdPeriph_Lib_V3.6.0 |
注意上面带【A】【B】【C】【D】【E】【F】标号的文件位置,后面会有相应操作。
新建项目
打开 Keil,选择 Project>New uVision project。
- 选择你要存放项目的文件夹(这个文件夹下有多个项目)
- 再新建一个文件夹(这个文件夹存放一个项目的所有东西,文件夹名称以后可以方便改)
- 选择新的空文件夹进入,设置工程的名字(比如这里为
STM32-proj
)。工程的名字可以设置为通用的名字(以后不太方便改)。
注意路径名称 不要有中文。
新建工程后,选择 STM32F103C8:
我们可以把弹出的新建工程小助手给关掉,这里暂时不演示其的使用。
我们就得到以下文件结构:
库函数移植
接下来我们将新建多个文件夹以对新文件进行分类,每个人有不同的风格,我这里就演示 江科大 的风格。
在项目文件夹中新建 Start 文件夹,并按照以下要求进行操作:
- 把固件库文件夹中【A】文件夹下的所有
.s
文件复制到这里。 - 把固件库文件夹中【B】标识的三个文件也复制到这里。
- 把固件库文件夹中【C】文件夹下的所有文件(2 个文件)复制到这里。
回到 Keil,现在将我们新建的 Start 添加到工程。
至于确定自己芯片型号的缩写,可看文末介绍。STM32F103C8T6 应选择后缀为
md
的启动文件。
同样的方法也将这几个也加进来,结果如下图:
上图中 Start 组里的文件我们是不需要进行修改的。(我们还可以在电脑文件管理器中将这些文件设置为只读,这样可以避免误修改。这时上图的文件图标上就会带有一把小钥匙,表示这是只读文件。)
接下来为工程添加头文件路径,不然编译的时候找不到头文件:
然后两次 OK,退出魔术棒弹窗。
main 函数
新建 User 文件夹(同样也是 江科大 的风格):
回到 Keil,新建组,并改名为 User。
在组里面新建文件:
进入 main.c,插入头文件:
main.c 内容如下:
1 |
|
选择编译并建立工程:
下面的提示栏显示 0 错误,0 警告,说明工程建立没问题:
基于寄存器开发 STM32 工程创建结束
进行到这里时并没有使用库函数。如果想用寄存器开发 STM32,那么新建一个工程到这里就结束了。可以继续阅读下面两节进行寄存器点灯操作。
接线与调试器配置
接线图:
注意,当你使用的引脚标号位置与上图不一致时,请以你使用的器件为准。
调试器配置:
继续点击 Setting,设置下载程序后立即复位运行,这样比较方便。否则下载之后都需要按一下复位按钮才能执行程序。
重新编译一下。
基于寄存器的 LED 点灯
本小节可略读。
接下来通过寄存器点亮连接 PC13(就在最小核心板上)的 LED 灯:
1 |
|
编译后没有错误即可下载:
程序现象为最小核心板的 PC13 连接的 LED 灯点亮。
基于寄存器编程代码简洁,但需要不断查询手册,过程比较繁杂。且为了不影响寄存器中的其它位,还需要进行 |=
和 &=
操作。
为工程添加库函数
新建 Library 文件夹(同样也是 江科大 的风格):
在项目文件夹中新建 Library 文件夹,并按照以下要求进行操作:
- 把固件库文件夹中【D】文件夹下的所有
.c
文件复制到这里。 - 把固件库文件夹中【E】文件夹下的所有
.h
文件复制到这里。
回到 Keil 软件,和 Start 文件夹的操作类似(往上翻复习一下)。添加组并命名 Library,添加已经存在的文件(Library 下所有的 .c
和 .h
文件,注意文件类型筛选器选择 All Files)。结果为:
Library 中的这些文件我们也不需要更改,可以把它们的权限设置为只读。
在项目文件夹中之前建立的 User 文件夹(存放 main.c 函数的文件夹)中:
- 把固件库文件夹中标记【F】的 3 个文件复制到这里。
回到 Keil 软件,把这三个文件也添加到 User 组里。
我们的 main.c 中第一行中添加了头文件 #include "stm32f10x.h"
,将光标放在头文件名中,右键选择打开头文件。我们看到一个条件编译:
意思是如果定义了 USE_STDPERIPH_DRIVER
(使用标准外设驱动)字符串,就引用 stm32f10x_conf.h
。接下来打开魔术棒(工程选项),将字符串粘贴到这里:
这样才能包含标准外设库。
STM32F10X_MD
字符串 Keil 已经定义好,不需要我们手动定义。
最后别忘了把 User 和 Library 文件夹添加到头文件路径中:
顺便提一点,在这个按钮中我们可以根据喜好调整组的顺序或向组添加文件(比如把 Start 和 Library 这些不需要更改的文件往上移):
到这里,重新编译一下,检查是否有错。
其实所有的
.h
文件是可以不必加到组里的。编译一次后 Keil 中也能看到.h
文件。这里我们还是沿用 江科大 的风格。
基于库函数的 LED 点灯
main.c 函数:
1 |
|
编译并下载,观察输出高电平或低电平的实验现象。
至此,基于标准库开发 STM32 工程创建及示例介绍完毕。
如果 GPIO_InitTypeDef
放在 RCC_APB2PeriphClockCmd
之后,编译时有时候会产生这种错误:
编译错误
error: #268: declaration may not appear after executable statement in block
解决方法见:Keil 的使用技巧与问题解决。
其它
移植 FreeRTOS
进一步,你可以尝试移植 FreeRTOS,详看:STM32 移植 FreeRTOS - 基于标准库
STM32 型号分类及缩写
缩写 | 释义 | Flash 容量 | 型号 |
---|---|---|---|
LD_VL | 小容量产品超值系列 | 16~32K | STM32F100 |
MD_VL | 中容量产品超值系列 | 64~128K | STM32F100 |
HD_VL | 大容量产品超值系列 | 256~512K | STM32F100 |
LD | 小容量产品 | 16~32K | STM32F101/102/103 |
MD | 中容量产品 | 64~128K | STM32F101/102/103 |
HD | 大容量产品 | 256~512K | STM32F101/102/103 |
XL | 加大容量产品 | 大于 512K | STM32F101/102/103 |
CL | 互联型产品 | - | STM32F105/107 |
STM32F103C8T6 的 Flash 容量为 64K。
工程架构
我们可以再捋一遍我们建立的工程的架构:
startup_xx.s:程序执行最基本的文件,定义了中断向量表,中断服务函数等。复位中断为程序的入口。