STM32定时器

简介

STM32的定时器可用于不同的目的,包括生成PWM信号、测量时间间隔、生成中断和控制外设等。它有几种不同类型的定时器,包括通用定时器、高级控制定时器、低功耗定时器和系统滴答定时器。

​ 定时器是对周期固定的脉冲信号进行计数,如MCU内部的外设时钟(APB)。

​ 计数器是对周期不确定的脉冲信号进行计数,如MCU的I/O引脚所引入的外部脉冲信号。

​ 结论:定时器和计数器本质上都是计数器,定时器是计数器的一种特例。

定时器分类

种类 功能
基本定时器 几乎没有任何输入/输出通道,常用作时基,实现基本的定时/计数功能
通用定时器 具备多路独立的捕获和比较通道,可以完成定时计数、输入捕获、输出比较等功能
高级定时器 除具备通用定时器的功能外,还具备带死区控制的互补信号输出、紧急刹车关断输入等功能,可用于电机控制和数字电源设计

定时器的时钟频率

外设总线挂在TIM外设

外设总线时钟APB1-AHB1 外设总线时钟APB2-AHB2
LPTIM1(低功耗定时器)
基本定时器 TIM6-TIM7
通用定时器 TIM2-TIM3-TIM4-TIM5-TIM12-TIM13-TIM14 TIM15-TIM16-TIM17
高级定时器 TIM1-TIM8
image-20221231132006932

由上图看出AHB1,2 和APB1,2 的总线频率为240Mhz 挂在在APB1,2和AHB1,2 上的定时器的频率为120Mhz

定时器的三种计数模式

image-20221231132738219

溢出值CNT与自动重载值ARR的关系列表

计数模式 计数器溢出值 计数器重载值
递增计数 CNT = ARR CNT = 0
递减计数 CNT = 0 CNT = ARR
中心对齐计数 CNT = ARR-1
CNT = 1
CNT = ARR
CNT = 0

定时器的定时时间计算公式

**定时时间 = 计数值*计数时间**

定时时间 = 计数值/时钟频率 \[ T_{(s)}=\frac{(ARR+1)*(PSC+1)}{𝐓𝐈𝐌\_𝐂𝐋_{Hz}} \] 例如:

即时500ms 使用tim2

因为tim2 挂载在APB2 TIM2的时钟频率为240Mhz PSC为2399 \[ 500_{ms}=\frac{(ARR+1)*(23999+1)}{240000} \] 通过计算Arr=4999

HAL库函数解析

HAL_TIM_Base_Start_IT

image-20221231141044345

回调函数HAL_TIM_PeriodElapsedCallback

image-20221231141223889

任务1定时闪烁指示灯

时钟的配置和之前的一样 并且将LED小灯打开

配置TIM2

image-20221231162909317

在Clock Source(中断来源) 使用Internal Clock

使能定时器2的中断中断优先级使用默认值

image-20221231163212877

配置定时时间

image-20221231163359779

这里我配置的为:

Prtscaler (定时器分频系数) : 23999

Counter Mode(计数模式) Up(向上计数模式)

Counter Period(自动重装载值) : 4999

CKD(时钟分频因子) : No Division 不分频

auto-reload-preload(自动重装载) : Enable 使能

代码编写

初始化使能定时器2

image-20221231170317204

添加定时器溢出的中断回调函数

image-20221231170409617

任务2 PWM

基本特性

脉冲宽度调制(PWM)是一种对模拟信号电平进行数字编码的方法。广泛应用于电机控制、灯光的亮度调节、功率控制等领域

PWM信号的两个基本参数

  • 周期(Period)

一个完整PWM波形所持续的时间

  • 占空比(Duty)

高电平持续时间(Ton)与周期时间(Period)的比值

周期计算公式

\[ Period(ms) = {( ARR + 1 ) * ( PSC + 1 )\over TIMx\_CLK_{(KHz)}} \]

TIMx_CLK:定时器X挂在总线的频率

占空比计算公式

\[ Duty = ((TIMx->CCR1) / (ARR+1) )* 100\% \]

使用的TIM几 就是TIM几的CRR

频率计算公式

周期的到倒数 \[ F_{KHz}={TIMx\_CLK_{(KHz)}\over (ARR+1)∗(PSC+1)} \] 例如:

我要设置一个频率为2Khz的PWM信号 周期为 2Ms 占空比为 47.5% 的信号

使用TIM2 挂在在APB1 频率为 240Mhz

PSC 为 239

ARR通过计算= 1999

CCR 通过计算为 950

PWM信号的电压调节原理

image-20221231171151053

PWM输出的工作原理

image-20221231171245742

参数计算公式

\[ Period(s) = ( ARR + 1 ) * ( PSC + 1 ) / TIMx\_CLK \]

\[ Duty = ( CRR / ( ARR + 1 ) ) * 100% \]

假设预分频时钟CK_PSC为100MHz,产生周期为1ms,占空比为47.5%的PWM信号

image-20221231171451379

多通道输出

​ 定时器的每个通道都可以输出PWM信号,对于同一个定时器而言,它的多个通道共享同一个自动重载寄存器,因此可以输出占空比不同,但周期相同的PWM信号。

image-20221231171712932

PWM输出的两种模式

PWM模式1

​ 递增计数时,当TIMx_CNT(当前计数值)<TIMx_CCR(捕获/比较值)时,通道输出为有效电平,否则为无效电平。递减计数模式则刚好相反。

PWM模式2

​ 递增计数时,当TIMx_CNT(当前计数值)<TIMx_CCR(捕获/比较值)时,通道输出为无效电平,否则为有效电平。递减计数模式则刚好相反。

递增计数,高电平有效时:

  • PWM1模式下的CCR用于控制高电平持续的时间

  • PWM2模式下的CCR用于控制低电平持续的时间

总结:互补输出

HAL库函数介绍

定时器PWM输出启动函数:HAL_TIM_PWM_Start

image-20221231172727456

**定时器比较/捕获寄存器设置函数:__HAL_TIM_SET_COMPARE**

image-20221231172745910

输出PWM信号

输出一个频率为2Khz的PWM信号 周期为 2Ms 占空比从0到100的PWM信号

PWM设置

image-20221231215916189

配置频率与周期

image-20221231220005448
image-20221231220356202

程序编写

在主程序中 启用TIM2计时器通道一的PWM输出

1
2
3
4
 /* USER CODE BEGIN 2 */  
//启动定时器Tim2 通道1输出为2ms pwm信号
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);
/* USER CODE END 2 */

在while循环中改变占空比

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{

/* USER CODE END WHILE */
for (int i = 0; i < 2000;i+=200) {
__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_1,i);
HAL_Delay(4);
}

/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */

下图为使用逻辑分析仪测得的波形

image-20221231223311979

任务3 使用超声波模块测距

使用超声波模块测距 距离小于5cm LED灯亮

简介

型号:HC-SR04

image-20220629181110841

超声波测距模块是用来测量距离的一种产品,通过发送和收超声波,利用时间差和声音传播速度,计算出模块到前方障碍物的距离。

  • 怎么让它发送波

​ Trig ,给Trig端口至少10us的高电平

  • 怎么知道它开始发了

​ Echo信号,由低电平跳转到高电平,表示开始发送波

  • 怎么知道接收了返回波

​ Echo,由高电平跳转回低电平,表示波回来了

  • 怎么算时间

​ Echo引脚维持高电平的时间!

​ 波发出去的那一下,开始启动定时器

​ 波回来的拿一下,我们开始停止定时器,计算出中间经过多少时间

  • 怎么算距离

​ 距离 = 速度 (340m/s)* 时间/2

image-20220629181318917

编写一个微秒的延迟程序

配置Tim2每计数一次 花费1微秒

image-20230101121931318
1
2
3
4
5
6
7
8
9
10
/* USER CODE BEGIN 0 */
void TIM2_Delay_us(uint16_t n_us){
//使能定时器2计数
__HAL_TIM_ENABLE(&htim2);
__HAL_TIM_SetCounter(&htim2,0);
while (__HAL_TIM_GetCounter(&htim2)< ((1*n_us)-1));
//关闭定时器2计数
__HAL_TIM_DISABLE(&htim2);
}
/* USER CODE END 0 */

配置GPIO口

Trig 需要发波 所以是output模式 连接到 PA0号GPIO口

image-20230101122013745

Echo 需要接受返回来的波 是Input模式 连接到 PA1号GPIO口

image-20230101122039881

主程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/* USER CODE BEGIN WHILE */
while (1)
{

/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */
//1.先给Trig一个最少10us的高电平
HAL_GPIO_WritePin(Trig_GPIO_Port,Trig_Pin,GPIO_PIN_SET);//拉高
TIM2_Delay_us(20);
HAL_GPIO_WritePin(Trig_GPIO_Port,Trig_Pin,GPIO_PIN_RESET);//拉低
//echo 由底电平转为高电平 表示发波完成 启动定时器计数
while (HAL_GPIO_ReadPin(Echo_GPIO_Port,Echo_Pin) == GPIO_PIN_RESET);
HAL_TIM_Base_Start(&htim2); //开启定时器
//由高电平转为低电平 表示波回来了 停止定时器计数
while (HAL_GPIO_ReadPin(Echo_GPIO_Port,Echo_Pin) == GPIO_PIN_SET);
HAL_TIM_Base_Stop(&htim2);//关闭计时器
cnt = __HAL_TIM_GetCounter(&htim2); //获取计数值
distance = cnt *340/2*0.000001*100; //单位 cm
if (distance < 5){ //判断如果小于5cm LED点亮 反之熄灭

HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_SET);

}else{
HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_RESET);
}
HAL_Delay(100);//防止系统卡死
}
/* USER CODE END 3 */