定时器中断
一、定时器工作原理
- TIM(Timer)定时器
- 定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断
- 16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时
- 不仅具备基本的定时中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能
- 根据复杂度和应用场景分为了高级定时器、通用定时器、基本定时器三种类型
基本定时器
PSC(Prescaler)
CNT(Counter)
ARR(AutoReloaderRegister)
预分频器时序
计数器计数频率:CK_CNT = CK_PSC / (PSC + 1)
一般72M/(PSC+1)
预装载功能:PSC,ARR以及捕获/比较寄存器有
计数器时序
计数器溢出频率:CK_CNT_OV = CK_CNT / (ARR + 1) = CK_PSC / (PSC + 1) / (ARR + 1)
一般72M/(PSC+1)/(ARR+1)
预装载功能
通用定时器
TRGI 外部时钟模式1 的输入可以是
- ETR引脚(外部输入方波)
- 其他定时器(实现级联)
- CH1引脚的边沿
- CH1,CH2引脚
定时器级联功能表
高级定时器
定时中断基本结构
二、定时器中断库函数
定时器中断
void TIM1_Int_Init(u16 arr, u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; //时基单元
NVIC_InitTypeDef NVIC_InitStructure; //NVIC
//TIM_InternalClockConfig(TIM1) //时钟选择,上电默认内部时钟,可以不写
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //时钟使能(peripheral外围设备)
这里经常不注意,APB12前后要对应
TIM_TimeBaseStructure.TIM_Period = arr; //重装载值
TIM_TimeBaseStructure.TIM_Prescaler = psc; //预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分割,用不到(输入的采样频率,可一定程度滤波,或 //者输入时钟的分频)
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数模式
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; //高级定时器1和8需要填这个(重复次数计数器)
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //初始化定时器时基单元
TIM_ClearFlag(TIM1,TIM_FLAG_Update); //为避免一上电就进中断
TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE ); //定时器中断配置,更新中断
NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure); //NVIC配置
TIM_Cmd(TIM1, ENABLE); //使能定时器
}
void TIM1_UP_IRQHandler(void)
{
if(TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET)
{
}
TIM_ClearFlag(TIM1, TIM_IT_Update );
}
- 一上电就进中断的问题
TIM_TimeBaseInit函数中最后一句
因为预分频器有缓冲寄存器,写的值只有在更新事件时才会真正起作用,为了让值立刻起作用,在最后手动生成了一个更新事件
这样,预分频器的值就有效了
但是就会进一次中断
解决:手动把更新中断标志位清除一下TIM_TimeBaseInit后,TIM_ITConfig开中断前
TIM_ClearFlag(TIM1,TIM_FLAG_Update); //为避免一上电就进中断
定时器外部时钟
接TIMx_ETR引脚
/**
* @brief Configures the External clock Mode2
* @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. //定时器
* @param TIM_ExtTRGPrescaler: The external Trigger Prescaler. //预分频
* This parameter can be one of the following values:
* @arg TIM_ExtTRGPSC_OFF: ETRP Prescaler OFF.
* @arg TIM_ExtTRGPSC_DIV2: ETRP frequency divided by 2.
* @arg TIM_ExtTRGPSC_DIV4: ETRP frequency divided by 4.
* @arg TIM_ExtTRGPSC_DIV8: ETRP frequency divided by 8.
* @param TIM_ExtTRGPolarity: The external Trigger Polarity. //触发极性,上升沿下降沿
* This parameter can be one of the following values:
* @arg TIM_ExtTRGPolarity_Inverted: active low or falling edge active.
* @arg TIM_ExtTRGPolarity_NonInverted: active high or rising edge active.
* @param ExtTRGFilter: External Trigger Filter. //滤波
* This parameter must be a value between 0x00 and 0x0F
* @retval None
*/
void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler,
uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);
将前面
//TIM_InternalClockConfig(TIM1) //时钟选择,上电默认内部时钟,可以不写
改
TIM_ETRClockMode2Config(TIM1,TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_NonInverted,0x00);
另外配置对应GPIO
并调整ARR PSC
三、定时器中断CubeMX
STM32的定时器开发基础_哔哩哔哩_bilibili
四、定时器中断寄存器
看数据手册吧