stm32定时器中断的配置步骤
1》TIM3 时钟使能
位于低速的APB1总线上(注意:高级定时器是在高速的APB2总线上);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
2》初始化定时器参数,设置自动重装值, 分频系数,计数方式等
voidTIM_TimeBaseInit(TIM_TypeDef*TIMx,TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
第一个参数:确定是哪个定时器
第二个参数:定时器初始化参数结构体指针
typedef struct
{
uint16_t TIM_Prescaler; /* 指定用于分频 TIM 时钟的预分频器值。
该参数可以是 0x0000 到 0xFFFF 之间的数字 */
uint16_t TIM_CounterMode; /* 指定计数器模式。TIM_CounterMode_Up */
uint16_t TIM_Period; /* 指定要加载到活动中的周期值次更新事件时自动重新加载注册。此参数必须是介于 0x0000 和 0xFFFF 之间的数字。 */
uint16_t TIM_ClockDivision; /* 指定时钟分频。TIM_CKD_DIV1 */
uint8_t TIM_RepetitionCounter;
/* 指定重复计数器值。每次 RCR 递减计数器达到零,生成更新事件并重新开始计数从 RCR 值 (N)。这意味着在 PWM 模式下,(N+1) 对应于:
- 边沿对齐模式下的 PWM 周期数
- 中心对齐模式下半个 PWM 周期的数量
此参数必须是介于 0x00 和 0xFF 之间的数字。
@note 此参数仅对 TIM1 和 TIM8 有效。 */
} TIM_TimeBaseInitTypeDef;
计数器模式:
通用定时器可以向上计数、向下计数、向上向下双向计数模式。
向上计数模式:计数器从0计数到自动加载值(TIMx_ARR),然后重新从0开始计数并且产生一个计数器溢出事件。
向下计数模式:计数器从自动装入的值(TIMx_ARR)开始向下计数到0,然后从自动装入的值重新开始,并产生一个计数器向下溢出事件。
中央对齐模式(向上/向下计数):计数器从0开始计数到自动装入的值-1,产生一个计数器溢出事件,然后向下计数到1并且产生一个计数器溢出事件;然后再从0开始重新计数。
TIM3 初始化:
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period = 5000;
TIM_TimeBaseStructure.TIM_Prescaler =7199;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
3》启用或禁用指定的 TIM 中断。
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);
参数:
第一个参数:TIMx 其中 x 可以是 1 到 17 以选择 TIMx 外设。 TIM3
第二个参数: 指定要启用或禁用的 TIM 中断源。 TIM_IT_Update
第三个参数: ENABLE 或 DISABLE。
3》设置 NVIC 相关寄存器,设置中断优先级
配置优先级分组
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
NVIC_PriorityGroup_0:0 位用于抢占优先级,4 位用于子优先级
根据指定初始化 NVIC 外设
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
typedef struct
{
uint8_t NVIC_IRQChannel; //指定要启用或禁用的 IRQ 通道。 TIM3_IRQn
uint8_t NVIC_IRQChannelPreemptionPriority; //指定抢占优先级,0到15之间的值
uint8_t NVIC_IRQChannelSubPriority; //指定子优先级
FunctionalState NVIC_IRQChannelCmd; // ENABLE 或 DISABLE
} NVIC_InitTypeDef;
3》使能 TIM3
启用或禁用指定的 TIM 外设:
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState)
参数:
第一个参数:TIMx:其中 x 可以是 1 到 17 以选择 TIMx 外设。
第二个参数:ENABLE 或 DISABLE。
3》编写中断服务函数
检查 TIM 中断是否发生:
ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT)
@retval TIM_IT 的新状态(SET 或 RESET)
该函数的作用:判断定时器 TIMx 的中断类型 TIM_IT 是否发生中断。
比如,我们要判断定时器 3 是否发生更新(溢出)中断,方法为:
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET){}
清除中断标志位
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT)
该函数的作用:清除定时器 TIMx 的中断 TIM_IT 标志位。
比如在 TIM3 的溢出中断发生后,我们要清除中断标志位,方法是:
TIM_ClearITPendingBit(TIM3, TIM_IT_Update );
注:固件库还提供了两个函数用来判断定时器状态以及清除定时器状态标志位的函数 TIM_GetFlagStatus 和 TIM_ClearFlag,他们的作用和前面两个函数的作用类似。只是在 TIM_GetITStatus 函数中会先判断这种中断是否使能,使能了才去判断中断标志位,而TIM_GetFlagStatus 直接用来判断状态标志位。
定时器中断服务函数的实现
void TIM3_IRQHandler(void) //TIM3 中断
{
if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)//检查TIM3更新中断发生与否
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除 TIM3 更新中断标志
LED1=!LED1;
}
}
时钟系统初始化的时候在默认的系统初始化函数 SystemInit 函数里面已经初始化 APB1 的时钟为 2 分频,所以 APB1 的时钟为 36M,而从 STM32 的内部时钟树图得知:当 APB1 的时钟分频数为 1 的时候, TIM2~7 的时钟为 APB1 的时钟,而如果 APB1 的时钟分频数不为 1,那么 TIM2~7 的时钟频率将为 APB1 时钟的两倍。因此, TIM3 的时钟为 72M,再根据我们设计的 arr 和 psc 的值,就可以计算中断时间了。
计算公式如下:
Tout= ((arr+1)*(psc+1))/Tclk;
其中:
Tclk: TIM3 的输入时钟频率(单位为 Mhz)。
Tout: TIM3 溢出时间(单位为 us)。