目录
[STM32 中定时器分类以及相关作用](#STM32 中定时器分类以及相关作用)
[STM32 中基本定时器的时钟源](#STM32 中基本定时器的时钟源)
[STM32 中基本定时器的基本结构](#STM32 中基本定时器的基本结构)
系统定时器
系统定时器(systick)--内核

系统定时器结构

系统滴答定时器寄存器--内核
处理器有一个 24bit 的定时器---SysTick,它从重装载值向下计数到 0,产生溢出,如果使能了中断,就会产生中断,在下一个时钟,再次将重装载值放到计数器中。
SYSTICK_LOAD 重装载值寄存器 -- 内核手册 4.5.2
重装载值寄存器是 24 位,所以可以填写的最大值 2^24-1
SYSTICK_VAL 当前值寄存器
SYSTICK_CTRL 控制和状态寄存器 -- 内核手册 4.5.1


定时周期的确定公式
-
根据选择的时钟源,CTRL 寄存器的位 2 置 1,选择 AHB(72M)作为时钟源
-
所以计数的频率 F=72M
-
更新 1 次数据的时间 t=1/F=1/72000000 s
-
定时器的中断触发周期 T=ARR*t
-
假如想要 1ms 的周期 T,需要计多少次数?
ARR:指重装载值
T=ARR*t=1ms=0.001s=ARR*1/72000000 s
ARR= T/t=1ms/(1/72000000 s)=72000
所以 ARR=72000
- 想想最大的中断的触发周期是多少?
T=ARR*t=2^24*1/72000000 s=0.23s
配置滴答定时器
cpp
SysTick_Config(SystemCoreClock/1000);//72000
系统定时器应用
应用1.定时器构造时间点任务,解决while循环阻塞问题

一定要清0

应用2.定时器构造精准的ms延时


应用3.按键非阻塞

main

STM32中的定时器
STM32 中定时器分类以及相关作用
STM32 定时器分为 3 类:基本定时、通用定时器和高级定时器等

作用:
基本定时器:定时
通用定时器:定时+PWM+输入捕获+编码
高级定时器:通用定时器+死区+刹车
实时时钟 独立看门狗 窗口看门狗 本质上都是定时器
使用不同系列芯片,一定要确定,有没有该资源
STM32 中基本定时器的时钟源

TIM1 到 TIM8 预分频器前面的时钟都是 72M 的
STM32 中基本定时器的基本结构
有黑影的是有影子寄存器


预分频器预装载

预分频器控制寄存器更改之后,不会立马生效,等这一次周期走完后,写到预分频缓冲器中才会生效。
预分频器是否开启

使能预装载就是必须走完当前周期,下个周期才会生效。
中断触发周期
定时器的频率 CK_PSC F=72000000HZ
定时器的计数频率 CK_CNT f=F/PSC PSC 预分频值
更新一次数据的时间 t=1/f=PSC/F
计数的周期(触发中断的周期) T=ARR*t=ARR*PSC/F ARR 重装载值寄存器
需要 1ms 的中断周期:
T=ARR*PSC/F=1ms ARR*PSC=1ms*F=0.001*72000000=72000
注意:PSC 和 ARR 都是 16 位的寄存器,最大只能填入 65535
需要 5ms 的中断周期:
T=ARR*PSC/F=5ms ARR*PSC=5ms*F=0.005*72000000=360000
定时器的最大中断触发周期:
T=ARR*t=ARR*PSC/F=65535*65535/72000000 s=59.65s
代码
Tim6为例
寄存器:
cpp
//1.开APB1的时钟
RCC->APB1ENR |= (0x01 << 4);
//2.CR1的位0置1
TIM6->CR1 |= (0x01 << 0);
//3.DIER的位0置1
TIM6->DIER |= (0x01 << 0);
//4.设置重装载寄存器
TIM6->ARR = 10000 - 1;
//5.设置预分频寄存器
TIM6->PSC = 7200 - 1;
//6.配置NVIC优先级
NVIC_SetPriority(TIM6_IRQn, 9);//抢占2次级1
//7.使能TIM6的NVIC
NVIC_EnableIRQ(TIM6_IRQn);
库函数:
cpp
uint16_t PrescalerValue = 0;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);//开TIM6时钟
PrescalerValue = (uint16_t) (SystemCoreClock / 10000) - 1;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;//定义结构体
TIM_TimeBaseStructure.TIM_Period = PrescalerValue;//重装载值
TIM_TimeBaseStructure.TIM_Prescaler = 7200 - 1;//预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = 0;//时钟分割,不等于6和7的时候才有用
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//不等于6和7的时候才有用,6 7 只能向上计数
TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);
TIM_Cmd(TIM6, ENABLE);//使能定时器
TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);//开启定时器中断
TIM_PrescalerConfig(TIM6, PrescalerValue, TIM_PSCReloadMode_Immediate);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
main.c
调用内核中断
cpp
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);