2 软件安装及创建工程
[toc]
注:笔记主要参考B站 江科大自化协 教学视频“STM32入门教程-2023持续更新中”。
注:工程及代码文件放在了本人的Github仓库。
2.1 软件安装
软件安装的步骤有:
- 安装Keil5 MDK。Keil5 MDK专门用于给ARM系列单片机进行编程,而之前的Keil5 C51是用来给51系列的单片机进行编程的。
- 安装器件支持包。只有Keil5才需要这一步,Keil4及之前的版本都不需要。因为现在的ARM芯片层出不穷,不可能每出一款新的芯片就升级整个软件,于是就将芯片的支持包单独拎出来,需要开发那个芯片就安装哪个器件支持包。若不安装器件支持包,那么在创建工程时不会出现对应的芯片型号。
方式一:离线安装。去Keil公司官网的器件支持包下载页面选择对应的公司及器件型号,然后在
Device Family Pack
文本框中点击“Download”。下载完成后在本地直接点击.pack
文件进行安装即可。这个文件会自动识别Keil5文件的安装目录。
方式二:在线安装,速度取决于网速。打开Keil软件点击“Pack Installer”,等待支持的公司及器件列表加载完成。STMicroelectronics公司列表下包含了所有的STM32芯片型号,而GigaDevice公司、MindMotion公司对于国产STM32芯片的兼容都很不错。然后在右侧的_DFP
文件后点击“Install”即可。
- 软件注册。不破解可能可能会有一些限制,如代码不能超过多少行等。破解软件可以按照UP主提供的百度网盘链接获取,也可以找淘宝店家索取。本质上是根据电脑ID生成密钥。注意破解时勾选ARM选项。
- 安装STLINK驱动。可与先将STLINK插入电脑上,看看设备管理器是否识别,若不识别才需要进行后续的操作。STLINK的驱动安装文件在“Keil安装目录→ARM→STLINK→USBDriver→dpinst_amd64.exe(x86是32位的)”;JLINK的驱动安装文件则在“Keil安装目录→ARM→Segger→JLink.exe”。
- 安装USB转串口驱动。与之前51单片机相同,同样可以先插上看设备管理器能否识别。若不能识别可以直接尝试系统自动安装,或者根据UP提供的“USB转串口CH340驱动”软件安装。
2.2 STM32的开发方式
目前STM32的开发方式主要有:
- 基于寄存器。与51单片机开发流程相同,用程序直接配置寄存器来实现功能。这种方式最底层、最直接、效率最高,但由于STM32结构复杂、寄存器太多,这种方式不推荐。
- 基于标准库(库函数)。使用ST官方提供的封装好的库函数,通过调用这些函数来间接的配置寄存器。由于ST公司对寄存器封装的比较好,所以这种方式不仅可以满足寄存器配置,还可以提升开发效率。也是本节课程使用的方法。
- 基于HAL库。可以使用图形化界面快速配置STM32,适合快速上手STM32。但这种方式隐藏了底层逻辑,不利于对STM32的进一步学习。推荐学习完库函数的方式后,再去了解这种开发方式,可以极大的提升开发效率。
使用库函数进行开发,需要准备STM32库函数。这个库函数由ST公司提供(注意上面的器件支持包是Keil公司提供,不要搞混了),然后参考CSDN博文 “STM32固件库的下载” 便可以找到自己芯片所对应的固件库。要是嫌麻烦可以直接跳转到最后的下载页面,选择对应的版本后(本教程用的是3.5.0)便可以下载。当然,贴心的UP主提供了STM32F10x标准外设库的压缩包“STM32F10x_StdPeriph_Lib_V3.5.0”,解压后文件如下图所示:
- _htmresc:存放两个图片,没啥用。
- Libraries:存放库函数的文件。
- Project:官方提供的工程示例和模板,使用库函数的时候可以参考。
- Utilities:STM32官方评估板的相关例程,这个评估板是STM32官方自己做的小电路板,专门用于测评STM32。
- Release_Notes.html:库函数的发布文档,有一些版本说明。
- stm32f10x_stdperiph_lib_um.chm:使用手册,说明如何使用库函数。
2.3 创建工程-基于寄存器
新建工程步骤:
- 建立工程文件夹,Keil中新建工程,选择型号。
- 工程文件夹里建立Start、User文件夹,复制固件库里面的文件到工程文件夹。
- Start部分1:启动文件,位于固件库文件夹“.\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm”。STM32的程序从启动文件执行。
- Start部分2:位于固件库目录“.\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x”的三个文件。“stm32f10x.h”描述STM32外设寄存器及其对应的地址,作用相当于51单片机中的头文件“REGX52.h”。“system_stm32f10x.h”、“system_stm32f10x.c”主要用于配置时钟,比如配置STM32的主频为72MHz。
- Start部分3:位于固件库目录“.\Libraries\CMSIS\CM3\CoreSupport”的两个文件。“core_cm3.h”、“core_cm3.c”是内核寄存器的描述文件,并且还带了一些内核的配置函数。
- User文件夹:存放用户编写的
main.c
等文件。
- 工程里对应建立Start、User等同名称的分组,然后将文件夹内的文件添加到工程分组里。
- Strart分组:注意启动文件的选择,只需根据下表选择其中一个
.s
文件。
- User分组:注意添加
main.c
文件时,路径要选上User文件夹,否则默认路径在文件外。下面给出main.c文件中的代码:
#include "stm32f10x.h" // Device header
int main(void){
while(1){
}
}
//注意最后一行必须是空着
- 工程选项,C/C++,Include Paths内声明所有包含头文件的文件夹,否则软件找不到
.h
文件。
- 点击魔术棒按钮 → C/C++ → Include Path → 右侧的三个点按钮,添加对应的文件夹即可。
- 要使用STLINK下载程序的话,需要在“魔术棒 → debug → use → ST-Link Debugger”,然后进一步点击右侧的“settings”,在第一个界面“debug”的port选择SW,在第三个界面“Flash Download”勾选Reset and Run”。
- 最后进行编译,通过。点击编译按钮右侧的“Download”按钮,便可以将程序下载在开发板上。
- 若报错,可以试一下点击魔法棒,target → ARMCompiler选择V5.06。
- 注:为了防止乱码问题,可以在扳手工具那里选择UTF-8编码。
工程到目前为止搭建完成。下面展示如何 基于寄存器,点亮LED。
根据上图,核心板上的LED一个连接着GND作为电源指示灯(上电常亮),另一个LED灯则连接STM32芯片的 引脚2-PC13 上。所以现在应该控制PC13引脚的高低电平:
#include "stm32f10x.h" // Device header
int main(void){
//配置RCC寄存器,使能GPIOC的时钟。GPIO都属于APB2外设
RCC->APB2ENR = 0x00000010;
//配置寄存器PC13:通用推挽输出模式、输出模式50MHz
GPIOC->CRH = 0x00300000;
//输出数据寄存器PC13:
GPIOC->ODR = 0x00002000;//LED灭
// GPIOC->ODR = 0x00000000;//LED亮
while(1){}
}
通过编写代码发现,基于寄存器开发STM32有2大弊端:
- 编程过程中需要不断翻看参考手册查看每个寄存器的每一位都是干什么的,十分的繁琐。
- 上述点灯过程中,将寄存器的其他15位输出都配置成立0,会影响其他端口的原有配置。若采用
&=
、|=
的方式会更加麻烦。
2.4 创建工程-基于库函数
新建工程步骤:
- 建立工程文件夹,Keil中新建工程,选择型号。
- 工程文件夹里建立Start、Library、User等文件夹,复制固件库里面的文件到工程文件夹。
- 工程里对应建立Start、Library、User等同名称的分组,然后将文件夹内的文件添加到工程分组里。
- 工程选项,C/C++,Include Paths内声明所有包含头文件的文件夹。
- 工程选项,C/C++,Define内定义USE_STDPERIPH_DRIVER。
- 工程选项,Debug,下拉列表选择对应调试器,Settings,Flash Download里勾选Reset and Run。
基于库函数的开发方式,就是在上述“基于寄存器”开发的基础上,真正引入库函数,并创建文件夹“Library”单独存放。新建工程步骤:
- 建立工程文件夹,Keil中新建工程,选择型号。
- 工程文件夹里建立Start、User、Library文件夹,复制固件库里面的文件到工程文件夹。
- Start部分1:启动文件,位于固件库文件夹“.\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm”。STM32的程序从启动文件执行。
- Start部分2:位于固件库目录“.\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x”的三个文件。“stm32f10x.h”描述STM32外设寄存器及其对应的地址,作用相当于51单片机中的头文件“REGX52.h”。“system_stm32f10x.h”、“system_stm32f10x.c”主要用于配置时钟,比如配置STM32的主频为72MHz。
- Start部分3:位于固件库目录“.\Libraries\CMSIS\CM3\CoreSupport”的两个文件。“core_cm3.h”、“core_cm3.c”是内核寄存器的描述文件,并且还带了一些内核的配置函数。
- Library部分1:位于固件库目录“.\Libraries\STM32F10x_StdPeriph_Driver\src”。其中的
misc.c
是内核的库函数,其他的都是内核外的外设库函数。- Library部分2:位于固件库目录“.\Libraries\STM32F10x_StdPeriph_Driver\inc”。是上述库函数的头文件。
- User部分1:存放用户编写的
main.c
等文件。- User部分2:位于固件库目录“.\Project\STM32F10x_StdPeriph_Template”中的三个文件。“stm32f10x_conf.h”用于配置库函数头文件的包含关系,并且也有用于参数检查的函数定义,所有的库函数都需要。“stm32f10x_it.h”、“stm32f10x_it.c”这两个文件用于存放中断函数。
- 工程里对应建立Start、User、Library等同名称的分组,然后将文件夹内的文件添加到工程分组里。
- Strart分组:注意启动文件的选择,只需根据下表选择其中一个
.s
文件。
- User部分1:注意添加
main.c
文件时,路径要选上User文件夹,否则默认路径在文件外。下面给出main.c文件中的代码:
#include "stm32f10x.h" // Device header
int main(void){
while(1){
}
}
//注意最后一行必须是空着
- User部分2:配置宏定义。要想使"stm32f10x_conf.h"被添加进来,从而使得所有的库函数定义生效,需要宏定义
USE_STDPERIPH_DRIVER
。右击"stm32f10x.h"滑倒最下面,可以看见此条定义语句。打开“魔术棒 → C/C++ → Define项目栏粘贴USE_STDPERIPH_DRIVER
→ OK”。
- 工程选项,C/C++,Include Paths内声明所有包含头文件的文件夹,否则软件找不到
.h
文件。
- 点击魔术棒按钮 → C/C++ → Include Path → 右侧的三个点按钮,将三个文件夹都添加进来。
- 要使用STLINK下载程序的话,需要在“魔术棒 → debug → use → ST-Link Debugger”,然后进一步点击右侧的“settings”,在第一个界面“debug”的port选择SW,在第三个界面“Flash Download”勾选Reset and Run”。
- 最后进行编译,通过。点击编译按钮右侧的“Download”按钮,便可以将程序下载在开发板上。
- 若报错,可以试一下点击魔法棒,target → ARMCompiler选择V5.06。
- 注:为了防止乱码问题,可以在扳手工具那里选择UTF-8编码。
- 小技巧:点击“三个箱子”按钮,可以改变组函数顺序。
工程到目前为止搭建完成。库函数本质上也是间接配置寄存器,所以总体步骤和上面基于寄存器点灯相似。下面展示如何 基于库函数,点亮LED。
#include "stm32f10x.h" // Device header
int main(void){
//1.开启GPIOC的外设时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
//2.配置寄存器PC13的端口模式
// 2.1首先配置GPIO结构体
GPIO_InitTypeDef GPIO_InitStructure;//给结构体起名字
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //寄存器模式为通用推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; //寄存器引脚为13
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出速度为50MHz
// 2.2然后才能调用函数配置寄存器
GPIO_Init(GPIOC, &GPIO_InitStructure);
//3.配置数据寄存器PC13的输出
GPIO_SetBits(GPIOC, GPIO_Pin_13); //将PC13设置为高电平,LED灭
// GPIO_ResetBits(GPIOC, GPIO_Pin_13); //将PC13设置为低电平,LED亮
while(1){}
}
代码调用本质上就一个User文件夹里面的main.c函数,其他的都是复制的,所以在这里就不展示了。
2.5 工程架构
- startup_xx.s:启动文件。程序执行最基本的文件,使用汇编语言编写,规定了在复位中断函数中,首先执行SystemInit文件,再执行主函数mian。还定义了所有的中断向量表、中断服务函数。
- 复位中断:整个程序的入口。当STM32上电复位/按下复位键之后,程序就会进入复位中断函数执行。复位中断函数首先执行SystemInit文件,再执行主函数mian,并且在执行过程中,可以被其他中断所打断。当然实际上单片机工作永远不会结束,所以主函数一般会让程序在最后停留在死循环while(1)中。
- system_xx.c/.h:包含了SystemInit的具体执行代码。
- main.c:包含了主函数的具体执行代码。
- stm32f10x_it.c/.h:定义了所有中断函数的底层代码。
- 其他用户文件:用户可以自己定义其他文件进行模块化编程。
最右侧的寄存器描述和库函数定义属于被动执行的部分,相当于STM32的资源,是所有文件在执行过程中都有可能调用的。
- 内核和外设寄存器描述:定义了寄存器及每一位寄存器的名字、地址信息等,但是直接调用寄存器实现某功能是非常麻烦的。
- 库函数:ST公司针对每一个外设都提供了一大堆函数,这些函数都封装了对于寄存器的操作,所以熟练掌握这些函数的调用套路,甚至于不需要了解器件手册,就可以很方便的实现相应的功能。
- 库函数配置:配置头文件的包含关系,包含了所有的库函数。而右键添加的“stm32f10x.h”则包含了这个库函数的配置,所以main函数中主只需要声明这一个头文件即可。