一、简介
*定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断
*16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时
*不仅具备基本的定时中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能
*根据复杂度和应用场景分为了高级定时器、通用定时器、基本定时器三种类型
二、定时器区别
1.通用定时器的特点描述
1.位于ABP1低速总线上
2.16位向下,向上/向下(中心对齐模式)计数模式,自动重装载计数器(TIMx_CNT)
3.16位可编程(可以实现修改)预分频器(TIMx_PSC),计数器时钟频率的分频系数为1~65535任意数值
4.四个独立通道(TIMx_CH1~4),通道用来支持:
①输入捕获
②输出比较
③PWM生成
④单脉冲模式输出
2.通用定时器的计数器模式
STM32通用定时器 可以向上,向下,向上/向下双向计数模式 :
① 向上计数模式:计数值从0 计数到自动加载值(TIM_ARR),产生一个计数溢出事件,然后重新从0开始计数
②向下计数模式:计数器从自动装入的值(TIM_ARR)开始向下计数到0,产生一个计数溢出事件,然后从计数装入值重新开始。
③中央对齐模式:计数器从0开始到(自动装入值-1),产生计数溢出事件,然后向下计数到1,产生定时器溢出事件,然后从0开始计数。
预分频器可以将计数器的时钟频率按1到65536之间的任意值分频。
ARR是自动重装载值(自己设定的)
CNT计数当前值(0到自动重装载值中间的某个值)
CCRX比较寄存器值
PSC是预分频系数
内部时钟源(CK_INT)
三、计数器时钟计算方法
预分频寄存器 :分频系数 (PSC+1) / N = CNT
定时器配置LED每秒闪烁一次:
Tout = [ 重装载值(ARR+1) * 分频系数(PSC+1)] /Tclk
Tout = 100000(9999+1) *7200(分频系数 7199+1) /72M(72 000 000)
计数器计数频率:CK_CNT = CK_PSC / (PSC + 1)
计数器溢出频率:CK_CNT_OV = CK_CNT / (ARR + 1) = CK_PSC / (PSC + 1) / (ARR + 1)
四、输入PWM模式
PWM模式1:
向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为有效电平,否则为无效电平;
向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为无效电平,否则为有效电平。
PWM模式2:
向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为无效电平,否则为有效电平;
向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为有效电平,否则为无效电平。
五、代码
PWM:
void motor_init(void)
{
TIM_TimeBaseInitTypeDef TIM_MotorInitStruct;
GPIO_InitTypeDef Motor_init;
TIM_OCInitTypeDef TIMPWMMotorinit;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);
//结构体配置 (需要放在前面) //gpio.h
Motor_init.GPIO_Mode =GPIO_Mode_AF_PP; //推挽复用输出
Motor_init.GPIO_Pin =GPIO_Pin_6;
Motor_init.GPIO_Speed =GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&Motor_init);
Motor_init.GPIO_Mode =GPIO_Mode_AF_PP; //推挽复用输出
Motor_init.GPIO_Pin =GPIO_Pin_5|GPIO_Pin_0|GPIO_Pin_1;
Motor_init.GPIO_Speed =GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&Motor_init);
TIM_MotorInitStruct.TIM_ClockDivision=TIM_CKD_DIV1; // 设置时钟分割 不分频
TIM_MotorInitStruct.TIM_CounterMode= TIM_CounterMode_Up; //TIM向上计数模式
TIM_MotorInitStruct.TIM_Period= 200-1; //ARR(199+1)
TIM_MotorInitStruct.TIM_Prescaler=7200-1; //PSC(7199+1)
TIM_TimeBaseInit(TIM3, &TIM_MotorInitStruct);
TIMPWMMotorinit.TIM_OCMode =TIM_OCMode_PWM2; //选择定时器模式1
TIMPWMMotorinit.TIM_OutputState =TIM_OutputState_Enable; //比较输出使能1
TIMPWMMotorinit.TIM_OCPolarity =TIM_OCPolarity_High; //预装载寄存器 选择有效输出极性
//TIM_OC1Init(TIM3, &TIMPWMMotorinit);
// TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Enable );
//tim3 1
TIM_OC2Init(TIM3, &TIMPWMMotorinit);
TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable );
//2
TIM_OC3Init(TIM3, &TIMPWMMotorinit);
TIM_OC3PreloadConfig(TIM3,TIM_OCPreload_Enable );
//tim3
TIM_OC4Init(TIM3, &TIMPWMMotorinit);
TIM_OC4PreloadConfig(TIM3,TIM_OCPreload_Enable );
//tim4
TIM_Cmd(TIM3, ENABLE);
}
定时器:
void tim_config(void)
{
TIM_TimeBaseInitTypeDef timInit;//定义初始化定时器结构体名
NVIC_InitTypeDef NVICInit; //定义中断的结构体名
//1.使能时钟 定时器时钟
RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM2, ENABLE);
TIM_InternalClockConfig(TIM2); // 配置定时器2为内部时钟模式
TIM_ClearFlag(TIM2, TIM_FLAG_Update);// 清除更新时的中断标志位,防止更新时程序直接进入中断
TIM_ITConfig(TIM2, TIM_IT_Update,ENABLE); //定时器中断配置
//2.配置tim的结构体
timInit.TIM_Period = 10000-1; //设置自动重装载值
timInit.TIM_CounterMode = TIM_CounterMode_Up; //配置计数模式 为向上
timInit.TIM_Prescaler = 7200 -1 ; //配置分频系数的值(计数器时钟的分频系数)
timInit.TIM_ClockDivision = TIM_CKD_DIV1; //(内部时钟分频)设置分频系数为1,不分频
TIM_TimeBaseInit(TIM2, &timInit); //调用初始化函数
//定时时间=(重装载值+1)*(计数器分频系数的值+1)/定时器的时钟:10000*7200/72000000(72M)
//3.打开定时器中断,配置中断结构体
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //配置优先级组,才可以进行抢占优先级和响应优先级设置
NVICInit.NVIC_IRQChannel = TIM2_IRQn;
NVICInit.NVIC_IRQChannelPreemptionPriority = 1;
NVICInit.NVIC_IRQChannelSubPriority = 1;
NVICInit.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVICInit);
TIM_Cmd(TIM2, ENABLE);
//4.中断服务函数
}