stm32-TIM-定时中断、内外时钟源选择
TIM介绍

计数器(CNT)是执行计数定时的寄存器,来一个时钟计数加一;预分频器(PSC)可以对计数器的时钟分频,使得计数更灵活;自动重装寄存器(ARR)是计数的目标值,到达目标值就申请中断。他们都是16位的,最大值是2的16次方=65536
赫兹就是频率,周期就是赫兹的倒数,最大定时时间=自动重装寄存器最大值*预分频器最大值*周期(1MHZ=10^6HZ),单位秒
三种定时器

基本定时器结构

基本定时器只能选择内部时钟,即系统频率
定时中断功能:通过内部时钟连接到预分频器,预分频器设置分频数,预分频器值为x,输出频率=输入频率/(x+1),然后计数器自增,增加到自动重装寄存器设定的值就清零,再自增。自动重装寄存器连接NVIC,达到设定值后可以申请中断,让CPU来处理,这样的中断叫更新中断;也可以不中断,而是引发一个事件,让别的电路运行,这叫更新事件。
主模式触发DAC功能:有时需要隔一段时间就让DAC输出一段波形,虽然可以在中断里触发DAC,但是这样主程序会被频繁中断。于是通过把更新事件通过主模式映射到TRGO(触发输出),TRGO再接到DAC的触发转换引脚,就不需要软件来触发了,实现了硬件自动化
通用定时器结构

通用定时器可以选择内部时钟,也可选择外部时钟
外部时钟可以来自TIMx_ETR引脚,经过极性选择,边沿检测和滤波等对波形进行整形。滤波之后就可以通过ETRF进入控制器再到时基单元,这一路叫外部时钟模式2;
还可以通过TRGI进入控制器作为时钟,这是外部时钟模式1,这个模式可以通过ETR引脚信号,此时和模式2没什么区别,只是会占用TRGI触发输入通道。也可以通过ITR信号,图中TRGO可以连接其他定时器,就是连接的其他定时器的ITR引脚,他们的ITR信号就可以作为这个定时器的时钟,实现了定时器级联。还可以选择TI1F_ED,它连接了下面CH1引脚。最后还有TI1FP1,TI2FP2,他们各自连接了CH1和CH2引脚,从这里获取时钟。
一般都使用内部时钟,外部时钟的话选择外部时钟模式2最直接简单。
下面左边是输入捕获电路,右边是输出比较电路,这二者不会同时发生,所以引脚和寄存器都是共用的。
高级定时器结构

相对于通用定时器,高级定时器在时基单元新加了重复次数计时器,可以实现几个计时周期才中断一次,不会每次到目标值都中断了。在输出比较电路上加了DTG寄存器,用来生成死区电路,防止开关转换瞬间桥臂直通;右边引脚也变为了一对,可生成互补PWM波形;最下面是刹车输入电路,当外部引脚BKIN产生刹车信号或者内部时钟故障时,就会关闭电机
定时中断结构

运行控制是控制定时开启关闭的,中断输出控制即是否允许对应中断
相关时序
预分频器时序

预分频缓冲器,也叫影子寄存器,当在计时途中改变了分频值时,有缓冲器就不会马上生效,而是在当前计时完后下一个周期才起作用。这是为了防止不同步产生的影响。自动重装器也有这样的影子寄存器
计数器时序

由这个公式,那么所需定时时间=(PSC+1)*(ARR+1)/72MHZ
无预装

无预装即没有缓冲,这是可以自行设置ARPE改变的。
有预装

此时改变重装值也只会在下一个周期开始生效
RCC时钟树

RCC时钟树是产生、配置时钟,并发送到各个外设的系统。图中左边是产生,右边分配
在产生时钟的电路中有四个振荡源:内部8MHZ的高速RC振荡源,外部4~16MHZ的高速石英晶体振荡器,即晶振,外部32.768KHZ的低速晶振,给RTC提供时钟,内部40KHZ的低速RC振荡器,给看门狗提供时钟。两个高速振荡源是给外设提供时钟的
系统会先暂时开启内部8MHZ的RC时钟,然后开启8MHZ的高速晶振进入PLL锁相环进行9倍倍频,得到72MHZ稳定后最终作为系统时钟。CSS是时钟安全系统,检测外部时钟状态,外部时钟失效时它会切换到8MHZRC内部时钟。
定时器内部时钟代码
要对定时器进行初始化,根据结构图,需要选择内外时钟源,配置时基单元,配置中断控制,配置NVIC,启动定时器。在此之前需要开启对应总线的时钟,以TIM2为例
初始化代码
void timer_init(void)
{
//依旧需要先开启时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
//接下来选择内外时钟源,这里选内部时钟
TIM_InternalClockConfig(TIM2);
//配置时基单元
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;//滤波器参数,对内部时钟没用,不分频
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//计数器模式,向上计数
TIM_TimeBaseInitStructure.TIM_Period=10000-1;//自动重装值
TIM_TimeBaseInitStructure.TIM_Prescaler=7200-1;//分频值
TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//重复次数计数器,高级定时器才需要,这里通用不用
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
//然后配置中断控制
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//itconfig就是允许外设中断的函数
//然后NVIC
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//分组2
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;//选择TIM2的通道
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//使能
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;//响应优先级
NVIC_Init(&NVIC_InitStructure);
//最后启动定时器
TIM_Cmd(TIM2,ENABLE);
}
中断函数代码
void TIM2_IRQHandler(void)
{
if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)
{
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
}
}
定时器外部时钟初始化代码
void timer_init(void)
{
//依旧需要先开启时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
//接下来选择内外时钟源,这里选ETR外部时钟模式2
TIM_ETRClockMode2Config(TIM2,TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_NonInverted,0X0F);
//使用了引脚,所以需要初始化GPIO,TIM2的ETR引脚在PA0
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
//配置时基单元
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//计数器模式,向上计数
TIM_TimeBaseInitStructure.TIM_Period=10-1;//自动重装值
TIM_TimeBaseInitStructure.TIM_Prescaler=1-1;//分频值
TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//重复计数计数器,高级定时器才需要,这里通用不用
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);//这里之后为了让重装值马上起作用,生成了一个更新事件和中断,使得一初始化就引脚中断了一次,不会从0开始
TIM_ClearFlag(TIM2,TIM_FLAG_Update);//所以使用清除一下标志位,不马上进入中断
//然后配置中断控制
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//itconfig就是允许外设中断的函数
//然后NVIC
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//分组2
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;//选择TIM2的通道
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//使能
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;//响应优先级
NVIC_Init(&NVIC_InitStructure);
//最后启动定时器
TIM_Cmd(TIM2,ENABLE);
}
中断函数代码类似
更多推荐



所有评论(0)