思澈SDK的显示框架介绍¶
简介¶
思澈的显示框架是基于rt_device框架的,具有如下特点:
同一个屏幕驱动、TP驱动、背光驱动可以在不同的开发板之间复用
同一个开发板可以通过menuconfig选择不同的屏幕模组
支持同时兼容多个屏幕驱动、TP驱动,根据ID来区分
这样设计确实提高了复用度,但也给屏幕模组驱动配置带来了分散性的问题:
屏幕模组的上下电、复位接口、pinmux的设置、背光用到的pwm等程序都与开发板的相关联(类似屏驱模组的BIOS)
屏幕驱动、TP驱动、背光驱动的编写需要基于上面提供的这些宏定义、IO接口来实现
最终将实现的屏幕驱动、TP驱动、背光驱动汇集成一个menuconfig菜单,供开发板选择。
目录结构¶
此处以eh-lb525板子,屏幕模组(nv3051f屏驱+gt911触控驱动), aw9364背光驱动芯片 为例:
SDK
│
├──customer
│ ├──boards
│ │ ├──eh-lb52xu #eh-lb525板子的板级目录
│ │ │ ├──bsp_lcd_tp.c #屏幕和TP上下电、复位接口实现、通信接口的pinmux配置等
│ │ │ └──Kconfig.board #屏幕和TP上下电、复位管脚的定义、pwm背光引脚的定义
│ │ │
│ │ │
│ │ └──Kconfig_lcd #屏幕模组的menuconfig菜单定义(汇集屏驱、TP驱动、背光类型、以及屏幕模组分辨率的宏定义)
│ │
│ │
│ └──peripherals
│ ├──nv3051f1 #nv3051f1屏幕驱动的目录
│ │ ├──nv3051f1.c #屏驱的实现
│ │ └──SConscript #编译链接文件
│ │
│ ├──gt911 #gt911触控驱动的目录
│ │ ├──gt911.c #触控驱动的c文件
│ │ ├──gt911.h #触控驱动的头文件
│ │ └──SConscript #编译链接文件
| |
│ ├──aw9364 #aw9364背光驱动芯片,背光设备“lcdlight”
│ │ ├──aw9364.c #背光驱动芯片的c文件
│ │ ├──aw9364.h #背光驱动芯片的头文件
│ │ └──SConscript #编译链接文件
│ │
│ └──Kconfig #屏驱IC、触控IC、背光IC的宏定义处
│
├──rtos
│ └──rtthread
│ └──bsp
│ └──sifli
│ └──drivers
│ ├──drv_touch.c #TP驱动管理层,对应用层提供“touch”设备
│ └──drv_lcd.c #LCD驱动的管理层,对应用层提供“lcd”设备
│
│
└──examples #示例应用
└──rt_driver #屏幕调试工程, 调用“lcd”和“touch"设备
屏幕部分¶
屏幕框架图¶
图内各项解释:
驱动层(drv_lcd.c) — 实现了名为“lcd”的rt_device,供上层操作屏幕。
中间绿色部分具体的驱动代码(为客户添加屏幕驱动的主要代码)
板级IO接口文件(bsp_lcd_tp.c, 或 drv_io.c) — 为屏幕驱动提供统一的上电、下电、复位的接口。
背光设备”lcdlight" — 为屏幕驱动提供统一的背光控制接口
HAL层(bf0_hal_lcdc.c) — 为屏幕驱动提供基本统一的参数配置、LCD寄存器读写等接口
注册屏驱到系统¶
思澈的屏驱框架支持同时注册多个屏驱到系统,通过宏LCD_DRIVER_EXPORT2
生成一个特殊段名的变量,链接到一起。
在nv3051f1.c中通过LCD_DRIVER_EXPORT2将屏驱的回调函数注册到系统,每个函数的详细解析请参考屏驱回调函数:
static const LCD_DrvOpsDef LCD_drv =
{
LCD_Init, //【必选】,屏驱初始函数(包括复位,初始化程序等)
LCD_ReadID, //【必选】,屏幕在位检测函数
LCD_DisplayOn, //【必选】,屏幕打开
LCD_DisplayOff, //【必选】,屏幕关闭
LCD_SetRegion, //【必选】,设置屏幕接受数据时的区域(2A,2B 的区域)
LCD_WritePixel, // 可选,写一个像素点到屏幕上
LCD_WriteMultiplePixels, //【必选】,写批量像素点到屏幕上
LCD_ReadPixel, // 可选,读屏幕上的一个像素点数据,返回像素的RGB值
LCD_SetColorMode, // 可选,切换输出给屏幕的颜色格式
LCD_SetBrightness, // 可选,设置屏幕的亮度
LCD_IdleModeOn, // 可选,进入待机显示模式(低功耗模式)
LCD_IdleModeOff, // 可选,退出待机显示模式(低功耗模式)
LCD_Rotate, // 可选,旋转屏幕一定角度
LCD_TimeoutDbg, // 可选,批量送数超时后,屏幕自检
LCD_TimeoutReset, // 可选,批量送数超时后,屏幕复位
LCD_ESDCheck, // 可选,屏幕定时ESD检测
};
LCD_DRIVER_EXPORT2(nv3051f1, LCD_ID, &lcdc_int_cfg, &LCD_drv,2);
屏幕在位检测¶
当系统注册了多个屏幕驱动时,如何判断使用哪个屏驱来驱动当前屏幕,就需要通过屏幕在位检测。方法是先调用每个屏驱的LCD_Init函数,让其初始化,然后在调用LCD_ReadID函数,如果LCD_ReadID函数返回的值与LCD_ID值相同时,认为屏幕在位,则使用该屏驱。否则继续调用下一个屏驱的LCD_Init和LCD_ReadID。
LCD_ID是通过LCD_DRIVER_EXPORT2传入的参数
屏幕刷新的像素对齐¶
有些屏驱的刷新区域有像素对齐要求,思澈的屏驱框架可以支持设置像素对齐(如果有的屏幕行列对齐要求不一致,则用最大的值。比如某屏幕行对齐要求是2,列对齐要求是4,则取4)。
屏驱IC的更新区域像素对齐要求一般在0x2A(起止列)和0x2B(起止行) 这个2个寄存器的描述里面, 如下图的这个IC行列都是要求2像素对齐:

触控部分¶
触控(TP)框架图¶
TP驱动注册到系统的接口¶
在gt911.c中通过INIT_COMPONENT_EXPORT注册初始化函数rt_tp_device_init,然后在rt_tp_device_init里面通过函数rt_touch_drivers_register,将TP驱动注册到系统。
static struct touch_drivers driver;
static struct touch_ops ops =
{
read_point, //TP数据读取回调函数
init, //TP初始化回调函数
deinit //TP去初始化回调函数
};
static int rt_tp_device_init(void)
{
driver.probe = probe; //TP在位检测回调函数
driver.ops = &ops;
driver.user_data = RT_NULL;
driver.isr_sem = rt_sem_create("gt911", 0, RT_IPC_FLAG_FIFO); //TP数据读取信号量
rt_touch_drivers_register(&driver); //注册到系统TP驱动框架
return 0;
}
INIT_COMPONENT_EXPORT(rt_tp_device_init); //注册初始化函数
背光部分¶
非自发光的屏幕一般需要背光,目前屏幕的背光驱动都通过各种办法,实现了一个“lcdlight”的rt_device设备,然后统一在屏驱的回调函数LCD_SetBrightness内使用。
目前支持2种模式:
PWM直驱背光,芯片直接输出PWM波形,直驱背光
外部背光驱动, 通过GPIO控制外部背光驱动芯片输出PWM波形,来驱动背光
PWM直驱背光¶
这种设备已经在drv_lcd.c里面注册了“lcdlight”的rt_device设备,见rt_hw_lcd_backlight_init函数。
使用的PWM频率默认是1KHz。
里面会用到2个宏LCD_PWM_BACKLIGHT_INTERFACE_NAME
和LCD_PWM_BACKLIGHT_CHANEL_NUM
,分别指定了PWM的设备名称和channel号,这2个宏一般在Kconfig.board里面定义。
注意:需要在menuconfig里面使能LCD_PWM_BACKLIGHT_INTERFACE_NAME
指定的pwm rt_device,例如指定"pwm2"时需要选择:
通过在屏幕模组里面选择宏LCD_USING_PWM_AS_BACKLIGHT来使用这种类型的背光。
外部背光驱动¶
例如aw9364.c,是在sif_aw9364_init函数里面注册的“lcdlight”的rt_device设备。
里面宏LCD_BACKLIGHT_CONTROL_PIN
来指定使用哪个GPIO来控制aw9364。这个宏也在Kconfig.board里面定义。
通过在屏幕模组里面选择宏BL_USING_AW9364来使用这种类型的背光。