TIM(Timer)定时器
定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断。
16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时。
不仅具备基本的定时中断,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能。
根据复杂度和应用场景分为:高级定时器、通用定时器、基本定时器三种类型。
1.RCC开启时钟
2.选择时基单元的时钟源,对于定时中断选择内部时钟源,
3.配置时基单元:预分频器、自动重装器、计数模式等
4.配置输出中断控制,允许更新中断输出到NVIC
5.配置NVIC,在NVIC中打开定时器中断的通道,并分配优先级
6.运行控制
7.使能计数器、定时器中断函数
定时器中断,使用通用寄存器TIM2
1.初始化定时器,RCC开启APB1总线时钟,(TIM2寄存器在APB1总线下)
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//开启APB1时钟
2.选择TIM2的时基单元时钟源为(InternalClock)内部时钟
TIM_InternalClockConfig(TIM2);//TIM2的时基单元的时钟,选择位内部时钟
3.结构体形式,初始化时基单元
定时频率 = 72MHz /(PSC+1)/(ARR+1)
定时1s,就是定时频率1Hz,既PSC=7200-1,ARR=10000-1,因为预分频器和计数器都有1个数的偏差。
ARR、PSC取值都在0~65535之间
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
//指定时钟分频(关系不大,此处选择一分频)
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
//计数模式:向上计数、向下计数和三种中央对齐的方式,此处选择向上计数
TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;
//ARR自动重装器的值
TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;
//PSC预分频器的值
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
//重复计数器的值,高级定时器需要使用的,此处赋0即可
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);//初始化时基单元
手动把更新中断标志位清除
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
4.使能更新中断,开启了更新中断到NVIC的通路
TIM_IT_Updata:更新中断
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);//更新中断到NVIC的通路
5.配置NVIC
NVIC优先级分组
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC结构体
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn;
//TIM2_IRQn,定时器TIM2在NVIC中的通道
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
//抢占优先级和响应优先级
NVIC_Init(&NVIC_InitStruct);
NVIC启动定时器
TIM_Cmd(TIM2,ENABLE);//启动定时器
6.中断函数
在启动文件中,找到所属的Header中断函数
检查中断标志位
清除标志位
void TIM2_IRQHandler(void)
{
if(TIM_GetITStatus(TIM2 , TIM_IT_Update) == SET)
{
TIM_ClearITPendingBit(TIM2 , TIM_IT_Update);
}
}
对射式红外传感器,定时器外部时钟中断
#include "stm32f10x.h" // Device header
void Timer_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_NonInverted, 0x00); // 通过ETR引脚的外部时钟模式2配置
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 10 - 1;
//自动重装值给10,从0到9
TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1;
//不需要分频,给1
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM2, ENABLE);
}
uint16_t Timer_GetCounter(void)
{
return TIM_GetCounter(TIM2);
}
/*
void TIM2_IRQHandler(void)
{
if(TIM_GetITStatus(TIM2 , TIM_IT_Update) == SET)
{
Num ++;
TIM_ClearITPendingBit(TIM2 , TIM_IT_Update);
}
}