一、基本定时器的使用流程
STM32的基本定时器功能:16 位的只能向上计数的定时器,只能定时;当累加的时钟脉冲超过预定值时,就能触发中断或DMA请求。
配置流程:
1、使能Timer_6/7定时器时钟,把RCC_APB1Periph_TIM6/7设置为ENABLE,函数如下:
void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
2、定时器初始化:
A、首先定义一个TIM_TimeBaseInitTypeDef类型的结构体,可命名为TIM_TimeBaseStructure(可自行定义);
B、对上定义的结构体内的变量进行赋值,其值定义如下:
typedef struct {
uint16_t TIM_Prescaler // 预分频器,
uint16_t TIM_CounterMode // 计数模式,基本定时器TIMx,x[6,7]没有
uint32_t TIM_Period // 定时器周期,计算个数
uint16_t TIM_ClockDivision // 时钟分频,基本定时器TIMx,x[6,7]没有
uint8_t TIM_RepetitionCounter // 重复计算器,高级定时器才需要配置,TIMx,x[1,8]
} TIM_TimeBaseInitTypeDef;
C、使用初始化函数,初始化:
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
3、清除TIMx标志位,使能中断更新设置:
A、清除TIMx,中断更新TIM_IT_Update的标志位:
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);
B、使能TIMx的中断更新TIM_IT_Update:
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);
4、打开定时器,对应函数:
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);
PS:在应用中,可以在使用时再打开定时器,定时器的其他初始化参数可以先调用配置;
5、定时器Timer中断的设置:
A、配置中断优先级分组:
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
B、NVIC_InitTypeDef类型结构体定义并设置参数,初始化中断源为定时器Timer中断的NVIC:
结构体定义:
typedef struct
{
uint8_t NVIC_IRQChannel; //中断源选择
uint8_t NVIC_IRQChannelPreemptionPriority; //抢占优先级
uint8_t NVIC_IRQChannelSubPriority; //子优先级
FunctionalState NVIC_IRQChannelCmd; //中断使能或者失能
} NVIC_InitTypeDef;
PS:中断源的命名可以在stm32f10x.h 头文件里面的 IRQn_Type 结构体定义,这个结构体包含了所有的中断源;
初始化函数:
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
6、中断服务函数的编写,中断函数的函数名不可以更改,中断服务函数的名字必须与启动文件的startup_stm32f10x_xx.s(如:startup_stm32f10x_hd.s)内找,定时器Timer的函数名如下:
void TIMx_IRQHandler(void);
二、定时器的定时时间计算:
定时时间:Time = CK_CLK / (TIM_Prescaler + 1) / (TIM_Period + 1); 如CK_CLK = 72MHz,TIM_Prescaler = 71,TIM_Period = 999;定时时间Time = 1ms,定时中断每1ms触发一次;
三、举例
1、定时器初始化:
/*定时时间 Time = 72M / (per+1) / (arr+1) us
void Timer7_InitConfig(u16 arr, u16 per)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE); //使能TIM时钟
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; //定义定时器初始化参数的结构体
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //1分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计算
TIM_TimeBaseStructure.TIM_Period = arr-1; //设置周期,即计算最大个数的值
TIM_TimeBaseStructure.TIM_Prescaler = per-1; //时钟分频系数,即对定时器的输入时钟再进行分频,分频后的时钟频率用来驱动计数器计数
TIM_TimeBaseInit(TIM7, &TIM_TimeBaseStructure); //定时器TIM7初始化
TIM_ClearITPendingBit(TIM7, TIM_IT_Update); //清除中断更新标志位
TIM_ITConfig(TIM7, TIM_IT_Update, ENABLE); //使能更新中断触发标志位
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断抢占优先级和响应优先级分组,按2bit设置中断抢占优先级,2bit设置中断响应优先级
NVIC_InitTypeDef NVIC_InitStructure; //定义中断设置结构体
NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn; //中断通道设置TIM7
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3 ; //抢占优先级为3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //响应优先级为3
NVIC_Init(&NVIC_InitStructure); //初始化
TIM_Cmd(TIM7,ENABLE); //打开定时器
}
2、中断函数
uint32_t TIM7_Timing-intrr-Count; //触发中断次数
void TIM7_IRQHandler(void)
{
TIM_Cmd(TIM7,DISABLE);
if(TIM_GetITStatus(TIM7, TIM_IT_Update) == SET) //判断中断标志位是否触发
{
TIM7_Timing-intrr-Count++; //中断次数加1
TIM_ClearITPendingBit(TIM7, TIM_IT_Update); //清除更新中断标志位
}
TIM_Cmd(TIM7,ENABLE);
}