RT-Thread开发之路(9)— 通过PWM控制液晶屏幕的亮度

RT-Thread开发之路(9)— 通过PWM控制液晶屏幕的亮度

通过PWM控制液晶屏幕的亮度

一、工程准备

在上一个工程:RT-Thread开发之路(8)— 通过TFTLCD液晶屏幕显示数据,我们已经完成了LCD的基本显示,可是我们会发现,LCD屏幕非常的亮,那么可以降低他的亮度吗,接下来我们就通过PWM来控制他的亮度。实际上只要控制他的背光引脚LCD_POWER即可。

二、开启PWM设备

打开board.h文件,找到PWM的配置处,按照其提示配置: 首先,打开【RT-Thread Settings】,找到PWM设备驱动程序,将其选中,然后保存使之生效 通过查看STM32L431的数据手册,可以看到,LCD_POWER即PB15引脚,可以由TIM1和TIM15两个定时器控制,但是TIM1是互补输出引脚,所以我们选择TIM15,在board.h的添加TIM15宏定义

#define BSP_USING_PWM15

接下来使用CubeMx生成HAL_TIM_Base_MspInit()和HAL_TIM_MspPostInit()函数,将SPI以及LCD需要的控制引脚设置为如图所示: 将HAL_TIM_Base_MspInit()修改为HAL_TIM_PWM_MspInit()后,和HAL_TIM_MspPostInit()函数复制到board.c里,这里后其其给的注释不一样,要注意,(可能是还没来得及修改注释)

void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef* tim_baseHandle)

{

if(tim_baseHandle->Instance==TIM15)

{

/* USER CODE BEGIN TIM15_MspInit 0 */

/* USER CODE END TIM15_MspInit 0 */

/* TIM15 clock enable */

__HAL_RCC_TIM15_CLK_ENABLE();

/* USER CODE BEGIN TIM15_MspInit 1 */

/* USER CODE END TIM15_MspInit 1 */

}

}

void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle)

{

GPIO_InitTypeDef GPIO_InitStruct = {0};

if(timHandle->Instance==TIM15)

{

/* USER CODE BEGIN TIM15_MspPostInit 0 */

/* USER CODE END TIM15_MspPostInit 0 */

__HAL_RCC_GPIOB_CLK_ENABLE();

/**TIM15 GPIO Configuration

PB15 ------> TIM15_CH2

*/

GPIO_InitStruct.Pin = GPIO_PIN_15;

GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

GPIO_InitStruct.Pull = GPIO_NOPULL;

GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;

GPIO_InitStruct.Alternate = GPIO_AF14_TIM15;

HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

/* USER CODE BEGIN TIM15_MspPostInit 1 */

/* USER CODE END TIM15_MspPostInit 1 */

}

}

然后打开stm32xxxx_hal_config.h文件,添加#define HAL_TIM_MODULE_ENABLED的注释去掉: 因为配置文件没有定义PWM15输出通道,所以我们需要添加一些配置,打开drives/include/config/目录下的pwm_config文件,添加如下代码,其中.channel可以采用相或的方式设置多个通道的初始化:channel1->0x01,channel2->0x02,channel3->0x04,channel1->0x08

#ifdef BSP_USING_PWM15

#ifndef PWM15_CONFIG

#define PWM15_CONFIG \

{ \

.tim_handle.Instance = TIM15, \

.name = "pwm15", \

.channel = 0x02 \

}

#endif /* PWM15_CONFIG */

#endif /* BSP_USING_PWM15 */

然后编译,很好,报错了,提示找不到TIM17,可是STM32L431RCT6本就没有TIM17, 这可能是一个bug我们直接将其注释掉: 下载运行,在msh下输入list_device,可以看到,pwm15已经注册上去了

三、编写代码,控制LCD背光

在main.c中,包含头文件,

#include "drv_lcd.h"

然后设置PWM15 的参数:

#define PWM_DEV_NAME "pwm15" /* PWM设备名称 */

#define PWM_DEV_CHANNEL 2 /* PWM通道 */

struct rt_device_pwm *pwm_dev; /* PWM设备句柄 */

接下来在main()中写入如下代码:

rt_uint32_t period, pulse;

period = 1000000; /* 周期为0.5ms,单位为纳秒ns */

pulse = 100000; /* PWM脉冲宽度值,单位为纳秒ns */

/* 查找设备 */

pwm_dev = (struct rt_device_pwm *)rt_device_find(PWM_DEV_NAME);

if (pwm_dev == RT_NULL)

{

rt_kprintf("pwm sample run failed! can't find %s device!\n", PWM_DEV_NAME);

return RT_ERROR;

}

/* 设置PWM周期和脉冲宽度默认值 */

rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period, pulse);

/* 使能设备 */

rt_pwm_enable(pwm_dev, PWM_DEV_CHANNEL);

还有一点要注意的是,将drv_lcd.c文件中lcd_gpio_init()中对LCD_PWR_PIN的初始化注释掉,不要设置其为通用推挽输出了, 然后编译下载运行,可以观察到其屏幕暗下来了:

四、优化代码

我们将lcd的代码放到一个文件夹里,新建一个线程,在线程中通过检测按键的按下来调节LCD的亮度,代码如下:

#include

#include

#include

#include "drv_lcd.h"

#define KEY1_PIN GET_PIN(B, 2)

#define KEY2_PIN GET_PIN(B, 3)

#define PWM_DEV_NAME "pwm15" /* PWM设备名称 */

#define PWM_DEV_CHANNEL 2 /* PWM通道 */

struct rt_device_pwm *pwm_dev; /* PWM设备句柄 */

/* 定义一个LCD线程句柄结构体指针 */

static rt_thread_t app_lcd_thread = RT_NULL;

void brightness_ctrl(rt_uint32_t bright)

{

if(bright > 100)

bright = 100;

/* 设置PWM周期和脉冲宽度 */

rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, 1000000, bright * 10000);

}

static void app_lcd_thread_entry(void *parameter)

{

rt_uint32_t ctrl_value = 10;

static int key_up = 1; /* 按键松开标志 */

rt_pin_mode(KEY1_PIN, PIN_MODE_INPUT_PULLUP);

rt_pin_mode(KEY2_PIN, PIN_MODE_INPUT_PULLUP);

/* 查找设备 */

pwm_dev = (struct rt_device_pwm *)rt_device_find(PWM_DEV_NAME);

if (pwm_dev == RT_NULL)

{

rt_kprintf("pwm run failed! can't find %s device!\n", PWM_DEV_NAME);

return ;

}

/* 使能设备 */

rt_pwm_enable(pwm_dev, PWM_DEV_CHANNEL);

brightness_ctrl(ctrl_value);

/* 设置背景色和前景色 */

lcd_set_color(WHITE, BLACK);

/* 在 LCD 上显示字符 */

lcd_show_string(10, 60, 32, "Hello!");

lcd_show_string(10, 100, 32, "RT-Thread");

/* 在 LCD 上画线 */

lcd_draw_line(0, 69+16+24+32, 240, 69+16+24+32);

/* 在 LCD 上画一个同心圆 */

lcd_draw_point(120, 194);

for (int i = 0; i < 46; i += 4)

{

lcd_draw_circle(120, 194, i);

}

lcd_show_string(200, 0, 24, "%3d",ctrl_value);

while (1)

{

/* 检测按键是否按下 */

if (key_up && ((rt_pin_read(KEY1_PIN) == 0) || (rt_pin_read(KEY2_PIN) == 0)) )

{

rt_thread_mdelay(50); /* 延时50ms消抖*/

key_up = 0;

if(rt_pin_read(KEY1_PIN) == 0)

{

rt_kprintf("key1 press \r\n");

if(ctrl_value > 4)

ctrl_value = ctrl_value -5;

brightness_ctrl(ctrl_value);

rt_kprintf("brightness level %d \r\n",ctrl_value);

}

else if(rt_pin_read(KEY2_PIN) == 0)

{

rt_kprintf("key2 press \r\n");

if(ctrl_value < 96)

ctrl_value = ctrl_value +5;

brightness_ctrl(ctrl_value);

rt_kprintf("brightness level %d \r\n",ctrl_value);

}

lcd_show_string(200, 0, 24, "%3d",ctrl_value);

}

else if((rt_pin_read(KEY1_PIN) == 1) && (rt_pin_read(KEY2_PIN) == 1))

{

key_up = 1; /* 按键已松开 */

}

rt_thread_mdelay(100);

}

}

static int app_lcd_init(void)

{

rt_err_t rt_err;

/* 创建LCD线程*/

app_lcd_thread = rt_thread_create("app_lcd thread",

app_lcd_thread_entry, RT_NULL, 2048, 6, 10);

/* 如果获得线程控制块,启动这个线程 */

if (app_lcd_thread != RT_NULL)

rt_err = rt_thread_startup(app_lcd_thread);

else

rt_kprintf("app_lcd_thread create failure !!! \n");

/* 判断线程是否启动成功 */

if( rt_err == RT_EOK)

rt_kprintf("app_lcd_thread startup ok. \n");

else

rt_kprintf("app_lcd_thread startup err. \n");

return rt_err;

}

INIT_APP_EXPORT(app_lcd_init);

可以实现需要的效果

相关推荐

2022世界杯观赛指南,请查收
温水煮青蛙是什么意思优质
刘涛生肖属什么,刘涛是什么属相