自学内容网 自学内容网

基本定时器---内部时钟中断

目录

一、定时器的概念

二、简单看看定时器电路图

1.基本定时器

​编辑

2.通用定时器 

3.高级定时器

三、定时器的基本结构

四、示例代码


一、定时器的概念

        定时器(TIM),可以对输入的时钟信号进行计数,并在计数值达到设定值的时候触发中断。

        STM32的定时器系统有一个最为重要的结构是时基单元,它由一个16位计数器,预分频器,和自动重装寄存器构成。在时钟信号来临的时候,首先会由预分频器对该信号进行分流,使得一部分或者全部的信号进入计时器开始计数,当计数值达到自动重装寄存器的值时,由硬件触发中断,将中断信号递交给NVIC最后进入CPU运行中断服务函数。在72MHz的时钟下最大可以实现59.65s的定时。当然如果你觉得这个时间不够长,还可以利用STM32的定时器级联功能,将一个定时器的中断信号作为第二个定时器的时钟输入,这样定时时长可以呈现几何状的爆炸增长。

        STM32的定时器不仅仅具有基本的定时中断功能,还包含了:内外时钟源选择、输入捕获(用于测量输入信号的脉冲长度)、输出比较(用于产生输出波形,如PWM(脉冲宽度调制))、编码器接口(适用于读取正交编码器的位置信息)、主从触发模式等多种功能。根据复杂度和应用场景,上述功能被划分到了高级定时器、通用定时器、基本定时器三个类型的定时器中。

二、简单看看定时器电路图

1.基本定时器

        这里面有一个影子寄存器(方框下面有阴影的就是影子寄存器),它有助于确保定时器的准确性和同步性。

  • 预装载寄存器是程序员可以直接访问和修改的寄存器。
  • 影子寄存器是定时器内部实际使用的寄存器,它的值由预装载寄存器在特定条件下更新而来
  • 影子寄存器的存在,使得我们在修改一个定时器的自动重装寄存器的值来控制定时时长的时候,不会立即生效,而是在当前时钟中断已经完成,到了更新事件/更新中断的节点才会被修改,这样就保证了定时器的准确性和同步性。

2.通用定时器 

        在这里,我们只需要着重关心上面框出来的部分即可,下面的其他功能之后会有所涉猎

3.高级定时器

高级定时器是在通用定时器的基础上增加了框图部分,大家可以先看看电路图,也是在之后会讲到

三、定时器的基本结构

        上面我们已经看到了各种定时器的基本电路图,已经了解了其原理。下图是对上述的总结框图,我们只需要按照这个图就可以配置好。

  1. 打开定时器的时钟
    • 使用RCC_APB1PeriphClockCmd或RCC_APB2PeriphClockCmd函数打开相应的定时器资源。
  2. 配置时钟源
    • 将时钟资源设为内部时钟源或外部时钟源。
  3. 配置时基单元
    • 设置计数器模式(向上、向下或中央对齐)。
    • 配置预分频器(PSC)和自动重装载寄存器(ARR)。
  4. 配置中断
    • 清除定时器更新标志位。
    • 使能定时器的更新中断。
  5. 配置NVIC中断分组
    • 设置中断的优先级和使能中断线路。
  6. 使能定时器
    • 启动定时器开始运行。

四、示例代码

void TIM2_Init()
{
    //打开RCC的定时器2时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
    
    //设置TIM2为内部时钟
    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);
    
    //清除定时器标志位:因为配置好上面的定时器后,就被视作产生一次更新中断,
    //然后标志位就被置1了,如果不清除定时器就是从1开始定时
     TIM_ClearFlag(TIM2, TIM_FLAG_Update);
    
    //打开TIM2的中断输出控制
    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
    
    //配置NVIC的分组和优先级
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_Init(&NVIC_InitStructure);
    
    //打开计数器,使能TIM2
    TIM_Cmd(TIM2, ENABLE);
}
//中断服务函数
void TIM2_IRQHandler(void)
{
    //检测是否由TIM2产生的中断
    if(TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
    {
        //清除TIM2产生中断的标志位
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
        
        //处理过程
        number++;
    }
}

原文地址:https://blog.csdn.net/2303_79336820/article/details/143793168

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!