1. 基础定时器中断点亮LED

任务目标

使用STM32基础定时器TIM6产生周期性更新中断,在中断服务函数中翻转LED引脚电平,实现精确的定时闪烁。本案例以STM32F103系列为例,TIM6属于基础定时器,无外部引脚,专用于内部定时触发。

硬件与依赖

  • STM32F103最小系统板(如蓝丸/红丸板),板载LED接PC13(高电平点亮)
  • STM32标准外设库(或HAL库,本案例使用标准库)
  • 编译工具:Keil MDK或arm-none-eabi-gcc + Makefile

实现原理

TIM6时钟源为APB1(36MHz),通过预分频器PSC和自动重装载寄存器ARR设定中断频率。中断频率计算公式:f = 36MHz / ((PSC+1) × (ARR+1))。本案例配置为1Hz闪烁(0.5s亮,0.5s灭),即中断频率2Hz。

关键完整代码

#include "stm32f10x.h"

// 定时参数:PSC=3599,ARR=4999 → 36MHz/3600/5000 = 2Hz
#define TIM_PSC    (3600 - 1)
#define TIM_ARR    (5000 - 1)

void TIM6_Init(void) {
    TIM_TimeBaseInitTypeDef TIM_InitStruct;
    NVIC_InitTypeDef NVIC_InitStruct;

    // 1. 使能TIM6时钟(APB1)
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);

    // 2. 配置定时器时基
    TIM_InitStruct.TIM_Prescaler = TIM_PSC;
    TIM_InitStruct.TIM_Period = TIM_ARR;
    TIM_InitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_InitStruct.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM6, &TIM_InitStruct);

    // 3. 使能更新中断
    TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);

    // 4. 配置NVIC
    NVIC_InitStruct.NVIC_IRQChannel = TIM6_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStruct);

    // 5. 启动定时器
    TIM_Cmd(TIM6, ENABLE);
}

void TIM6_IRQHandler(void) {
    if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET) {
        TIM_ClearITPendingBit(TIM6, TIM_IT_Update);
        GPIO_WriteBit(GPIOC, GPIO_Pin_13, 
            (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_13)));
    }
}

void LED_Init(void) {
    GPIO_InitTypeDef GPIO_InitStruct;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_Init(GPIOC, &GPIO_InitStruct);
    GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_SET);  // 初始熄灭
}

int main(void) {
    LED_Init();
    TIM6_Init();
    while (1) {
        // 主循环无任务,等待中断
    }
}

编译与烧录

  1. 在Keil中创建工程,选择芯片型号STM32F103C8,添加上述代码及标准外设库源文件(stm32f10x_gpio.c、stm32f10x_tim.c、stm32f10x_rcc.c、misc.c)。
  2. 工程选项 → C/C++ → Define 中添加 USE_STDPERIPH_DRIVER, STM32F10X_MD。
  3. 编译生成HEX文件,通过ST-Link或串口ISP烧录至开发板。
  4. 验证方法

    烧录后观察板载LED:应呈现周期性的亮灭交替,每次状态持续0.5秒(完整周期1秒)。若LED不闪烁,依次检查:

    • 电源与调试器连接是否正常
    • LED引脚是否为PC13(部分板子LED接PA1或PB12,需调整代码)
    • 用示波器或逻辑分析仪测量PC13波形,应为2Hz方波

    预期输出:LED以1Hz频率闪烁(亮0.5s→灭0.5s循环)。修改TIM_PSC或TIM_ARR可改变闪烁频率,例如将ARR改为999,则中断频率变为10Hz,LED闪烁加快至5Hz。