差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

后一修订版
前一修订版
stm32:tim [2025/01/20 13:35] – 创建 laythystm32:tim [2025/01/23 19:43] (当前版本) laythy
行 1: 行 1:
-TIM(TIMER)定时器\\+===TIM(TIMER)定时器===
 实际上是计数器,对输入的时钟(方波信号)进行计数,并在计数值达到设定值时触发中断。\\ 实际上是计数器,对输入的时钟(方波信号)进行计数,并在计数值达到设定值时触发中断。\\
 当输入的时钟是线性的基准时钟,计数器就变成了定时器。\\ 当输入的时钟是线性的基准时钟,计数器就变成了定时器。\\
 16位计数器,预分频器。\\ 16位计数器,预分频器。\\
  
 +===定时器类型===
 +{{ :stm32:timertype.jpeg?nolink |}}
 +STM32E103C8T6定时器资源:TIM1、TIM2、TIM3、TIM4\\
 +
 +===基本定时器结构===
 +{{ :stm32:basictimerstructure.png?nolink |}}
 +PSC、CNT、自动重装载寄存器这三个部分构成一个**时基单元**。\\
 +其中RCC_TIMxCLK = 72Mhz(CK_INT直接接到CK_PSC)。\\
 +  - PSC预分频器:对CK_PSC分频,写0就是不分频,写n就是n+1分频。PSC是16位预分频器,故最大可以写65535,即65536分频。\\
 +  - CNT计数器:对预分频后的信号CK_INT计数,吗,每一个周期的上升沿计数+1,不断自增。\\
 +  - 自动重装载寄存器:存储目标计数值,当CNT==目标值时,产生中断信号,并且清零CNT。\\
 +UI表示更新中断(update interrupt),通往NVIC。U表示产生一个更新事件(update event),不触发中断。\\
 +
 +===通用定时器结构===
 +{{ :stm32:generaltimerstructure.png?nolink |}}
 +如图,时钟输入信号可以是:内部RCC时钟和外部时钟。而外部时钟又可以是:TIMx_ETR、ITR0-3、TI1F_ED、TI1FP1、TI2FP2。首选:RCC时钟。\\
 +
 +===定时中断基本结构===
 +{{ :stm32:simpletimerstructure-white.png?nolink |}}
 +
 +===RCC时钟树===
 +{{ :stm32:rccclocktree.png?nolink |}}
 +
 +===例程:定时1秒===
 +<code>
 +// Timer.c
 +
 +#include "stm32f10x.h"                  // Device header
 +
 +void Timer2_Init(void)
 +{
 +    // 时钟
 +    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
 +    TIM_InternalClockConfig(TIM2); // 可不写这一句,上电默认内部时钟源
 +    
 +    // 时基单元
 +    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStrucure;
 +    TIM_TimeBaseInitStrucure.TIM_ClockDivision = TIM_CKD_DIV1;
 +    TIM_TimeBaseInitStrucure.TIM_CounterMode = TIM_CounterMode_Up;
 +    TIM_TimeBaseInitStrucure.TIM_Period = 10000 - 1; // ARR
 +    TIM_TimeBaseInitStrucure.TIM_Prescaler = 7200 - 1; // PSC
 +    TIM_TimeBaseInitStrucure.TIM_RepetitionCounter = 0; //通用定时器没有重复计数器
 +    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStrucure);
 +    // 计数器溢出频率公式 CK_CNT_OV =  CK_PSC / (PSC+1)*(ARR+1)
 +    // 要定时1秒,即溢出频率1hz,解得 ARR=9999, PSC=7199(非唯一)
 +    // 注意ARR和PSC都是16位的, 取值范围都是0-65535
 +    
 +    // 下面这一句防止复位就执行一次中断,对应1秒+1的情况就是复位值为0. 否则刚复位显示就是1.
 +    TIM_ClearFlag(TIM2, TIM_FLAG_Update);
 +    
 +    // IT中断使能
 +    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //更新中断
 +    
 +    // NVIC
 +    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
 +    NVIC_InitTypeDef NVIC_InitStrucure;
 +    NVIC_InitStrucure.NVIC_IRQChannel = TIM2_IRQn;
 +    NVIC_InitStrucure.NVIC_IRQChannelCmd = ENABLE;
 +    NVIC_InitStrucure.NVIC_IRQChannelPreemptionPriority = 2;
 +    NVIC_InitStrucure.NVIC_IRQChannelSubPriority = 1;
 +    NVIC_Init(&NVIC_InitStrucure);
 +    
 +    // 启动定时器
 +    TIM_Cmd(TIM2, ENABLE);
 +}
 +
 +void TIM2_IRQHandler(void)
 +{
 +    if(TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
 +    {
 +        extern uint16_t ticktok;
 +        ticktok++;
 +        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
 +    }
 +}
 +</code>
 +
 +<code>
 +// main.c
 +
 +#include "stm32f10x.h"                  // Device header
 +#include "OLED.h"
 +#include "Timer.h"
 +
 +uint16_t ticktok = 0;
 +
 +int main(void)
 +{
 +    Timer2_Init();
 +    OLED_Init();
 +    OLED_ShowString(1, 1, "ticktok:");
 +    
 +    while(1)
 +    {
 +        OLED_ShowNum(1, 9, ticktok, 5);
 +    }
 +}
 +</code>