STM32 定时器中断
通用定时器工作过程:
时钟选择:
计数器时钟可以由下列时钟源提供:
- 内部时钟(CK_INT)
- 外部时钟模式1:外部输入脚(TIx)
- 外部时钟模式2:外部触发输入(ETR)
- 内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器,如可以配置一个定时器Timer1而作为另一个定时器Timer2的预分频器。
内部时钟选择
时钟计算方法:
默认调用SystemInit函数情况下:
SYSCLK=72M
AHB时钟=72M
APB1时钟=36M
所以APB1的分频系数=AHB/APB1时钟=2
所以,通用定时器时钟CK_INT=2*36M=72M
计数器模式: 通用定时器可以向上计数、向下计数、向上向下双向计数模式。
- 向下计数模式(时钟分频因子=1(意思就是:CK_PSC=CK_CNT))
-
向上计数模式(时钟分频因子=1)
-
中央对齐计数模式(时钟分频因子=1 ARR=6)
定时器中断实验相关寄存器: -
计数器当前值寄存器CNT
-
预分频寄存器TIMx_PSC
- 自动重装载寄存器(TIMx_ARR)
- 控制寄存器1(TIMx_CR1)
- DMA中断使能寄存器(TIMx_DIER)
常用库函数
定时器参数初始化:
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
ypedef struct
{
uint16_t TIM_Prescaler;//预分频系数的设置
uint16_t TIM_CounterMode;//计数模式
uint16_t TIM_Period;//自动装载值
uint16_t TIM_ClockDivision;//输入捕获会用到
uint8_t TIM_RepetitionCounter;//高级定时器会用到
} TIM_TimeBaseInitTypeDef;
TIM_TimeBaseStructure.TIM_Period = 4999;
TIM_TimeBaseStructure.TIM_Prescaler =7199;
TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode =TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
定时器使能函数:
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState)
定时器中断使能函数:
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);
状态标志位获取和清除:
FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);
void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);
ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT);
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);
定时器中断实现步骤:
- 能定时器时钟。
RCC_APB1PeriphClockCmd();
- 初始化定时器,配置ARR,PSC。
TIM_TimeBaseInit();
- 开启定时器中断,配置NVIC。
void TIM_ITConfig();
NVIC_Init();
- 使能定时器。
TIM_Cmd();
- 编写中断服务函数。
TIMx_IRQHandler();//中断函数要判断中断标志位,和手动清除中断标志位
ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT);
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);
Tout(溢出时间)=(ARR+1)(PSC+1)/Tclk
其中arr为你重装的值,
psc是预分频计时器的值(预分频系数),
Tclk是时钟频率
Tclk/(psc+1)是定时器的时钟
(psc+1))/Tclk*1是计算的计数器 减少/增加 一个数所用的时间;
那么(psc+1))/Tclk*(arr+1)就是一次定时器的时间:
然后继续重装arr再次计数,计时:
就构成一个循环;
- TIM2-TIM5的时钟不是直接来自于APB1,而是来自于输入为APB1的一个倍频器。这个倍频器的作用是:当APB1的预分频系数为1时,这个倍频器不起作用,当APB1的预分频系数为其他数值时(即预分频系数为2、4、8或16),这个倍频器起作用,定时器的时钟频率等于APB1的频率的2倍。
- 分频系数就是对定时器时钟进行多少分频之后在使用,最好设置为定时器时钟的倍数,方便运算;重新装载值是计算这么多值,时间到了之后重新开始计算的值,每一次计数的时间为分频之后时钟的到时;
假设定时器时钟为72M,分频系数设置为7200-1,那现在定时器的时钟为10kHz,每计一个数花费1/(10000)秒,重装值设置为5000-1,那一次溢出的时间为500ms。
分频值是是指你将系统时钟的频率减小,假设时钟频率是 72Mhz,然后分频值是 7199,现在你的定时器值就是 10kHz,表示每计一个数,然后过了 1/(10^4)秒,然后你的重装值就是你的时间了,如果值是 9999,就表示定时时间为 1s。
定时器配置代码:
void TIM4_Init(u16 ar,u16 rs)
{
TIM_TimeBaseInitTypeDef TIM_InitStrue;
NVIC_InitTypeDef NVIC_InitStrue;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);//使能定时器时钟
TIM_InitStrue.TIM_Period=ar;//自动装载值
TIM_InitStrue.TIM_Prescaler=rs;//预分频系数的设置
TIM_InitStrue.TIM_CounterMode=TIM_CounterMode_Up;
TIM_InitStrue.TIM_ClockDivision=TIM_CKD_DIV1;//设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseInit(TIM4,&TIM_InitStrue);//初始化定时器,对定时器进行配置
TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);//开启定时器中断
NVIC_InitStrue.NVIC_IRQChannel=TIM4_IRQn;
NVIC_InitStrue.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=2;
NVIC_InitStrue.NVIC_IRQChannelSubPriority=2;
NVIC_Init(&NVIC_InitStrue);//初始化中断,设置中断的优先级
TIM_Cmd(TIM4,ENABLE);//使能定时器
}
void TIM4_IRQHandler(void)
{
if(TIM_GetITStatus(TIM4,TIM_IT_Update)!=RESET)
{
LED1=!LED1;
TIM_ClearITPendingBit(TIM4,TIM_IT_Update);//清除中断标志位
}
}
实验现象:LED0闪烁,时间间隔就是定时器的溢出时间
更多推荐
所有评论(0)