目录
(4)Keil工程中新建“Library”组并添加库函数相关文件
(2)工程文件夹里建立Start、Library、User等文件夹,复制固件库里面的文件到工程文件夹;
(3)工程里对应建立Start、Library、User等同名称的分组,然后将文件夹内的文件添加到工程分组里;
(4)工程选项,C/C++,Include Paths内声明所有包含头文件的文件夹;
(5)工程选项,C/C++,Define内定义USE_STDPERIPH_DRIVER;
(6)工程选项,Debug,下拉列表选择对应调试器,Settings,FlashDownload里勾选Reset and Run。
1. stm32f10x.h与core_cm3.c/.h:外设和内核外设的寄存器描述
2. misc.c/.c stm32f10x_adc.c/.h...库函数及库函数配置文件
3. stm32f10x_conf.h:配置头文件的包含关系
1. STM32开发方式
目前STM32的开发方式主要有以下几种:
- 方式1:基于寄存器。和51单片机的开发方式一样,使用程序直接配置寄存器来实现想要的功能。该方式最底层、最直接、效率更高一些,但是由于STM32的结构复杂,寄存器太多,所以基于寄存器的方式目前是不推荐的。
- 方式2:基于标准库。也就是库函数的方式,该方式是使用ST官方提供的封装好的函数,通过调用这些函数来间接地配置寄存器。由于ST对寄存器封装的比较好,所以这种方式既能满足对寄存器的配置,对开发人员也比较友好,有利于提高开发效率。(本课程使用该方式进行开发)
- 方式3:基于HAL库。可以用图形化界面快速配置STM32,该方式比较适合快速上手STM32的情况,但是这种方式隐藏了底层逻辑。如果对STM32不熟悉,基本只能停留在很浅的水平,因此不推荐先试用HAL库进行开发。但可以学习完标准库后再了解一下该方式。
2. STM32库函数文件目录
STM32的工程结构较为复杂,需要用到很多文件。之后开发用到的代码也都是需要建立在工程结构上的,所以在开始学习后续内容之前需要学习如何新建STM32的工程。
使用库函数的方式进行开发,需要准备STM32库函数的压缩包。文件夹目录如下:
- _htmresc:Logo图片,无用。
- Libraries:库函数的文件,在新建工程时需要使用。
- Project:官方提供的工程示例和模板,以后使用库函数的时候可以参考。
- Utilities:STM32官方评估板的相关例程。评估板是官方用STM32做的一个小电路板,用来测评STM32。该文件夹中存放的就是小电路板的测评程序。
- Release_Notes.html:库函数的发布文档。
- stm32f10x_stdperiph_lib_um.chm:库函数的使用手册。
3. 新建基于寄存器开发的STM32工程
(1)建立存放工程的文件夹
新建文件夹,文件名为“STM32Project”,以后的工程都存放在该文件夹下,这样方便工程管理。STM32工程可参照以下目录创建:
一级目录 | 二级目录 | 三级目录 |
STM32Project | ||
工程名称(根据具体作用命名) | ||
Project(通用项目名称) |
(2)打开Keil5软件新建并保存工程
点击Project---New uVision Project---工程存放路径存放至刚新建的文件夹下。在此路径需要再新建一个文件夹用于存放本次工程。---工程文件名推荐使用通用名称:“Project”。工程具体的作用可以在文件夹名称中进行说明,比如“2-1 STM32工程模板”。文件夹的名称是很方便改的,但项目名称不容易更改。



(3)选择器件型号
Software Packs---STMicroelectronics---STM32F1 Series---STM32F103C8。

点击OK后会弹出一个Manage Run-Time Environment的窗口,这是Keil软件的一个新建工程小助手,可以帮助快速新建工程,暂时不需要该助手,关闭即可。

(4)从固件库中选取必要的工程文件添加到项目文件夹下
相关资料下载链接:资料下载
选择“STM32入门教程资料”资料进行下载,该文件中有下述步骤用到的固件库。
① 必要文件1:启动文件
路径:STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm

STM32的程序从启动文件开始执行的,将以上文件全部复制粘贴到工程项目文件夹中。在该文件夹中新建一个文件夹,名为“Start”,并把文件粘贴进去。
关于新建工程的启动文件选择办法,详情见:[拓展知识1] 新建工程的启动文件选择。
② 必要文件2:外设寄存器描述及时钟配置文件
路径 :
STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x
- 文件1:stm32f10x.h
STM32的外设寄存器描述文件,它的作用和51单片机的头文件REGX52.H相同,用来描述STM32有哪些寄存器和它对应的地址。
- 文件2:system_stm32f10x.c
- 文件3:system_stm32f10x.h
system_stm32f10x.c和system_stm32f10x.h两个system文件是用来配置时钟的,STM32主频72MHz,就是system文件里的函数配置的。
同样也需要将这三个文件复制下来,也粘贴到Start文件夹下。

③ 必要文件3:内核寄存器描述文件
STM32是由内核和内核外围的设备组成的,而且内核的寄存器描述和外围设备的描述文件不是在一起的,所以还需要添加一个内核寄存器的描述文件。
路径:
STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\CoreSupport

core_cm3.c和core_cm3.h这两个cm3(Cortex-M3)文件就内核的寄存器描述,它同样带了一些内核的配置函数,因此多了个.c文件。将这两个文件复制下来,也粘贴到Start文件夹下。
到此为止,工程的必要文件就复制完成了。
(5)将第4步的必要文件添加到工程中



启动文件需要选择:“startup_stm32f10x_md.s”文件。
工程中Start文件夹内容参考如下图,具体有:①启动文件;②内核寄存器描述文件;③外设寄存器描述及时钟配置文件。

文件图标上的小钥匙图标,表示该文件是只读文件,内部的信息是不允许修改的。
(6)在工程选项中添加第4步新建文件夹的头文件路径
需要在工程选项中添加新建文件夹的头文件路径,否则软件无法找到.h文件的。


(7)新建main函数,验证工程是否可以正常运行
① 新建“User”文件夹
打开工程文件夹,新建文件夹并命名为“User”,main函数放到该文件夹中。

② 工程项目中添加New group并命名为“User”

③ User文件夹中添加新的C文件,命名为“main.c”
注意添加头文件路径。



④ 在新建的“main.c”文件中输入代码并编译
注意文件内部代码的最后一行必须是空行,否则编译器会报出警报。

代码编辑完成后,点击左上角的"Build",进行编译并建立工程。
若下面Build Output窗口给出的提示信息是:"0 Error(s), 0 Warning(s)"就证明我们新建的工程没问题,可以正常运行。
该工程还没有添加STM32的库函数,所以它还只是一个基于寄存器开发的工程,如果想用寄存器开发STM32,那么工程建到这里就可以了。
4. 新建基于标准库开发的STM32工程
(1)在工程文件夹中新建文件夹并命名为“Library”
注意添加头文件路径。
在“3. 新建基于寄存器开发的STM32工程”的基础上,继续在工程文件夹下添加新文件夹并命名为“Library”,用于存放库函数。
(2)在“Library”文件夹中添加库函数的源文件
路径:STM32F10x_StdPeriph_Lib_V3.5.0\STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\STM32F10x_StdPeriph_Driver\src
Ctrl+A全选复制并粘贴到工程文件夹的“Library”文件夹下。

其中,“misc.c”是内核的库函数,其他的就是内核外的外设库函数了。mics是混杂的意思,ST公司将内核的库函数放置到杂项中。
(3)在“Library”文件夹中添加库函数的头文件
路径:
STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\STM32F10x_StdPeriph_Driver\inc
Ctrl+A全选复制并粘贴到工程文件夹的“Library”文件夹下。

(4)Keil工程中新建“Library”组并添加库函数相关文件


到此,所有库函数相关的文件都已添加到工程项目当中。

(5)添加库函数必要的配置文件
对于这个库函数来说,目前还无法使用,我们需要再添加必要的配置文件。
路径:
STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Template
conf(configuration)文件用来配置库函数头文件的包含关系的,其中还有用于参数检查的函数定义,这是所有库函数所必须的。两个it(interrupt)文件用于存放中断函数的。
将这三个文件复制并粘贴到项目文件夹的“User”文件夹下,并在Keil5软件中将文件添加到“User”组中。
(6)添加宏定义

打开文件后下拉到8296行,这里有一个条件编译,意思是如果你定义了USER_STDPERIPH_DRIVER这个字符串,下面的“#include”语句才有效。

复制该字符串, 打开工程选项进行设置。包含标准外设库,也就是库函数。


可以看到库函数文件基本都是仅可读,不可更改的文件。在开发过程中我们唯一需要更改的就只有“User”组中的文件。
5. 基于寄存器开发和标准库开发的区别
这里的代码案例仅进行基于寄存器开发和基于标准库开发的对比,具体代码详解请参考后续的项目讲解文章。
(1)基于寄存器开发
以最简单的点亮一颗LED小灯项目为例,基于寄存器开发的方式需要不断地查手册来了解每个寄存器的每一位是什么作用。基于寄存器开发方式虽然代码简洁,但不大方便。
基于寄存器开发方式的点亮LED灯案例代码
(2)基于库函数开发
库函数其实也是间接地配置寄存器,所以步骤是相同的。

首先使能时钟,库函数中有使能时钟的RCC_APB2PeriphClockCmd函数来开启时钟。可右键跳跃到该函数的宏定义。其中有函数的简洁和参数说明。
经过函数的包装,我们不需要去查询手册看寄存器设置。基于库函数开发的代码虽然比较长,但语义更加明确,也不需要查表计算寄存器的值。我们只需要调用库函数,按照它的提示,把参数填好即可。所以说从这点对比来看,库函数比寄存器开发是有很大优势的。
6. 新建工程步骤总结
(1)建立工程文件夹,Keil中新建工程,选择型号;
(2)工程文件夹里建立Start、Library、User等文件夹,复制固件库里面的文件到工程文件夹;
这一步是为了添加工程文件准备的,建立文件夹是因为文件比较多,需要进行分类管理。文件夹的数量和名称没有限制,可以根据自己的理解来创建。
Tips:需要用到文件一定要复制到工程文件夹里,不要添加工程文件夹外面的文件。否则外面的文件一旦位置变动,工程里就无法正常找到文件了。因此需要复制文件到工程中,确保工程的独立性。
(3)工程里对应建立Start、Library、User等同名称的分组,然后将文件夹内的文件添加到工程分组里;
此步骤是为了方便在Keil中管理文件,因为Keil没法直接添加文件夹,在Keil中添加组,然后添加文件。
Tips:.h文件不参与编译,很多工程一般只添加.c文件,而.h文件并不添加进Keil分组中的。但将.h文件添加进工程比较方便,而且.h文件也需要经常打开查看,因此也可以将.c与.h文件都添加到工程中。
(4)工程选项,C/C++,Include Paths内声明所有包含头文件的文件夹;
由于Start、Library等文件夹都是自己创建的,Keil软件并不知道,如果要用自己文件夹中的.h文件,就必须声明一下该文件夹的路径。因此最好将所有新建的文件夹都声明一下路径,这样就可以避免.h文件无法找到的问题。
(5)工程选项,C/C++,Define内定义USE_STDPERIPH_DRIVER;
这是使用库函数的条件编译,使用库函数就必须定义该使用标准外设驱动的字符串。
(6)工程选项,Debug,下拉列表选择对应调试器,Settings,FlashDownload里勾选Reset and Run。
选择调试器并进行下载,本教程选择ST-LINK。
[拓展知识1] 新建工程的启动文件选择
新建工程第一个加的就是启动文件,这个启动文件有很多类型,选择哪一个需要根据芯片的型号来选择。下表是STM32F1系列中的型号分类,其中根据Flash的大小,分为了小容量、中容量、大容量、加大容量等产品。
如果使用STM32F100的型号,就选择带VL的启动文件,然后再根据Flash的大小来选择LD、MD还是HD。如果使用STM32F101/102/103的型号,就选择不带VL的,然后再根据Flash的大小来进行选择。

[拓展知识2] Keil工程架构
为了更好地理解工程,我们需要了解工程中每个文件的作用,以及为什么需要这些文件。

主动执行部分
1.startup_xx.s:启动文件
(1)复位中断
这是程序执行最基本的文件,Keil中启动文件是用汇编语言写的,启动文件内定义了中断向量表、中断服务函数等内容。这个中断服务函数有个“复位中断”,这是整个程序的入口。当STM32上电复位或者按下复位键后,程序就会进入复位中断函数执行。复位中断函数主要做两件事:调用SystemInit、调用main。

(2)其他中断
这些中断达到触发条件后会自动执行。中断函数的定义在“stm32f10x_it.c/.h”中。
2. system_xx.c/ .h:设置微控制器启动
初始化嵌入式闪存接口、锁相环、更新系统内核的时钟变量。我们需要知道,在main函数执行之前,单片机就已经执行一部分预处理任务了,将闪存接口、时钟等一系列碎片化的部分配置好。
3. 其他用户文件
用户可以自己定义一些用户文件,来封装一些模块供主函数和中断函数调用。这样有利于程序结构的模块化,否则将所有程序都堆积在主函数不美观。
以上是工程结构中“主动执行”的部分,图片最右侧为“被动执行”的部分。
被动执行部分
被动执行部分相当于STM32的资源,在主函数或中断函数中就可以调用这些资源。
1. stm32f10x.h与core_cm3.c/.h:外设和内核外设的寄存器描述

其中都是寄存器和寄存器每一位的名字,还有地址信息等。如果直接调用这些寄存器来使用STM32,那就是寄存器的开发方式。我们已经尝试过该开发方式有一些弊端,较为麻烦。因此ST公司提供了库函数文件。
2. misc.c/.c stm32f10x_adc.c/.h...库函数及库函数配置文件
每一个外设都提供了大量的函数,这些函数封装了寄存器的操作,给用户提供了更加人性化的函数调用方式,只要学会了操作方法那么配置一个外设是很方便的。

3. stm32f10x_conf.h:配置头文件的包含关系
conf文件include了所有的库函数头文件。

[拓展知识3] Keil5 IDE的使用小技巧
(1)修改字体属性
Keil5默认的字体视觉效果不佳,可能也会遇到中文编码错误显示"????"的问题。可以在"Configuration"中进行字体及编码设置。

工具栏-Configuration...

Colors & Fonts-C/C++ Editor files-Text-Courier New...

根据个人需要,修改字体属性
(2)中文乱码问题解决办法
遇到中文乱码问题时:

Editor-Encode in UTF-8 without signature
(3)设置Tab键大小

Editor-C/C++ files-Tab size: 4