本帖最后由 南河壹号 于 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的分享
|