前置介绍
TIM 高级定时器框图

1. 时钟源选择与触发输入
这是定时器的"心脏"部分,负责为整个定时器系统提供时钟信号。
- 内部时钟 :通常来自RCC的
CK_TIM18,这是最常用的时钟源。 - 外部时钟模式1:可以通过ETR引脚输入外部信号,经过极性选择和分频后作为时钟。
- 外部时钟模式2:可以使用其他定时器的触发输出(TRGI)或其他内部信号(如ITRx)作为时钟源。
- 触发控制器:这部分逻辑决定了定时器何时开始计数、何时复位等,它接收来自ETR、ITR等信号的控制。
2. 触发控制器与从模式控制器
这部分主要负责与其他外设的同步。
- 触发控制器:生成触发输出信号(TRGO),可以连接到其他定时器或DAC/ADC,用于触发它们的转换或同步操作。
- 从模式控制器:接收外部触发信号(TRGI),根据配置的模式(如复位模式、门控模式、触发模式等)来控制本定时器的计数器(CNT)行为。
3. 核心时基单元
这是定时器最基础的计数部分,决定了定时的时间基准。
- 预分频器(PSC):对输入的时钟信号(CK_PSC)进行分频,得到计数器时钟(CK_CNT)。
公式通常为:
。
- 计数器(CNT):核心计数寄存器,根据时钟信号进行向上、向下或中央对齐计数。
- 自动重装载寄存器(ARR):设定计数的目标值。当CNT的值达到ARR的值时,会产生更新事件(溢出或下溢),计数器会重置或改变方向。
4. 输入捕获单元
这部分用于测量外部信号的脉宽或频率。
- 通道输入(TI1-TI4):外部信号通过TIMx_CHx引脚进入。
- 滤波与边沿检测:信号经过数字滤波器去除噪声,并可以选择在上升沿或下降沿触发捕获。
- 捕获/比较寄存器(CCR):当检测到指定的边沿时,当前的CNT值会被锁存到CCR寄存器中。通过计算两次捕获值的差,即可算出信号的周期或脉宽。
5. 输出比较单元
这部分用于生成特定频率或占空比的波形(如PWM)。
- 比较逻辑:将CNT的值与捕获/比较寄存器(CCR)中的预设值进行比较。
- 输出控制:当CNT与CCR匹配时,根据配置的模式(如翻转、置位、复位、PWM模式),改变输出引脚(TIMx_CHx)的电平状态。
- 死区时间插入(DTG):在互补输出(如CHxN)时,为了防止上下桥臂直通,会插入一段死区时间。
6. 刹车与死区功能
这是高级控制定时器特有的安全功能,常用于电机控制。
- 刹车输入(BKIN):这是一个紧急停止信号。当BKIN引脚检测到有效电平(如外部故障信号)时,定时器会立即强制关闭输出通道,保护电路安全。
- 时钟安全系统:也可以配置为在时钟失效时触发刹车。
项目配置
这里使用的 TIM1 , TIM1 是高级定时器

Clock Source 时钟源, 选择 Internal Clock
PSC 分频系数, 设置为 7200 - 1
Counter Period 自动重装值, 设置为 1000-1
下面的 Repetition Counter (RCR) 重复计数器, 核心作用是控制 "更新事件"的触发频率, 允许计数器在完成多次溢出后才产生一个更新中断或 DMA 请求

NVIC Settings 设置 TIM1 update interrupt 更新中断 为 Enabled 使能

可以到 NVIC 中, 设置中断的优先级.
代码部分
/* USER CODE BEGIN PV */
uint32_t tim1_arr[2] = { 1000 - 1, 10000 - 1}; // index 0: 每100ms产生一次中断, index 1: 每(1000ms)秒产生一次中断
uint8_t mode = 0; // 模式
/* USER CODE END PV */
/* USER CODE BEGIN 2 */
// 启动定时器中断
HAL_TIM_Base_Start_IT(&htim1);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if (HAL_GPIO_ReadPin(GPIOA, KEY1_Pin) == GPIO_PIN_SET)
{
// KEY1 被按下
mode = !mode; // 切换模式
HAL_TIM_Base_Stop_IT(&htim1); // 先关定时器
__HAL_TIM_SET_AUTORELOAD(&htim1, tim1_arr[mode]); // 修改 ARR (自动重装值)
__HAL_TIM_SET_COUNTER(&htim1, 0); // 清零 CNT
// 规范, 虽然已经停止了定时器, 但是为了防止之前的计数没有完成.
HAL_TIM_Base_Start_IT(&htim1); // 重启定时器
// 等待按键松开, 防止多次修改.
while(HAL_GPIO_ReadPin(GPIOA, KEY1_Pin) == GPIO_PIN_SET);
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE BEGIN 4 */
/**
* @brief TIM 定时器更新中断回调函数
* @param htim 定时器句柄指针
* @retval 无
* @note 本函数由 HAL 库在定时器溢出时自动调用
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
// 判断是否是 TIM1 的中断
if (htim -> Instance == TIM1)
{
// 翻转 LED 电平
HAL_GPIO_TogglePin(GPIOA, LED_R_Pin|LED_G_Pin|LED_B_Pin);
}
}
/* USER CODE END 4 */
实验现象
与上一节实验现象相同


按下按键 (KEY1), LED 灯在两种模式(100ms 闪烁 / 1000ms 闪烁)中切换.