STM32F1定时器资源:
F1系列中,除了互联型的产品,共有 8 个定时器,分为基本定时器,通用定时器和高级定时器。
基本定时器TIM6 和TIM7:
① 16 位的只能向上计数的定时器,只能定时,没有外部 IO。
通用定时器 TIM2/3/4/5
①16 位的可以向上/下计数的定时器,可以定时
②可以输出比较
③可以输入捕捉
④每个定时器有四个外部 IO。
高级定时器 TIM1/8:
①16 位的可以向上/下计数的定时器,可以定时
②可以输出比较
③可以输入捕捉
④可以有三相电机互补输出信号
⑤每个定时器有 8 个外部 IO。
基本定时器TIM6/7:
基本定时器的核心是时基
①时钟源
定时器时钟 TIMxCLK,即内部时钟 CK_INT,经 APB1 预分频器后分频提供,如果 APB1 预分频系数等于 1,则频率不变(72MHz)。库函数中 APB1 预分频的系数是 2,即 PCLK1=36M,所以定时器时钟 TIMxCLK=36*2=72M。
程序中可以看出APB1时钟是由AHB进行2分频得到:72MHz/2= 36MHz
②计数器时钟
定时器时钟经过 PSC 预分频器之后,即 CK_CNT,用来驱动计数器计数。PSC 是一个 16 位的预分频器,可以对定时器时钟 TIMxCLK 进行 1~65536 之间的任何一个数进行分频。具体计算方式为:CK_CNT=TIMxCLK/(PSC+1)。 psc是从0开始的
③计数器
计数器 CNT 是一个 16 位的计数器,只能往上计数,最大计数值为 65535。当计数达到自动重装载寄存器的时候产生更新事件,并清零从头开始计数。
④自动重装载寄存器
自动重装载寄存器 ARR 是一个 16 位的寄存器,这里面装着计数器能计数的最大数值。当计数到这个值的时候,如果使能了中断的话,定时器就产生溢出中断。
定时时间的计算
定时器的定时时间等于计数器的中断周期乘以中断的次数。
(1)计数器在 CK_CNT 的驱动下,计一个数的时间T= 1/(TIMxCLK/(PSC+1));
(2)重装载值为ARR,则中断周期为 T*ARR
(3)如果在中断服务程序里面设置一个变量 time,用来 记 录 中 断 的 次 数 , 那 么 就 可 以 计 算 出 我 们 需 要 的 定 时 时 间 等 于 : time*T*ARR。
如TIMxCLK=72 000 000, PSC=7199, ARR=49,则一次中断时间是:5ms
结构体:
1 typedef struct 2 { 3 uint16_t TIM_Prescaler; //16位 预分频值 4 uint16_t TIM_CounterMode; //计数模式(向上、向下...) 基本定时器只能向上,故不用设置 5 uint16_t TIM_Period; //16位 定时器周期 ARR自动重装值 6 uint16_t TIM_ClockDivision; //时钟分频 设置定时器时钟 CK_INT 频率与数字滤波器采样时钟频率分频比,基本定时器没有此功能,不用设置 7 uint8_t TIM_RepetitionCounter; //重复计数器,只有TIM1和TIM8才有 利用它可以非常容易控制输出 PWM 的个数 8 9 } TIM_TimeBaseInitTypeDef;
实验代码:
通过TIM6实现基本定时功能使LED翻转
1 #include "user_timer.h" 2 #include "user_delay1.h" 3 4 //文件:基本定时器tim6和tim7 5 //功能:实现5ms定时 6 7 uint8_t Timer_count =0; 8 //定时器优先级配置函数 9 static void NVIC_Config(void) 10 { 11 12 NVIC_InitTypeDef NVIC_InitStructure; 13 //优先级配置 14 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 0--4 0--4 15 16 NVIC_InitStructure.NVIC_IRQChannel =TIM6_IRQn; 17 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 1; //抢占优先级 18 NVIC_InitStructure.NVIC_IRQChannelSubPriority= 3; //响应优先级 19 NVIC_InitStructure.NVIC_IRQChannelCmd =ENABLE; 20 NVIC_Init(&NVIC_InitStructure); 21 } 22 23 24 //定时器配置函数 25 void TIM6_Time_Init(u16 arr,u16 psc)//如arr=49 psc=7199 ---10khz(0.1ms)--5ms 26 { 27 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 28 29 NVIC_Config(); 30 31 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6,ENABLE); //开时钟--APB1时钟为36M, 但是TIM2-7的时钟是由36M的2倍频过来的 72MHz 32 33 TIM_TimeBaseStructure. TIM_Period = arr;//自动重装值 34 TIM_TimeBaseStructure.TIM_Prescaler =psc; //时钟预分频数 35 //TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1; //设置时钟分割 //基本定时器没有此功能 36 //TIM_TimeBaseStructure.TIM_CounterMode =TIM_CounterMode_Up; //默认向上计数 37 TIM_TimeBaseInit(TIM6,&TIM_TimeBaseStructure); //初始化TIM6 38 39 TIM_ClearFlag(TIM6,TIM_FLAG_Update); //清除计数器中断标志位 40 TIM_ITConfig(TIM6,TIM_IT_Update, ENABLE );//TIM中断使能 41 42 TIM_Cmd(TIM6, ENABLE); //使能定时器 43 } 44 45 46 /***********中断服务函数************/ 47 void TIM6_IRQHandler(void) 48 { 49 if(TIM_GetITStatus(TIM6, TIM_IT_Update)) //是否产生中断 50 { 51 Timer_count++; 52 if(Timer_count==200) 53 { 54 GPIOD->ODR ^= GPIO_Pin_2; 55 Timer_count=0; 56 } 57 60 TIM_ClearITPendingBit(TIM6,TIM_IT_Update);//清除中断标志位 61 } 62 }