1. 裸机系统下的前后台架构

裸机系统下的前后台架构 学习卡片

任务说明

本案例要求在一个裸机(无操作系统)环境下,采用前后台架构实现LED闪烁功能。所谓前后台,即:后台为永不退出的主循环(while(1)),负责轮询事件标志并执行相应处理;前台为中断服务程序(ISR),负责响应硬件事件(如定时器溢出)并置位事件标志。通过该案例,理解前后台架构中“中断产生事件、主循环处理事件”的基本协作模式。

硬件连接与依赖

本案例以STM32F103系列MCU为运行目标,使用标准外设库(StdPeriph_Lib)。硬件连接如下:

  • LED正极经220Ω限流电阻接PC13(STM32最小系统板载LED),阴极接地;
  • 使用TIM2作为定时中断源,配置为1ms周期中断。

所需文件:main.c、stm32f10x_it.c(中断向量)、stm32f10x_conf.h(外设库配置头文件)。工程需包含标准外设库源码及启动文件。

前后台架构协作关系 前台(中断服务) TIM2_IRQHandler 每1ms触发一次 time_tick++ 后台(主循环) while(1) 轮询 time_tick 翻转LED 事件标志(共享变量) TIM2 硬件定时器 溢出 → 触发中断 周期 = 1ms GPIO PC13 输出高低电平 驱动LED亮灭 硬件触发 写寄存器 共享变量传递 硬件中断路径

代码实现

以下代码实现完整的LED闪烁功能:TIM2每1ms触发一次中断,在ISR中累加time_tick;主循环检测到500ms到达时翻转LED状态。核心逻辑如下:

// main.c
#include "stm32f10x.h"

volatile uint32_t time_tick = 0;   // 前台ISR写入,后台主循环读取

void TIM2_IRQHandler(void)         // 前台:定时器中断服务
{
    if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
        time_tick++;               // 每1ms加1
    }
}

static void LED_GPIO_Init(void)
{
    GPIO_InitTypeDef gpio;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    gpio.GPIO_Pin   = GPIO_Pin_13;
    gpio.GPIO_Mode  = GPIO_Mode_Out_PP;
    gpio.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_Init(GPIOC, &gpio);
}

static void TIM2_Init(void)
{
    TIM_TimeBaseInitTypeDef tim;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    tim.TIM_Prescaler     = 7200 - 1;   // 72MHz/7200 = 10kHz
    tim.TIM_CounterMode   = TIM_CounterMode_Up;
    tim.TIM_Period        = 10 - 1;     // 10kHz/10 = 1kHz → 1ms
    tim.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInit(TIM2, &tim);
    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
    NVIC_EnableIRQ(TIM2_IRQn);
    TIM_Cmd(TIM2, ENABLE);
}

int main(void)
{
    uint32_t last_tick = 0;
    LED_GPIO_Init();
    TIM2_Init();
    
    while (1) {                        // 后台:主循环
        if (time_tick - last_tick >= 500) {  // 500ms到
            last_tick = time_tick;
            GPIO_WriteBit(GPIOC, GPIO_Pin_13,
                (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_13)));
        }
    }
}

编译与烧录

使用Keil MDK或IAR建立工程,添加上述main.c及标准外设库源文件(如stm32f10x_tim.c、stm32f10x_gpio.c、stm32f10x_rcc.c),包含对应头文件路径。编译生成HEX文件后,通过ST-Link或J-Link烧录至STM32F103开发板。

验证方法与判定标准

验证步骤:

  1. 将程序烧录至开发板,确认PC13引脚连接的LED正常点亮;
  2. 观察LED是否以约1Hz频率(每500ms翻转一次,即亮500ms、灭500ms)持续闪烁;
  3. 在调试器中设置断点于TIM2_IRQHandler,确认每1ms进入一次中断;
  4. 在while(1)循环中观察time_tick变量持续递增。

判定标准:

  • LED以肉眼可见的稳定频率闪烁(周期约1s),无停顿或跳变;
  • 中断服务函数被周期性调用,time_tick值单调递增;
  • 主循环中LED翻转间隔与time_tick差值500ms对应,证明前后台协作正确。

若LED不闪烁或频率异常,检查TIM2时钟配置(确认系统主频为72MHz)及GPIO引脚连接是否正确。