新建一个STM32F767工程(基于HAL库)

 使用STM32CubeMX可以生成一个直接可用的Keil工程,但为了加深对程序框架的理解与把控,从零开始新建一个工程也是有必要的,本文将简述这一过程。

开发环境

硬件环境

  • 电脑:Windows 10 Home x64
  • Apollo STM32F767开发板(ST-LINK V2仿真器)

软件环境

  • Keil Version 5.24.1 (Pack Installer:Keil.STM32F7xx_DFP.2.9.0.pack)
  • STM32CubeMX Version 4.25.0(Packages Manager:STM32CubeF7)

文件准备

参照库

 工程的建立基于ST官方的库函数,即STM32CubeF7固件库中的相关文件。库文件如图所示,当前使用的固件库版本为V1.11.0

建立工程文件夹

 选择创建工程的目录,在该目录下新建demo文件夹存储工程。在demo文件夹下,建立DriversIncMDK-ARMSrc四个子文件夹,同时依照如下方法在子文件夹中增加相应文件。

增加Drivers文件夹及相关文件

 在demo文件夹下新建Drivers文件夹,并按照如下方式增加相应文件。

Drivers\CMSIS\Include

 建立Drivers\CMSIS\Include文件夹,将STM32CubeF7固件库中Drivers\CMSIS\Include下如下头文件复制到文件夹中。

  • cmsis_armcc.h
  • core_cm7.h
  • core_cmFunc.h
  • core_cmInstr.h
  • core_cmSimd.h

 以上文件均为CMSIS Cortex内核支持相关头文件。CMSIS(Cortex Microcontroller Software Interface Standard)即为ARM Cortex微处理器软件接口标准,其结构如图所示。

Drivers\CMSIS\STM32F7xx\Include

 建立Drivers\CMSIS\STM32F7xx\Include文件夹,将STM32CubeF7固件库中Drivers\CMSIS\Device\ST\STM32F7xx\Include中如下头文件复制到文件夹中。

文件 说明
stm32f7xx.h 外设访问层头文件,确立stm32f767xx.h被include。
stm32f767xx.h 外设访问层头文件,进行寄存器操作结构体以及掩码等相关定义。
system_stm32f7xx.h 系统相关头文件,进行系统、时钟等初始化。

Drivers\CMSIS\STM32F7xx\Source

 建立Drivers\CMSIS\STM32F7xx\Source文件夹,将STM32CubeF7固件库中Drivers\CMSIS\Device\ST\STM32F7xx\Source\Templates中如下头文件复制到文件夹中。

文件 说明
system_stm32f7xx.c 与system_stm32f7xx.h对应,进行系统、时钟等初始化。

Drivers\STM32F7xx_HAL_Driver\Inc

 建立Drivers\STM32F7xx_HAL_Driver\Inc文件夹,将STM32CubeF7固件库中Drivers\STM32F7xx_HAL_Driver\Inc中如下头文件复制到文件夹中。

文件 说明
stm32f7xx_hal.h HAL通用外设头文件
stm32f7xx_hal_cortex.h Cortex内核通用外设头文件
stm32f7xx_hal_def.h HAL通用define等头文件
stm32f7xx_hal_flash.h/stm32f7xx_hal_flash_ex.h HAL Flash以及拓展头文件
stm32f7xx_hal_gpio.h/stm32f7xx_hal_gpio_ex.h HAL GPIO以及拓展头文件
stm32f7xx_hal_pwr.h/stm32f7xx_hal_pwr_ex.h HAL PWR以及拓展头文件
stm32f7xx_hal_rcc.h/stm32f7xx_hal_rcc_ex.h HAL RCC以及拓展头文件

Drivers\STM32F7xx_HAL_Driver\Inc\Legacy

 建立Drivers\STM32F7xx_HAL_Driver\Inc\Legacy文件夹,将STM32CubeF7固件库中Drivers\STM32F7xx_HAL_Driver\Inc\Legacystm32_hal_legacy.h复制到文件夹中,该文件为hal库的遗留头文件。

Drivers\STM32F7xx_HAL_Driver\Src

 建立Drivers\STM32F7xx_HAL_Driver\Src文件夹,将STM32CubeF7固件库中Drivers\STM32F7xx_HAL_Driver\Src中如下源文件复制到文件夹中。源文件与Drivers\STM32F7xx_HAL_Driver\Inc中头文件对应,这里不再说明。

增加Inc文件夹及相关文件

 在demo文件夹下新建Inc文件夹,将STM32CubeF7固件库中Projects\STM32F767ZI-Nucleo\Templates\Inc中如下头文件复制到文件夹中。

文件 说明
stm32f7xx_hal_conf.h HAL配置文件头文件
stm32f7xx_it.h HAL中断头文件

 注意,在stm32f7xx_hal_conf.h中,从第51行开始定义使能的外设,本程序的目的在于设置一个最精简工程,因此只使能必需的外设,即HAL_MODULE_ENABLEDHAL_GPIO_MODULE_ENABLEDHAL_RCC_MODULE_ENABLEDHAL_FLASH_MODULE_ENABLEDHAL_PWR_MODULE_ENABLEDHAL_CORTEX_MODULE_ENABLED使能,其余均注释掉。这里与包含的头文件源文件均是对应的。

 在Inc文件夹下新建main.h头文件,并加入代码如下。

1
2
3
4
5
6
#ifndef __MAIN_H
#define __MAIN_H
#include "stm32f7xx_hal.h"
#endif /* __MAIN_H */

 该头文件将被include到main函数中。

增加MDK-ARM文件夹及相关文件

 在demo文件夹下新建MDK-ARM文件夹,将STM32CubeF7固件库中Drivers\CMSIS\Device\ST\STM32F7xx\Source\Templates\armstartup_stm32f767xx.s头文件复制到文件夹中。该文件为处理器的启动文件。

增加Src文件夹及相关文件

 在demo文件夹下新建Src文件夹,将STM32CubeF7固件库中Projects\STM32F767ZI-Nucleo\Templates\Src中如下头文件复制到文件夹中。

文件 说明
stm32f7xx_hal_msp.c MCU support package源文件
stm32f7xx_it.c HAL中断源文件

 在Inc文件夹下新建main.c源文件,并加入代码如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include "main.h"
uint32_t mainloop = 0;
int main(void)
{
HAL_Init();
while (1)
{
mainloop++;
}
}

 至此,文件准备完毕。

建立工程

  • 打开keil新建工程,芯片选择STM32767IGTx,将工程文件命名为demo并保存在MDK-ARM目录下。

  • 选中demo工程,右键打开Manage Project Items,将Targets修改为demo,按照下图依次增加Groups与其中的Files。

  • 打开Options for Target ‘demo’->C/C++Define中加入加入USE_HAL_DRIVER,STM32F767xx定义,该定义将引导相关头文件确定该型号芯片的相关设置。

  • 打开Options for Target ‘demo’->C/C++,选择下方Include Paths,加入如下包含路径。这样Keil可以搜索到所需要的头文件。

  • 打开Options for Target ‘demo’->Debug,设置仿真器为ST-Link

打开Options for Target ‘demo’->Utilities,设置Flash算法并勾选Reset and Run,这样程序下载完毕后将自动复位运行。

编译运行程序

 编译程序,采用debug方式进行烧录,同时观察mainloop变量,可以看到该变量随着执行循环而不断增加。

 至此,工程建立与测试完成。

程序结构的优化

 程序完成基本功能之后,可以进行进一步的程序结构优化,具体如下。

设立mytype.h数据类型头文件

 对于不同的处理器与编译器,数据类型的命名方式有所不同,为了便于程序的编写与移植,可以用typedef对数据类型进行重新定义。打开Keil_v5\ARM\ARMCC\include路径下stdint.h文件,以此为参考设置自己的数据类型对照。建立mytype.h并放在demo文件夹下Inc文件夹,该文件具体内容如下。该文件应当被所有用户源文件使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/*
* mytype.h
*
* Created on: 2018-3-19
* Author: Di
*/
#ifndef MYTYPE_H_
#define MYTYPE_H_
#include "stdint.h"
typedef int8_t int8;
typedef int16_t int16;
typedef int32_t int32;
typedef int64_t int64;
typedef uint8_t uint8;
typedef uint16_t uint16;
typedef uint32_t uint32;
typedef uint64_t uint64;
typedef volatile int8 vint8;
typedef volatile uint8 vuint8;
typedef volatile int16 vint16;
typedef volatile uint16 vuint16;
typedef volatile int32 vint32;
typedef volatile uint32 vuint32;
typedef volatile int64 vint64;
typedef volatile uint64 vuint64;
typedef float float32;
typedef double float64;
#endif /* MYTYPE_H_ */

设立commom.h通用头文件

 对于不同的处理器,所有的硬件外设都需要调用库函数的通用外设头文件,以及设立的mytype.h数据类型头文件。可以建立一个commom.h通用头文件,创立新的用户文件直接将其include即可。建立commom.h并放在demo文件夹下Inc文件夹,该文件具体内容如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*
* common.h
*
* Created on: 2018-3-19
* Author: Di
*/
#ifndef COMMON_H_
#define COMMON_H_
#define TRUE 1
#define FALSE 0
#define HIGH 1
#define LOW 0
#include "stm32f7xx_hal.h"
#include "mytype.h"
#endif /* COMMON_H_ */

设立includes.h总包含头文件

 main函数中,需要包含所有的控制文件,可以单独建立一个includes.h总包含头文件,将需要包含的头文件统一管理即可。建立includes.h并放在demo文件夹下Inc文件夹,该文件具体内容如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
/*
* includes.h
*
* Created on: 2018-3-19
* Author: Di
*/
#ifndef INCLUDES_H_
#define INCLUDES_H_
#include "common.h"
#endif /* INCLUDES_H_ */

main.c修改

 有了includes.h总包含头文件,可以将main.c函数的include中仅仅设置为includes.h一项。

一个示例工程

 工程模板建立后,举例展示如何使用模板。这里添加GPIO控制相关文件。

增加gpio.h文件

 建立gpio.h并放在demo文件夹下Inc文件夹,该文件具体内容如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*
* gpio.h
*
* Created on: 2018-3-19
* Author: Di
*/
#ifndef GPIO_H_
#define GPIO_H_
#include "common.h"
void MX_GPIO_Init(void);
#endif /* GPIO_H_ */

增加gpio.c文件

 建立gpio.c并放在demo文件夹下Src文件夹,该文件具体内容如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*
* gpio.c
*
* Created on: 2018年3月19日
* Author: jiaod
*/
#include "gpio.h"
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0|GPIO_PIN_1, GPIO_PIN_RESET);
/*Configure GPIO pins : PB0 PB1 */
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

includes.h中包含gpio.h

 在includes.hinclude gpio.h文件。在工程中Manage Project ItemsApplication\User下加入gpio.c文件。

 此时,main函数中以及可以调用gpio.h/gpio.c中有关GPIO的函数。main.c文件修改如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include "includes.h"
uint32_t mainloop = 0;
int main(void)
{
HAL_Init();
MX_GPIO_Init();
while (1)
{
mainloop++;
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_1);
HAL_Delay(500);
}
}

 这样,就完成了程序结构的优化。

文章目录
  1. 1. 开发环境
    1. 1.1. 硬件环境
    2. 1.2. 软件环境
  2. 2. 文件准备
    1. 2.1. 参照库
    2. 2.2. 建立工程文件夹
    3. 2.3. 增加Drivers文件夹及相关文件
      1. 2.3.1. Drivers\CMSIS\Include
      2. 2.3.2. Drivers\CMSIS\STM32F7xx\Include
      3. 2.3.3. Drivers\CMSIS\STM32F7xx\Source
      4. 2.3.4. Drivers\STM32F7xx_HAL_Driver\Inc
      5. 2.3.5. Drivers\STM32F7xx_HAL_Driver\Inc\Legacy
      6. 2.3.6. Drivers\STM32F7xx_HAL_Driver\Src
    4. 2.4. 增加Inc文件夹及相关文件
    5. 2.5. 增加MDK-ARM文件夹及相关文件
    6. 2.6. 增加Src文件夹及相关文件
  3. 3. 建立工程
  4. 4. 编译运行程序
  5. 5. 程序结构的优化
    1. 5.1. 设立mytype.h数据类型头文件
    2. 5.2. 设立commom.h通用头文件
    3. 5.3. 设立includes.h总包含头文件
    4. 5.4. main.c修改
  6. 6. 一个示例工程
    1. 6.1. 增加gpio.h文件
    2. 6.2. 增加gpio.c文件
    3. 6.3. includes.h中包含gpio.h
|