(6条消息) 使用SysTick作为HAL的基础时钟

HAL需要设置一个定时器作为基础时钟。基础时钟通过定时溢出中断产生嘀嗒信号,嘀嗒信号的缺省频率是1000Hz,也就是基础时钟的定时周期是1ms。基础时钟主要用于实现延时函数HAL_Delay(),或在一些有超时(timeout)设置的函数里确定延时。

在不使用FreeRTOS的时候,STM32CubeMX里默认地将基础时钟源设置为SysTick定时器,如图1所示。SysTick是Cortex-M内核自带的一个24位的定时器,将SysTick作为HAL的基础时钟后,在NVIC中会自动启用SysTick的中断,并且优先级设置为最高,如图2所示。可以修改SysTick的中断优先级,但是不能在图2中禁用SysTick中断。

图1 在SYS中设置HAL的基础时钟源为SysTick

图2 使用SysTick作为HAL基础时钟源的NVIC设置

1. 基础时钟的初始化

在STM32CubeMX生成的初始化代码中,HAL_Init()是在main()函数中执行的第一行代码。HAL_Init()对SysTick定时器进行设置,使其定时中断周期为1ms。函数HAL_Init()的代码如下。HAL_StatusTypeDef HAL_Init(void){/* Configure Flash prefetch, Instruction cache, Data cache */#if (INSTRUCTION_CACHE_ENABLE != 0U)__HAL_FLASH_INSTRUCTION_CACHE_ENABLE();#endif /* INSTRUCTION_CACHE_ENABLE */#if (DATA_CACHE_ENABLE != 0U)__HAL_FLASH_DATA_CACHE_ENABLE();#endif /* DATA_CACHE_ENABLE */#if (PREFETCH_ENABLE != 0U)__HAL_FLASH_PREFETCH_BUFFER_ENABLE();#endif /* PREFETCH_ENABLE *//* 设置中断优先级分组策略 */HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);/* 使用SysTick作为基础时钟,配置嘀嗒周期为1ms  */HAL_InitTick(TICK_INT_PRIORITY);HAL_MspInit();  /* 底层硬件初始化*/return HAL_OK;}

其中,执行的HAL_InitTick(TICK_INT_PRIORITY)是对SysTick定时器进行定时周期和中断的设置,HAL_InitTick()是在文件stm32f4xx_hal.c中用__weak修饰符定义的弱函数,代码如下:__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority){/* 配置SysTick定时周期为1ms */if (HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) > 0U){return HAL_ERROR;}/* 配置SysTick定时器的中断优先级 */if (TickPriority < (1UL << __NVIC_PRIO_BITS)){HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);uwTickPrio = TickPriority;}else{return HAL_ERROR;}return HAL_OK;}

作为弱函数,HAL_InitTick()可以被重新实现。在使用SysTick作为基础时钟时,使用的就是文件stm32f4xx_hal.c中的HAL_InitTick()。

函数HAL_Init()中最后调用的函数HAL_MspInit()也是一个弱函数,在HAL驱动中就是个空函数。在STM32CubeMX生成的初始化代码中,在文件stm32f4xx_hal_msp.c中重新实现了这个函数,功能就是启用了RCC的时钟信号,并设置中断优先级分组策略,也就是图2中用户设置的优先级分组策略。void HAL_MspInit(void){__HAL_RCC_SYSCFG_CLK_ENABLE();__HAL_RCC_PWR_CLK_ENABLE();HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);}

所以,执行函数HAL_Init()后,就设置了SysTick定时器的定时周期和中断优先级。默认的SysTick定时周期为1ms,产生的嘀嗒信号频率为1000Hz。

2. 基础时钟的中断处理

在文件stm32f4xx_it.c中自动生成了SysTick定时器中断的ISR函数,其代码如下:void SysTick_Handler(void){HAL_IncTick();}

在SysTick定时器的定时溢出中断里就执行了函数HAL_IncTick(),这是在文件stm32f4xx_hal.c中实现的函数,函数的代码如下:__weak void HAL_IncTick(void){uwTick += uwTickFreq;}

它的功能就是使得全局变量uwTick递增,这个变量就是嘀嗒信号的计数值。当嘀嗒信号频率为1000Hz时,uwTickFreq的值为1;当嘀嗒信号频率为100Hz时,uwTickFreq的值为10。

在文件stm32f4xx_hal.c中还定义了操作滴答定时器的两个函数,用于暂停和恢复滴答定时器,都是用__weak定义的弱函数,代码如下:__weak void HAL_SuspendTick(void){  /* 禁止 SysTick 中断 */SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;}__weak void HAL_ResumeTick(void){  /* 开启 SysTick 中断 */SysTick->CTRL  |= SysTick_CTRL_TICKINT_Msk;}

常用的延时函数HAL_Delay()就是利用嘀嗒信号来实现的,函数HAL_Delay()的代码如下:__weak void HAL_Delay(uint32_t Delay){uint32_t tickstart = HAL_GetTick();//获取嘀嗒信号当前计数值uint32_t wait = Delay;if (wait < HAL_MAX_DELAY)   //最少延时1ms{wait += (uint32_t)(uwTickFreq);   // uwTickFreq默认值为1}while((HAL_GetTick() - tickstart) < wait){}}

程序中调用的函数HAL_GetTick()的功能就是返回全局变量uwTick,也就是嘀嗒信号的当前计数值。函数HAL_Delay()的输入参数Delay是以毫秒为单位的延时时间。延时的原理就是先读取嘀嗒信号的当前计数值保存到变量tickstart,计算在此基础上延时所需要的计数值差量wait,然后在while循环中不断用函数HAL_GetTick()读取滴答信号当前技术值,计算相对于tickstart的差量,当差量超过wait时就达到了延时时间。

在HAL库中使用SysTick作为基础定时器时,其作用就是用于产生嘀嗒信号计数值,然后用于延时计算。如果不需要用到延时计算,停掉SysTick定时器对系统运行是没有什么影响的。例如,在使用低功耗设计时,为了使系统进入睡眠模式后不被SysTick的中断唤醒,就停掉了SysTick定时器。

(0)

相关推荐

  • ​STM32延时函数的四种方法

    单片机编程过程中经常用到延时函数,最常用的莫过于微秒级延时delay_us()和毫秒级delay_ms().本文基于STM32F207介绍4种不同方式实现的延时函数. 普通延时 这种延时方式应该是大家 ...

  • (6条消息) HAL和FreeRTOS的基础时钟

    在STM32CubeMX里启用FreeRTOS后,生成代码时会出现一个如图所示的对话框,提示要使用一个非SysTick定时器作为HAL的基础时钟.为什么要这么设置?什么是HAL的基础时钟?为什么不使用 ...

  • (7条消息) C++中位运算的使用方法

    一:简介1 位逻辑运算符:& (位   "与")  and^  (位   "异或")|   (位    "或")   or~  (位 ...

  • (35条消息) 中国城域网路由情况介绍

    中国的城域网,大概有三张比较典型的,一个是中国移动的CMnet,一个是中国电信IP城域网,还有一个是中国网通IP城域网.作为接入最后的阵地,城域网的业务是最复杂的.含盖了IPTV,语音,Interne ...

  • (35条消息) 家用宽带网络与服务器使用的网络有什么不同?

    很多人都知道,服务器的网络跟家用网络有很多区别.其中有很多技术大牛,都是使用家里的宽带做很多别人使用公网服务器才能完成的服务. 但是对于普通人来讲,似乎都觉得没什么区别,本文就此简单做一下区分: 固定 ...

  • 怎么设置微信公众号添加关注后自动回复多条消息

    怎么设置微信公众号添加关注后自动回复多条消息

  • (40条消息) 5G网络(接入网+承载网+核心网)

    前一段时间自己一直在做某市的5G试点项目,对5G的无线接入网相关技术有了更深入的认识.因此,希望通过无线接入网为线索(行话叫锚点),帮大家梳理一下无线侧接入网+承载网+核心网的架构,这里以接入网为主, ...

  • (7条消息) 国家信息化体系六要素

    历史的温度:寻找历史背面的故事.热血和真性情作者:张玮出版社:中信出版集团股份有限公司好评:100% 销售量:0 ¥34.3 历史的温度2:细节里的故事.彷徨和信念作者:张玮出版社:中信出版集团股份有 ...

  • (7条消息) QStringLiteral

    QStringLieral是Qt5中新引入的一个用来从"字符串常量"创建QString对象的宏(字符串常量指在源码中由双引号包含的字符串).在这篇博客我讲解释它的的内部实现和工作原 ...

  • (40条消息) Fastly释Lucet原生WebAssembly编译程序和Runtime

    云端服务供货商Fastly释出Lucet开源项目,这是原生的WebAssembly编译程序和Runtime,目的是要将WebAssembly带出浏览器,在开发者的应用程序中,安全地执行不受信任的Web ...