STM32 HAL库开发学习13. 定时器及基本定时器使用

B站影视 港台电影 2025-06-07 16:06 2

摘要:定时器的核心是一个计数器,该计数器会按照一定的时钟频率进行加 1 或减 1 操作。当计数器的值达到预设的阈值(即自动重装载值)时,会触发特定的事件,如产生中断、更新输出信号等。同时,计数器可以根据配置自动重新开始计数,形成周期性的定时操作。

实现定时器的方式一般有软件、硬件两种方式,本文主要针对STM32的硬件定时器。

定时器的核心是一个计数器,该计数器会按照一定的时钟频率进行加 1 或减 1 操作。当计数器的值达到预设的阈值(即自动重装载值)时,会触发特定的事件,如产生中断、更新输出信号等。同时,计数器可以根据配置自动重新开始计数,形成周期性的定时操作。

通用定时器TIM2、TIM3、TIM4、TIM516 位(TIM2、TIM5 为 32 位)向上、向下、向上/向下(中央对齐)PWM 输出、4个输入捕获、输出比较、编码器接口、触发 DAC/ADCAPB1定时器类型定时器计数器位数计数模式预分频系数产生 DMA 请示捕获/比较通道互补输出高级定时器TIM1、TIM816 位向上1 - 65536支持4 个有通用定时器TIM2、TIM532 位向上、向下、中央对齐1 - 65536支持4 个无通用定时器TIM3、TIM416 位向上、向下、中央对齐1 - 65536支持4 个无通用定时器TIM1216 位向上1 - 65536不支持2 个无通用定时器TIM13、TIM1416 位向上1 - 65536不支持1 个无通用定时器TIM1516 位向上1 - 65536支持2 个有基本定时器TIM16、TIM1716 位向上1 - 65536支持1 个有基本定时器TIM6、TIM716 位向上1 - 65536支持1 个有

基本定时器有TIM6/TIM7,其主要特性有:

基本定时器使用 16 位的计数器,计数模式为向上计数,即从 0 开始计数,逐步递增,直到达到自动重载寄存器(ARR)中设置的值,然后计数器会重新归零并开始下一轮计数。可编程预分频器可以对定时器的时钟源进行分频,预分频系数范围通常为 1 - 65536。通过设置预分频寄存器(PSC)的值,可以调整定时器的计数频率,从而实现不同的定时精度。自动重载寄存器(ARR)用于存储计数器的上限值。当计数器的值达到 ARR 中设置的值时,会产生更新事件,计数器会重新归零。计数器溢出(达到 ARR 值)时会产生更新事件。更新事件可以用于触发一些操作,例如触发 DAC(数模转换器)或 ADC(模数转换器)的转换。基本定时器可以产生 DMA(直接内存访问)请求。当定时器产生更新事件时,可以触发 DMA 传输,将数据从一个内存位置传输到另一个内存位置,而无需 CPU 的干预,提高系统效率。


在STM32F1中,TIM1和TIM8是挂载在APB2总线上,(最大稳定频率72MHz)
而TIM2~5挂载在APB1总线上(最大频率36MHz)。

并不是挂载在APB1上,定时器频率最大就是36MHz,还要取决于预分频系数,如下图所示的 TIM1 Timer x1,2 Multiplier。

计数器模式溢出条件向上CNT==ARR向下CNT==0中心对齐CNT == ARR-1 、 CNT==10:无更新中断1: 有更新中断

在中断服务函数中,需要手动清除中断标志位,否则会一直触发中断。

HAL_TIM_Base_MspInit(&htim); 配置NVIC,CLOCK等, GPIO配置

HAL_NVIC_SetPriority(TIMx_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIMx_IRQn);

__HAL_TIM_CLEAR_IT(&htim, TIM_IT_UPDATE);

另外有一个定时器更新中断回调函数,在中断服务函数中会自动调用,该函数用户可以自行重写:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);

本示例使用定时器6,实现500ms定时器更新中断,控制GPIO口翻转。本项目在之前项目基础上增加配置,省略了GPIO等配置说明 。
时钟频率设置如下:


超时时间=(499+1)*(7999+1)/8MHz = 500ms。

/*** @brief TIM6 Initialization Function* @param None* @retval None*/static 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 = 7999;htim6.Init.CounterMode = TIM_COUNTERMODE_UP;htim6.Init.Period = 499;htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;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 */}/*** @brief This function handles TIM6 global interrupt.*/void TIM6_IRQHandler(void){/* USER CODE BEGIN TIM6_IRQn 0 *//* USER CODE END TIM6_IRQn 0 */HAL_TIM_IRQHandler(&htim6);/* USER CODE BEGIN TIM6_IRQn 1 *//* USER CODE END TIM6_IRQn 1 */}/* 在TIM6初始化函数末尾添加 *//* USER CODE BEGIN TIM6_Init 2 */HAL_TIM_Base_Start_IT(&htim6); // 启动定时器中断/* USER CODE END TIM6_Init 2 *//* 定时器6中断回调 */void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){if(htim->Instance == TIM6){// 这里添加中断处理代码HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_0);}}

来源:编程圈子

相关推荐