FreeRTOS定时器的介绍和使用

目录

1,常见定时器

高级控制定时器(TIM1)

通用定时器(TIM2、TIM3、TIM4、TIM5、TIM15、TIM16、TIM17)

基本定时器(TIM6、TIM7)

低功耗定时器(LPTIM1)

         2,以TIM6定时器为例,介绍定时器的使用

1,定时器实例选择

2,配置所需定时器

3,设置频率

4,中断回调函数

         3,TIM6定时器代码(初始化后自动生成)

         4,使用示例


 定时器本质上是对时钟信号进行计数。系统时钟会产生稳定的周期性脉冲信号,定时器有一个计数器,每接收到一个时钟脉冲,计数器的值就会加 1(或减 1)。当计数器的值达到预设的阈值时,定时器就会触发相应的事件,如产生一个中断信号、输出一个特定的电平信号等。

1,常见定时器

高级控制定时器(TIM1)

  • 功能特点:高级控制定时器是功能最强大的定时器之一,具备 16 位向上、向下、向上 / 向下自动装载计数器,还拥有可编程死区控制的互补输出、紧急刹车功能等。
  • 应用场景:非常适合用于电机控制,如控制三相无刷直流电机的驱动信号;也可用于电力电子中的 PWM 整流器和逆变器控制,能精确控制脉冲宽度和相位。

通用定时器(TIM2、TIM3、TIM4、TIM5、TIM15、TIM16、TIM17)

  • 功能特点:通用定时器包含 16 位或 32 位(TIM2 和 TIM5 为 32 位)向上、向下、向上 / 向下自动装载计数器,支持输入捕获、输出比较、PWM 生成等多种功能。
  • 应用场景:可用于测量外部信号的频率和脉宽(输入捕获功能),如测量传感器输出的脉冲信号;还能产生各种占空比和频率的 PWM 信号,用于控制 LED 的亮度、舵机的角度等。

基本定时器(TIM6、TIM7)

  • 功能特点:基本定时器为 16 位向上自动装载计数器,主要功能是产生时基,可用于驱动 DAC(数模转换器)或者作为简单的定时功能。
  • 应用场景:在需要周期性触发 DAC 转换的应用中,基本定时器可以精确控制转换的时间间隔;也可用于简单的定时任务,如定时唤醒系统中的某个模块。

低功耗定时器(LPTIM1)

  • 功能特点:低功耗定时器在低功耗模式下仍能正常工作,具备 16 位向上计数器,可使用内部或外部时钟源。
  • 应用场景:适用于对功耗要求较高的应用,如电池供电的设备。在设备处于低功耗模式时,LPTIM1 可以进行定时唤醒操作,以检查外部事件或进行数据采集,同时降低系统功耗。

2,以TIM6定时器为例,介绍定时器的使用

1,定时器实例选择

FreeRTOS定时器的介绍和使用_第1张图片

if (htim->Instance == TIM1) {
    HAL_IncTick();
}
  • htim->Instance 用于获取当前触发定时器周期结束事件的定时器实例。TIM1 是定时器 1 的实例。
  • HAL_IncTick() 是一个 HAL 库提供的函数,用于增加系统的滴答计数器的值。在 FreeRTOS 或者其他实时操作系统中,这个滴答计数器通常用于系统的时间管理,例如任务的调度、延时等。所以当定时器 1 的周期结束事件发生时,会调用 HAL_IncTick() 来更新系统的时间。

2,配置所需定时器

FreeRTOS定时器的介绍和使用_第2张图片

溢出周期 T=fCK_TIM​(PSC+1)×(ARR+1)​  (可以自己设置合适的)

3,设置频率

FreeRTOS定时器的介绍和使用_第3张图片

更新项目

4,中断回调函数

/* USER CODE BEGIN Callback 0 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  if (htim->Instance == TIM1) {
    HAL_IncTick();
  }    //定时器模板实例(基准)

  BaseType_t xHighPriorityTaskWoken = pdFALSE;    //xHighPriorityTaskWoken 是一个变量,用于标记在中断服务程序中是否有更高优先级的任务被唤醒。初始值被设置为 pdFALSE,表示没有更高优先级的任务被唤醒。

	if(htim->Instance == TIM6)    //如果TIM6定时器开启
	{
	
		//执行操作
		portYIELD_FROM_ISR(xHighPriorityTaskWoken);    //如果有更高优先级的任务被唤醒,则在退出中断后执行任务切换。
        HAL_TIM_Base_Stop(&htim6);    //结束定时器中断计数
	}
  /* USER CODE END Callback 1 */
}
 /* USER CODE END Callback 0 */

 3,TIM6定时器代码(初始化后自动生成)

中tim.c文件中。

void MX_TIM6_Init(void)
{

  /* USER CODE BEGIN TIM6_Init 0 */

  /* USER CODE END TIM6_Init 0 */

  TIM_MasterConfigTypeDef sMasterConfig = {0};

  /* USER CODE BEGIN TIM6_Init 1 */

  /* USER CODE END TIM6_Init 1 */
  htim6.Instance = TIM6;
  htim6.Init.Prescaler = 1279;
  htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim6.Init.Period = 62500;
  htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim6) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM6_Init 2 */

  /* USER CODE END TIM6_Init 2 */

}

4,使用示例

static void keyTask(void *pvParameters)
{
	uint8_t keyValue;
	extern TIM_HandleTypeDef htim6;			
	while(1)
	{
		keyValue = KeyScan();			
		if(keyValue == KEY2_PRES)
		{
			//KEY2按键按下,启动TIM6定时器一次,在定时器TIM6中断里,将LED0点亮
			HAL_TIM_Base_Start_IT(&htim6);
			printf("KEY2按下,启动TIM6...\r\n");
		}
		vTaskDelay(pdMS_TO_TICKS(100));
	}
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  
  if (htim->Instance == TIM1) {
    HAL_IncTick();
  }
  /* USER CODE BEGIN Callback 1 */
	/*configSUPPORT_DYNAMIC_ALLOCATION 1*/
	BaseType_t xHighPriorityTaskWoken = pdFALSE;
	if(htim->Instance == TIM6)
	{
        HAL_GPIO_WritePin(GPIOC,GPIO_PIN_10,GPIO_PIN_RESET);		  
		HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);		  
		HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
		vTaskDelay(pdMS_TO_TICKS(1000));
		portYIELD_FROM_ISR(xHighPriorityTaskWoken);
		HAL_TIM_Base_Stop(&htim6);
	}
  /* USER CODE END Callback 1 */
}

你可能感兴趣的:(单片机,嵌入式硬件)