/*自己一直记不住的几个知识点整理,所以脚踩西瓜皮写到哪里是哪里,没有系统的学习价值*/
1.STM32常规定时器资源概览
①系统滴答计时器 systick
②看门狗定时器 watchdog
③实时时钟 rtc
④基本定时器 TIMx(x为几请自行查阅芯片手册)
⑤通用定时器 TIMx(同上)
⑥高级定时器 TIMx(同上)
注意:SysTick是集成在cortex-m内核中的,并不属于单片机的外设(peripheral),主要作用是给各类RTOS提供时钟节拍做时间基准。HAL库中的HAL_Delay()函数也是以它为基准,因此我们在给单片机移植RTOS时应该尽量避免使用HAL_Delay()函数。
定时器基本用途:输出比较、输入捕获、PWM生成、单脉冲模式输出等。
2.通用定时器介绍
通用定时器由一个可编程预分频器(Prescaler✖16)驱动的16位自动重装载主计数器(counter period)构成,可以对内部时钟或触发源以及外部时钟或触发源进行计数。
基本原理:①定时器时钟信号送入16位可编程预分频器,该预分频器系数∈[0,65535];
②等待预分频器溢出后,会向16位的空计数器发出一个脉冲信号。
总结:预分频器本质上是一个加法计数器,预分频系数实际上就是加计数的溢出值。cortex内核单片机内部有两根时钟总线,APB1与APB2,通用计数器挂载在APB1上,高级计时器挂载在APB2上。如图1所示假设我们的内核需要一个10000ms的周期计时,那么我们可以使能外部高速时钟给石英晶体振荡器加上一个电场,由于石英晶体具有各向异性它会周期地进行简谐振动。接下来令初始时钟信号是1k Hz,即让时钟信号线上存在一个周期位1ms的方波信号,然后把预分频系数设为10,即预分频器接受十个方波上升沿(0~9)之后输出一个周期为10ms的方波信号传入主计数器,主计数器计数值设置为1000,同样地再接受完1000个(0~999)上升沿之后主计数器会输出一个周期为10000ms的方波信号。(如果还想了解分频、倍频原理的话就自己翻翻模电书吧这里不细讲了。)这里机制也还没介绍完,还有影子寄存器、自动重装载寄存器啥的,大家感兴趣可以去看B站Keysking的视频动画讲解的,或者自己动手翻翻数据手册。
图1(有谁能在评论区教教我CSDN怎么画框图么😀)
这里再贴一下CubeMX里的时钟树方便理解记忆。
图2 将F429时钟树APB时钟线信号设置为90M Hz
3.定时器发生中断的计算方法
定时时间=(Prescaler+1)*(Counter Period+1)/定时器时钟频率
4.应用场景举例
HAL库函数实现us级别延时:
/* 个人代码库
*
* 基于TIM的us级别延时函数与ms级别延时函数
* Cubemx里面勾选Internal Clock,并且设置一个通用计时器的Prescaler的数值设置为x
* x是时钟树上计时器频率的“M数” 减一
* 适用于一般的通信协议
*
* 修改历史 版本号 作者 修改内容
*-----------------------------------------------------
* 2023.12.14 v1.0 Jumayusi 创建文件
*-----------------------------------------------------
*/
#include "delay.h"
//延时nus
//nus:要延时的us数
void delay_us(uint32_t us)
{
uint16_t differ = 0xffff-us-5;
__HAL_TIM_SET_COUNTER(&htim5,differ);
HAL_TIM_Base_Start(&htim5);
while(differ < 0xffff-5){
differ = __HAL_TIM_GET_COUNTER(&htim5);
}
HAL_TIM_Base_Stop(&htim5);
}
//延时nms
//nms:要延时的ms数
void delay_ms(uint16_t nms)
{
uint32_t i;
for(i=0;i<nms;i++)
{
delay_us(1000);
}
}
#ifndef _DELAY_H
#define _DELAY_H
#include "main.h"
#include "tim.h"
void delay_us(uint32_t nus);
void delay_ms(uint16_t nms);
#endif
/*有不对的地方还请各位大佬斧正,拜谢。*/