16.1 初学者重要提示
对于一些常用的函数,大家一定要熟练的掌握都实现了什么功能,比如HAL_Init,HAL_RCC_OscConfig,HAL_RCC_ClockConfig等。最好的办法是把这些函数的源码读一遍。
16.2 那些是必备的API
这里我们通过一个简单的初始化流程来了解STM32H7的工程模板所必备的库文件和API:
第1步:系统上电复位,进入启动文件startup_stm32h743xx.s,在这个文件里面执行复位中断服务程序。
在复位中断服务程序里面执行函数SystemInit,此函数在文件system_stm32h7xx.c里面。
之后是调用编译器封装好的函数,比如用于MDK的启动文件是调用__main,最终进入到main函数。
第2步:进入到main函数就可以开始用户应用程序编程了。在这个函数里面要做几个重要的初始化,依次是:
MPU初始化,需要用到库文件stm32h7xx_hal_cortex.c和stm32h7xx_hal_cortex.h。
Cache初始化,需要用到core_cm7.h文件。
HAL库初始化函数HAL_Init,需要用到文件stm32h7xx_hal.c。
系统时钟初始化,需要用到库文件stm32h7xx_hal_rcc.c。
前面的两步完成后,就可以开始做用户需要的按键、串口等方面的初始化和应用代码的实现了。这里把我们需要学习的几个库文件整理出来,依次有:
startup_stm32h743xx.s
system_stm32h7xx.c
stm32h7xx_hal.c
stm32h7xx_hal_cortex.c
stm32h7xx_hal_rcc.c
core_cm7.h
其中startup_stm32h743xx.s和system_stm32h7xx.c已经在第13章为大家讲解过,这里不再赘述。而MPU和Cache涉及到的文件core_cm7.h在第23和24章为大家讲解。本章教程重点为大家讲解文件stm32h7xx_hal.c、stm32h7xx_hal_cortex.c和sm32h7xx_hal_rcc.c。
16.3 源文件stm32h7xx_hal.c(重要)
这个文件比较杂,像基准电压大小配置,EXTI配置,IO补偿配置等都在这个文件里面设置。学习这个文件注意事项:
HAL库中各个外设驱动里面的延迟实现是基于此文件提供的时间基准,而这个时间基准既可以使用滴答定时器实现也可以使用通用的定时器实现,默认情况下是用的滴答定时器。
函数HAL_Init里面会调用时间基准初始化函数HAL_InitTick,而调用函数HAL_RCC_ClockConfig也会调用时间基准初始化函数HAL_InitTick。
如果在中断服务程序里面调用延迟函数HAL_Delay要特别注意,因为这个函数的时间基准是基于滴答定时器或者其他通用定时器实现,实现方式是滴答定时器或者其他通用定时器里面做了个变量计数。如此一来,结果是显而易见的,如果其他中断服务程序调用了此函数,且中断优先级高于滴答定时器,会导致滴答定时器中断服务程序一直得不到执行,从而卡死在里面。所以滴答定时器的中断优先级一定要比它们高。
16.3.1 函数HAL_Init
函数原型:
HAL_StatusTypeDef HAL_Init(void)
{
/* 设置中断优先级分组 */
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
/* 使用滴答定时器做为默认时基,配置为1ms滴答,另外系统上电后默认使用的HIS时钟 */
if(HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK)
{
return HAL_ERROR;
}
/* 初始化底层硬件 */
HAL_MspInit();
/* 返回函数状态 */
return HAL_OK;
}
函数描述:
此函数用于初始化HAL库,此函数主要实现如下功能:
设置NVIC优先级分组是4。
设置滴答定时器的每1ms中断一次。
HAL库不像之前的标准库,在系统启动函数SystemInit里面做了RCC初始化,HAL库是没有做的,所以进入到main函数后,系统还在用内部高速时钟HSI,对于H7来说,HSI主频是64MHz。
函数HAL_Init里面调用的HAL_MspInit一般在文件stm32h7xx_hal_msp.c里面做具体实现,主要用于底层初始化。当前此函数也在文件stm32h7xx_hal.c里面,只是做了弱定义。
函数参数:
返回值,返回HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
注意事项:
必须在main函数里面优先调用此函数。
用户务必保证每1ms一次滴答中断。
关于优先级分组的设置可以看第21章节。
使用举例:
此函数的使用比较简单,上电后优先调用即可。
16.3.2 函数HAL_DeInit
函数原型:
HAL_StatusTypeDef HAL_DeInit(void)
{
/* 复位所有外设 */__set_PRIMASK
__HAL_RCC_AHB3_FORCE_RESET();
__HAL_RCC_AHB3_RELEASE_RESET();
/* 省略未写 */
__HAL_RCC_APB4_FORCE_RESET();
__HAL_RCC_APB4_RELEASE_RESET();
/* 复位底层硬件初始化 */
HAL_MspDeInit();
/* 返回值 */
return HAL_OK;
}
函数描述:
此函数用于复位HAL库和滴答时钟。
复位了AHB1,2,3,4的时钟以及APB1L,APB1H,APB2,3,4的时钟。
函数HAL_DeInit里面调用的HAL_MspDeInit一般在文件stm32h7xx_hal_msp.c里面做具体实现,主要用于底层初始化,跟函数HAL_Init里面调用的HAL_MspInit是一对。当前此函数也在文件stm32h7xx_hal.c里面,只是做了弱定义。
使用举例:
此函数的使用比较简单,需要调用的时候直接调用即可。
16.3.3 函数HAL_InitTick
函数原型:
__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
/* Configure the SysTick to have interrupt in 1ms time basis*/
if (HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) > 0U)
{
return HAL_ERROR;
}
/* Configure the SysTick IRQ priority */
if (TickPriority < (1UL << __NVIC_PRIO_BITS))
{
HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
uwTickPrio = TickPriority;
}
else
{
return HAL_ERROR;
}
/* Return function status */
return HAL_OK;
}
函数描述:
此函数用于初始化滴答时钟,此函数相关问题如下:
此函数有个前缀__weak ,表示弱定义,用户可以重定义。
此函数用于初始化滴答时钟1ms中断一次,并且为滴答中断配置一个用户指定的优先级。
此函数由HAL_Init调用,或者任何其它地方调用函数HAL_RCC_ClockConfig配置RCC的时候也会调用HAL_InitTick。
调用基于此函数实现的HAL_Delay要特别注意,因为这个函数的时间基准是基于滴答定时器或者其他通用定时器实现,实现方式是滴答定时器或者其他通用定时器里面做了个变量计数。如此一来,结果是显而易见的,如果其他中断服务程序调用了此函数,且中断优先级高于滴答定时器,会导致滴答定时器中断服务程序一直得不到执行,从而卡死在里面。所以滴答定时器的中断优先级一定要比它们高。
函数参数:
形参TickPriority用于设置滴答定时器优先级。
返回值,返回HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
使用举例:
此函数由HAL_Init调用,无需用户操作,除非需要重定义。
16.3.4 Systick的相关函数
调用了函数HAL_Init后,Systick相关的函数就可以使用了。这些函数如下:
函数原型:
__weak void HAL_IncTick(void)
__weak uint32_t HAL_GetTick(void)
uint32_t HAL_GetTickPrio(void)
HAL_StatusTypeDef HAL_SetTickFreq(HAL_TickFreqTypeDef Freq)
HAL_TickFreqTypeDef HAL_GetTickFreq(void)
__weak void HAL_Delay(uint32_t Delay)
__weak void HAL_SuspendTick(void)
__weak void HAL_ResumeTick(void)
函数描述:
这些函数就比较简单了,下面把这些函数实现的功能做个简单的说明:
函数HAL_IncTick在滴答定时器中断里面被调用,实现一个简单的计数功能,因为一般滴答定时器中断都是配置的1ms,所以计数全局变量uwTick每毫秒加1。
函数HAL_GetTick用于获取全局变量uwTick当前的计数。
函数HAL_GetTickPrio用于获取滴答时钟优先级。
函数HAL_SetTickFreq和HAL_GetTickFreq是一对,前者用于设置滴答中断频率,后再用于获取滴答中断频率。
函数HAL_Delay用于阻塞式延迟,默认单位是ms。
函数HAL_SuspendTick和HAL_ResumeTick是一对,前者用于挂起滴答定时器,后者用于恢复。
注意事项:
函数有个前缀__weak ,表示弱定义,用户可以重定义。
使用举例:
这些函数都比较简单,这里就不举例了。需要的时候,直接调用即可。
16.3.5 函数HAL_SYSCFG_VREFBUF_VoltageScalingConfig
函数原型:
void HAL_SYSCFG_VREFBUF_VoltageScalingConfig(uint32_t VoltageScaling)
函数描述:
此函数用于配置STM32H7内部电压基准大小。
当形参VoltageScaling = SYSCFG_VREFBUF_VOLTAGE_SCALE0时
输出基准是2.048 V,条件是VDDA >= 2.4V。
当形参VoltageScaling = SYSCFG_VREFBUF_VOLTAGE_SCALE1时
输出基准是2.5 V,条件是VDDA >= 2.8V。
当形参VoltageScaling = SYSCFG_VREFBUF_VOLTAGE_SCALE2时
输出基准是1.5 V,条件是VDDA >= 1.8V。
当形参VoltageScaling = SYSCFG_VREFBUF_VOLTAGE_SCALE3时
输出基准是1.8 V,条件是VDDA >= 2.1V。
16.3.6 H7自带电压基准相关函数
函数原型:
void HAL_SYSCFG_VREFBUF_VoltageScalingConfig(uint32_t VoltageScaling)
void HAL_SYSCFG_VREFBUF_TrimmingConfig(uint32_t TrimmingValue)
HAL_StatusTypeDef HAL_SYSCFG_EnableVREFBUF(void)
void HAL_SYSCFG_DisableVREFBUF(void)
函数描述:
函数HAL_SYSCFG_VREFBUF_VoltageScalingConfig
此函数用于配置STM32H7内部电压基准是否在芯片内部与VREF+引脚接通。
形参为SYSCFG_VREFBUF_HIGH_IMPEDANCE_DISABLE时,表示导通。
形参为SYSCFG_VREFBUF_HIGH_IMPEDANCE_ENABLE时,表示高阻,即不导通。
函数HAL_SYSCFG_VREFBUF_TrimmingConfig
此函数用于内部电压基准的校准调节。
函数HAL_SYSCFG_Ena
『本文转载自网络,版权归原作者所有,如有侵权请联系删除』