按定时器的功能可以分为定时,输出比较(输出PWM波),输入捕获(测量输入信号的脉冲宽度,频率),互补输出,按照定时器分类可以分为基本定时器(只有定时功能),通用定时器(有前三个功能),高级定时器(有全部功能),对于我们的F103系列有2个高级定时器TIM1和TIM8,4个通用定时器TIM2/3/4/5,2个基本定时器TIM6和TIM7
基本定时器没有外部的GPIO,不能实现输入捕获和输出比较,只能用来定时,它的时钟来自PCLK1,为72M,可实现1-65536分频, 高级定时器来自APB2,一般也为72M
1
该部分为时钟源,上面的图示已经说明基本定时器的时钟源来自PCLK1,为72M,具体定时器的时钟为多少还要看预分频系数为多少
2.
该部分为控制器部分,控制器用于控制定时器的复位,使能,计数,触发DAC,涉及到的寄存器为:CR1/2,DIER,EGR,SR
3
该部分为时基,包括预分频器,计数器,自动重装载寄存器,1-16位的预分频器PSC对内部时钟CK_PSC进行分配之后,得到计数器时钟CK_CNT = CK_PSC/(PSC+1),计数器CNT在计数器时钟的驱动下开始计数,计数一次的时间为1/CK_CNT,所以计数的时间为自动重装载寄存器(ARR+1)乘以1/CK_CNT,特别注意的是PSC和ARR都有影子寄存器,功能框图上有个影子寄存器,影子寄存器的存在起到一个缓冲的作用,用户值->寄存器->影子寄存器->起作用,如果不使用影子寄存器则用户值在写到寄存器之后则里面起作用,由TIMx_CR1:APRE位控制,还有一个是TIM1和TIM8重复计数寄存器(TIMx_RCR),它用来记录计数结束产生的次数,当我们往该寄存器[7:0]位写入x时,则定时器要发生x次计数结束才会发生中断,也就是我们总计数时间为单次计数时间乘以x.
bsp_timer.c
#include "bsp_basrtimer.h"
void NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
// 设置中断组为0
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
// 设置中断来源
NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn;
// 设置主优先级为 0
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
// 设置抢占优先级为3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void Timer_Config(void)
{
// 开启定时器时钟,即内部时钟CK_INT=72M
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6,ENABLE);
TIM_TimeBaseInitTypeDef Time_InitStructure;
// 时钟分频因子1
Time_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
// 计数器计数模式,基本定时器只能向上计数,没有计数模式的设置
Time_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
/ 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
Time_InitStructure.TIM_Period = 999;
// 时钟预分频数为
Time_InitStructure.TIM_Prescaler = 71;
// 重复计数器的值,基本定时器没有,不用管
Time_InitStructure.TIM_RepetitionCounter = 0;
// 初始化定时器
TIM_TimeBaseInit(TIM6, &Time_InitStructure);
// 清除计数器中断标志位
TIM_ClearFlag(TIM6, TIM_FLAG_Update);
// 开启计数器中断
TIM_ITConfig(TIM6,TIM_IT_Update,ENABLE);
// 使能计数器
TIM_Cmd(TIM6, ENABLE);
}
void CONFIG(void)
{
NVIC_Config();
Timer_Config();
}
main.c
#include "bsp_usart.h"
#include "hseconfig.h"
#include "bsp_basrtimer.h"
__IO uint16_t time = 0;
int main(void)
{
//uint8_t i=0;
HseConfig(9);
//NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
USART1_Init(9600);
printf("这是一个中断实验\n");
CONFIG();
while(1)
{
if(time == 500)
{
time = 0;
printf("进入中断啦\n");
}
}
}
中断服务函数
void TIM6_IRQHandler(void)
{
if(TIM_GetITStatus(TIM6,TIM_IT_Update)!=RESET)
{
time ++;
TIM_ClearITPendingBit(TIM6,TIM_FLAG_Update);
}
}