c语言写使用stm32芯片,利用按键来控制led灯呼吸速度,并将pwm的频率和实时占空比显示在OLED显示屏上
时间: 2025-01-19 11:16:43 浏览: 104
使用STM32芯片控制LED灯的呼吸效果,并通过按键调整呼吸速度,同时将PWM的频率和实时占空比显示在OLED显示屏上,可以按照以下步骤进行:
### 硬件连接
1. **STM32开发板**:确保已经正确连接了LED灯、按键和OLED显示屏。
2. **LED灯**:连接到STM32的一个PWM输出引脚。
3. **按键**:连接到STM32的一个GPIO输入引脚。
4. **OLED显示屏**:通过I2C或SPI接口连接到STM32。
### 软件实现
1. **初始化GPIO、PWM和OLED显示屏**。
2. **配置按键中断**,用于检测按键按下事件。
3. **编写PWM控制函数**,根据按键输入调整PWM占空比。
4. **编写OLED显示函数**,实时更新显示PWM的频率和占空比。
### 示例代码
以下是一个简单的示例代码,演示如何实现上述功能:
```c
#include "stm32f1xx_hal.h"
#include "ssd1306.h"
#include "fonts.h"
#define BUTTON_PIN GPIO_PIN_0
#define BUTTON_GPIO_PORT GPIOA
#define LED_PIN GPIO_PIN_1
#define LED_GPIO_PORT GPIOA
volatile uint32_t pwm_frequency = 1000; // 初始PWM频率
volatile uint32_t pwm_duty_cycle = 50; // 初始占空比
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM2_Init(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM2_Init();
ssd1306_Init();
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
while (1)
{
// 更新OLED显示
char buffer[16];
sprintf(buffer, "Freq: %lu Hz", pwm_frequency);
ssd1306_SetCursor(2, 0);
ssd1306_WriteString(buffer, Font_11x18, White);
sprintf(buffer, "Duty: %lu%%", pwm_duty_cycle);
ssd1306_SetCursor(2, 20);
ssd1306_WriteString(buffer, Font_11x18, White);
ssd1306_UpdateScreen();
}
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == BUTTON_PIN)
{
// 按键按下,调整PWM占空比
pwm_duty_cycle += 10;
if (pwm_duty_cycle > 100)
pwm_duty_cycle = 0;
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, (pwm_duty_cycle * (htim2.Init.Period + 1)) / 100);
}
}
static void MX_TIM2_Init(void)
{
__HAL_RCC_TIM2_CLK_ENABLE();
TIM_HandleTypeDef htim2;
htim2.Instance = TIM2;
htim2.Init.Prescaler = 72 - 1; // 1 MHz
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 1000 - 1; // 1 kHz
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_PWM_Init(&htim2);
TIM_OC_InitTypeDef sConfigOC = {0};
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = (pwm_duty_cycle * (htim2.Init.Period + 1)) / 100;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1);
}
static void MX_GPIO_Init(void)
{
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
// 配置按键引脚为输入
GPIO_InitStruct.Pin = BUTTON_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(BUTTON_GPIO_PORT, &GPIO_InitStruct);
// 配置LED引脚为复用推挽输出
GPIO_InitStruct.Pin = LED_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LED_GPIO_PORT, &GPIO_InitStruct);
// 配置中断优先级并使能
HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI0_IRQn);
}
void SystemClock_Config(void)
{
// 系统时钟配置代码
}
```
### 代码说明
1. **初始化部分**:初始化HAL库、GPIO、PWM和OLED显示屏。
2. **主循环**:实时更新OLED显示,显示当前PWM频率和占空比。
3. **中断回调函数**:检测按键按下事件,调整PWM占空比。
4. **PWM初始化**:配置TIM2定时器为PWM模式,并设置初始频率和占空比。
5. **GPIO初始化**:配置按键引脚为输入,LED引脚为复用推挽输出,并使能中断。
### 注意事项
1. **库文件**:确保在项目中正确添加了STM32 HAL库和SSD1306 OLED显示屏驱动库。
2. **中断优先级**:根据实际需求调整中断优先级。
3. **系统时钟配置**:根据具体的STM32型号和硬件配置调整系统时钟配置。
阅读全文