本帖最后由 正点原子运营 于 2024-6-11 16:28 编辑
1)实验平台:正点原子 精英STM32F103开发板
2) 章节摘自【正点原子】STM32F103开发指南 V1.3
6)正点原子STM32技术交流QQ群:672399978
在前面的章节我们介绍了STM32F1xx官方固件包的一些知识,本章我们将重点讲解新建HAL库版本的MDK工程的详细步骤。我们把本章新建好的工程放在光盘里,路径:4,程序源码\2,标准例程-HAL库版本\实验0基础入门实验\实验0-3,新建工程实验-HAL库版本,大家在学习新建工程过程中间遇到一些问题,可以直接打开这个工程,然后对比学习。 本章将分为如下两个小节: 8.1 新建HAL库版本MDK工程 8.2 下载验证
8.1 新建HAL库版本MDK工程 本节我们将教大家如何新建一个STM32F103的MDK5工程。为了方便大家参考,我们将本节最终新建好的工程模板存放在“A盘:4、程序源码\1,标准例程-寄存器版本\实验0 基础入门实验\实验0-3,新建工程实验-HAL库版本”,如遇新建工程问题,请打开该实验对比。 在新建工程之前,首先我们要做如下准备: 1) STM32Cube官方固件包:我们使用的固件包版本是STM32Cube_FW_F1_V1.8.3,固件包路径:A盘à8,STM32参考资料à1,STM32CubeF1固件包。 2) 开发环境搭建:前面已经第三章已教大家搭建。
8.1.1新建工程文件夹 新建工程文件夹分为2个步骤:1,新建工程文件夹;2,拷贝工程相关文件。 1. 新建工程文件夹首先我们要在电脑某个路径下新建一个文件作为工程的根目录文件,后续的工程文件都将在这个文件夹里建立,我们把这个文件夹重命名为“实验0-3,新建工程实验-HAL库版本”。如图8.1.1.1所示。 为了让工程的文件目录结构更加清晰,我们会在工程的根目录文件夹下建立以下几个文件夹,文件夹名称及其作用如表8.1.1.1所示: 新建完成以后,最后得到我们的工程根目录文件夹如图8.1.1.2所示。 另外我们的工程根文件目录下还有一个名为keilkill.bat的可执行文件,双击便可执行。其作用是删除编译器编译后的中间文件,减少工程占用的硬盘空间,方便我们打包。还有一个名为readme的记事本文件,其作用是介绍本实验的各种信息。 工程根目录的文件夹新建好后,我们需要拷贝一些工程相关文件过来(主要是在Drivers文件夹里面),以便等下的新建工程需要。 2. 拷贝工程相关文件接下来,我们按图8.1.1.2的根目录文件夹顺序介绍每个文件夹及其需要拷贝的文件。 Drivers文件夹 该文件夹用于存放与硬件相关的驱动层文件,一般包括如表8.1.1.2所示的三个文件夹: BSP文件夹,用于存放正点原子提供的板级支持包驱动代码(原HARDWARE文件夹下),如:LED、蜂鸣器、按键等。本章我们暂时用不到该文件夹,不过可以先建好备用。 SYSTEM文件夹,用于存放正点原子提供的系统级核心驱动代码,sys.c/h,usart.c/h,delay.c/h,方便大家快速搭建自己的工程。该文件同样可以从“A盘à4,程序源码à2,标准例程-HAL库版本”文件夹里面的任何一个实验的Drivers文件夹里面拷贝过来。 CMSIS文件夹,用于存放CMSIS底层代码(ARM和ST提供),如:启动文件(.s文件)、stm32f1xx.h等各种头文件。该文件夹我们可以直接从STM32CubeF1固件包(路径:A盘à8,STM32参考资料à1,STM32CubeF1固件包)里面拷贝,CMSIS的文件夹路径在“STM32CubeF1固件包àDrivers”。由于这个文件夹原来设计是用于匹配全部F1系列的芯片的,导致非常大,部分文件对我们的例程来说不会使用到,而且浪费磁盘的存储空间,所以我们会对这个文件夹进行精简:打开目录“CMSIS\Device\ ST\STM32F1xx”,其中的Include文件夹里都是芯片的头文件我们只留下如图8.1.1.3这三个头文件,其他删除。 Source文件夹下的Templates文件夹留下如图8.1.1.4的内容。 图8.1.1.4 Templates文件夹留下的文件 arm文件夹存放的是启动文件,我们只需要startup_stm32f103xe.s,其他全部删除。如图8.1.1.5所示。 最后就是CMSIS文件夹下的Include文件夹,里面都是内核的头文件,我们只需要如图8.1.1.6的内容。 图8.1.1.6 CMSIS/Include文件夹留下的文件 到这里CMSIS文件夹就处理完成了。精简后的CMSIS文件夹大家也可以在“A盘à4,程序源码à2,标准例程-HAL版本”文件夹里面的任何一个实验的Drivers文件夹里面拷贝过来。 STM32F1xx_HAL_Driver文件夹,用于存放ST提供的F1xx HAL库驱动代码。该文件夹我们可以直接从STM32CubeF1固件包里面拷贝。直接拷贝“STM32CubeF1固件包àDrivers”路径下的 “STM32F1xx_HAL_Driver”文件夹到我们工程的Drivers下。该文件夹目录最终如图8.1.1.7的内容。 图8.1.1.7 STM32F1xx_HAL_Driver文件夹留下的文件 到这里,我们就完成了把官方固件包中必要的驱动文件添加到我们工程文件中。 最终我们新建的Drivers文件夹目录下的文件构成如图8.1.1.8所示。 图8.1.1.8 工程根目录下的Drivers文件夹 关于工程根目录下的Drivers文件操作到这里就完成了。在此过程遇到问题的话,请大家多参考我们提供的“实验0-3,新建工程实验-HAL库版本工程”,一步步操作。
Middlewares文件夹 Middlewares文件夹用于存放正点原子提供的中间层组件文件和第三方中间层文件,比如:USMART、MALLOC、TEXT、FATFS、USB、LWIP、各种OS、各种GUI等等。我们新建工程实验暂时用不到,留空就行,后面的实验将会陆续添加各种文件。 Output文件夹 Output文件夹用于存放编译器编译工程输出的中间文件,比如:.hex、.bin、.o文件等。这里不需要操作,后面只需要在MDK里面设置该文件夹为编译输出文件的存放文件夹就行。 Projects文件夹 Projects文件夹用于存放MDK工程,因为我们的工程是基于ARM,所以我们在Projects文件夹里面新建一个命名为MDK-ARM的文件夹,用于存放MDK的工程文件,如图8.1.1.9所示。 图8.1.1.9 在Projects文件夹下新建MDK-ARM文件夹 User文件夹 User文件夹用于存放HAL库用户配置文件、main.c、中断处理文件,以及配置文件stm32f1xx_hal_conf.h。 我们首先从官方固件包里面直接拷贝官方的模板工程下的HAL库用户配置文件和中断处理文件到我们的User文件夹里。官方的模板工程路径:STM32Cube_FW_F1_V1.8.0\Projects\ STM3210E_EVAL \Templates,打开Template_Project文件夹,如图8.1.1.10所示。 我们需要的文件就在Inc和Src文件夹里面,在这两个文件夹里面找到:stm32f1xx_it.c、stm32f1xx_it.h、stm32f1xx_hal_conf.h这三个文件,并且拷贝到我们的User文件夹下。 main.c文件我们也是放在User文件夹下,后面在MDK里面教大家新建.c文件并保存。User文件夹最终构成图如图8.1.1.11所示。 8.1.2 新建工程 1. 建立初步工程 打开Keil uVision5,点击菜单Project->New Uvision Project,如图8.1.2.1所示。 然后弹出工程命名和保存的操作窗口,工程文件保存路径为:实验0-2,新建工程实验-HAL库版本\Projects\MDK-ARM,工程名字我们取:atk_f103,最后点击保存即可。具体操作窗口如图8.1.2.2所示。 接下来会弹出一个选择Device的界面,就是选择我们的芯片设备型号,大家根据自己使用的芯片型号依次选择即可。STM32F103 战舰开发板的芯片型号是:STM32F103ZET6,所以我们选择:STMicroelectronicsàSTM32F1SeriesàSTM32F103àSTM32F103ZE(如果使用的是其他芯片,选择相应的型号就可以了),如图8.1.2.3所示。 特别注意:一定要安装对应的器件支持包(即pack包)才会显示这些内容哦,如果没得选择,请关闭MDK,然后安装光盘:6,软件资料\1,软件\MDK5\ Keil.STM32F1xx_DFP.2.3.0这个安装包后重试。 点击OK后,弹出Manage Run-Time Environment对话框,如图8.1.2.4所示: 图8.1.2.4 Manage Run-Time Environment界面 在这个界面,我们可以添加自己需要的组件,从而方便构建开发环境,不过这里我们不需要。我们直接点击Cancel即可。这样就得到了我们的初步工程,如图8.1.2.5所示。 这只是一个工程的框架,我们还需要把自己需要用到的文件添加到工程里面。虽然前面,我们在工程文件夹里放了很多文件,但是它们并没有关联到工程里面。 我们看看初步工程建立好后,MDK-ARM文件夹的内容,如图8.1.2.6所示。 这里我们说明一下,atk_f103.uvprojx是工程文件,非常关键,不能轻易删除,MDK5.31生成的工程文件是以.uvprojx为后缀。DebugConfig,Listings和Objects三个文件夹是MDK自动生成的文件夹。其中DebugConfig文件夹用于存储一些调试配置文件,Listings和Objects文件夹用来存储MDK编译过程的一些中间文件。这里,我们把Listings和Objects文件夹删除,我们后面会把编译中间文件存放到Output文件夹。当然,我们不删除这两个文件夹也没有关系,只是我们不用它而已。 至此,我们还只是建了一个框架,还有好几个步骤要做,比如添加文件、魔术棒设置、编写main.c等。
8.1.3 添加文件本节将分3个步骤:1,设置工程名和分组;2,添加启动文件;3,添加User源码;4,添加SYSTEM源码;5,添加STM32F1xx_HAL_Driver源码。 1. 设置工程名和分组名在ProjectàTarget上右键,选择Manage Project Items…(方法一)或在菜单栏点击品字形红绿白图标(方法二)进入工程管理界面,如下图8.1.3.1所示: 图8.1.3.1 点击ManagementProject Itmes 在工程管理界面,我们可以执行设置工程名字(Project Targets)、分组名字(Groups)以及添加每个分组的文件(Files)等操作。我们设置工程名字为:Template,并设置五个分组:Startup(存放启动文件)、User(存放main.c等用户代码)、Drivers/SYSTEM(存放系统级驱动代码)、Drivers/STM32F1xx_HAL_Driver(存放ST提供的HAL库驱动代码)、Readme(存放工程说明文件),如图8.1.3.2所示: 设置好之后,我们点击OK,回到MDK主界面,可以看到我们设置的工程名和分组名如图8.1.3.3所示。 这里我们只是新建了一个简单的工程,并没有添加BSP、Middlewares等分组,后面随着工程复杂程度的增加,我们需要一步步添加对应的分组。 注意:为了让工程结构清晰,我们会尽量让MDK的工程分组和我们前面新建的工程文件夹对应起来,由于MDK分组不支持多级目录,因此我们将路径也带入分组命名里面,以便区分。如:User分组对应User文件夹里面的源码,Drivers/SYSTEM分组,对应Drivers/SYSTEM文件夹里面的源码,Drivers/STM32F1xx_HAL_Driver分组对应Drivers/STM32F1xx_HAL_Driver文件夹里面的源码等。 2. 添加启动文件启动文件(.s文件)包含STM32的启动代码,其主要作用包括:1、堆栈(SP)的初始化;2、初始化程序计数器(PC);3、设置向量表异常事件的入口地址;4、调用main函数等,是每个工程必不可少的一个文件,我们在本书第九章会有详细介绍。 该文件由ST官方提供,对于STM32F103来说有4个启动文件可选,如表8.1.3.1所示: 启动文件存放的位置在前面也有所说明,因为我们开发板使用的是STM32F103ZET6,对应的启动文件为:startup_stm32f103xe.s。 关于启动文件的说明,我们就介绍这么多,接下来我们看如何添加启动文件到工程里面。我们有两种方法给MDK的分组添加文件:1,双击Project下的分组名添加。2,进入工程管理界面添加。 这里我们使用方法1添加(路径:实验0-3,新建工程实验-HAL库版本\Drivers\CMSIS\ Device\ST\STM32F1xx\Source\Templates\arm),如图8.1.3.4所示: 图8.1.3.4 双击分组添加启动文件(startup_stm32f103xe.s) 上图中,我们也可以点击Add按钮进行文件添加。添加完后,点击Close,完成启动文件 添加,得到工程分组如图8.1.3.5所示: 3. 添加User源码这里我们在工程管理界面(方法2)进行User源码添加。点击:
按钮,进入工程管理界面,选中User分组,然后点击:Add Files,进入文件添加对话框,依次添加stm32f1xx_it.c和system_stm32f1xx.c到该分组下,如图8.1.3.6所示: 注意:这些源码都是在第8.1.1小节的第二步拷贝过来的,如果之前没拷贝,是找不到这些源码的。添加完成后,如图8.1.3.7所示: 4. 添加SYSTEM源码同样的,我们也是在工程管理界面进行SYSTEM源码添加。点击: 按钮,进入工程管理界面,选中Drivers/SYSTEM分组,然后点击:Add Files,进入文件添加对话框,依次添加delay.c、sys.c和usart.c到该分组下,如图8.1.3.8所示: 添加完成后,如图8.1.3.9所示: 5. 添加STM32F1xx_HAL_Driver源码接下来我们往Drivers/STM32F1xx_HAL_Driver分组里添加文件,这里的操作跟前面添加SYSTEM源码一样的。点击: 按钮,进入工程管理界面,选中Drivers/STM32F1xx_HAL_Driver分组,然后点击:Add Files,进入文件添加对话框,依次添加stm32f1xx_hal.c、stm32f1xx_hal_cortex.c、stm32f1xx_hal_dma.c、stm32f1xx_hal_gpio.c、stm32f1xx_hal_gpio_ex.c、stm32f1xx_hal_rcc.c、stm32f1xx_hal_rcc_ex.c、stm32f1xx_hal_uart.c和stm32f1xx_hal_usart.c到该分组下,如图8.1.3.10所示: 图8.1.3.10 添加STM32F1xx_HAL_Driver源码 添加完成后,如图8.1.3.11所示: 图8.1.3.11 STM32F1xx_HAL_Driver源码添加完成 可以看到分组中有些.c文件有个小钥匙的符号,这是因为官方的固件包的文件设置了只读权限,我们取消只读权限就好了,方法如图8.1.3.12所示。 8.1.4 魔术棒设置为避免编写代码和编译报错,我们需要通过魔术棒对MDK工程进行相关设置。在MDK主界面,点击:
(魔术棒图标,即Options for Target按钮),进入工程设置对话框,我们将进行如下几个选项卡的设置。 1. 设置Target选项卡在魔术棒àTarget选项卡里面,我们进行如图8.1.4.1所示设置: 上图中,我们设置芯片所使用的外部晶振频率为8Mhz,选择ARM Compiler版本为:Use default compiler version 5(即AC5编译器)。 这里我们说明一下AC5和AC6编译的差异,如表8.1.4.1所示: 由于AC5对中文支持比较好,且兼容性相对好一点,为了避免不必要的麻烦,我们推荐大家使用AC5编译器。为了让大家自由选择,我们正点原子的源码,也是支持AC6编译器 的,不过在选项卡设置上稍有差异,具体差异如表8.1.4.2所示: 2. 设置Output选项卡在魔术棒àOutput选项卡里面,进行如图8.1.4.2所示设置: 注意,我们勾选:Browse Information,用于输出浏览信息,这样就可以使用go to definition查看函数/变量的定义,对我们后续调试代码比较有帮助,如果不需要调试代码,则可以去掉这个勾选,以提高编译速度。 3. 设置Listing选项卡在魔术棒àListing选项卡里面,进行如图8.1.4.3所示设置: 经过Output和Listing这两步设置,原来存储在Objects和Listings文件夹的内容(中间文件)就都改为输出到Output文件夹了。 4. 设置C/C++选项卡在魔术棒àC/C++选项卡里面,进行如图8.1.4.4所示设置: 在②处设置了全局宏定义:USE_HAL_DRIVER和STM32F103xE,他们之间是用英文逗号隔开的。添加全局宏定义标识符,在工程中任何地方都可见,在stm32f1xx.h里面会用到该宏定义。 在③处设置了优化等级为-O0,可以得到最好的调试效果,当然为了提高优化效果提升性能并降低代码量,可以设置-O1~-O3,数字越大效果越明显,不过也越容易出问题。注意:当使用AC6编译器的时候,这里推荐默认使用-O1优化。 在④处勾选C99模式,即使用C99 C语言标准。 在⑤处,我们可以进行头文件包含路径设置,点击此按钮,进行如图8.1.4.5所示设置: 上图中我们设置了5个头文件包含路径,其中4个在Drivers文件夹下,一个在User文件夹下。为避免频繁设置头文件包含路径,正点原子最新源码的include全部使用相对路径,也就是我们只需要在头文件包含路径里面指定一个文件夹,那么该文件夹下的其他文件夹里面的源码,如果全部是使用相对路径,则无需再设置头文件包含路径了,直接在include里面就指明了头文件所在。 关于相对路径,这里大家记住3点: 1,默认路径就是指MDK工程所在的路径,即.uvprojx文件所在路径(文件夹) 2,“./”表示当前目录(相对当前路径,也可以写做“.\”) 3,“../”表示当前目录的上一层目录(也可以写做“..\”) 举例来说,上图中:..\..\Drivers\CMSIS\Device\ST\STM32F1xx\Include,前面两个“..\”,表示Drivers文件夹在当前MDK工程所在文件夹(MDK-ARM)的上2级目录下,具体解释如图8.1.4.6所示: 图8.1.4.6..\..\Drivers\CMSIS\Device\ST\STM32F1xx\Include的解释 上图表示根据头文件包含路径:..\..\Drivers\CMSIS\Device\ST\STM32F1xx\Include,编译器可以找到⑥处所包含的这些头文件,即代码里面可以直接include这些头文件使用。 再举个例子,在完成如图8.1.4.5所示的头文件包含路径设置以后,我们在代码里面编写: - #include "./SYSTEM/sys/sys.h"
复制代码即表示当前头文件包含路径所指示的4个文件夹里面,肯定有某一个文件夹包含了:SYSTEM/sys/sys.h的路径,实际上就是在Drivers文件夹下面,两者结合起来就相当于: - #include "../../Drivers/SYSTEM/sys/sys.h"
复制代码这就是相对路径。它既可以减少头文件包含路径设置(即减少MDK配置步骤,免去频繁设置头文件包含路径的麻烦),同时又可以很方便的知道头文件具体在那个文件夹,因此我们推荐在编写代码的时候使用相对路径。 关于相对路径,我们就介绍这么多,大家搞不明白的可以在网上搜索相关资料学习,也可以在后面的学习,分析我们其他源码,慢慢体会,总之不难,但是好用。 最后,我们如果使用AC6编译器,则在图6.1.4.4的Misc Controls处需要设置:-Wno-invalid-source-encoding,避免中文编码报错,如果使用AC5编译器,则不需要该设置!! 5. 设置Debug选项卡在魔术棒àDebug选项卡里面,进行如图8.1.4.7所示设置: 图中,我们选择使用:CMSIS-DAP仿真器,使用SW模式,并设置最大时钟频率为10Mhz,以得到最高下载速度。当我们将仿真器和开发板连接好,并给开发板供电以后,仿真器就会找到开发板芯片,并在SW Device窗口显示芯片的IDCODE、Device Name等信息(图中⑤处),当无法找到时,请检查供电和仿真器连接状况。 6. 设置Utilities选项卡在魔术棒àUtilities选项卡里 面,进行如图6.1.4.8所示设置: 图中⑥处下载算法,是MDK默认添加的,针对STM32F10x大容量系列产品(FLASH容量在256KB~512KB之间)。一般我们用这个即可。如果⑥处没有下载算法,则点击⑦处按钮,执行添加一下下载算法即可(名字和⑥处的算法名字一样)。 8.1.5 添加main.c,并编写代码在MDK主界面,点击:
,新建一个main.c文件,并保存在User文件夹下。然后双击User分组,弹出添加文件的对话框,将User文件夹下的main.c文件添加到User分组下。得到如图8.1.5.1所示的界面: 图8.1.5.1 在User分组下加入main.c文件 至此,我们就可以开始编写我们自己的代码了。我们在main.c文件里面输入如下代码: - <div align="left"><font face="Tahoma"><font size="3">#include "./SYSTEM/sys/sys.h"</font></font></div><div align="left"><font face="Tahoma"><font size="3">#include "./SYSTEM/usart/usart.h"</font></font></div><div align="left"><font face="Tahoma"><font size="3">#include "./SYSTEM/delay/delay.h"</font></font></div><div align="left"><font face="Tahoma"><font size="3"> </font></font></div><div align="left"><font face="Tahoma"><font size="3">void led_init(void); /* LED初始化函数声明 */</font></font></div><div align="left"><font face="Tahoma"><font size="3"> </font></font></div><div align="left"><font face="Tahoma"><font size="3">int main(void)</font></font></div><div align="left"><font face="Tahoma"><font size="3">{</font></font></div><div align="left"><font face="Tahoma"><font size="3"> HAL_Init(); /* 初始化HAL库 */</font></font></div><div align="left"><font face="Tahoma"><font size="3"> sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */</font></font></div><div align="left"><font face="Tahoma"><font size="3"> delay_init(72); /* 延时初始化 */</font></font></div><div align="left"><font face="Tahoma"><font size="3"> led_init(); /* LED初始化 */</font></font></div><div align="left"><font face="Tahoma"><font size="3"> while(1)</font></font></div><div align="left"><font face="Tahoma"><font size="3"> { </font></font></div><div align="left"><font face="Tahoma"><font size="3"> HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET); /* PB5置1 */ </font></font></div><div align="left"><font face="Tahoma"><font size="3"> HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_RESET); /* PE5置0 */ </font></font></div><div align="left"><font face="Tahoma"><font size="3"> delay_ms(500);</font></font></div><div align="left"><font face="Tahoma"><font size="3"> HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_RESET); /* PB5置0 */</font></font></div><div align="left"><font face="Tahoma"><font size="3"> HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_SET); /* PE5置1 */</font></font></div><div align="left"><font face="Tahoma"><font size="3"> delay_ms(500); </font></font></div><div align="left"><font face="Tahoma"><font size="3"> }</font></font></div><div align="left"><font face="Tahoma"><font size="3">}</font></font></div><div align="left"><font face="Tahoma"><font size="3"> </font></font></div><div align="left"><font face="Tahoma"><font size="3">/**</font></font></div><div align="left"><font face="Tahoma"><font size="3"> * @brief 初始化LED相关IO口, 并使能时钟</font></font></div><div align="left"><font face="Tahoma"><font size="3"> * <a href="home.php?mod=space&uid=271674" target="_blank">@param</a> 无</font></font></div><div align="left"><font face="Tahoma"><font size="3"> * @retval 无</font></font></div><div align="left"><font face="Tahoma"><font size="3"> */</font></font></div><div align="left"><font face="Tahoma"><font size="3">void led_init(void)</font></font></div><div align="left"><font face="Tahoma"><font size="3">{</font></font></div><div align="left"><font face="Tahoma"><font size="3">GPIO_InitTypeDef gpio_initstruct;</font></font></div><div align="left"><font face="Tahoma"><font size="3"> __HAL_RCC_GPIOB_CLK_ENABLE();</font></font></div><div align="left"><font face="Tahoma"><font size="3"> __HAL_RCC_GPIOE_CLK_ENABLE();</font></font></div><div align="left"><font face="Tahoma"><font size="3"> </font></font></div><div align="left"><font face="Tahoma"><font size="3"> gpio_initstruct.Pin = GPIO_PIN_5; /* LED0引脚 */</font></font></div><div align="left"><font face="Tahoma"><font size="3"> gpio_initstruct.Mode =GPIO_MODE_OUTPUT_PP; /* 推挽输出 */</font></font></div><div align="left"><font face="Tahoma"><font size="3"> gpio_initstruct.Pull = GPIO_PULLUP; /* 上拉 */</font></font></div><div align="left"><font face="Tahoma"><font size="3"> gpio_initstruct.Speed =GPIO_SPEED_FREQ_HIGH; /* 高速 */</font></font></div><div align="left"><font face="Tahoma"><font size="3"> HAL_GPIO_Init(GPIOB, &gpio_initstruct); /* 初始化LED0引脚 */</font></font></div><div align="left"><font face="Tahoma"><font size="3"> </font></font></div><div align="left"><font face="Tahoma"><font size="3"> gpio_initstruct.Pin = GPIO_PIN_5; /* LED1引脚 */</font></font></div><div align="left"><font face="Tahoma"><font size="3"> HAL_GPIO_Init(GPIOE, &gpio_initstruct); /* 初始化LED1引脚 */</font></font></div><div align="left"><font face="Tahoma"><font size="3">}</font></font></div>
复制代码此部分代码,在A盘à4,程序源码à1,标准例程-HAL库版本à 实验0 基础入门实验à实验0-3,新建工程实验-HAL库版本àUseràmain.c里面有,大家可以自己输入,也可以直接拷贝。强烈建议自己输入,以加深对程序的理解和印象!! 注意,这里的include就是使用的相对路径,关于相对路径,请参考前面C/C++选项卡设置章节进行学习。 编写完main.c以后,我们点击:
(Rebuild)按钮,编译整个工程,编译结果如图8.1.5.2。 我们在BuildOutput下找到第一个错误,双击这个错误信息定位到错误发生的代码位置。如图这个错误说找不到main.h,因为我们也不需要用到main.h,双击这个错误会弹出下面的STM32F1xx_it.c文件对应包含main.h的语句。我们只需要把它删除,然后重新编译。 再次编译,发现还有一处警告,这里是HAL_IncTick函数没有声明,如图8.1.5.3所示。 因为这个函数是在STM32F1xx_hal.c定义了,并且在STM32F1xx_hal.h声明了。我们把STM32F1xx_hal.h包含进来即可。这里还有一个原因是整个工程没有包含STM32F1xx_hal.h的语句,我们需要用到它,所以在这里把它包含进来。官方的main.h是有包含这个头文件的。我们不用main.h文件,我们在STM32F1xx_it.c文件刚才删除包含main.h的语句的位置,编写包含STM32F1xx_hal.h语句,如图8.1.5.3所示。 图8.1.5.3 包含STM32F1xx_hal.h头文件到工程 再进行编译就会发现0错误0警告,结果如图8.1.5.4所示: 编译结果提示:代码总大小(Porgram Size)为:FLASH占用5780字节(Code + RO + RW),SRAM占用1928字节(RW + ZI);并成功创建了Hex文件(可执行文件,放在Output目录下)。 另外,我们在Readme分组下还没有添加任何文件,由于只是添加一个说明性质的文件(.txt),并不是工程必备文件,因此这里我们就不添加了,开发板光盘的源码我们是有添加的,大家可以去参考一下。 至此,新建寄存器版本MDK工程完成。 8.2 下载验证有两种方法可以给STM32F103芯片下载代码:1,使用串口下载;2,使用仿真器下载。这两种下载方法,我们在本书的4.2和4.3节给大家有做过详细介绍。这里我们以仿真器下载为例,在MDK主界面,点击:
(下载按钮,也可以按键盘快捷键:F8),就可以将代码下载到开发板,如图8.2.1所示: 上图提示:Application running…,则表示代码下载成功,且开始运行。可以看到LED0和LED1交叉闪烁。 |