1.基本定时器介绍
基本定时器 TIM6 和 TIM7 包含一个 16 位自动重载计数器,该计数器由可编程预分频器驱动。
此类定时器不仅可用作通用定时器以生成时基,还可以专门用于驱动数模转换器 (DAC)。实际上,此类定时器内部连接到 DAC 并能够通过其触发输出驱动 DAC。
这些定时器彼此完全独立,不共享任何资源。
2.基本定时器的主要特性
(1)16 位自动重载递增计数器
(2)16 位可编程预分频器,用于对计数器时钟频率进行分频(即运行时修改),分频系数介于 1 和 65536 之间
(3)用于触发 DAC 的同步电路
(4)发生如下更新事件时会生成中断/DMA 请求:计数器上溢
3.基本定时器的配置
根据上图我们总结一下大致的配置流程:
(1)开启相对应的时钟线
(2)确保相对应的定时器已经完成初始化
(3)配置定时器的更新中断使能
(4)配置优先级分组
(5)NVIC初始化
其实整体配置过程与之前讲的外设中断和SysTick定时器中断大同小异。做完以上定时器中断初始化配置后,接下来完成对中断函数的内容编写就可以使用了。下面是分别用TIM6实现和SysTick一样的定时功能,TIM7实现定时中断功能。
//实现xms的延时
void TIM6_DelayMs(u16 x)
{
//开启TIM6时钟线
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6,ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
//基本定时器没有这个部分,可以选择配置默认值(不分频)或不配
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
//配置为向上计数
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
//配置重装载值
TIM_TimeBaseInitStruct.TIM_Period = 2*x-1;
//定时器内分频倍数
TIM_TimeBaseInitStruct.TIM_Prescaler = 42000-1;
//仅限于TIM1/TIM8配置PWM需要
//TIM_TimeBaseInitStruct.TIM_RepetitionCounter = ;
TIM_TimeBaseInit(TIM6, &TIM_TimeBaseInitStruct);
//软件产生更新事件
TIM_GenerateEvent(TIM6, TIM_EventSource_Update);
//清除标志位
TIM_ClearFlag(TIM6, TIM_FLAG_Update);
//清空计数器
TIM_SetCounter(TIM6, 0);
//使能定时器
TIM_Cmd(TIM6, ENABLE);
//等待计数完成
while(TIM_GetFlagStatus(TIM6, TIM_FLAG_Update) == RESET);
}
//实现xμs的延时
void TIM6_DelayUs(u16 x)
{
//开启TIM6时钟线
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6,ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
//基本定时器没有这个部分,可以选择配置默认值(不分频)或不配
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
//配置为向上计数
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
//配置重装载值
TIM_TimeBaseInitStruct.TIM_Period = 2*x-1;
//定时器内分频倍数
TIM_TimeBaseInitStruct.TIM_Prescaler = 42-1;
//仅限于TIM1/TIM8配置PWM需要
//TIM_TimeBaseInitStruct.TIM_RepetitionCounter = ;
TIM_TimeBaseInit(TIM6, &TIM_TimeBaseInitStruct);
//软件产生更新事件
TIM_GenerateEvent(TIM6, TIM_EventSource_Update);
//清除标志位
TIM_ClearFlag(TIM6, TIM_FLAG_Update);
//清空计数器
TIM_SetCounter(TIM6, 0);
//使能定时器
TIM_Cmd(TIM6, ENABLE);
//等待计数完成
while(TIM_GetFlagStatus(TIM6, TIM_FLAG_Update) == RESET);
}
//初始化TIM7
void TIM7_Init(u16 x)
{
//开启TIM7时钟线
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7,ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
//基本定时器没有这个部分,可以选择配置默认值(不分频)或不配
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
//配置为向上计数
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
//配置重装载值
TIM_TimeBaseInitStruct.TIM_Period = 2*x-1;
//定时器内分频倍数
TIM_TimeBaseInitStruct.TIM_Prescaler = 42000-1;
//仅限于TIM1/TIM8配置PWM需要
//TIM_TimeBaseInitStruct.TIM_RepetitionCounter = ;
TIM_TimeBaseInit(TIM7, &TIM_TimeBaseInitStruct);
//软件产生更新事件
TIM_GenerateEvent(TIM7, TIM_EventSource_Update);
//清除标志位
TIM_ClearFlag(TIM7, TIM_FLAG_Update);
//清空计数器
TIM_SetCounter(TIM7, 0);
//使能定时器
TIM_Cmd(TIM7, ENABLE);
}
//TIM7中断初始化函数
void TIM7_ITInit(u16 x, u8 PreemptionPriority, u8 SubPriority)
{
//x毫秒触发一次中断
TIM7_Init(x);
//开启TIM7更新中断
TIM_ITConfig(TIM7, TIM_IT_Update, ENABLE);
//配置优先级组
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
//NVIC初始化
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = TIM7_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = PreemptionPriority;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = SubPriority;
NVIC_Init(&NVIC_InitStruct);
}
//TIM7中断处理函数
void TIM7_IRQHandler(void)
{
//判断产生的中断是否为更新中断
if(TIM_GetITStatus(TIM7, TIM_IT_Update) == SET)
{
//中间写你需要在更新中断时执行的操作
LED2_T;
//清除更新中断标志位
TIM_ClearITPendingBit(TIM7, TIM_IT_Update);
}
}
补充:由于影子寄存器的存在,我们在对定时器内部的PSC(预分频器)和自动重载寄存器操作后,需要写一个更新中断才能让值写入相对应的影子寄存器,我们的写入操作才能生效。
具体的标准库函数参照stm32f4xx_tim.c或stm32f4xx_tim.h。