新建 HAL 库版本 MDK 工程

新建 HAL 库版本 MDK 工程

本次我们将新建一个 STM32F429 的 HAL 库版本 MDK5 工程

整个新建过程比较复杂,我们将其拆分为 5 个步骤

一、新建工程文件夹

新建工程文件夹分为 2 个步骤:

  1. 新建工程文件夹;
  2. 拷贝工程相关文件。

1、新建工程文件夹

首先我们在桌面新建一个工程根目录文件夹,后续的工程文件都将在这个文件夹里建立,我们把这个文件夹重命名为:实验 0-3,新建工程实验-HAL 库版本。如图所示:

新建 HAL 库版本 MDK 工程

为了让工程的文件目录结构更加清晰易懂,我们会在工程根目录文件夹下建立以下几个文件夹,每个文件夹名称及其作用如表所示:

名称 作用
Drivers 存放与硬件相关的驱动层文件
Middlewares 存放正点原子提供的中间层组件文件和第三方中间层文件
Output 存放工程编译输出文件
Projects 存放 MDK 工程文件
User 存放 HAL 库用户配置文件、main.c、中断处理文件,以及分散加载文件

新建完成以后,最后得到我们的工程根目录文件夹如下图所示。

新建 HAL 库版本 MDK 工程

另外我们的工程根文件目录下还有一个名为 keilkill.bat 的可执行文件,双击便可执行。其作用是删除编译器编译后的无关文件,减少工程占用的内存,方便打包。还有一个名为 readme 的记事本文件,其作用是介绍本实验的各种信息。

工程根目录及其相关文件夹新建好以后,我们需要拷贝一些工程相关文件过来(主要是在 Drivers 文件夹里面),以便等下的新建工程需要。

2、拷贝工程相关文件

接下来,我们按上图的根目录文件夹顺序介绍每个文件夹及其需要拷贝的文件。

Drivers 文件夹

该文件夹用于存放与硬件相关的驱动层文件,一般包括如下表所示的三个文件夹:

文件夹名称 作用
BSP 存放开发板板级支持包驱动代码,如各种外设驱动
CMSIS 存放 CMSIS 底层代码,如启动文件(.s 文件)、stm32f4xx.h 等
STM32F4xx_HAL_Driver 存放 HAL 库驱动代码源文件
SYSTEM 存放正点原子系统级核心驱动代码,如 sys.c、delay.c 和 usart.c
  • BSP 文件夹,用于存放正点原子提供的板级支持包驱动代码,如:LED、蜂鸣器、按键等。
  • CMSIS 文件夹,用于存放 CMSIS 底层代码(ARM 和 ST 提供),如:启动文件(.s 文件)、stm32f4xx.h 等各种头文件。该文件夹我们可以直接从 STM32CubeF4 固件包里面拷贝,不过由于固件包里面的 CMISIS 兼容了太多芯片,导致非常大(170 MB),因此我们根据实际情况,对其进行了大幅精简,精简后的 CMSIS 文件夹大小为 1.6 MB 左右。精简后的 CMSIS 文件夹大家可以在:正点原子官方程序源码→1,标准例程-HAL 库版本 文件夹里面的任何一个实验的 Drivers 文件夹里面拷贝过来。
  • SYSTEM 文件夹,用于存放正点原子提供的系统级核心驱动代码,如:sys.c、delay.c 和 usart.c 等,方便大家快速搭建自己的工程。该文件同样可以从:A 盘→4,程序源码→1,标准例程-HAL 库版本 文件夹里面的任何一个实验的 Drivers 文件夹里面拷贝过来。
  • STM32F4xx_HAL_Driver 文件夹,用于存放 ST 提供的 F4xx HAL 库驱动代码。该文件夹我们可以直接从 STM32CubeF4 固件包里面拷贝。直接拷贝“STM32CubeF4 固件包→Drivers”路径下的 “STM32F4xx_HAL_Driver”文件夹到我们工程的 Drivers 下,只保留 Inc 和 Src 文件夹即可。

执行完以上操作后,Drivers 文件夹最终结构如下图所示:

新建 HAL 库版本 MDK 工程

Middlewares 文件夹

该文件夹用于存放正点原子和其他第三方提供的中间层代码(组件/Lib 等),如:USMART、MALLOC、TEXT、FATFS、USB、LWIP、各种 OS、各种 GUI 等等。本章我们暂时用不到该文件夹,不过可以先建好备用,后面的实验将会陆续添加各种文件。

Output 文件夹

该文件夹用于存放编译器编译工程输出的中间文件,比如:.hex、.bin、.o 文件等等。这里

不需要操作,后面只需要在 MDK 里面设置该文件夹为编译过程中间文件的存放文件夹就行。

Projects 文件夹

该文件夹用于存放编译器(MDK、IAR 等)工程文件,我们主要用 MDK,为了方便区分,我们在该文件夹下新建:MDK-ARM 文件夹,用于存放 MDK 的工程文件,如下图所示:

新建 HAL 库版本 MDK 工程

User 文件夹

User 文件夹用于存放 HAL 库用户配置文件、main.c、中断处理文件,以及分散加载文件。

我们首先从官方固件包里面直接拷贝官方的模板工程下的 HAL 库用户配置文件和中断处理文件到我们的 User 文件夹里。官方的模板工程路径:STM32Cube_FW_F4_V1-27-0ProjectsSTM324x9I_EVALTemplates,打开 Templates 文件夹,如下图所示。

新建 HAL 库版本 MDK 工程

我们需要的文件就在 Inc 和 Src 文件夹里面,在这两个文件夹里面找到:stm32f4xx_it.c、stm32f4xx_it.h、stm32f4xx_hal_conf.h 这三个文件,并且拷贝到我们的 User 文件夹下。

main.c 文件我们也是放在 User 文件夹里面的,后面在 MDK 里面教大家新建.c文件并保存。

二、新建工程框架

首先,打开 MDK 软件。然后点击 Project→New uVision Project 如图下所示:

新建 HAL 库版本 MDK 工程

然后弹出工程命名和保存的操作窗口,我们将工程文件保存路径设置在上一节新建的工程文件夹内,具体路径为:Projects→MDK-ARM,工程名字我们取:koi_f429,最后点击保存即可。

之后,弹出器件选择对话框,选择芯片型号,如下图所示:

新建 HAL 库版本 MDK 工程

点击 OK,MDK 会弹出 Manage Run-Time Environment 对话框,如图下所示:

新建 HAL 库版本 MDK 工程

这是 MDK5 新增的一个功能,在这个界面,我们可以添加自己需要的组件,从而方便构建开发环境,不过这里我们不做介绍。所以在上图所示界面,我们直接点击 Cancel,即可,得到下图所示界面:

新建 HAL 库版本 MDK 工程

此时,我们打开 MDK-ARM 文件夹,会看到 MDK 在该文件夹下自动创建了 3 个文件夹(DebugConfig、Listings 和 Objects),如图下所示:

新建 HAL 库版本 MDK 工程

这三个文件夹的作用如下表所示:

文件夹 作用
DebugConfig 用于存放调试设置信息文件(.dbgconf),不可删除!
Listings 用于存放编译过程产生的链接列表等文件
Objects 用于存放编译过程产生的调试信息、.hex、预览、.lib 文件等

编译过程产生的链接列表、调试信息、预览、lib 等文件,统称为中间文件。为了统一管理,方便使用,我们会把输出在 Listings 和 Objects 文件夹的内容,统一改为输出到 Output 文件夹(通过魔术棒设置),我们先把 MDK 自动生成的这两个文件夹(Listings 和 Objects)删除

至此,我们还只是建了一个框架,还有好几个步骤要做,比如添加文件、魔术棒设置、编写 main.c 等。

三、添加文件

本节将分 5 个步骤:1,设置工程名和分组名;2,添加启动文件;3,添加 SYSTEM 源码;4,添加 User 源码;5,添加 STM32F4xx_HAL_Driver 源码。

1、设置工程名和分组名

在 Project→Target 上右键,选择 Manage Project Items…(方法一)或在菜单栏点击品字形红绿白图标(方法二)进入工程管理界面,如图下所示:

新建 HAL 库版本 MDK 工程

在工程管理界面,我们可以执行设置工程名字(Project Targets)、分组名字(Groups)以及添加每个分组的文件(Files)等操作。我们设置工程名字为:Template,并设置四个分组:Startup(存放启动文件)、User(存放 main.c 等用户代码)、Drivers/SYSTEM(存放系统级驱动代码)Driver/STM32F4xx_HAL_Driver(存放 HAL 库代码)、Readme(存放工程说明文件),如图下所示:

新建 HAL 库版本 MDK 工程

设置好之后,我们点击 OK,回到 MDK 主界面,可以看到我们设置的工程名和分组名如图下所示:

新建 HAL 库版本 MDK 工程

这里我们只是新建了一个简单的工程,并没有添加 BSP、Middlewares 等分组,后面随着工程复杂程度的增加,我们需要一步步添加对应的分组。

【注意】:

​ 为了让工程结构清晰,我们会尽量让 MDK 的工程分组和我们前面新建的工程文件夹对应起来,由于 MDK 分组不支持多级目录,因此我们将路径也带入分组命名里面,以便区分。如:User 分组对应 User 文件夹里面的源码,Drivers/SYSTEM 分组,对应 Drivers/SYSTEM 文件夹里面的源码,Drivers/BSP 分组对应 Drivers/BSP 文件夹里面的源码等。

2、添加启动文件

启动文件(.s 文件)包含 STM32 的启动代码,其主要作用包括:

  • 堆栈(SP)的初始化;
  • 初始化程序计数器(PC);
  • 设置向量表异常事件的入口地址;
  • 调用 main 函数等。

是每个工程必不可少的一个文件,我们在本书第九章会有详细介绍。

启动文件由 ST 官方提供,存放在 STM32CubeF4 软件包的:Drivers → CMSIS → Device →ST → STM32F4xx → Source → Templates → arm 文件夹下。因为我们开发板使用的是STM32F429IGT6,对应的启动文件为:startup_stm32f429xx.s,为了节省空间,在精简版 CMSIS文件夹里面我们把其他启动文件都删了。

关于启动文件的说明,我们就介绍这么多,接下来我们看如何添加启动文件到工程里面。

我们有两种方法给 MDK 的分组添加文件:

  1. 双击 Project 下的分组名添加。
  2. 进入工程管理界面添加。

3、添加 SYSTEM 源码

这里我们在工程管理界面(方法 2)进行 SYSTEM 源码添加。点击:按钮,进入工程管理界面,选中 Drivers/SYSTEM 分组,然后点击:Add Files,进入文件添加对话框,依次添加delay.c、sys.c 和 usart.c 到该分组下,如下图所示:

新建 HAL 库版本 MDK 工程

4、添加 User 源码

这里我们在工程管理界面(方法 2)进行 User 源码添加。点击: 按钮,进入工程管理界面,选中 User 分组,然后点击:Add Files,进入文件添加对话框,依次添加 stm32f4xx_it.c 和 system_stm32f4xx.c 到该分组下,如下图所示:

新建 HAL 库版本 MDK 工程

5、添加 STM32F4xx_HAL_Driver 源码

接下来我们往 Drivers/STM32F4xx_HAL_Driver 分组里添加文件。点击: 按钮,进入工程管理界面,选中 Drivers/STM32F4xx_HAL_Driver 分组,然后点击:Add Files,进入文件添加对话 框 , 依 次 添 加 stm32f4xx_hal.c 、 stm32f4xx_hal_cortex.c 、 stm32f4xx_hal_dma.c 、stm32f4xx_hal_dma_ex.c、stm32f4xx_hal_gpio.c、stm32f4xx_hal_pwr.c、stm32f4xx_hal_pwr_ex.c、stm32f4xx_hal_rcc.c、stm32f4xx_hal_rcc_ex.c、stm32f4xx_hal_uart.c、stm32f4xx_hal_usart.c 到该分组下,如图下所示:

新建 HAL 库版本 MDK 工程

添加完成后,如图下所示:

新建 HAL 库版本 MDK 工程

可以看到分组中有些.c 文件有个小钥匙的符号,这是因为官方的固件包的文件设置了只读权限,我们取消只读权限就好了,方法如下图所示。

新建 HAL 库版本 MDK 工程

四、魔术棒设置

为避免编写代码和编译报错,我们需要通过魔术棒对 MDK 工程进行相关设置。在 MDK主界面,点击: (魔术棒图标,即 Options for Target 按钮),进入工程设置对话框,我们将进行如下几个选项卡的设置。

1. 设置 Target 选项卡

新建 HAL 库版本 MDK 工程

选择 ARM Compiler 版本为:Use default compiler version 5(即 AC5 编译器)

这里我们说明一下 AC5 和 AC6 编译的差异,如下表所示:

对比项 AC5 AC6 说明
中文支持 较好 较差 AC6 对中文支持极差,goto definition 无法使用,误报等
代码兼容性 较好 较差 AC6 对某些代码优化可能导致运行异常,需慢慢调试
编译速度 较慢 较快 AC6 编译速度比 AC5 快
语法检查 一般 严格 AC6 语法检查非常严格,代码严谨性较好

由于 AC5 对中文支持比较好,且兼容性相对好一点,为了避免不必要的麻烦,我们推荐大家使用 AC5 编译器。为了让大家自由选择,我们正点原子的源码,也是支持 AC6 编译器的,不过在选项卡设置上稍有差异,具体差异如下表所示:

选项卡 AC5 AC6 说明
Target 选择 AC5 编译器 选择 AC6 编译器 选择对应的编译器
C/C++ Misc Controls
无需设置
Misc Controls 设置:
-Wno-invalid-source-encoding
AC6 需设置编译选项以关闭对

2. 设置 Output 选项卡

在魔术棒→Output 选项卡里面,进行如下图所示设置:

新建 HAL 库版本 MDK 工程

注意,我们勾选:Browse Information,用于输出浏览信息,这样就可以使用 go to definition查看函数/变量的定义,对我们后续调试代码比较有帮助,如果不需要调试代码,则可以去掉这个勾选,以提高编译速度。

3. 设置 Listing 选项卡

新建 HAL 库版本 MDK 工程

经过 Output 和 Listing 这两步设置,原来存储在 Objects 和 Listings 文件夹的内容(中间文件)就都改为输出到 Output 文件夹了。

4. 设置 C/C++ 选项卡

在魔术棒→C/C++选项卡里面,进行如下图所示设置:

新建 HAL 库版本 MDK 工程

  • 设置了全局宏定义:STM32F429xx,用于定义所用 STM32 型号,在 stm32f4xx.h 里面会用到该宏定义。

  • 设置了优化等级为-O0,可以得到最好的调试效果,当然为了提高优化效果提升性能并降低代码量,可以设置-O1~-O3,数字越大效果越明显,不过也越容易出问题。注意:当使用AC6 编译器的时候,这里推荐默认使用-O1 优化。

  • 勾选 C99 模式,即使用 C99 C 语言标准。

  • 进行头文件包含路径设置

    新建 HAL 库版本 MDK 工程

上图中我们设置了 6 个头文件包含路径,其中 3 个在 Drivers 文件夹下,一个在 User 文件夹下,一个在 Middlewares 文件夹下。为避免频繁设置头文件包含路径,正点原子最新源码的 include 全部使用相对路径,也就是我们只需要在头文件包含路径里面指定一个文件夹,那么该文件夹下的其他文件夹里面的源码,如果全部是使用相对路径,则无需再设置头文件包含路径了,直接在 include 里面就指明了头文件所在。

关于相对路径,这里大家记住 3 点:

  1. 默认路径就是指 MDK 工程所在的路径,即.uvprojx 文件所在路径(文件夹)
  2. “./”表示当前目录(相对当前路径,也可以写做“.”)
  3. “../”表示当前目录的上一层目录(也可以写做“..”)

举例来说,上图中:....DriversCMSISDeviceSTSTM32F4xxInclude,前面两个“..”,表示 Drivers 文件夹在当前 MDK 工程所在文件夹(MDK-ARM)的上 2 级目录下,具体解释如下图所示:

新建 HAL 库版本 MDK 工程

上图表示根据头文件包含路径:....DriversCMSISDeviceSTSTM32F4xxInclude,编译器可以找到⑥处所包含的这些头文件,即代码里面可以直接 include 这些头文件使用。

#include "./SYSTEM/sys/sys.h"

即表示当前头文件包含路径所指示的 4 个文件夹里面,肯定有某一个文件夹包含了:SYSTEM/sys/sys.h 的路径,实际上就是在 Drivers 文件夹下面,两者结合起来就相当于:

#include "../../Drivers/SYSTEM/sys/sys.h"

这就是相对路径。它既可以减少头文件包含路径设置(即减少 MDK 配置步骤,免去频繁设置头文件包含路径的麻烦),同时又可以很方便的知道头文件具体在那个文件夹,因此我们推荐在编写代码的时候使用相对路径。

最后,我们如果使用 AC6 编译器,则在 魔术棒→C/C++选项卡 的 Misc Controls 处需要设置:-Wno-invalid-source-encoding,避免中文编码报错,如果使用 AC5 编译器,则不需要该设置!

5. 设置 Debug 选项卡

在魔术棒→Debug 选项卡里面,进行如下图所示设置:

新建 HAL 库版本 MDK 工程

图中,我们选择使用:CMSIS-DAP 仿真器,使用 SW 模式,并设置最大时钟频率为 10Mhz,以得到最高下载速度。当我们将仿真器和开发板连接好,并给开发板供电以后,仿真器就会找到开发板芯片,并在 SW Device 窗口显示芯片的 IDCODE、Device Name 等信息(图中⑤处),当无法找到时,请检查供电和仿真器连接状况。

6. 设置 Utilities 选项卡

在魔术棒→Debug 选项卡里面,进行如下图所示设置:

新建 HAL 库版本 MDK 工程

图中⑥处下载算法,是 MDK 默认添加的,针对 STM32F4xx 大容量系列产品(FLASH 容量为 1M)。一般我们用这个即可。如果⑥处没有下载算法,则点击⑦处按钮,执行添加一下下载算法即可(名字和⑥处的算法名字一样)。

五、添加 main.c,并编写代码

在 MDK 主界面,点击: 📄,新建一个 main.c 文件,并保存在 User 文件夹下。然后双击 User 分组,弹出添加文件的对话框,将 User 文件夹下的 main.c 文件添加到 User 分组下。

至此,我们就可以开始编写我们自己的代码了。我们在 main.c 文件里面输入如下测试代码:

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
int main(void)
{
    uint8_t t = 0;
    sys_stm32_clock_init(360, 25, 2, 4); /* 设置时钟,168Mhz */
    delay_init(180); /* 延时初始化 */
    while (1)
    {
        HAL_GPIO_WritePin(GPIOH,GPIO_PIN_11,GPIO_PIN_RESET);     /* LED0 亮 */
        HAL_GPIO_WritePin(GPIOH,GPIO_PIN_12,GPIO_PIN_SET);      /* LED1 灭 */
        HAL_Delay(1000);
        //delay_ms(500);
        HAL_GPIO_WritePin(GPIOH,GPIO_PIN_11,GPIO_PIN_SET);       /* LED0 灭 */
        HAL_GPIO_WritePin(GPIOH,GPIO_PIN_12,GPIO_PIN_RESET);    /* LED1 亮 */
        HAL_Delay(1000);
        //delay_ms(500);
    }
}

/**
 * @brief       初始化LED相关IO口, 并使能时钟
 * @param       无
 * @retval      无
 */
void led_init(void)
{
    GPIO_InitTypeDef gpio_init_struct;
    
    __HAL_RCC_GPIOH_CLK_ENABLE();                       /* LED0,LED1时钟使能 */

    gpio_init_struct.Pin = GPIO_PIN_11;                  /* LED0引脚 */
    gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;        /* 推挽输出 */
    gpio_init_struct.Pull = GPIO_PULLUP;                /* 上拉 */
    gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;      /* 高速 */
    HAL_GPIO_Init(GPIOH, &gpio_init_struct);            /* 初始化LED0引脚 */

    gpio_init_struct.Pin = GPIO_PIN_12;                 /* LED1引脚 */
    HAL_GPIO_Init(GPIOH, &gpio_init_struct);            /* 初始化LED1引脚 */

    HAL_GPIO_WritePin(GPIOH, GPIO_PIN_11, GPIO_PIN_SET); /* LED0 灭 */
    HAL_GPIO_WritePin(GPIOH, GPIO_PIN_12, GPIO_PIN_SET);/* LED1 灭 */
}

原文链接: https://www.cnblogs.com/lxd-koi/p/17028894.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    新建 HAL 库版本 MDK 工程

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/309908

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月16日 上午11:17
下一篇 2023年2月16日 上午11:17

相关推荐