打印
[APM32F1]

定时器的使用——基本定时

[复制链接]
220|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 南河壹号 于 2023-9-12 16:37 编辑

通用定时器简介
通用定时器以时基单元为核心,拥有输入捕获和输出比较等功能,可以用来测量脉冲宽度、频率和占空比,以及产生输出波形。当然还有最基本的功能——定时,定时器和定时器之间是相互独立的,它们可以实现同步和级联。今天我们实现最简单的功能——定时

时基单元
时基单元包含:
  ● 计数器寄存器(TIMx_CNT)
  ● 预分频器寄存器 (TIMx_PSC)
  ● 自动装载寄存器 (TIMx_ARR)
计数器寄存器、自动装载寄存器和预分频器寄存器可以由软件读写,并且在计数器运行时仍可以读写

计数器寄存器(TIMx_CNT):该寄存器是定时器的计数器,该寄存器存储了当前定时器的计数值。

预分频寄存器(TIMx_PSC):该寄存器用于对时钟进行分频,然后提供给计数器,作为计数器的时钟。
TIM_PrescalerConfig(TIM2 , 7200-1 , TIM_PSCReloadMode_Immediate);//设置预分频值,且立即装入
//函数本质上是产生一次更新事件(在TIMx_EGR寄存器中设置UG位产生一个更新事件),把预分频值装入预分频器寄存器

自动重装载寄存器(TIMx_ARR):该寄存器在物理上实际对应着 2 个寄存器。一个是程序员可以直接操作的,另外一个是程序员看不到的,这个看不到的寄存器被叫做影子寄存器。事实上真正起作用的是影子寄存器。根据 TIMx_CR1 寄存器中 APRE 位的设置:APRE=0 时,预装载寄存器的内容可以随时传送到影子寄存器;而 APRE=1 时,在每一次更新事件(UEV)时,才把预装在寄存器的内容传送到影子寄存器。

计数器模式
向上计数模式
在向上计数模式中,计数器从0计数到自动加载值(TIMx_ARR计数器的内容),然后重新从0开始计数并且产生一个计数器溢出事件。
每次计数器溢出时(上溢)可以产生更新事件,在TIMx_EGR寄存器中设置UG位也同样可以产生一个更新事件。

向下计数模式
在向下模式中,计数器从自动装入的值(TIMx_ARR计数器的值)开始向下计数到0,然后从自动装入的值重新开始并且产生一个计数器向下溢出事件。
每次计数器溢出时(下溢)可以产生更新事件,在TIMx_EGR寄存器中设置UG位,也同样可以产生一个更新事件。

中央对齐模式(向上/向下计数)
在中央对齐模式,计数器从0开始计数到自动加载的值(TIMx_ARR寄存器)−1,产生一个计数器溢出事件,然后向下计数到1并且产生一个计数器下溢事件;然后再从0开始重新计数。
在这个模式,不能写入TIMx_CR1中的DIR方向位。它由硬件更新并指示当前的计数方向。
可以在每次计数上溢和每次计数下溢时产生更新事件;也可以通过(软件或者使用从模式控制器)设置TIMx_EGR寄存器中的UG位产生更新事件。

时钟选择
计数器时钟可由下列时钟源提供:
  ● 内部时钟(CK_INT)
  ● 外部时钟模式1:外部输入脚(TIx)
  ● 外部时钟模式2:外部触发输入(ETR)
  ● 内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器
定时器的时钟来源具体选择哪个可以通过从模式控制寄存器TIMx_SMCR 寄存器的相关位来设置。

内部时钟源(CK_INT)
如果禁止了从模式控制器(TIMx_SMCR寄存器的SMS=000),则CEN(TIMx_CR1寄存器)、DIR(TIMx_CR1寄存器)和UG位(TIMx_EGR寄存器)是事实上的控制位,并且只能被软件修改(UG位仍被自动清除)。只要CEN位被写成’1’,预分频器的时钟就由内部时钟CK_INT提供。

外部时钟模式1:外部输入脚(TIx)
当从模式控制寄存器TIMx_SMCR寄存器的SMS=111时,此模式被选中。计数器可以在选定输入端的每个上升沿或下降沿计数


外部时钟模式2:外部触发输入(ETR)
选定此模式的方法为:令从模式控制寄存器TIMx_SMCR寄存器中的ECE=1
计数器能够在外部触发ETR的每一个上升沿或下降沿计数。



内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器
使用该模式时,可以将另一个TIM设置为主模式,从而可以TRGO输出时钟,用作该TIM的时钟。


TIM_TimeBaseInitTypeDef结构体
typedef struct
{
  uint16_t TIM_Prescaler;\\TIM_Prescaler:设置用来作为TIMx时钟频率除数的预分频值。它的取值必须为0x0000~OxFFFF。
         
  uint16_t TIM_CounterMode;\\TIM_CounterMode:选择计数器模式   
   
  uint16_t TIM_Period;\\TIM_Period:设置计数周期。它的取值必须为0x0000~0xFFFF。  
         
  uint16_t TIM_ClockDivision;\\TIM_ClockDivision:设置时钟分割——不分频、二分频、四分频
   
  uint8_t TIM_RepetitionCounter;\\TIM_RepetitionCounter是高级定时器才有用的  

} TIM_TimeBaseInitTypeDef;

定时器定时中断配置流程:
  • 定义结构体变量
  • 开启TIMx时钟
  • 结构体变量赋值
  • 初始化定时器
  • 配置NVIC
  • 清除中断标志位
  • 使能中断
  • 使能定时器
  • 编写中断服务函数

#include "basictim.h"

void NVIC_BasicTim_Config(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
   
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
   
    NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_Init(&NVIC_InitStructure);
   
}

void BasicTim_Config(uint16_t Period,uint16_t Prescaler)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
   
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6,ENABLE);
   
    //定时时间:Period/(主频/Prescaler)
    TIM_TimeBaseInitStructure.TIM_Period = Period-1;
    TIM_TimeBaseInitStructure.TIM_Prescaler = Prescaler-1;
    TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;     //不分频
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM6,&TIM_TimeBaseInitStructure);
   
//  TIM_PrescalerConfig(TIM2 , 7200-1 , TIM_PSCReloadMode_Immediate);
   
    NVIC_BasicTim_Config();
   
    TIM_ClearITPendingBit(TIM6,TIM_IT_Update);
    TIM_ITConfig(TIM6,TIM_IT_Update,ENABLE);
    TIM_Cmd(TIM6,ENABLE);
   
   
}


源码自取:

链接:https://pan.baidu.com/s/1tCIY84VpgIlzzNnvO1kILg
提取码:1234
--来自百度网盘超级会员V5的分享



使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

5

主题

7

帖子

0

粉丝