目录
一、通用定时器库函数工程模板
1、TIM_TimeBaseInitTypeDef
该结构体在基本定时器进行了介绍,其中通用定时器可以使用TIM_ClockDivision、TIM_CounterMode即时钟分频因子、计数模式。
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
#define TIM_CKD_DIV1 ((uint16_t)0x0000)
#define TIM_CKD_DIV2 ((uint16_t)0x0100)
#define TIM_CKD_DIV4 ((uint16_t)0x0200)
#define TIM_CounterMode_Up ((uint16_t)0x0000)
#define TIM_CounterMode_Down ((uint16_t)0x0010)
#define TIM_CounterMode_CenterAligned1 ((uint16_t)0x0020)
#define TIM_CounterMode_CenterAligned2 ((uint16_t)0x0040)
#define TIM_CounterMode_CenterAligned3 ((uint16_t)0x0060)
TIM_CLOCKDIVISION_DIV1
: 不进行时钟分频(默认值)。TIM_CLOCKDIVISION_DIV2
: 时钟频率为原来的一半。TIM_CLOCKDIVISION_DIV4
: 时钟频率为原来四分之一。
2、时钟
可以看到通用定时器的TIM2-TIM5都是挂载在APB1上。
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
#define RCC_APB1Periph_TIM2 ((uint32_t)0x00000001)
#define RCC_APB1Periph_TIM3 ((uint32_t)0x00000002)
#define RCC_APB1Periph_TIM4 ((uint32_t)0x00000004)
#define RCC_APB1Periph_TIM5 ((uint32_t)0x00000008)
3、初始化
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
// 开启定时器时钟,即内部时钟CK_INT=72M
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
TIM_TimeBaseStructure.TIM_Period=(1000-1);
// 时钟预分频数
TIM_TimeBaseStructure.TIM_Prescaler= 71;
// 时钟分频因子
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
// 计数器计数模式,设置为向上计数
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
// 初始化定时器
TIM_TimeBaseInit(GENERAL_TIM, &TIM_TimeBaseStructure);
可以看到基本上和前文所述的基本定时器一致,可以额外设置时钟分频因子和计数模式而已,而NVIC分配那几乎就一致了。
4、中断服务函数
几乎和基本定时器一致。
void TIM2_IRQHandler(void)
{
if ( TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET )
{
time++;
TIM_ClearITPendingBit(TIM2, TIM_FLAG_Update);
}
}
二、通用定时器库函数API
1、初始化封装
// 中断优先级配置
static void GENERAL_TIM_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
// 设置中断组为0
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
// 设置中断来源
NVIC_InitStructure.NVIC_IRQChannel = GENERAL_TIM_IRQ ;
// 设置主优先级为 0
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
// 设置抢占优先级为3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
static void GENERAL_TIM_Mode_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
// 开启定时器时钟,即内部时钟CK_INT=72M
GENERAL_TIM_APBxClock_FUN(GENERAL_TIM_CLK, ENABLE);
// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
TIM_TimeBaseStructure.TIM_Period=GENERAL_TIM_Period;
// 时钟预分频数
TIM_TimeBaseStructure.TIM_Prescaler= GENERAL_TIM_Prescaler;
// 时钟分频因子
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
// 计数器计数模式,设置为向上计数
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
// 重复计数器的值,没用到不用管
TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
// 初始化定时器
TIM_TimeBaseInit(GENERAL_TIM, &TIM_TimeBaseStructure);
// 清除计数器中断标志位
TIM_ClearFlag(GENERAL_TIM, TIM_FLAG_Update);
// 开启计数器中断
TIM_ITConfig(GENERAL_TIM,TIM_IT_Update,ENABLE);
// 使能计数器
TIM_Cmd(GENERAL_TIM, ENABLE);
}
void GENERAL_TIM_Init(void)
{
GENERAL_TIM_NVIC_Config();
GENERAL_TIM_Mode_Config();
}
2、中断服务函数封装
void GENERAL_TIM_IRQHandler (void)
{
if ( TIM_GetITStatus( GENERAL_TIM, TIM_IT_Update) != RESET )
{
time++;
TIM_ClearITPendingBit(GENERAL_TIM , TIM_FLAG_Update);
}
}
可以看到进行一个额外的定义,实现多类的通用。
#define GENERAL_TIM2 1
#define GENERAL_TIM3 0
#define GENERAL_TIM4 0
#define GENERAL_TIM5 0
#if GENERAL_TIM2
#define GENERAL_TIM TIM2
#define GENERAL_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd
#define GENERAL_TIM_CLK RCC_APB1Periph_TIM2
#define GENERAL_TIM_Period (1000-1)
#define GENERAL_TIM_Prescaler 71
#define GENERAL_TIM_IRQ TIM2_IRQn
#define GENERAL_TIM_IRQHandler TIM2_IRQHandler
#elif GENERAL_TIM3
#define GENERAL_TIM TIM3
#define GENERAL_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd
#define GENERAL_TIM_CLK RCC_APB1Periph_TIM3
#define GENERAL_TIM_Period (1000-1)
#define GENERAL_TIM_Prescaler 71
#define GENERAL_TIM_IRQ TIM3_IRQn
#define GENERAL_TIM_IRQHandler TIM3_IRQHandler
#elif GENERAL_TIM4
#define GENERAL_TIM TIM4
#define GENERAL_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd
#define GENERAL_TIM_CLK RCC_APB1Periph_TIM4
#define GENERAL_TIM_Period (1000-1)
#define GENERAL_TIM_Prescaler 71
#define GENERAL_TIM_IRQ TIM4_IRQn
#define GENERAL_TIM_IRQHandler TIM4_IRQHandler
#elif GENERAL_TIM5
#define GENERAL_TIM TIM5
#define GENERAL_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd
#define GENERAL_TIM_CLK RCC_APB1Periph_TIM5
#define GENERAL_TIM_Period (1000-1)
#define GENERAL_TIM_Prescaler 71
#define GENERAL_TIM_IRQ TIM5_IRQn
#define GENERAL_TIM_IRQHandler TIM5_IRQHandler
#endif
三、高级定时器库函数工程模板
1、TIM_TimeBaseInitTypeDef
可以额外使用重复计数器TIM_RepetitionCounter。
// 重复计数器的值
TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
- 配置了定时器的更新事件发生的次数。定时器发生更新事件(如溢出)之前,需要重复计数器计数到设定的值。通过这种方式,你可以增加定时器更新事件的间隔,达到在定时器溢出之前等待更多计数周期的效果。
- 通常与高级定时器(如
TIM1
和TIM8
)一起使用,适用于高级定时器的双通道输出比较、PWM 或死区插入等功能。
2、时钟
可以看到高级定时器TIM1、TIM8的时钟挂载在APB2上。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
#define RCC_APB2Periph_TIM1 ((uint32_t)0x00000800)
#define RCC_APB2Periph_TIM8 ((uint32_t)0x00002000)
3、初始化
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
// 开启定时器时钟,即内部时钟CK_INT=72M
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
TIM_TimeBaseStructure.TIM_Period=(1000-1);
// 时钟预分频数
TIM_TimeBaseStructure.TIM_Prescaler= 71;
// 时钟分频因子
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
// 计数器计数模式,设置为向上计数
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
// 重复计数器的值
TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
// 初始化定时器
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
至于NVIC也是几乎重复。
4、中断服务函数
几乎重复。
void TIM1_UP_IRQHandler (void)
{
if ( TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET )
{
time++;
TIM_ClearITPendingBit(TIM1, TIM_FLAG_Update);
}
}
四、高级定时器库函数API
1、初始化封装
// 中断优先级配置
static void ADVANCE_TIM_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
// 设置中断组为0
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
// 设置中断来源
NVIC_InitStructure.NVIC_IRQChannel = ADVANCE_TIM_IRQ ;
// 设置主优先级为 0
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
// 设置抢占优先级为3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
static void ADVANCE_TIM_Mode_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
// 开启定时器时钟,即内部时钟CK_INT=72M
ADVANCE_TIM_APBxClock_FUN(ADVANCE_TIM_CLK, ENABLE);
// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
TIM_TimeBaseStructure.TIM_Period=ADVANCE_TIM_Period;
// 时钟预分频数
TIM_TimeBaseStructure.TIM_Prescaler= ADVANCE_TIM_Prescaler;
// 时钟分频因子
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
// 计数器计数模式,设置为向上计数
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
// 重复计数器的值
TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
// 初始化定时器
TIM_TimeBaseInit(ADVANCE_TIM, &TIM_TimeBaseStructure);
// 清除计数器中断标志位
TIM_ClearFlag(ADVANCE_TIM, TIM_FLAG_Update);
// 开启计数器中断
TIM_ITConfig(ADVANCE_TIM,TIM_IT_Update,ENABLE);
// 使能计数器
TIM_Cmd(ADVANCE_TIM, ENABLE);
}
void ADVANCE_TIM_Init(void)
{
ADVANCE_TIM_NVIC_Config();
ADVANCE_TIM_Mode_Config();
}
#define ADVANCE_TIM1 // 如果使用TIM8,注释掉这个宏即可
#ifdef ADVANCE_TIM1 // 使用高级定时器TIM1
#define ADVANCE_TIM TIM1
#define ADVANCE_TIM_APBxClock_FUN RCC_APB2PeriphClockCmd
#define ADVANCE_TIM_CLK RCC_APB2Periph_TIM1
#define ADVANCE_TIM_Period (1000-1)
#define ADVANCE_TIM_Prescaler 71
#define ADVANCE_TIM_IRQ TIM1_UP_IRQn
#define ADVANCE_TIM_IRQHandler TIM1_UP_IRQHandler
#else // 使用高级定时器TIM8
#define ADVANCE_TIM TIM8
#define ADVANCE_TIM_APBxClock_FUN RCC_APB2PeriphClockCmd
#define ADVANCE_TIM_CLK RCC_APB2Periph_TIM8
#define ADVANCE_TIM_Period (1000-1)
#define ADVANCE_TIM_Prescaler 71
#define ADVANCE_TIM_IRQ TIM8_UP_IRQn
#define ADVANCE_TIM_IRQHandler TIM8_UP_IRQHandler
#endif
2、中断服务函数封装
void ADVANCE_TIM_IRQHandler (void)
{
if ( TIM_GetITStatus( ADVANCE_TIM, TIM_IT_Update) != RESET )
{
time++;
TIM_ClearITPendingBit(ADVANCE_TIM , TIM_FLAG_Update);
}
}
可以看到,如果只进行定时计数的功能,用通用定时器和高级定时器简直就是浪费,毫无意义。
HAL库的配置同理基本定时器的HAL库,基本上没啥太多修改的,不再额外阐述了。
标签:ADVANCE,定时器,HAL,GENERAL,NVIC,TIM,库函数,define From: https://blog.csdn.net/qq_39376872/article/details/144290953