高级定时器:TIME1 、TIME8
通用定时器:TIME2TIME5,TIM9TIM14
基本定时器:TIME6 和 TIME7 等
TIM2~TIM5 的寄存器介绍:
控制寄存器 1(TIMx_CR1):只用到了 TIMx_CR1 的最低位,也就是计数器使能位,该位必须置 1,才能让定时器开始计数。
DMA/中断使能寄存器(TIMx_DIER)。该寄存器是一个 16 位的寄存器,第 0 位,该位是更新中断允许位,定时器的更新中断该位要设置为 1,来允许由于更新事件所产生的中断。
预分频寄存器(TIMx_PSC)。该寄存器用设置对时钟进行分频,然后提供给计数器,作为计数器的时钟。
注意点:高级定时器和 TIM9~TIM11 的时钟不是来自 APB1,而是来自 APB2 的。
TIMx_CNT 寄存器,该寄存器是定时器的计数器,存储了当前定时器的计数值。
自动重装载寄存器(TIMx_ARR),该寄存器在物理上实际对应着 2 个寄存器。
HAL库定时器配置步骤:
1 )TIM3时钟使能。
HAL 中定时器使能是通过宏定义标识符来实现对相关寄存器操作的,方法如下:
__HAL_RCC_TIM3_CLK_ENABLE(); //使能 TIM3 时钟
2)初始化定时器参数, 设置自动重装值 ,分频系数 ,计数方式等 。
在HAL库中,定时器的初始化参数是通过定时器初始化函数HAL_TIM_Base_Init实现的:
HAL_StatusTypeDef HAL_TIM_Base_Init(TIM_HandleTypeDef *htim);
typedef struct
{
TIM_TypeDef *Instance; 寄存器基地址比如要初始化串口1,那么 Instance 的值为 TIM1
TIM_Base_InitTypeDef Init;
HAL_TIM_ActiveChannel Channel; 设置活跃通道
DMA_HandleTypeDef *hdma[7]; DMA 功能
HAL_LockTypeDef Lock;
__IO HAL_TIM_StateTypeDef State;
}TIM_HandleTypeDef;
第二个参数 Init 为真正的初始化结构体 TIM_Base_InitTypeDef 类型
typedef struct
{
uint32_t Prescaler; //预分频系数
uint32_t CounterMode; //计数方式
uint32_t Period; //自动装载值 ARR
uint32_t ClockDivision; //时钟分频因子
uint32_t RepetitionCounter; 设置重复计数器寄存器的值
} TIM_Base_InitTypeDef;
TIM_HandleTypeDef TIM3_Handler; //定时器句柄
TIM3_Handler.Instance=TIM3; //通用定时器 3
TIM3_Handler.Init.Prescaler=8999; //分频系数
TIM3_Handler.Init.CounterMode=TIM_COUNTERMODE_UP; //向上计数器
TIM3_Handler.Init.Period=4999; //自动装载值
TIM3_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;//时钟分频因子
HAL_TIM_Base_Init(&TIM3_Handler);
3)使能定时器更新中断,使能定时器
HAL_TIM_Base_Start_IT():使能定时器和更新中断两个功能。
HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim);
__HAL_TIM_ENABLE_IT(htim, TIM_IT_UPDATE);//使能句柄指定的定时器更新中断
__HAL_TIM_DISABLE_IT (htim, TIM_IT_UPDATE);//关闭句柄指定的定时器更新中断
__HAL_TIM_ENABLE(htim);//使能句柄 htim 指定的定时器
__HAL_TIM_DISABLE(htim);//关闭句柄 htim 指定的定时器
4 )TIM3中断优先级设置。
HAL 库为定时器初始化定义了回调函数 HAL_TIM_Base_MspInit。一般情况下,与MCU有关的时钟使能,以及中断优先级配置我们都会放在该回调函数内部。
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim);
5 )编写中断服务函数。
TIM3_IRQHandler(); TIM3中断服务函数
定时器中断共用处理函数 HAL_TIM_IRQHandler:
而函数 HAL_TIM_IRQHandler 内部,会对相应的中断标志位进行详细判断,判断确定中断
来源后,会自动清掉该中断标志位,同时调用不同类型中断的回调函数。所以我们的中断控制逻辑只用编写在中断回调函数中,并且中断回调函数中不需要清中断标志位。
void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim);
比如定时器更新中断回调函数为:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);
常用的几个回调函数:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);//更新中断
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim);//输出比较
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim);//输入捕获
void HAL_TIM_TriggerCallback(TIM_HandleTypeDef htim);//触发中断
TIM3中断时间计算:
TIM3 的溢出时间。因为系统初始化 SystemInit 函数里面已经初始化APB1的时钟为 4 分频,所以 APB1 的时钟为 42M,根据STM32F4 的内部时钟树图APB1 的时钟分频数为 1 的时候,TIM2~7 以及 TIM12~14 的时钟为 APB1 的时钟,而如果 APB1 的时钟分频数不为 1,那么 TIM2~7 以及 TIM12~14 的时钟频率将为 APB1时钟的两倍。因此,TIM3 的时钟为 84M,根据arr 和 psc 的值,计算中断时间:
计算公式如下:
Tout= ((arr+1)(psc+1))/Tclk;
其中:
Tclk:TIM3 的输入时钟频率(单位为 Mhz)。
Tout:TIM3 溢出时间(单位为 us)。
当 TIM3_CNT 的值等于 TIM3_ARR 的值的时候,就会产生 TIM3 的更新中断, 然后TIM3_CNT 再从 0 开始计数。
假设定时器的时钟84Mhz,分频系数为 8400,所以分频后的计数频率为 84Mhz/8400=10KHz,然后计数到 5000,所以时长为 5000/10000=0.5s,也就是 500ms。
高级定时器:TIME1 、TIME8
通用定时器:TIME2TIME5,TIM9TIM14
基本定时器:TIME6 和 TIME7 等
TIM2~TIM5 的寄存器介绍:
控制寄存器 1(TIMx_CR1):只用到了 TIMx_CR1 的最低位,也就是计数器使能位,该位必须置 1,才能让定时器开始计数。
DMA/中断使能寄存器(TIMx_DIER)。该寄存器是一个 16 位的寄存器,第 0 位,该位是更新中断允许位,定时器的更新中断该位要设置为 1,来允许由于更新事件所产生的中断。
预分频寄存器(TIMx_PSC)。该寄存器用设置对时钟进行分频,然后提供给计数器,作为计数器的时钟。
注意点:高级定时器和 TIM9~TIM11 的时钟不是来自 APB1,而是来自 APB2 的。
TIMx_CNT 寄存器,该寄存器是定时器的计数器,存储了当前定时器的计数值。
自动重装载寄存器(TIMx_ARR),该寄存器在物理上实际对应着 2 个寄存器。
HAL库定时器配置步骤:
1 )TIM3时钟使能。
HAL 中定时器使能是通过宏定义标识符来实现对相关寄存器操作的,方法如下:
__HAL_RCC_TIM3_CLK_ENABLE(); //使能 TIM3 时钟
2)初始化定时器参数, 设置自动重装值 ,分频系数 ,计数方式等 。
在HAL库中,定时器的初始化参数是通过定时器初始化函数HAL_TIM_Base_Init实现的:
HAL_StatusTypeDef HAL_TIM_Base_Init(TIM_HandleTypeDef *htim);
typedef struct
{
TIM_TypeDef *Instance; 寄存器基地址比如要初始化串口1,那么 Instance 的值为 TIM1
TIM_Base_InitTypeDef Init;
HAL_TIM_ActiveChannel Channel; 设置活跃通道
DMA_HandleTypeDef *hdma[7]; DMA 功能
HAL_LockTypeDef Lock;
__IO HAL_TIM_StateTypeDef State;
}TIM_HandleTypeDef;
第二个参数 Init 为真正的初始化结构体 TIM_Base_InitTypeDef 类型
typedef struct
{
uint32_t Prescaler; //预分频系数
uint32_t CounterMode; //计数方式
uint32_t Period; //自动装载值 ARR
uint32_t ClockDivision; //时钟分频因子
uint32_t RepetitionCounter; 设置重复计数器寄存器的值
} TIM_Base_InitTypeDef;
TIM_HandleTypeDef TIM3_Handler; //定时器句柄
TIM3_Handler.Instance=TIM3; //通用定时器 3
TIM3_Handler.Init.Prescaler=8999; //分频系数
TIM3_Handler.Init.CounterMode=TIM_COUNTERMODE_UP; //向上计数器
TIM3_Handler.Init.Period=4999; //自动装载值
TIM3_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;//时钟分频因子
HAL_TIM_Base_Init(&TIM3_Handler);
3)使能定时器更新中断,使能定时器
HAL_TIM_Base_Start_IT():使能定时器和更新中断两个功能。
HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim);
__HAL_TIM_ENABLE_IT(htim, TIM_IT_UPDATE);//使能句柄指定的定时器更新中断
__HAL_TIM_DISABLE_IT (htim, TIM_IT_UPDATE);//关闭句柄指定的定时器更新中断
__HAL_TIM_ENABLE(htim);//使能句柄 htim 指定的定时器
__HAL_TIM_DISABLE(htim);//关闭句柄 htim 指定的定时器
4 )TIM3中断优先级设置。
HAL 库为定时器初始化定义了回调函数 HAL_TIM_Base_MspInit。一般情况下,与MCU有关的时钟使能,以及中断优先级配置我们都会放在该回调函数内部。
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim);
5 )编写中断服务函数。
TIM3_IRQHandler(); TIM3中断服务函数
定时器中断共用处理函数 HAL_TIM_IRQHandler:
而函数 HAL_TIM_IRQHandler 内部,会对相应的中断标志位进行详细判断,判断确定中断
来源后,会自动清掉该中断标志位,同时调用不同类型中断的回调函数。所以我们的中断控制逻辑只用编写在中断回调函数中,并且中断回调函数中不需要清中断标志位。
void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim);
比如定时器更新中断回调函数为:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);
常用的几个回调函数:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);//更新中断
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim);//输出比较
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim);//输入捕获
void HAL_TIM_TriggerCallback(TIM_HandleTypeDef htim);//触发中断
TIM3中断时间计算:
TIM3 的溢出时间。因为系统初始化 SystemInit 函数里面已经初始化APB1的时钟为 4 分频,所以 APB1 的时钟为 42M,根据STM32F4 的内部时钟树图APB1 的时钟分频数为 1 的时候,TIM2~7 以及 TIM12~14 的时钟为 APB1 的时钟,而如果 APB1 的时钟分频数不为 1,那么 TIM2~7 以及 TIM12~14 的时钟频率将为 APB1时钟的两倍。因此,TIM3 的时钟为 84M,根据arr 和 psc 的值,计算中断时间:
计算公式如下:
Tout= ((arr+1)(psc+1))/Tclk;
其中:
Tclk:TIM3 的输入时钟频率(单位为 Mhz)。
Tout:TIM3 溢出时间(单位为 us)。
当 TIM3_CNT 的值等于 TIM3_ARR 的值的时候,就会产生 TIM3 的更新中断, 然后TIM3_CNT 再从 0 开始计数。
假设定时器的时钟84Mhz,分频系数为 8400,所以分频后的计数频率为 84Mhz/8400=10KHz,然后计数到 5000,所以时长为 5000/10000=0.5s,也就是 500ms。
举报