00. 目录
01. HAL库概述
HAL库,全称为Hardware Abstraction Layer(硬件抽象层)库,是STMicroelectronics(ST)为STM32微控制器提供的较新的固件库。以下是关于HAL库的详细介绍:
HAL库的定义与特点
- 定义:HAL库是一个中间件,为应用程序和硬件之间提供了一个接口,允许开发者在不知道底层硬件细节的情况下编写控制硬件的代码。
- 特点
- 跨平台支持:HAL库支持STM32全系列微控制器,使得开发者编写的代码可以在不同的STM32产品之间移植。
- 结构统一:为所有外设提供统一的API和驱动结构,简化了开发过程。
- 易于使用:封装了许多底层的硬件操作,使开发者能够快速上手,并专注于应用层逻辑的开发。
- 与STM32CubeMX工具集成:STM32CubeMX可以自动生成HAL库的初始代码,方便开发者配置硬件。
HAL库的优势
- 简化开发:HAL库提供了一组标准化的函数和宏,用于访问和控制硬件,使开发者能够更快速、更简单地开发应用程序。
- 提高软件重用性和移植性:通过抽象硬件功能,HAL库使应用程序能够在不同的硬件平台上运行,提高了软件的移植性。
- 易于维护和升级:当硬件发生变化时,只需修改HAL库的相关部分,而无需修改应用程序代码。
- 提高性能:HAL库通常经过优化,以提供高效的硬件访问和最小的软件开销。
HAL库与标准库的区别
- 抽象级别:HAL库提供了更高级别的抽象,封装了更多的底层硬件操作,而标准库则更接近寄存器操作,提供了更多的控制权。
- 学习曲线:对于初学者来说,HAL库的学习曲线相对较平缓,因为它封装了许多复杂的硬件操作;而标准库则要求开发者具备较高的硬件知识,学习曲线较陡。
- 开发效率:由于HAL库提供了统一的API和驱动结构,并集成了STM32CubeMX工具,因此可以大大提高开发效率;而标准库则可能需要开发者花费更多时间学习和理解底层硬件。
HAL库版本
STM32Cube-FW-F1-V1.8.0.rar
02. 创建工程步骤
2.1在建立工程之前,我们在电脑的某个目录下面建立一个文件夹,名字为 00_Template。
笔者目录为E:\Program Data\keil\00_Template
2.2 在上述00_Template目录下创建一下四个目录
CORE 用来存放核心文件和启动文件,OBJ 是用来存放编译过程文件以及hex 文件,HALLIB 文件夹顾名思义用来存放 ST 官方提供的库函数源码文件。
2.3 点击 MDK 的菜单:Project –>New Uvision Project ,
2.4 将目录定位到刚才建立的文件夹00_Template 之下,然后定位到 USER 目录下面,我们的工程文件就都保存到 USER 文件夹下面。工程命名为Template,点击保存。
2.5 选择 CPU 的界面,就是选择我们的芯片型号。
STMicroelectronics→STM32F1 Series→STM32F103→STM32F103ZET6(如果使用的是其他系列的芯片,选择相应的型号就可以了)
温馨提示
一定要安装对应的器件 pack 才会显示这些内容哦!
2.6 MDK 会弹出 Manage Run-Time Environment 对话框, 点击取消即可。
2.7 点击取消之后得到如下界面
2.8 将固件库目录下面的 src,inc 文件夹拷贝到我们刚才建立的 STM32F10x_FWLib 文件夹下面。
固件库目录:STM32Cube_FW_F1_V1.8.0\Drivers\STM32F1xx_HAL_Driver
目的目录:00_Template\HALLIB
2.9 将固件库包里面相关的启动文件复制到我们的工程目录 CORE 之下。
STM32Cube_FW_F1_V1.8.0\Drivers\CMSIS\Include下面,将文件cmsis_armcc.h,
cmsis_armclang.h, cmsis_compiler.h, core_cm3.h, cmsis_version.h复制到CORE 目录里面。
2.10 将里面startup_stm32f103xe.s文件复制到CORE下面
定位到目录STM32Cube_FW_F1_V1.8.0\Drivers\CMSIS\Device\ST\STM32F1xx\Source\Templates\arm下面,将里面 startup_stm32f103xe.s文件复制到 CORE 下面。
2.11 将三个文件stm32f1xx.h,system_stm32f1xx.h 和 stm32f103xe.h,复制到我们的USER目录之下。
STM32Cube_FW_F1_V1.8.0\Drivers\CMSIS\Device\ST\STM32F1xx\Include下面将里面的三个文件stm32f1xx.h,system_stm32f1xx.h 和 stm32f103xe.h,复制到我们的 USER目录之下。
2.12 将2个文件stm32f1xx_it.h,stm32f1xx_hal_conf.h 复制到 USER 目录下面。
STM32Cube_FW_F1_V1.8.0\Projects\STM3210E_EVAL\Templates\Inc目录中stm32f1xx_it.h,stm32f1xx_hal_conf.h 复制到 USER 目录下面。
2.13 打开Src目录,将下面的四个源文件system_stm32f1xx.c,stm32f1xx_it.c, stm32f1xx_hal_msp.c 和 main.c 同样全部复制到 USER 目录下面。
STM32Cube_FW_F1_V1.8.0\Projects\STM3210E_EVAL\Templates\Src
2.14 将上述文件添加到我们的工程中去。右键点击 Target1,选择 Manage Project Items。
2.15 Project Targets一栏,我们将Target名字修改为Template,然后在Groups一栏删掉一个SourceGroup1,建立三个 Groups:USER,CORE,HALLIB。然后点击 OK。
2.16 右键点击点击Tempate,选择选择 Manage Project Itmes,然后选择需要添加文件的 Group,添加对应的文件。
这里第一步我们选择HALLIB,然后点击右边的 Add Files,定位到我们刚才建立的目录\HALLIB\Src 下面,将里面所
有的文件选中(Ctrl+A),然后点击 Add,然后 Close.可以看到 Files 列表下面包含我们添加的文件,这里需要说明一下,对于我们写代码,如果我们只用到了其中的某个外设,
我们就可以不用添加没有用到的外设的库文件。例如我只用 GPIO,我可以只用添加stm32f1xx_gpio.c 而其他外设相关的可以不用添加。这里我们全部添加进来是为了后面方便,不用每次添加,当然这样的坏处是工程太大,编译起来速度慢,用户可以自行选择。
stm32f1xx_hal_msp_template.c 文件内容是一些空函数,一般也不需要引入。删除某个方法如下
用上面同样的方法,将 Groups 定位到 CORE,USER分组之下,添加需要的文件。CORE 分组下面需要添加的文件为一些头文件以及启动文件 startup_stm32f103xe.s( 注意,默认添加的时候文件类型为.c,添加.h 头文件和 startup_stm32f103xe.s 启动文件的时候,你需为 要选择文件类型为 All files 才能看得到这些文件)。
USER 分组下面需要添加的文件 USER 目录下面所有的.c 文件:main.c,stm32f1xx_hal_msp.c,stm32f1xx_it.c 和 system_stm32f1xx.c 四个文件。
添加完必要的文件到工程之后,最后点击 OK,回到工程主界面。
2.17 选择编译中间文件编译后存放目录
在编译之前我们首先要选择编译中间文件编译后存放目录。方法是点击魔术棒,然后选择“Output”选项下面的“Select folder for objects…”,然后选择目录为我们上面新建的 OBJ 目录。这里大家注意,如果我们不设置 Output 路径,那么默认的编译中间文件存放目录就是 MDK 自动生成的 Objects 目录和 Listings 目录。
2.18 设置头文件目录
对于任何一个工程,我们都需要把工程中引用到的所有头文件的路径都包含到进来 。回到工程主菜单,点击魔术棒 ,出来一个菜单,然后点击 c/c++选项.然后点击Include Paths 右边的按钮。弹出一个添加 path 的对话框,然后我们将图上面的 3 个目录添加进去。记住,keil 只会在一级目录查找,所以如果你的目录下面还有子目录,记得 path一定要定位到最后一级子目录。然后点击 OK.
这里大家需要注意,这里添加的路径必须添加到头文件所在目录的最后一级。这里我们需要添加的头文件路径包括:\CORE, \USER\,以及\HALLIB\Inc。这里还需要提醒大家,HAL库存放头文件子目录是\HALLIB\Inc,不是 HALLIB\Src,其次很多朋友都是这里弄错导致报很多奇怪的错误。
2.19 添加宏定义
USE_HAL_DRIVER,STM32F103xE
接下来对于 STM32F103 系列的工程,还需要添加全局宏定义标识符,所谓全局宏定义标识符,就是在工程中任何地方都可见。添加方法是点击魔术棒之后,进入 C/C++选项卡,然后在 Define 输入框连输入:USE_HAL_DRIVER,STM32F103xE。注意这里是两个标识符USE_HAL_DRIVER 和 STM32F103xE, 他们之间是用逗号隔开的
2.20 修改main.c如下
#include "stm32f1xx.h"
void Delay(__IO uint32_t nCount);
void Delay(__IO uint32_t nCount)
{
while(nCount--){}
}
void Stm32_Clock_Init(uint32_t PLL)
{
HAL_StatusTypeDef ret = HAL_OK;
RCC_OscInitTypeDef RCC_OscInitStructure;
RCC_ClkInitTypeDef RCC_ClkInitStructure;
RCC_OscInitStructure.OscillatorType=RCC_OSCILLATORTYPE_HSE; //时钟源为HSE
RCC_OscInitStructure.HSEState=RCC_HSE_ON; //打开HSE
RCC_OscInitStructure.HSEPredivValue=RCC_HSE_PREDIV_DIV1; //HSE预分频
RCC_OscInitStructure.PLL.PLLState=RCC_PLL_ON; //打开PLL
RCC_OscInitStructure.PLL.PLLSource=RCC_PLLSOURCE_HSE; //PLL时钟源选择HSE
RCC_OscInitStructure.PLL.PLLMUL=PLL; //主PLL倍频因子
ret=HAL_RCC_OscConfig(&RCC_OscInitStructure);//初始化
if(ret!=HAL_OK) while(1);
//选中PLL作为系统时钟源并且配置HCLK,PCLK1和PCLK2
RCC_ClkInitStructure.ClockType=(RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2);
RCC_ClkInitStructure.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK; //设置系统时钟时钟源为PLL
RCC_ClkInitStructure.AHBCLKDivider=RCC_SYSCLK_DIV1; //AHB分频系数为1
RCC_ClkInitStructure.APB1CLKDivider=RCC_HCLK_DIV2; //APB1分频系数为2
RCC_ClkInitStructure.APB2CLKDivider=RCC_HCLK_DIV1; //APB2分频系数为1
ret=HAL_RCC_ClockConfig(&RCC_ClkInitStructure,FLASH_LATENCY_2); //同时设置FLASH延时周期为2WS,也就是3个CPU周期。
if(ret!=HAL_OK) while(1);
}
int main(void)
{
GPIO_InitTypeDef GPIO_Initure;
HAL_Init(); //???HAL?
Stm32_Clock_Init(RCC_PLL_MUL9); //设置时钟,72M
__HAL_RCC_GPIOB_CLK_ENABLE(); //??GPIOB??
__HAL_RCC_GPIOE_CLK_ENABLE(); //??GPIOE??
GPIO_Initure.Pin=GPIO_PIN_5; //PB5
GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //????
GPIO_Initure.Pull=GPIO_PULLUP; //??
GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH; //??
HAL_GPIO_Init(GPIOB,&GPIO_Initure);
GPIO_Initure.Pin=GPIO_PIN_5; //PE5
HAL_GPIO_Init(GPIOE,&GPIO_Initure);
while(1)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET); //PB5?1
HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_SET); //PE5?1
Delay(0x7FFFFF);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_RESET); //PB5?0
HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_RESET); //PE5?0
Delay(0x7FFFFF);
}
}
2.21 删除stm32f1xx_hal_msp.c文件中21行#include “main.h”
stm32f1xx_hal_msp.c(21): error: ‘main.h’ file not found
2.22 删除stm32f1xx_it.c文件中23行#include “main.h”
stm32f1xx_it.c(23): error: ‘main.h’ file not found
2.23 删除一下两个文件
stm32f1xx_hal_timebase_rtc_alarm_template.c
stm32f1xx_hal_timebase_tim_template.c
2.24 编译整个工程,如果没有任何报错,则整个工程已经创建好了。