stm32pwm呼吸灯按键
时间: 2025-06-04 09:58:03 浏览: 7
### STM32 PWM 呼吸灯效果结合按键控制
为了实现基于STM32的PWM呼吸灯效果并结合按键控制,可以通过配置定时器生成PWM信号,并利用外部中断检测按键状态。以下是完整的解决方案:
#### 配置说明
1. **PWM配置**: 使用TIM3作为PWM输出源,通过调整占空比实现LED亮度的变化。
2. **GPIO初始化**: 将指定端口配置为PWM输出模式和输入模式(用于按键检测)。
3. **按键处理**: 利用EXTI外设捕获按键事件,切换呼吸灯的工作状态。
---
#### 示例代码
以下是一个完整的示例程序,展示如何实现该功能:
```c
#include "stm32f10x.h"
// 定义全局变量
uint8_t isBreathing = 1; // 是否执行呼吸灯效果标志位
void TIM3_PWM_Init(void);
void GPIO_Configuration(void);
void EXTI_Key_Init(void);
int main(void) {
// 初始化硬件资源
GPIO_Configuration();
TIM3_PWM_Init();
EXTI_Key_Init();
uint16_t dutyCycle = 0;
int direction = 1;
while (1) {
if (isBreathing) { // 如果允许呼吸灯效果
if ((direction == 1 && dutyCycle >= 99) || (direction == -1 && dutyCycle <= 1)) {
direction *= -1; // 反转方向
}
dutyCycle += direction;
// 动态修改TIM3通道1的CCR寄存器值
TIM_SetCompare1(TIM3, dutyCycle);
delay_ms(20); // 调整延时时间以改变呼吸频率
} else {
TIM_SetCompare1(TIM3, 50); // 固定占空比为50%
delay_ms(100);
}
}
}
/**
* @brief 配置TIM3为PWM模式
*/
void TIM3_PWM_Init() {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Period = 100 - 1; // 自动重装载值
TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1; // 预分频器
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_Pulse = 0; // 初始占空比为0%
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
TIM_Cmd(TIM3, ENABLE);
}
/**
* @brief 配置GPIO引脚
*/
void GPIO_Configuration() {
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
// 配置PA6为TIM3_CH1复用功能
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 配置PC13为按键输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOC, &GPIO_InitStructure);
}
/**
* @brief 配置按键外部中断
*/
void EXTI_Key_Init() {
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
AFIO_EXTICheckConfig(AFIO_EXTISourcePortC, AFIO_EXTISourcePin13);
EXTI_InitStructure.EXTI_Line = EXTI_Line13;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/**
* @brief 外部中断服务函数
*/
void EXTI15_10_IRQHandler(void) {
if (EXTI_GetITStatus(EXTI_Line13) != RESET) {
isBreathing ^= 1; // 切换呼吸灯工作状态
EXTI_ClearITPendingBit(EXTI_Line13);
}
}
```
---
#### 关键点解析
1. **PWM动态调整**
在`while`循环中,通过逐步增加或减少`dutyCycle`变量来模拟呼吸灯的效果[^1]。
2. **按键中断处理**
当按下按键时触发外部中断,切换`isBreathing`的状态,从而暂停或恢复呼吸灯效果[^2]。
3. **延迟函数**
`delay_ms()` 函数需自行定义,通常可通过SysTick或其他定时器实现。
---
###
阅读全文
相关推荐

















