打印
[STM32F7]

在STM32上通过按键实现呼吸灯和流水灯两种模式的切换

[复制链接]
2997|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 合同圣诞节fy 于 2024-6-1 08:40 编辑

在STM32上通过按键实现呼吸灯和流水灯两种模式的切换,可以遵循以下步骤。这涉及到配置按键的输入、LED的输出以及定时器的使用来控制LED的亮度和切换模式。

硬件连接
假设使用一个按键和多个LED:

一个按键连接到一个GPIO输入引脚。
多个LED连接到多个GPIO输出引脚。
软件设计
按键检测:

配置按键为GPIO输入,并启用中断或轮询检测按键状态。
每次按键按下时,切换模式。
模式切换:

使用一个变量来存储当前模式(呼吸灯模式或流水灯模式)。
在按键中断服务例程或轮询检测函数中,切换该变量的值。
呼吸灯:

使用PWM(脉宽调制)来控制LED的亮度,实现呼吸效果。
配置一个定时器来生成PWM信号。
流水灯:

使用定时器中断或延时函数,依次点亮和熄灭LED,实现流水效果。

使用特权

评论回复
沙发
合同圣诞节fy|  楼主 | 2024-6-1 08:40 | 只看该作者
代码实现
以下是一个基于STM32 HAL库的示例代码:

硬件初始化
c

#include "stm32f4xx_hal.h"

#define NUM_LEDS 4  // 假设有4个LED

// LED引脚和端口定义
GPIO_TypeDef* LED_PORT[NUM_LEDS] = {GPIOA, GPIOA, GPIOA, GPIOA};
const uint16_t LED_PIN[NUM_LEDS] = {GPIO_PIN_0, GPIO_PIN_1, GPIO_PIN_2, GPIO_PIN_3};

// 按键引脚和端口定义
#define BUTTON_PORT GPIOC
#define BUTTON_PIN GPIO_PIN_13

// 当前模式
volatile uint8_t mode = 0;  // 0: 呼吸灯模式, 1: 流水灯模式

// 初始化GPIO
void GPIO_Init(void)
{
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();

    GPIO_InitTypeDef GPIO_InitStruct = {0};

    // 初始化LED引脚
    GPIO_InitStruct.Pin = LED_PIN[0] | LED_PIN[1] | LED_PIN[2] | LED_PIN[3];
    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_InitStruct.Pin = BUTTON_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(BUTTON_PORT, &GPIO_InitStruct);

    // 启用按键中断
    HAL_NVIC_SetPriority(EXTI15_10_IRQn, 2, 0);
    HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
}

使用特权

评论回复
板凳
合同圣诞节fy|  楼主 | 2024-6-1 08:40 | 只看该作者
按键中断处理
c

// 按键中断处理函数
void EXTI15_10_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(BUTTON_PIN);
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if (GPIO_Pin == BUTTON_PIN)
    {
        mode = !mode;  // 切换模式
    }
}

使用特权

评论回复
地板
合同圣诞节fy|  楼主 | 2024-6-1 08:41 | 只看该作者
定时器和PWM配置
c

TIM_HandleTypeDef htim2;
TIM_OC_InitTypeDef sConfigOC;

void TIM2_Init(void)
{
    __HAL_RCC_TIM2_CLK_ENABLE();

    htim2.Instance = TIM2;
    htim2.Init.Prescaler = 84 - 1;  // 1 MHz
    htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim2.Init.Period = 1000 - 1;  // 1 kHz
    htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
    HAL_TIM_PWM_Init(&htim2);

    sConfigOC.OCMode = TIM_OCMODE_PWM1;
    sConfigOC.Pulse = 0;
    sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
    sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
    HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1);

    HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
}

使用特权

评论回复
5
合同圣诞节fy|  楼主 | 2024-6-1 08:41 | 只看该作者
主程序
c

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    GPIO_Init();
    TIM2_Init();

    uint32_t pwm_value = 0;
    uint32_t direction = 1;  // 1: 增加, 0: 减少
    uint32_t led_index = 0;

    while (1)
    {
        if (mode == 0)  // 呼吸灯模式
        {
            // 调整PWM值
            if (direction)
            {
                pwm_value += 1;
                if (pwm_value >= 1000)
                {
                    direction = 0;
                }
            }
            else
            {
                pwm_value -= 1;
                if (pwm_value == 0)
                {
                    direction = 1;
                }
            }
            __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, pwm_value);
        }
        else  // 流水灯模式
        {
            // 依次点亮和熄灭LED
            HAL_GPIO_WritePin(LED_PORT[led_index], LED_PIN[led_index], GPIO_PIN_SET);
            HAL_Delay(100);
            HAL_GPIO_WritePin(LED_PORT[led_index], LED_PIN[led_index], GPIO_PIN_RESET);

            led_index++;
            if (led_index >= NUM_LEDS)
            {
                led_index = 0;
            }
        }

        HAL_Delay(10);  // 小延时,避免CPU占用过高
    }
}

使用特权

评论回复
6
合同圣诞节fy|  楼主 | 2024-6-1 08:42 | 只看该作者
代码说明
GPIO初始化:配置LED引脚为输出模式,按键引脚为中断输入模式。
按键中断处理:按键按下时切换模式。
定时器和PWM初始化:配置定时器2用于PWM输出控制LED亮度。
主循环:
根据当前模式执行不同的LED控制逻辑。
呼吸灯模式下,通过PWM调节LED亮度。
流水灯模式下,依次点亮和熄灭LED。
通过以上步骤,可以在STM32上通过按键实现呼吸灯和流水灯两种模式的切换。如果需要更复杂的效果或更高的精度,可以进一步调整定时器配置和PWM参数。

使用特权

评论回复
7
kepe| | 2024-7-31 00:26 | 只看该作者
使用一个变量来存储当前模式:

c
复制代码
typedef enum { MODE_BREATHING, MODE_RUNNING } led_mode_t;
led_mode_t current_mode = MODE_BREATHING;

使用特权

评论回复
8
kepe| | 2024-7-31 00:35 | 只看该作者
在按键中断服务例程中切换模式:

c
复制代码
void EXTIx_IRQHandler(void) {
    if (EXTI_GetITStatus(EXTI_LineX) != RESET) {
        current_mode = (current_mode == MODE_BREATHING) ? MODE_RUNNING : MODE_BREATHING;
        EXTI_ClearITPendingBit(EXTI_LineX);
    }
}

使用特权

评论回复
9
kqh11a| | 2024-8-28 12:22 | 只看该作者
breathe_led 函数能通过调整 PWM 占空比控制 LED 亮度。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

17

主题

54

帖子

0

粉丝