登录/注册

普中stm32开发板带您进入ARM世界定时器中断

普中stm32开发板带您进入ARM世界定时器中断

更多

好的!使用 普中 STM32 开发板 实现 定时器中断 是学习 ARM Cortex-M 内核(特别是 STM32)中断系统和定时器外设的绝佳入门实践。下面我将用中文详细解释步骤和关键概念,并提供一个基于 HAL 库的示例代码框架。

核心概念:

  1. 定时器 (TIM): STM32 内部有多个高级/通用/基本定时器。它们本质上是一个计数器,可以根据时钟源(通常是系统时钟或其分频)自动递增或递减。当计数器达到特定值(自动重装载值)时,可以产生事件或中断。
  2. 中断 (Interrupt): 一种硬件机制。当某个特定事件(如定时器溢出)发生时,处理器会暂停当前正在执行的代码,转而去执行一段预先定义好的代码(中断服务程序 ISR),执行完毕后再返回原程序继续执行。这允许 MCU 及时响应外部或内部事件。
  3. 定时器中断: 配置定时器在特定时间间隔(由时钟频率、预分频器和自动重装载值决定)产生溢出更新事件,并允许这个事件触发中断。在中断服务程序中,你可以执行周期性任务(如翻转 LED、读取传感器、发送数据等)。

实现步骤 (基于 STM32 HAL 库):

假设你使用的是普中开发板常见的 STM32F1 系列(如 STM32F103ZE),并使用 CubeMX 初始化或直接编写 HAL 库代码。以下步骤以通用定时器 TIMx (例如 TIM2, TIM3, TIM4) 为例:

  1. 使能时钟:

    • 定时器本身需要时钟才能工作。
    • 如果使用 GPIO 控制 LED 来验证中断,还需要使能对应 GPIO 端口的时钟。
    • HAL 库函数:__HAL_RCC_TIMx_CLK_ENABLE();__HAL_RCC_GPIOx_CLK_ENABLE(); (替换 x 为你的定时器和 GPIO 编号)。
    // 例如,使能 TIM2 和 GPIOA (假设 LED 在 PA5)
    __HAL_RCC_TIM2_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();
  2. 配置 GPIO (用于 LED):

    • 将连接 LED 的引脚配置为推挽输出模式。
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = GPIO_PIN_5;        // 替换为你的实际 LED 引脚号
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // 替换为你的实际 GPIO 端口
  3. 配置定时器基础参数:

    • 使用 HAL_TIM_Base_Init() 函数初始化定时器。
    • 需要填充 TIM_HandleTypeDef 结构体和 TIM_Base_InitTypeDef 结构体。
    • 关键参数:
      • Prescaler (预分频器):对定时器时钟源进行分频。定时器实际时钟 = 定时器输入时钟 / (Prescaler + 1)。用于调整计数速度。
      • Period (自动重装载值):计数器计数到这个值后,会产生更新事件(并可能溢出归零或根据计数方向处理)。Period + 1 就是计数器从 0 计到溢出所需的计数值。
      • CounterMode:计数模式,通常用 TIM_COUNTERMODE_UP (向上计数)。
      • ClockDivision:时钟分频(用于数字滤波器),通常用 TIM_CLOCKDIVISION_DIV1
    TIM_HandleTypeDef htim2; // 定时器句柄
    
    htim2.Instance = TIM2; // 选择定时器2
    htim2.Init.Prescaler = 7199; // 预分频值 (示例:72MHz / (7199 + 1) = 10KHz)
    htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim2.Init.Period = 9999; // 自动重装载值 (示例:10000 个计数)
    htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; // 建议启用预装载
    
    if (HAL_TIM_Base_Init(&htim2) != HAL_OK) {
        // 初始化错误处理
        Error_Handler();
    }

    计算中断时间间隔:

    • 假设系统时钟 (SYSCLK) = 72 MHz
    • 定时器时钟 (TIMxCLK) = SYSCLK = 72 MHz (对于 APB1 上的 TIM2/3/4,如果 APB1 预分频器是 1,否则需要计算)
    • 定时器实际计数频率 = TIMxCLK / (Prescaler + 1) = 72,000,000 / (7199 + 1) = 72,000,000 / 7200 = 10,000 Hz (10 KHz)
    • 中断频率 = 定时器实际计数频率 / (Period + 1) = 10,000 / (9999 + 1) = 10,000 / 10,000 = 1 Hz (1 秒一次中断)
    • 所以,这个配置会让 TIM2 每 1 秒产生一次更新中断。
  4. 配置定时器中断:

    • 使用 HAL_TIM_Base_Start_IT() 函数启动定时器并开启更新中断。
    • 使用 HAL_NVIC_SetPriority() 设置定时器中断通道的优先级。
    • 使用 HAL_NVIC_EnableIRQ() 使能定时器中断通道。
    // 启动定时器并开启更新中断
    if (HAL_TIM_Base_Start_IT(&htim2) != HAL_OK) {
        // 启动错误处理
        Error_Handler();
    }
    
    // 设置中断优先级 (根据你的系统配置调整优先级和子优先级)
    HAL_NVIC_SetPriority(TIM2_IRQn, 1, 0); // TIM2_IRQn 是 TIM2 的中断号
    // 使能 TIM2 中断
    HAL_NVIC_EnableIRQ(TIM2_IRQn);
  5. 编写中断服务程序 (ISR):

    • stm32f1xx_it.c 文件中找到对应定时器的中断向量函数(如 TIM2_IRQHandler)。
    • 在这个函数里,必须调用 HAL_TIM_IRQHandler(&htim2);。这个 HAL 库函数会检查中断源并调用相应的回调函数。
    • 关键: 在 ISR 中执行的操作必须尽量简短!避免长时间阻塞影响其他中断或主程序。
    // 在 stm32f1xx_it.c 文件中
    void TIM2_IRQHandler(void) {
        // 调用 HAL 库的中断处理函数
        HAL_TIM_IRQHandler(&htim2);
    }
  6. 编写定时器溢出更新中断回调函数:

    • HAL 库提供了一个弱定义的 HAL_TIM_PeriodElapsedCallback() 函数。当更新中断发生时,HAL_TIM_IRQHandler() 会调用这个函数。
    • 你需要在你的主程序文件(如 main.c)中重写 (Override) 这个函数,添加你希望在每次定时器中断发生时执行的代码(如翻转 LED)。
    // 在 main.c 文件中 (或其他用户文件)
    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
        // 检查是哪个定时器触发的回调
        if (htim->Instance == TIM2) {
            // 执行你的中断任务,例如翻转 LED (PA5)
            HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
        }
        // 可以在这里检查其他定时器...
    }
  7. 主函数 (main):

    • 调用上面的初始化函数(时钟、GPIO、定时器)。
    • 启动定时器中断。
    • 进入主循环。主循环可以执行其他任务,中断会异步发生。
    int main(void) {
        HAL_Init(); // 初始化 HAL 库
        SystemClock_Config(); // 配置系统时钟 (通常由 CubeMX 生成或自己实现)
    
        // 初始化 GPIO (LED)
        MX_GPIO_Init(); // 或者直接调用你写的 GPIO 初始化函数
    
        // 初始化定时器 TIM2
        MX_TIM2_Init(); // 或者直接调用你写的 TIM2 初始化函数
    
        // 启动 TIM2 中断模式
        if (HAL_TIM_Base_Start_IT(&htim2) != HAL_OK) {
            Error_Handler();
        }
    
        // 设置并使能 NVIC
        HAL_NVIC_SetPriority(TIM2_IRQn, 1, 0);
        HAL_NVIC_EnableIRQ(TIM2_IRQn);
    
        while (1) {
            // 主循环,可以执行其他任务
            // 例如:HAL_Delay(100); 或者处理其他逻辑
            // 注意:避免在中断和主循环中同时操作同一个资源(如全局变量)时产生冲突,可能需要临界区保护。
        }
    }

总结与关键点:

  1. 时钟是核心: 清楚系统时钟、定时器时钟源、预分频后的实际计数时钟之间的关系是计算中断间隔的基础。
  2. HAL 库流程:
    • HAL_TIM_Base_Init:配置定时器参数。
    • HAL_TIM_Base_Start_IT:启动定时器并开启更新中断。
    • HAL_NVIC_*:配置中断优先级和使能。
    • TIMx_IRQHandler:中断入口,调用 HAL_TIM_IRQHandler
    • HAL_TIM_IRQHandler:库函数,根据中断标志调用对应回调。
    • HAL_TIM_PeriodElapsedCallback你需要重写的函数,放置你的中断处理逻辑。
  3. 中断服务程序 (ISR) 要短小精悍! 避免复杂计算、长时间延时(如 HAL_Delay)、或可能阻塞的操作。通常只设置标志位、翻转 IO、更新简单计数器等。
  4. 预装载 (AutoReloadPreload): 启用 (TIM_AUTORELOAD_PRELOAD_ENABLE) 可以确保在更新周期时新值能平滑加载,避免在写入新 Period 值时产生毛刺。
  5. 验证: 最简单的验证方式就是在回调函数中翻转一个 LED。观察 LED 是否按照你计算的时间间隔闪烁。
  6. 查找资料: 普中开发板通常有配套资料。查找你板载 MCU 的具体型号(如 STM32F103ZET6)的参考手册和数据手册,查看定时器章节和中断向量表。查看开发板原理图,确认 LED 连接的引脚。

动手实践:

  1. 根据你的开发板型号和使用的 IDE (Keil, IAR, STM32CubeIDE),创建一个新工程。
  2. 按照上述步骤编写代码。特别注意替换 TIMxGPIOxPINxIRQn 为实际使用的值,并根据你的时钟配置计算 PrescalerPeriod 以达到期望的中断时间。
  3. 编译、下载程序到开发板。
  4. 观察 LED 是否按预期闪烁。如果没有,检查:
    • 时钟配置是否正确(SystemClock_Config)?
    • 定时器时钟是否使能?
    • GPIO 配置和初始化是否正确?LED 引脚是否接对?
    • 中断优先级设置和使能是否做了?
    • 是否在 stm32f1xx_it.c 中调用了 HAL_TIM_IRQHandler
    • 是否正确地重写了 HAL_TIM_PeriodElapsedCallback
    • 计算 PrescalerPeriod 的公式是否正确?用示波器或逻辑分析仪看引脚波形最直接。

通过这个实验,你就成功利用 STM32 的定时器中断实现了周期性任务,这是嵌入式 ARM 开发中非常基础和重要的技能!祝你成功进入 ARM 世界!

STM32H757I-EVAL开发板

1970-01-01 08:00:00 至 1970-01-01 08:00:00

定时器中断是什么意思,定时器中断的工作原理

定时器中断是由单片机中的定时器溢出而申请的

2023-07-23 09:45:48

STM32定时器中断应用实例

本文将介绍:通过STM32cube mx配置工程文件,实现定时器中断的功能。

2023-04-21 11:36:46

STM32定时器中断显示时间

前言利用STM32的定时器中断,实现时间的显示。我们知道利用定时器

资料下载 訾存贵 2021-12-24 18:56:06

基于cubemx的stm32开发之路(使用正点原子战舰V3开发板)——基本定时器的应用

1hz的闪烁实验设备正点原子新战舰V3 STM32F103ZET6开发板学习板st-link烧录

资料下载 万物死 2021-12-08 15:21:11

STM32CubeMX_定时器中断_PWM

文章目录前言STM32CubeMX新建工程基本定时器配置生成代码定时器中断

资料下载 佚名 2021-12-05 13:51:04

单片机定时器中断后计数器中断进入

情况再次执行定时器中断(中断嵌套?)解决:中断在执行时,如果又有一个

资料下载 贾虎世 2021-12-03 19:36:02

【MCU】基于STM32CubeMX定时器中断实现LED闪烁

基于STM32CubeMX定时器中断实现 LED 闪烁本实验基于STM32

资料下载 佚名 2021-10-29 11:06:09

STM32开发板

STM32开发板 STM32F103RCT6最小系统板 ARM 一键串口

2023-04-04 11:05:04

STM32定时器的分类及中断原理

本文主要介绍常规定时器中的TIM3,实现定时器中断的功能。

2023-01-12 17:29:17

STM32定时器立即进入更新中断服务程序问题

我们在基于ST的标准库或基于CubeMx建立工程,当用到定时器并启用其更新中断时,可能会遇到一使能定时器

2022-07-27 09:13:08

stm32定时器中断进入不了中断服务程序是为什么?

stm32定时器中断时进入不了

2021-11-29 06:45:43

使用通用定时器进行中断的原理

stm32入门——定时器中断产生定时中断是

2021-08-13 09:00:10

开发板定时器中断C语言实现

普中开发板的定时器

2021-07-21 06:36:12

stm32定时器中断与误区

在用到STM32定时器的更新中断时,发现有些情形下只要开启定时器就立即

2019-06-17 15:48:20

7天热门专题 换一换
相关标签