从源代码来看HAL库函数(一) HAL基础函数
全局变量
__IO uint32_t uwtick
- 这个变量充当了一个运行时长计数的作用,每发生一次SysTick中断就会加一,直至溢出,可以计算一下,溢出时间为2^32/1000/3600(以每1ms+1来算),大概要1193个小时,约50天,一般情况下是不用担心它会溢出的。
- uint32_t uwTickPrio = (1UL << __NVIC_PRIO_BITS )
- SysTick计数器中断优先级,应该是最高优先级
HAL_TickFreqTypeDef uwTickFreq = HAL_TICK_FREQ_DEFAULT
enum HAL_TickFreqTypeDef { HAL_TICK_FREQ_10HZ = 100U, HAL_TICK_FREQ_100HZ = 10U, HAL_TICK_FREQ_1KHZ = 1U, HAL_TICK_FREQ_DEFAULT = HAL_TICK_FREQ_1KHZ}
这是一个枚举变量,定义了SysTick的中断频率,也就是1khz,1ms中断一次,这里也可以看到,HAL库中SysTick中断频率只有10HZ,100HZ,1000HZ这三种选择,最高只能支持1ms的计数中断,所以不能用它来产生us级别的中断计数延时,但是我们可以不使用HAL库提供的延时函数,可以利用时钟摘取的方式来实现我们自己的ms和us级延时,参考正点原子提供的delay延时函数实现。
HAL_StatusTypeDef HAL_Init (void)
该函数被调用来初始化HAL库,在main函数里面必须是首先被执行。
函数一共做了以下几件事:
- 配置SysTick来产生1ms的时基(此时还并未配置系统时钟来源,因此这时使用的HSI)
- 配置中断分组
- 调用
HAL_MspInit
来进行低级硬件初始化
00142 HAL_StatusTypeDef HAL_Init(void)
00143 {
00144 /* Configure Flash prefetch */
00145 #if (PREFETCH_ENABLE != 0)
00146 #if defined(STM32F101x6) || defined(STM32F101xB) || defined(STM32F101xE) || defined(STM32F101xG) || \
00147 defined(STM32F102x6) || defined(STM32F102xB) || \
00148 defined(STM32F103x6) || defined(STM32F103xB) || defined(STM32F103xE) || defined(STM32F103xG) || \
00149 defined(STM32F105xC) || defined(STM32F107xC)
00150
00151 /* Prefetch buffer is not available on value line devices */
00152 __HAL_FLASH_PREFETCH_BUFFER_ENABLE();
00153 #endif
00154 #endif /* PREFETCH_ENABLE */
00155
00156 /* Set Interrupt Group Priority */
00157 HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
00158
00159 /* Use systick as time base source and configure 1ms tick (default clock after Reset is HSI) */
00160 HAL_InitTick(TICK_INT_PRIORITY);
00161
00162 /* Init the low level hardware */
00163 HAL_MspInit();
00164
00165 /* Return function status */
00166 return HAL_OK;
00167 }
HAL_StatusTypeDef HAL_InitTick (uint32_t TickPriority)
该函数配置SysTick时钟来产生默认1ms的中断,同时指定了SysTick的中断优先级。
该函数被HAL_Init
调用来初始化SysTick
00234 __weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
00235 {
//配置SysTick来产生1ms的中断时基
00237 if (HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) > 0U)
00238 {
00239 return HAL_ERROR;
00240 }
00241 // 配置SysTick的中断优先级
00243 if (TickPriority < (1UL << __NVIC_PRIO_BITS))
00244 {
00245 HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
00246 uwTickPrio = TickPriority;
00247 }
00248 else
00249 {
00250 return HAL_ERROR;
00251 }
00252
00254 return HAL_OK;
00255 }
__weak void HAL_MspInit(void)
前面讲了HAL_Init
会调用这个函数来完成低等级硬件初始化,那么这个函数实际完成了什么呢?
以下代码是参考手册里的函数体,可以看到这个函数什么也没干,毕竟我们还没给它分配初始化任务
00200 __weak void HAL_MspInit(void)
00201 {
00202 /* NOTE : This function should not be modified, when the callback is needed,
00203 the HAL_MspInit could be implemented in the user file
00204 */
00205 }
以下代码是通过STM32CubeMx生成的,可以看到,配置完成之后,HAL_MspInit完成了使能需求时钟,配置中断分组,以及配置调试接口的任务。
因此,该函数的函数体内容是根据用户需求来动态修改的,会根据任务的不同拥有不同的函数体,当然你也可以添加你自己的需求代码。但要注意这个函数调用的时机是在main函数的最开始,由HAL_Init来调用的。不需要手动调用。之后你会看到好多类似的Init函数都不用自己来调用。
void HAL_MspInit(void)
{
__HAL_RCC_AFIO_CLK_ENABLE();
__HAL_RCC_PWR_CLK_ENABLE();
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);
__HAL_AFIO_REMAP_SWJ_DISABLE();
}
void HAL_Delay(uint32_t Delay)
该函数提供了精确到ms的延时。默认情况下,该函数使用SysTick
定时器来当作时钟源。
该函数定义在stm32f1xx_hal.c
的360行。
__weak void HAL_Delay(uint32_t Delay)
{
uint32_t tickstart = HAL_GetTick();
uint32_t wait = Delay;
/* Add a freq to guarantee minimum wait */
if (wait < HAL_MAX_DELAY)
{
wait += (uint32_t)(uwTickFreq);
}
while ((HAL_GetTick() - tickstart) < wait)
{
}
}
从代码可以看出该延时采用阻塞延时的方式,利用时钟摘取的方式获取当前运行时刻,来实现延时。__weak
前缀表示该函数可以被重写。
uint32_t HAL_GetTick(void)
该函数返回了一个32位数值,代表了当前运行的时间,以ms为单位
该函数定义在stm32f1xx_hal.c
的304行。
__weak uint32_t HAL_GetTick(void)
{
return uwTick;
}
从源代码可以看出该函数很简单,只是返回了全局变量uwtick
的值,同样,该函数是可以被重写的
void HAL_IncTick (void)
前面讲HAL_GetTick
是返回当前的计数值,那么这个函数就是被SysTick_Handler来调用,每次产生中断就调用它来自增uwtick
00293 __weak void HAL_IncTick(void)
00294 {
00295 uwTick += uwTickFreq; //HAL_TICK_FREQ_1KHZ = 1U,所以这里这么写,如果修改了SysTick的中断频率,这里也相应的改变了
00296 }
HAL_TickFreqTypeDef HAL_GetTickFreq(void)
该函数返回了SysTick的中断频率
00344 HAL_TickFreqTypeDef HAL_GetTickFreq(void)
00345 {
00346 return uwTickFreq;
00347 }
uint32_t HAL_GetTickPrio (void)
该函数返回SysTick的中断优先级
00313 uint32_t HAL_GetTickPrio(void)
00314 {
00315 return uwTickPrio;
00316 }
void HAL_SuspendTick ( void )
停止SysTick计数和中断,
00386 __weak void HAL_SuspendTick(void)
00387 {
00388 /* Disable SysTick Interrupt */
00389 CLEAR_BIT(SysTick->CTRL, SysTick_CTRL_TICKINT_Msk);
00390 }
void HAL_ResumeTick (void)
重新开始SysTick计数和中断
00402 __weak void HAL_ResumeTick(void)
00403 {
00404 /* Enable SysTick Interrupt */
00405 SET_BIT(SysTick->CTRL, SysTick_CTRL_TICKINT_Msk);
00406 }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)