一、内部时钟选择
(计数器时钟可以有多个时钟源提供:内部时钟、外部时钟模式1、外部时钟模式2、内部触发模式。本次以内部时钟为时钟源,进行学习)
1、选择内部时钟 2、设置预分频系数、自动重装载值 3、使能定时器,写中断服务函数
通用定时器来源时APB1时钟,经过一个倍频系数产生CK_PSC,再通过一个分频产生CK_CNT。
如果APB1的分频系数为1,则通用定时器时钟就等于APB1时钟,否则通用定时器时钟就为APB1时钟的2倍。
例如:默认调用Systemlnit函数情况下:SYSCLK=168M AHB时钟=168M APB1时钟=42M
APB1的分频系数=AHB/APB1时钟=4 所以,通用定时器时钟CK_INT=2*42M=84M
二、计数模式详细工作原理
1、向下计数模式:计数器从0计数到自动加载值(TIMx_ARR),然后重新从0开始计数并且产生一个计数器溢出事件。
假设时钟分频因子为1,则CK_INT与APB1相同,定时器时钟=CK_INT。首先使能定时器(CNT_EN),向上计数到重装载值36,计数到36之后会产生一个溢出事件并溢出,产生更新事件,接着计数器再次从0开始计数到36后再次产生更新事件。第一次向上计数到ARR产生一个中断,然后又从0开始第二次向上计数到ARR产生中断,即计时的长度就是从第一次计数开始到第二次计数开始(0~ARR之间)。
2、向下计数模式
同向上计数模式差不多,只是向下计数是从初值开始递减计数直到0
3、中央对齐计数模式
从自动重装载值计数到0会产生更新事件,然后再从0开始计数到ARR再次产生更新事件。
三、向上计数模式使用通用定时器
1、计数器当前值寄存器(TIMx_CNT)16位计数器
2、预分频寄存器(TIMx_PSC)16位设置预分频值
3、自动重装载寄存器(TIMx_ARR)16位寄存器
4、控制寄存器1(TIMx_CR1)位4控制计数方向(向上/向下),位0施恩计数器
5、DMA中断使能寄存器(TIMx_DIER)使能中断
四、常用库函数
1、定时器参数初始化:void TIM_TimeBaseInit(TIM_TypeDef* TIMx,TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
typedef struct
{
uint16_t TIM_Prescaler; //预分频系数PSC
uint16_t TIM_CounterMode;//计数器模式DIR
uint32_t TIM_Period;//自动装载值
uint16_t TIM_ClockDivision; //输入捕获
uint8_t TIM_RepetitionCounter;
}
TIM_TimeBaseStructure.TIM_Period=4999;//设置自动装载值
TIM_TimeBaseStructure.TIM_Prescaler=7199;//预分频系数
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;//计数器计数模式
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
2、定时器使能函数:
void TIM_Cmd(TIM_TypeDef* TIMx,FuctionalState NewState);
3、定时器中断使能函数:
void TIM_ITConfig(TIM_TypeDef* TIMx,uint16_t TIM_IT,FunctionalState NewState);
4、状态标志位获取和清除:
FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);
void TIM_ClearFlag(TIM_TypeDef* TIMx,uint16_t TIM_FLAG);
ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx,uint16_t TIM_IT);
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx,uint16_t TIM_IT):
五、定时器中断使能步骤
1、使能定时器时钟:RCC_APB1PeriphClockCmd();
2、初始化定时器,配置ARR、PSC:TIM_YimeBaseInit();
3、开启定时器中断,配置NVIC:NVIC_Init();
4、使能定时器:TIM_Cmd();
5、编写中断服务函数:TIMx_IRQHandler();
6、代码(通过定时器中断配置,每500ms中断一次,然后中断服务函数中控制LED实现LED1状态取反闪烁,溢出时间:Tout=(ARR+1)(PSC+1)/Tclk)
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
delay_init(168);
LED_Init();
TIM3_Int_Init(4999,8399);
while(1){
LED0=!LED0;
delay_ms(500);
LED1=!LED1;
}
}
void TIM3_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitABC;
NVIC_InitTypeDef NVIC_InitABC;
RCC_AHB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
TIM_TimeBaseInitABC.TIM_Period=arr;
TIM_TimeBaseInitABC.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInitABC.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInitABC.TIM_Prescaler=psc;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitABC);
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
NVIC_InitABC.NVIC_IRQChannel=TIM3_IRQn;
NVIC_InitABC.NVIC_IRQChannelCmd=0x01;
NVIC_InitABC.NVIC_IRQChannelPreemptionPriority=0x03;
NVIC_InitABC.NVIC_IRQChannelSubPriority=ENABLE;
NVIC_Init(&NVIC_InitABC);
TIM_Cmd(TIM3,ENABLE);
}
void TIM3_IRQHandler(void){
if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET)
{
LED1=!LED1;
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}
}
#ifndef _TIMER_H
#define _TIMER_H
#include"sys.h"
void TIM3_Tin_Init(u16 arr,u16 psc);//16位寄存器,arr重装载值,psc预分频系数
#endif
定时器中断实验