STM32 入门:软件PWM呼吸灯

在这里插入图片描述

STM32 微控制器因性能强、外设丰富且性价比高,成为嵌入式开发热门选择。掌握 GPIO 配置与操作,是 STM32 开发入门的关键。本文以 STM32F103C8T6 为例,结合软件 PWM 呼吸灯实例展开讲解。

一、GPIO 基础概念

GPIO 是 STM32 与外部交互的基础接口,可设为输入或输出模式。STM32F103C8T6 的 GPIO 端口(如 GPIOA、GPIOB、GPIOC 等)引脚能独立配置,满足多样化开发需求。

二、GPIO 配置步骤

在使用 GPIO 之前,需要对其进行一系列的配置,以确保其工作在预期的模式下。下面以配置 PC13 引脚为输出模式为例,详细介绍 GPIO 的配置步骤。

  1. 使能 GPIO 时钟:在 STM32 中,每个外设都有独立的时钟控制,GPIO 也不例外。要使用 GPIO,首先需要使能其对应的时钟。对于 PC13 引脚,其位于 GPIOC 端口,使用以下代码使能 GPIOC 的时钟:
RCC\_APB2PeriphClockCmd(RCC\_APB2Periph\_GPIOC, ENABLE);

这段代码通过调用RCC_APB2PeriphClockCmd函数,将 GPIOC 的时钟使能,确保后续对 GPIOC 端口的操作能够正常进行。

2. 配置 GPIO 初始化结构体:STM32 标准库提供了GPIO_InitTypeDef结构体,用于配置 GPIO 的各种参数。对于 PC13 引脚的输出配置,代码如下:

GPIO\_InitTypeDef GPIO\_InitStructure;

GPIO\_InitStructure.GPIO\_Mode = GPIO\_Mode\_Out\_PP;

GPIO\_InitStructure.GPIO\_Pin = GPIO\_Pin\_13;

GPIO\_InitStructure.GPIO\_Speed = GPIO\_Speed\_50MHz;
  • GPIO_Mode_Out_PP表示将引脚配置为推挽输出模式。推挽输出模式可以直接输出高电平和低电平,适用于驱动一些需要较大电流的负载,如 LED 灯。

  • GPIO_Pin_13指定要配置的引脚为 PC13。

  • GPIO_Speed_50MHz设置引脚的输出速度为 50MHz,该速度可以满足大多数应用场景的需求。

  1. 初始化 GPIO:在完成GPIO_InitTypeDef结构体的配置后,使用以下代码将配置应用到 GPIOC 端口的 PC13 引脚上:
GPIO\_Init(GPIOC, \&GPIO\_InitStructure);

GPIO_Init函数会根据GPIO_InitStructure结构体中的参数,对 GPIOC 端口的 PC13 引脚进行初始化,使其工作在设定的输出模式下。

三、软件 PWM 呼吸灯原理

PWM(Pulse Width Modulation)即脉冲宽度调制,是一种通过改变脉冲信号的占空比(高电平持续时间与周期的比值)来控制输出信号平均值的技术。在本实例中,通过软件 PWM 来控制 LED 灯的亮度,实现呼吸灯效果。其原理是通过不断改变 PWM 信号的占空比,使 LED 灯的亮度在最暗到最亮之间逐渐变化,从而产生呼吸灯的效果。

四、软件 PWM 呼吸灯代码解析

下面对实现软件 PWM 呼吸灯的代码进行详细解析。

  1. 定义相关参数
\#define PWM\_PERIOD 1000  // PWM周期(ms),可根据需要调整

\#define STEP\_SIZE 10    // 亮度变化步进值,值越小变化越平滑

PWM_PERIOD定义了 PWM 信号的周期为 1000ms,即 1 秒。STEP_SIZE定义了每次亮度变化的步进值为 10,该值决定了呼吸灯亮度变化的平滑程度。

2. GPIO 初始化函数

void gpio\_init(void)

{

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    GPIO_ResetBits(GPIOC, GPIO_Pin_13);  

}

该函数完成了 GPIOC 端口 PC13 引脚的初始化工作,使 PC13 引脚工作在推挽输出模式下,并将其初始状态设置为低电平,即 LED 灯熄灭。

3. 软件 PWM 函数

void PWM(unsigned int duty\_cycle)

{

    if(duty_cycle > PWM_PERIOD) {
        duty_cycle = PWM_PERIOD;  // 限制最大值
    }
    
    GPIO_SetBits(GPIOC, GPIO_Pin_13);  // LED亮
    delay_ms(duty_cycle);
    GPIO_ResetBits(GPIOC, GPIO_Pin_13); // LED灭
    delay_ms(PWM_PERIOD - duty_cycle);  // 补足周期时间

}

PWM函数用于实现软件 PWM 功能。函数接收一个参数duty_cycle,表示 PWM 信号的占空比(0 - 1000)。首先,函数对duty_cycle进行检查,如果其值超过了PWM_PERIOD,则将其设置为PWM_PERIOD,以确保占空比在合理范围内。然后,通过GPIO_SetBits函数将 PC13 引脚置为高电平,使 LED 灯亮起,并保持duty_cycle毫秒;接着,通过GPIO_ResetBits函数将 PC13 引脚置为低电平,使 LED 灯熄灭,并保持PWM_PERIOD - duty_cycle毫秒,从而补足 PWM 周期的时间。

4. 主函数

int main(void)

{
    unsigned int brightness = 0;  // 当前亮度值
    unsigned int direction = 1;   // 1表示变亮,0表示变暗
    
    gpio_init();
    delay_init();
    
    while (1)
    {
        // 渐亮过程
        if(direction) {
            brightness += STEP_SIZE;
            if(brightness >= PWM_PERIOD) {
                brightness = PWM_PERIOD;
                direction = 0;  // 达到最亮后开始变暗
            }
        }
        // 渐暗过程
        else {
            brightness -= STEP_SIZE;
            if(brightness <= 0) {
                brightness = 0;
                direction = 1;  // 达到最暗后开始变亮
            }
        }
        
        PWM(brightness);  // 以当前亮度值执行PWM
    }
}

在主函数中,定义了两个变量brightnessdirection,分别用于记录当前 LED 灯的亮度值和亮度变化的方向。通过调用gpio_init函数初始化 GPIO,调用delay_init函数初始化延时函数(delay_init函数在delay.h头文件中定义,用于提供精确的延时功能)。在无限循环中,根据direction的值判断是渐亮还是渐暗过程。如果是渐亮过程,则将brightness增加STEP_SIZE,当brightness达到PWM_PERIOD时,将direction设置为 0,表示开始渐暗;如果是渐暗过程,则将brightness减少STEP_SIZE,当brightness减到 0 时,将direction设置为 1,表示开始渐亮。最后,调用PWM函数,以当前的brightness值作为占空比,实现 LED 灯的呼吸灯效果。

总结:

通过对 STM32 基础 GPIO 配置与软件 PWM 呼吸灯实现的介绍,相信读者对 STM32 的 GPIO 操作有了更深入的理解。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐