HAL库--20170905

来源:互联网 发布:谁发现了美洲大陆知乎 编辑:程序博客网 时间:2024/06/18 11:26

HAL库,全称Hardware Abstract Layer,也叫硬件抽象层。这里简单介绍一下利用cubeMX生成的程序结构。

这里的例子是stm32f103中的一个电机驱动程序,程序本身不重要,主要是看自动生成的程序的结构。

先看整个工程:

一共四个文件夹。

第一个文件夹是stm32f1xx_hal_driver,可以看作是以前的库函数文件夹。里面的c文件有三种:stm32f1xx_hal_ppp.c,stm32f1xx_hal_ppp_ex.c,stm32f1xx_hal.c。其中ppp代表外设名,stm32f1xx_hal_ppp.c包含了外设ppp相关的函数,stm32f1xx_hal_ppp_ex.c包含外设ppp的一些拓展函数,stm32f1xx_hal.c包含HAL库的初始化函数。后面会介绍一些其中的函数。

第二个文件夹是用户文件夹application/user,意味着里面的文件是根据用户自己的需求修改的,工程刚生成的时候有三个c文件:main.c,stm32f1xx_hal_msp.c,stm32f1xx_it.c。

stm32f1xx_it.c是中断文件,虽然在用户文件夹中,但是从来对它进行修改。需要写中断服务函数时,直接重新在main.c文件中写对应的回调函数即可。

stm32f1xx_hal_msp.c文件是一个比较重要的文件,虽然平时也不会对它进行修改。msp在这里是MCU specific package的缩写,可以理解为特别的包,“特别”是指这个文件里面的一些参数是由用户自己提供的,不是库自带的。在工程初始化的过程中,它会先用一个通用的初始化函数初始化一遍,然后再用带有用户给的参数的初始化函数初始化。后半段过程就需要msp这个文件里的函数,另外,带有用户参数的函数也会使用msp在函数名中体现出来,例如HAL_MspInit()与HAL_Init()。

main.c是主函数,下面过一遍主函数的执行流程。

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */  HAL_Init();  /* Configure the system clock */  SystemClock_Config();  /* Initialize all configured peripherals */  MX_GPIO_Init();  MX_SPI1_Init();  MX_USART2_UART_Init();
整体上看,首先是调用HAL_Init()函数对外设、flash接口与systick计时器进行初始化,然后是配置时钟,最后初始化外设。

具体到每个函数,HAL_Init()函数中,按照默认的参数配置完优先级等参数,最后调用了HAL_MspInit()函数。这个函数在工程中一共有两个,一个由_weak定义,存在于库函数中。另一个在stm32f1xx_hal_msp.c中,按照用户的参数初始化了优先级等参数。第二个函数的存在会覆盖_weak定义的函数,这就起到了一个便于移植的效果。移植只需要更改用户文件里的东西,一方面,工程初始化时都会先使用默认的参数初始化一遍,即使不小心移植漏了一些配置代码,也不会出现致命的错误。另一方面,只需要改一个文件里的内容,即使不懂驱动层也可以改程序。

说完了HAL_Init()函数的工作方式,外设的初始化也是同样的思想。例如,对spi外设初始化的函数MX_SPI!_Init(),首先将用户的参数存在一个SPI的结构体中,再调用HAL_SPI_Init(&hspi1),该函数首先检查参数是否正确,然后就调用了HAL_SPI_MspInit(hspi),注意这里已经将前面提到的SPI结构体作为参数赋予了msp初始化函数。最终就根据SPI结构体的值,通过HAL_SPI_MspInit()函数进行初始化的过程,包括模式的选择、优先级的配置等等。

原创粉丝点击