2. 使用定时器产生PWM波控制LED亮度

任务目标

在GD32微控制器上使用定时器产生PWM信号,通过软件循环改变占空比,驱动LED实现呼吸灯效果。通过本案例理解PWM波的产生原理及占空比与亮度的对应关系。

硬件准备

  • GD32开发板(以GD32F103系列为例)
  • LED一个(串联330Ω限流电阻)
  • 连接线若干

LED正极接开发板PA7引脚(TIMER2_CH0默认映射),负极经限流电阻接地。

实现原理

定时器TIMER2配置为PWM输出模式,通道0映射到PA7。通过修改比较寄存器TIMER_CH0CV的值改变占空比。当占空比从0%逐渐增至100%再递减回0%,LED呈现由暗到亮再到暗的呼吸效果。PWM频率设为1kHz,避免肉眼可见闪烁。

关键完整代码

#include "gd32f10x.h"

#define PWM_PERIOD   999    // 自动重载值,PWM频率 = 72MHz/(999+1) = 72kHz
#define STEP_VALUE   5      // 占空比变化步长

void gpio_config(void) {
    rcu_periph_clock_enable(RCU_GPIOA);
    gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_7);
}

void timer_config(void) {
    rcu_periph_clock_enable(RCU_TIMER2);
    
    timer_deinit(TIMER2);
    timer_parameter_struct timer_initpara;
    timer_struct_para_init(&timer_initpara);
    
    timer_initpara.prescaler         = 0;          // 72MHz时钟不分频
    timer_initpara.period            = PWM_PERIOD; // 自动重载值
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;
    timer_init(TIMER2, &timer_initpara);
    
    // 配置通道0为PWM模式1
    timer_channel_output_config(TIMER2, TIMER_CH_0, TIMER_OC_MODE_PWM1);
    timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 0);
    timer_channel_output_state_config(TIMER2, TIMER_CH_0, TIMER_CCX_ENABLE);
    
    timer_auto_reload_shadow_enable(TIMER2);
    timer_enable(TIMER2);
}

int main(void) {
    gpio_config();
    timer_config();
    
    uint16_t duty = 0;
    int8_t direction = 1;
    
    while (1) {
        timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, duty);
        delay_1ms(2);  // 每2ms调整一次占空比
        
        duty += direction * STEP_VALUE;
        if (duty >= PWM_PERIOD) {
            duty = PWM_PERIOD;
            direction = -1;
        } else if (duty == 0) {
            direction = 1;
        }
    }
}

/* 简易毫秒延时,依赖系统主频72MHz */
void delay_1ms(uint32_t count) {
    volatile uint32_t i;
    while (count--) {
        for (i = 0; i < 7200; i++);
    }
}

编译与烧录

  1. 使用Keil MDK或IAR创建工程,选择对应GD32型号。
  2. 添加上述代码,并包含GD32标准外设库头文件路径。
  3. 编译工程,通过SWD或串口下载生成的HEX文件到开发板。

验证方法

观察LED亮度是否呈现周期性由暗到亮再到暗的平滑变化,完整周期约0.8秒(400步×2ms)。若LED恒亮或恒灭,检查PA7连接是否正确、定时器时钟是否使能。使用示波器或逻辑分析仪测量PA7引脚,应看到频率约72kHz、占空比周期性变化的方波信号。

常见问题

  • LED不亮:检查GPIO模式是否为复用推挽(GPIO_MODE_AF_PP),确认TIMER2时钟已使能。
  • 亮度变化不流畅:减小STEP_VALUE或增大延时时间,使占空比变化更细腻。
  • PWM频率过高:当前72kHz超出LED视觉响应范围,若需降低频率可增大预分频器值(如设为71则频率降为1kHz)。