本任务要求在KeilμVision5集成开发环境下建立基于STM32F4标准外设库的工程,在工程中添加必要的文件,正确地配置、编译工程,并将其下载至开发板中运行。
本任务涉及的知识点有:
● STM32F4标准外设库中的重要文件;
● STM32F4标准外设库帮助文档的使用方法;
● 基于STM32F4标准外设库的工程的建立步骤。
通过对任务1.1的学习,我们已经了解了STM32F4标准外设库的文件结构。但如果要建立基于STM32F4标准外设库的工程,则仅了解库的文件结构是不够的,还要进一步学习库里的重要文件。
工程建立所需的文件主要位于STM32F4标准外设库的Libraries文件夹和Project文件夹中。Libraries文件夹中包含CMSIS与STM32F4xx_StdPeriph_Driver两个子文件夹。Project文件夹中包含stm32f4xx_it.c和stm32f4xx_conf.h文件。
(1)CMSIS文件夹
CMSIS文件夹的结构如图1-2-1所示。
图1-2-1 CMSIS文件夹的结构
图1-2-1中的Device和Include文件夹中存放了建立工程所需的文件,它们的介绍如下。
①stm32f4xx.h
文件路径:Libraries\CMSIS\Device\ST\STM32F4xx\Include。
stm32f4xx.h文件包括STM32F4系列微控制器的中断优先级定义、外设寄存器的结构体类型定义和寄存器操作的宏定义等。
②system_stm32f4xx.c
文件路径:Libraries\CMSIS\Device\ST\STM32F4xx\Source\Templates。
system_stm32f4xx.c文件定义了一个重要函数,即STM32F4芯片通电后的系统时钟初始化函数——SystemInit()函数。这个函数在启动文件中用汇编语言调用,并根据相关配置参数进行系统时钟的初始化。如STM32F407ZGT6的系统时钟默认被初始化为168 MHz。
③system_stm32f4xx.h
文件路径:Libraries\CMSIS\Device\ST\STM32F4xx\Include。
system_stm32f4xx.h文件是system_stm32f4xx.c的头文件。
④startup_stm32f40_41xx.s
文件路径:Libraries\CMSIS\Device\ST\STM32F4xx\Source\Templates\arm。
startup_stm32f40_41xx.s文件是STM32F4系列微控制器在MDK-Arm-STM32集成开发环境中的启动文件,它是用汇编语言编写的。若用户使用不同的集成开发环境,则应选择相应的启动文件。
⑤core_cm4.h、core_cmFunc.h、corecmInstr.h、core_cmSimd.h
文件路径:Libraries\CMSIS\Include。
Include文件夹中包含了遵循CMSIS标准的Cortex-M内核通用的头文件,它们为基于Cortex-M内核的SoC芯片外设提供了内核API,定义了与内核相关的寄存器。STM32F4系列微控制器的工程中需要core_cm4.h、core_cmFunc.h、corecmInstr.h、core_cmSimd.h这4个头文件。
(2)STM32F4xx_StdPeriph_Driver文件夹
STM32F4xx_StdPeriph_Driver文件夹的结构如图1-2-2所示。
图1-2-2 STM32F4xx_StdPeriph_Driver文件夹的结构
由图1-2-2可知,STM32F4xx_StdPeriph_Driver文件夹中有两个子文件夹,分别是inc文件夹和src文件夹。其中,src文件夹存放STM32F4系列微控制器所有外设的驱动程序源代码,inc文件夹存放外设驱动程序源代码相应的头文件。这两个文件夹里的内容是标准外设库的核心内容。
(3)中断服务程序文件stm32f4xx_it.c
STM32F4系列微控制器的中断服务程序一般在stm32f4xx_it.c文件中进行编写,相应的头文件是stm32f4xx_it.h。在ST公司官方工程模板的这个文件里已经定义了一些系统异常(特殊中断)的接口函数,我们还可在此文件中自行定义普通中断服务程序函数。上述两个文件的路径:Project\STM32F4xx_StdPeriph_Templates。
(4)标准外设库功能裁减文件stm32f4xx_conf.h
STM32F4系列微控制器的外设种类繁多,为了精简工程并提高编译速度,可将暂时不用的外设库文件从工程中删除,通过配置stm32f4xx_conf.h文件可实现上述功能。该文件的路径:Project\STM32F4xx_StdPeriph_Templates。
我们在使用STM32F4标准外设库进行程序设计时,经常要调用某种外设驱动的库函数。库函数的数量庞大,为了实现快速调用,我们应熟练掌握库函数的查阅方法。
STM32F4标准外设库提供了一个帮助文档,名为“stm32f4xx_dsp_stdperiph_lib_um.chm”,通过这个文档可以快速查阅函数原型、功能说明、参数说明、返回值及其出处。
打开帮助文档后,依次展开标签:Modules→STM32F4xx_StdPeriph_Driver,可找到各种外设(如ADC、DMA、TIM、USART等)的库函数说明,如图1-2-3所示。
图1-2-3 外设的库函数说明
从图1-2-3中可以看到,GPIO_ReadInputData()函数被选中。右侧窗格显示了函数原型、功能说明、参数说明、返回值、出处等信息。如果用户对相关的结构体类型存在疑问,可单击超链接跳至其定义处进行查看。
一个STM32工程通常包含多个源代码。随着对STM32学习的深入,我们建立的工程将会越来越复杂,包含的源代码数量也会越来越多。为了实现工程的科学管理,我们应对工程文件夹的命名与结构进行合理规划。
STM32工程包含的文件主要有以下几类:用户编写的应用层程序文件、硬件外设驱动程序文件、STM32F4标准外设库文件、Cortex-M4内核相关文件与启动文件等。为了使工程结构更加清晰,我们可通过建立文件夹来分门别类地存放上述文件。
先建立名为“STM32F407_Template”的工程文件夹,并在其下建立5个子文件夹。工程子文件夹的名称与用途如表1-2-1所示。
表1-2-1 工程子文件夹的名称与用途
注:表中工程子文件夹的结构仅供参考,用户可根据自己的工作习惯进行调整。
工程文件夹建好以后,在新建工程前,我们应将必要的文件先加入相应的子文件夹中。
(1)USER文件夹
将stm32f4xx.h、system_stm32f4xx.c、system_stm32f4xx.h、stm32f4xx_it.c、stm32f4xx_it.h和stm32f4xx_conf.h文件复制到USER文件夹中,这些文件的具体路径见1.2.2节。另外,新建main.c文件并存入此文件夹中。
(2)HARDWARE文件夹
本工程未涉及硬件驱动程序的编写,故此文件夹暂时留空。
(3)FWLIB文件夹
将STM32F4xx_StdPeriph_Driver文件夹中的inc和src文件夹中的所有内容复制到FWLIB文件夹中,并保留原始文件架构。
(4)CORE文件夹
将startup_stm32f40_41xx.s、core_cm4.h、core_cmFunc.h、corecmInstr.h和core_cmSimd.h文件复制到CORE文件夹中,这些文件的具体路径见1.2.2节。
打开KeilμVision5软件,单击“Project”菜单下的“new uVision Project”选项新建工程,保存工程名为“Template”,并将其存放在USER文件夹中。
工程保存完毕后,工程建立向导会弹出“MCU型号选择”对话框,用户可根据开发板所用的MCU型号进行配置,然后单击“OK”按钮进行保存。MCU型号选择界面如图1-2-4所示,图中选取的MCU型号为STM32F407ZGTx。
图1-2-4 MCU型号选择界面
工程建好以后,为了使工程架构更加清晰,我们应将程序文件归类分组。分组的依据是工程子文件夹的架构。我们在KeilμVision5软件开发窗口左侧的Project窗格上单击右键,在弹出的快捷菜单中选择“Manage Project Items…”选项,即可进入工程管理窗口,如图1-2-5所示。
图1-2-5 工程管理窗口
根据工程子文件夹的架构,我们为“Groups”栏添加USER、HARDWARE、FWLIB、CORE等几个分组,并在分组中添加相应的程序文件。完成后的工程分组情况如图1-2-6所示。
图1-2-6 工程分组情况
此处主要添加“.c”和“.s”文件,“.h”文件无须添加。
STM32F407微控制器没有FMC、DMA2D和LTDC外设,将所有的STM32F4标准外设库文件都加入工程以后,工程在编译时会出错。我们可将相应的库文件从工程中屏蔽以解决此问题,具体的操作流程如下:
(1)在要屏蔽的文件上右击;
(2)在弹出的快捷菜单中选择“Options for File…”菜单项;
(3)在弹出的配置界面中,取消“Include In Target Build”复选框的勾选;
(4)单击“OK”按钮确认。
编译选项配置的具体步骤如图1-2-7和图1-2-8所示。
图1-2-7 编译选项配置一
图1-2-8 编译选项配置二
在工程中加入必要的文件后,还须对工程进行配置才能对其进行编译。主要配置步骤如下。
(1)晶振频率配置
晶振频率应根据开发板实际使用的MCU型号进行配置。单击KeilμVision5软件工具栏上的“魔术棒”图标,弹出“工程配置”对话框后,切换至“Target”标签。编者使用的STM32F4开发板上的晶振频率为8 MHz,所以应将Xtal(MHz)后的数字修改为“8.0”,如图1-2-9所示。
图1-2-9 晶振频率配置
(2)编译输出文件配置
工程编译过程将产生很多中间文件,可专门指定一个目录对它们进行存放。将“工程配置”对话框中的“Target”标签切换至“Output”标签后,选择表1-2-1中提到的OBJ文件夹,单击“Select Folder for Objects”按钮,即可对编译输出文件的存放路径进行配置。另外,如果需要编译产生“.hex”文件,可勾选“Create HEX File”复选框,如图1-2-10所示。
(3)重要宏定义与包含头文件的路径配置
STM32F4标准外设库支持F4全系列产品的编程调用,型号包括STM32F40x、STM32F41x和STM32F42X等,各型号在外设数量、Flash容量等方面均有差异。为了提高代码的易用性,STM32F4标准外设库采用预编译的方法决定源代码是否参与编译。
编者使用的STM32F4开发板上的MCU型号为STM32F407ZGT6,为了使标准外设库中相应的代码生效,需要增加“STM32F40_41xxx”宏定义,同时增加“USE_STDPERIPH_DRIVER”宏定义,代表使用标准外设库进行程序开发,如图1-2-11所示。
图1-2-10 编译输出文件配置
图1-2-11 重要宏定义与包含头文件的路径配置
在使用KeilμVision5进行工程编译之前,我们需要指定“.h”头文件所在的路径,否则在编译时会出现无法找到头文件的情况。单击“Include Paths”右侧的按钮,可将需要包含的“.h”头文件所在的路径都加入其中,如图1-2-11所示。
(4)仿真器类型配置
KeilμVision5支持的仿真器类型很多。工程编译成功以后,在将程序下载到MCU中或者运行软件仿真之前,我们应根据实际所用的仿真器类型对工程进行配置。将“工程配置”对话框中的“C/C++”标签切换到“Debug”标签后,可以看到“Debug”配置界面分左右两边,左侧的内容与软件仿真有关,右侧的内容涉及程序下载与硬件在线仿真。单击右侧的下拉按钮,可以看到KeilμVision5支持13种仿真器,包括J-LINK/J-TRACE Cortex、CMSIS-DAPDebugger、ST-LinkDebugger等,如图1-2-12所示。
图1-2-12 仿真器类型配置
(5)仿真器参数配置
STM32微控制器支持通过JTAG接口或SW接口与仿真器相连进行在线调试。完整的JTAG接口为20Pin,接口体积大且占用较多的GPIO引脚资源,一般用于JLink仿真器。而SW接口只需3根连线即可实现,一般用于ST-Link仿真器。单击图1-2-12右上角的“Settings”按钮,打开“仿真器参数配置”对话框,用户可根据所使用的仿真器进行Port参数的配置,如图1-2-13所示。如果将开发板与仿真器正确连接并通电,该对话框还可显示识别到的MCU。
图1-2-13 仿真器参数配置
(6)Flash参数配置
KeilμVision5支持STM32全系列MCU的开发,各型号的Flash类型(内置或外置)或Flash容量都不尽相同,因此在程序下载前应根据MCU型号正确配置Flash参数。在“仿真器参数配置”对话框中单击“Flash Download”标签,在“Programming Algorithm”选项区可进行Flash参数的配置。
STM32F407ZGT6型号MCU的内置Flash容量为1MB,单击“Add”按钮后选择正确的选项即可。一般来说,如果在新建工程的“MCU型号选择”步骤中选择了特定型号的MCU,KeilμVision5将会自动完成Flash参数配置工作。具体配置如图1-2-14所示。
图1-2-14 Flash参数配置
完成工程的所有配置之后,可对工程进行编译并下载。先编写一个简单的main()函数,在“main.c”文件中输入以下代码:
1 #include "stm32f4xx.h" 2 3 void Delay(__IO uint32_t nCount); 4 5 /** 6 * @brief Main program 7 * @param None 8 * @retval None 9 */ 10 int main(void) 11 { 12 GPIO_InitTypeDef GPIO_InitStructure; 13 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); 14 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; 15 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; 16 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 17 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; 18 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; 19 GPIO_Init(GPIOF, &GPIO_InitStructure); 20 21 /* 无限循环 */ 22 while (1) 23 { 24 GPIO_SetBits(GPIOF,GPIO_Pin_9 | GPIO_Pin_10); 25 Delay(0x7FFFFF); 26 GPIO_ResetBits(GPIOF,GPIO_Pin_9 | GPIO_Pin_10); 27 Delay(0x7FFFFF); 28 } 29 } 30 31 /** 32 * @brief 软件延时函数 33 * @param None 34 * @retval None 35 */ 36 void Delay(__IO uint32_t nCount) 37 { 38 while(nCount--){} 39 }
单击工具栏中的“Build(功能键F7)”按钮可对工程进行编译,编译无误后单击“Download(功能键F8)”按钮可将工程下载至开发板运行,如图1-2-15所示。
图1-2-15 编译并下载工程