stm32F103用pwm控制led灯的亮度,一个按键用来增加亮度,一个按键用来减少亮度,并用oled显示灯的亮度等级,用keil编写代码
时间: 2024-06-08 22:09:31 浏览: 142
STM32 通过按键控制LED灯亮度
3星 · 编辑精心推荐
以下是基于STM32F103C8T6芯片,使用PWM控制LED灯亮度,两个按键分别用来增加和减少亮度,并在OLED上显示灯的亮度等级的代码。请注意,本代码仅供参考,可能需要根据具体硬件和软件环境进行适当修改。
首先,需要在Keil中创建一个新的工程,并添加以下文件:
- stm32f10x.h
- stm32f10x_gpio.h
- stm32f10x_rcc.h
- stm32f10x_tim.h
- ssd1306.h
- ssd1306.c
接下来,需要进行一些初始化设置:
```c
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_tim.h"
#include "ssd1306.h"
// 定义LED灯连接的GPIO口和引脚
#define LED_GPIO_PORT GPIOA
#define LED_GPIO_PIN GPIO_Pin_1
// 定义按键连接的GPIO口和引脚
#define BTN_INC_GPIO_PORT GPIOA
#define BTN_INC_GPIO_PIN GPIO_Pin_2
#define BTN_DEC_GPIO_PORT GPIOA
#define BTN_DEC_GPIO_PIN GPIO_Pin_3
// 定义PWM输出连接的GPIO口和引脚
#define PWM_GPIO_PORT GPIOA
#define PWM_GPIO_PIN GPIO_Pin_0
// 定义PWM定时器和通道
#define PWM_TIMER TIM2
#define PWM_TIMER_RCC RCC_APB1Periph_TIM2
#define PWM_TIMER_FREQ 72000000
#define PWM_TIMER_CHNL TIM_Channel_1
// 定义OLED连接的I2C接口
#define OLED_I2C I2C1
// 定义亮度等级的最大值和最小值
#define BRIGHTNESS_MAX 100
#define BRIGHTNESS_MIN 0
// 定义当前亮度等级
static uint8_t brightness = 50;
```
接下来,需要进行GPIO和PWM的初始化:
```c
void GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
// 使能GPIO和PWM时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(PWM_TIMER_RCC, ENABLE);
// 配置LED灯连接的GPIO口为推挽输出
GPIO_InitStruct.GPIO_Pin = LED_GPIO_PIN;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(LED_GPIO_PORT, &GPIO_InitStruct);
// 配置按键连接的GPIO口为上拉输入
GPIO_InitStruct.GPIO_Pin = BTN_INC_GPIO_PIN | BTN_DEC_GPIO_PIN;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(BTN_INC_GPIO_PORT, &GPIO_InitStruct);
// 配置PWM输出连接的GPIO口为复用推挽输出
GPIO_InitStruct.GPIO_Pin = PWM_GPIO_PIN;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(PWM_GPIO_PORT, &GPIO_InitStruct);
}
void PWM_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_OCInitTypeDef TIM_OCInitStruct;
// 配置PWM定时器的时钟和分频
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_Period = 99; // PWM频率为720KHz/(99+1)=7.2KHz
TIM_TimeBaseInitStruct.TIM_Prescaler = (PWM_TIMER_FREQ / 72000000) - 1;
TIM_TimeBaseInit(PWM_TIMER, &TIM_TimeBaseInitStruct);
// 配置PWM定时器的输出通道
TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStruct.TIM_Pulse = 0;
TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(PWM_TIMER, &TIM_OCInitStruct);
// 启动PWM定时器
TIM_Cmd(PWM_TIMER, ENABLE);
}
```
然后,需要编写按键检测和亮度控制的代码:
```c
void BTN_Check(void)
{
static uint8_t btn_inc_last = 1;
static uint8_t btn_dec_last = 1;
uint8_t btn_inc_current = GPIO_ReadInputDataBit(BTN_INC_GPIO_PORT, BTN_INC_GPIO_PIN);
uint8_t btn_dec_current = GPIO_ReadInputDataBit(BTN_DEC_GPIO_PORT, BTN_DEC_GPIO_PIN);
// 检测按键是否按下
if ((btn_inc_last == 1) && (btn_inc_current == 0)) // 按键1按下
{
if (brightness < BRIGHTNESS_MAX)
{
brightness++;
}
}
if ((btn_dec_last == 1) && (btn_dec_current == 0)) // 按键2按下
{
if (brightness > BRIGHTNESS_MIN)
{
brightness--;
}
}
// 保存当前按键状态
btn_inc_last = btn_inc_current;
btn_dec_last = btn_dec_current;
}
void LED_SetBrightness(uint8_t level)
{
uint16_t pwm_value = level * 100 / BRIGHTNESS_MAX;
TIM_SetCompare1(PWM_TIMER, pwm_value);
}
void OLED_ShowBrightness(uint8_t level)
{
char buf[16];
sprintf(buf, "Brightness: %d%%", level);
SSD1306_Clear();
SSD1306_GotoXY(0, 0);
SSD1306_Puts(buf, &Font_7x10, SSD1306_COLOR_WHITE);
SSD1306_UpdateScreen(OLED_I2C);
}
```
最后,在主函数中循环调用按键检测和亮度控制的函数,并定时更新OLED上的亮度等级:
```c
int main(void)
{
// 初始化GPIO和PWM
GPIO_Config();
PWM_Config();
// 初始化OLED
SSD1306_Init();
OLED_ShowBrightness(brightness);
while (1)
{
BTN_Check();
LED_SetBrightness(brightness);
OLED_ShowBrightness(brightness);
delay_ms(100);
}
}
```
完整的代码如下:
阅读全文