十一. 定时系统
【STM32】HAL库 STM32CubeMX教程六----定时器中断_stm32 hal定时器中断-优快云博客
HAL库STM32常用外设教程(四)—— 定时器 基本定时_trigger event selection reset-优快云博客
几大定时器之间的区别是什么?
定时器的工作原理是怎样的?
定时器的计数方法是怎样的?
定时器顾名思义,定时用的,主要分为基本定时,通用定时,高级定时三类,这三类除了基本定时是向上计数外,通用和标准区别不算太大。定时器的功能常和中断是进行联动的
定时器的计数方法主要有三种:
- 向上计数:即定时器中的数值寄存器数值按照频率递增,一直增加到溢出值触发中断。
- 向下计数:即定时器中的数值寄存器数值按照频率递减,一直增减到0值触发中断。
- 向上/下计数(中央对齐模式):计数器从0增加到装入值 -1 产生一个溢出事件(中断),再向下计数到1产生溢出事件
10.1 基本定时系统
基本定时是一种向上定时系统,其物理原理主要如下:
总的来说有以下几部分构成:
- 时钟源
- 分频计数器时钟
- 递增(减)计数器
- 溢出重装器
10.1.2 基本定时器代码实现
实现计时具体的计数代码原理是怎样的?
基本定时器(TIM6,TIM7)主要是挂在外设APB1总线上,其时钟源分频则参照APB分频方式。
在设置时有个APB1默认时钟源,选择好后再设置初始化分频系数,而最终频率为 Psclk / (设置分频因子 + 1)得到最终频率,最终每次中断触发时间为 (1 / 最终频率), 再在每次中断回调函数中设置一个累加变量即可。
初始化
- 基本GPIO初始化
- 中断初始化(中断优先级,中断使能)
TIM_HandleTypeDef htim6;
//计数器变量
extern volatile uint32_t time;
/*
* 注意:TIM_TimeBaseInitTypeDef结构体里面有5个成员,TIM6和TIM7的寄存器里面只有
* TIM_Prescaler和TIM_Period,所以使用TIM6和TIM7的时候只需初始化这两个成员即可,
* 另外三个成员是通用定时器和高级定时器才有.
*-----------------------------------------------------------------------------
* TIM_Prescaler 都有
* TIM_CounterMode TIMx,x[6,7]没有,其他都有(基本定时器)
* TIM_Period 都有
* TIM_ClockDivision TIMx,x[6,7]没有,其他都有(基本定时器)
* TIM_RepetitionCounter TIMx,x[1,8]才有(高级定时器)
*-----------------------------------------------------------------------------
*/
void MX_TIM6_Init(void)
{
//用于配置主从模式,即是否需要其他寄存器协助工作
TIM_MasterConfigTypeDef sMasterConfig = {
0};
htim6.Instance = TIM6;
//设置预分频,实际频率为 72MHz / (BASIC_TIMx_PRESCALER+1)
htim6.Init.Prescaler = 71;
htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
//溢出值至设置,也就是每次技术周期设置
htim6.Init.Period = 1000; //即实际一次中断为 1/(1M(1000000) * 1000) = 1ms
htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&htim6) != HAL_OK)
{
Error_Handler();
}
//触发输出信号,即定时器在溢出时触发
/*
TIM_TRGO_RESET:触发信号在计数器溢出时输出。
TIM_TRGO_ENABLE:定时器计数时触发信号输出。
TIM_TRGO_UPDATE:定时器更新事件触发信号输出
*/
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 */
}
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_baseHandle->Instance==TIM6)
{
/* USER CODE BEGIN TIM6_MspInit 0 */
/* USER CODE END TIM6_MspInit 0 */
/* TIM6 clock enable */
//6的相关时钟打开
__HAL_RCC_TIM6_CLK_ENABLE();
/* USER CODE BEGIN TIM6_MspInit 1 */
//时钟相关中断设置
HAL_NVIC_SetPriority(TIM6_IRQn,1, 0);
HAL_NVIC_EnableIRQ(TIM6_IRQn);
/* USER CODE END TIM6_MspInit 1 */
}
}
中断产生与计数实现
HAL库中,完成一个中断后并不会立即退出(这和标准库还是有区别的),而是进入到回调函数中去,因此重写回调函数即可。
extern TIM_HandleTypeDef htim6;
void TIM6_IRQHandler()
{
HAL_TIM_IRQHandler(&htim6);
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
time++;
}
main
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "tim.h"
#include "usart.h"
#incl