欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

使用其他定时器作为HAL的基础时钟

程序员文章站 2022-06-08 20:50:27
...

在不使用FreeRTOS的时候,SysTick是默认的HAL基础时钟源,但是在SYS模块中,也可以选择其他定时器作为基础时钟源,例如可以选择基础定时器TIM6作为HAL的基础时钟源。

使用其他定时器作为HAL的基础时钟

图1 选用TIM6作为HAL的基础时钟

选择TIM6作为基础时钟源后,TIM6就不能在作为其他用途,在STM32CubeMX中不能再对TIM6做任何设置。在NVIC中,TIM6的中断被自动启用,优先级被设置为最高。可以修改TIM6的中断优先级,但是不能关闭TIM6的中断。同时,SysTick定时器的中断也还是被自动启用的,且不能关闭,如图2所示。

使用其他定时器作为HAL的基础时钟

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

1. 基础时钟的初始化

在使用定时器TIM6作为HAL的基础时钟源并用STM32CubeMX生成代码后,\Src目录下新增了一个文件stm32f4xx_hal_timebase_TIM.c,这个文件里重新实现了文件stm32f4xx_hal.c中的3个弱函数,用定时器TIM6替代了SysTick的功能。文件stm32f4xx_hal_timebase_TIM.c的完整代码如下:

	/* 文件: stm32f4xx_hal_timebase_TIM.c    -----------------------------------------*/
	#include "stm32f4xx_hal.h"
	#include "stm32f4xx_hal_tim.h"
	 
	TIM_HandleTypeDef      htim6; 
	
	HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
	{
	  RCC_ClkInitTypeDef    clkconfig;
	  uint32_t              uwTimclock = 0;
	  uint32_t              uwPrescalerValue = 0;
	  uint32_t              pFLatency;
	  
	  HAL_NVIC_SetPriority(TIM6_DAC_IRQn, TickPriority ,0);  //设置TIM6的中断优先级
	  HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn);    //开启TIM6中断 
	  __HAL_RCC_TIM6_CLK_ENABLE();   //开启TIM6的时钟
	  
	  HAL_RCC_GetClockConfig(&clkconfig, &pFLatency); //获取时钟配置
	  uwTimclock = 2*HAL_RCC_GetPCLK1Freq();  //计算TIM6的时钟频率,是PCLK1的2倍
	   
	  /* 计算分频系数,使TIM计数器时钟信号为1MHz*/
	  uwPrescalerValue = (uint32_t) ((uwTimclock / 1000000) - 1);
	  
	  /* 初始化 TIM6,使其定时周期为 1ms */
	  htim6.Instance = TIM6;
	  htim6.Init.Period = (1000000 / 1000) - 1;
	  htim6.Init.Prescaler = uwPrescalerValue;
	  htim6.Init.ClockDivision = 0;
	  htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
	  if(HAL_TIM_Base_Init(&htim6) == HAL_OK)
	  {
	    return HAL_TIM_Base_Start_IT(&htim6);   //以中断方式启动TIM6
	  }
	  return HAL_ERROR;
	}
	
	void HAL_SuspendTick(void)
	{  /* 禁止 TIM6 的UEV中断 */
	  __HAL_TIM_DISABLE_IT(&htim6, TIM_IT_UPDATE);  
	}
	
	void HAL_ResumeTick(void)
	{
	  /* 卡其 TIM6 的UEV中断 */
	  __HAL_TIM_ENABLE_IT(&htim6, TIM_IT_UPDATE);
	}

函数HAL_InitTick()是在HAL_Init()中被调用的,重新实现的这个函数对定时器TIM6进行了初始化配置,设置其中断优先级,配置其分频系数、计数周期等,使其定时器周期为1ms。

重新实现的函数HAL_ResumeTick()和HAL_SuspendTick()也是对TIM6的操作。

2. 基础时钟的中断处理

在使用定时器TIM6作为HAL的基础时钟源并用STM32CubeMX生成代码后,在文件stm32f4xx_it.c中没有了SysTick的ISR函数,有TIM6的ISR函数。TIM6的ISR函数代码如下:

	void TIM6_DAC_IRQHandler(void)
	{
	  HAL_TIM_IRQHandler(&htim6);
	}

定时器的UEV事件的回调函数是HAL_TIM_PeriodElapsedCallback,在文件main.c中就重新实现了这个函数,其功能就是执行函数HAL_IncTick(),代码如下:

	void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
	{
	  if (htim->Instance == TIM6) {
	    HAL_IncTick();
	  }
	}

所以,在使用TIM6作为HAL的基础时钟时,TIM6完全替代了SysTick的功能。

下一篇   FreeRTOS的基础时钟

主题   HAL和FreeRTOS的基础时钟

相关标签: HAL 基础时钟