完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
RTOS 提供了一套完整的屏幕驱动,支持 RGB, i8080, SPI, DBI 格式的屏幕。
(1)RGB 接口 RGB接口在全志平台又称HV接口(Horizontal同步和Vertical同步)。有些LCD屏支持高级的功能比如 gamma,像素格式的设置等,但是 RGB 协议本身不支持图像数据之外的传输,所以无法通过 RGB 管脚进行对 LCD 屏进行配置,所以拿到一款 RGB 接口屏,要么不需要初始化命令,要么这个屏会提供额外的管脚给 SoC 来进行配置,比如 SPI 和 I2C 等。RGB 屏幕有许多格式,不同的位宽,不同的时钟周期。下表是位宽与时钟周期的区别。 位宽时钟周期数颜色数量和格式并行串行 RGB 24 bits1 cycle16.7M colors, RGB888并行 18 bits1 cycle262K colors, RGB666并行 16 bits1 cycle65K colors, RGB565并行 6 bits3 cycles262K colors, RGB666串行 6 bits3 cycles65K colors, RGB565串行 串行 RGB 是相对于并行 RGB 来说,而并不是说它只用一根线来发数据,只要通过多个时钟周期才能把一个像素的数据发完,那么这样的 RGB 接口就是串行 RGB。 (2)I8080 屏幕 Intel 8080 接口屏(又称 MCU 接口),很老的协议,一般用在分辨率很小的屏上。 管脚的控制脚有6种:
SPI LCD 是使用 SPI 总线传输图像数据的屏幕,只会出现在很低分辨率的屏幕上。一般来说开屏前都需要初始化操作。 适配 LCD 屏幕的步骤
code">lichee/rtos‑hal/hal/source/disp2/disp/lcd/default_panel.cLCD 面板特化驱动部分 LCD 面板需要写 IIC,SPI初始化,或者有特殊的上下电要求,需要编写特化的屏幕驱动 code">lichee/rtos‑hal/hal/source/disp2/disp/lcd/配置文件其中 “芯片型号” 例如 r128s3,和 “板子名称” 例如 pro,请根据实际替换。 code">board/芯片型号/板子名称/configs/屏幕驱动配置lcd 相关代码包含在 disp 驱动模块中,执行命令进入 menuconfig 配置主界面,并按以下步骤操作: 添加新屏添加一款新屏幕通常需要以下步骤:
code">struct __lcd_panel default_panel = { /* panel driver name, must mach the lcd_drv_name in sys_config.fex */ .name = "default_lcd", .func = { .cfg_panel_info = LCD_cfg_panel_info, .cfg_open_flow = LCD_open_flow, .cfg_close_flow = LCD_close_flow, },};
函数原型: code">static __s32 LCD_open_flow(__u32 sel)函数常用内容为: code">static __s32 LCD_open_flow(__u32 sel){ LCD_OPEN_FUNC(sel, LCD_power_on,10); LCD_OPEN_FUNC(sel, LCD_panel_init, 50); LCD_OPEN_FUNC(sel, sunxi_lcd_tcon_enable, 100); LCD_OPEN_FUNC(sel, LCD_bl_open, 0); return 0;}如上,调用四次 LCD_OPEN_FUNC 注册了四个回调函数,对应了四个开屏流程, 先注册先执行。实际上注册多少个函数是用户自己的自由,只要合理即可。
函数原型: code">void LCD_OPEN_FUNC(__u32 sel, LCD_FUNC func, __u32 delay)参数说明: func 是一个函数指针,其类型是:void (*LCD_FUNC) (__u32 sel),用户自己定义的函数必须也要用统一的形式。比如: code">void user_defined_func(__u32 sel){ // do something}delay 是执行该步骤后,再延迟的时间,时间单位是毫秒。 LCD_OPEN_FUNC 的第二个参数是前后两个步骤的延时长度,单位 ms,注意这里的数值请按照屏手册规定去填,乱填可能导致屏初始化异常或者开关屏时间过长,影响用户体验。 LCD_close_flow与 LCD_open_flow 对应的是 LCD_close_flow,它用于注册关屏函数。使用 LCD_CLOSE_FUNC 进行函数注册,先注册先执行。这里只是注册回调函数,不是立刻执行。 code">static s32 LCD_close_flow(u32 sel){ /* close lcd backlight, and delay 0ms */ LCD_CLOSE_FUNC(sel, LCD_bl_close, 0); /* close lcd controller, and delay 0ms */ LCD_CLOSE_FUNC(sel, sunxi_lcd_tcon_disable, 50); /* open lcd power, than delay 200ms */ LCD_CLOSE_FUNC(sel, LCD_panel_exit, 100); /* close lcd power, and delay 500ms */ LCD_CLOSE_FUNC(sel, LCD_power_off, 0); return 0;}
函数原型: code">static void LCD_cfg_panel_info(__panel_extend_para_t *info)TCON 的扩展参数只能在屏文件中配置,参数的定义: LCD_FRMLcd Frame Rate Modulator, FRM 是解决由于 PIN 减少导致的色深问题,有些 LCD 屏的像素格式是 18bit 色深(RGB666)或 16bit 色深(RGB565),建议打开 FRM 功能,通过 dither 的方式弥补色深,使显示达到 24bit 色深(RGB888)的效果。如下图所示,上图是色深为 RGB66 的 LCD 屏显示,下图是打开 dither 后的显示,打开 dither 后色彩渐变的地方过度平滑。 参数设置相应值对应含义为: code">0:RGB888 ‑‑ RGB888 direct1:RGB888 ‑‑ RGB666 dither2:RGB888 ‑‑ RGB565 dither LCD_GAMMA_ENLcd Gamma Correction Enable,设置相应值的对应含义为: code">0:LCD 的 Gamma 校正功能关闭1:LCD 的 Gamma 校正功能开启设置为 1 时,需要在屏驱动中对 lcd_gamma_tbl[256] 进行赋值。 LCD_CMAP_ENLcd Color Map Enable, 设置为 1 时,需要对 lcd_cmap_tbl [2][3][4] 进行赋值 Lcd Color Map Table。 每个像素有 R、G、B 三个单元,每四个像素组成一个选择项,总共有 12 个可选。数组第一维表示奇偶行,第二维表示像素的 RGB,第三维表示第几个像素,数组的内容即表示该位置映射到的内容。 LCD CMAP 是对像素的映射输出功能,只有像素有特殊排布的 LCD 屏才需要配置。 LCD CMAP 定义每行的 4 个像素为一个总单元,每个像素分 R、G、B 3 个小单元,总共有 12 个小单元。通过 lcd_cmap_tbl 定义映射关系,输出的每个小单元可随意映射到 12 个小单元之一。 code">__u32 lcd_cmap_tbl[2][3][4] = { { {LCD_CMAP_G0,LCD_CMAP_B1,LCD_CMAP_G2,LCD_CMAP_B3}, {LCD_CMAP_B0,LCD_CMAP_R1,LCD_CMAP_B2,LCD_CMAP_R3}, {LCD_CMAP_R0,LCD_CMAP_G1,LCD_CMAP_R2,LCD_CMAP_G3}, }, { {LCD_CMAP_B3,LCD_CMAP_G2,LCD_CMAP_B1,LCD_CMAP_G0}, {LCD_CMAP_R3,LCD_CMAP_B2,LCD_CMAP_R1,LCD_CMAP_B0}, {LCD_CMAP_G3,LCD_CMAP_R2,LCD_CMAP_G1,LCD_CMAP_R0}, },};如上,上三行代表奇数行的像素排布,下三行代表偶数行的像素排布; 每四个像素为一个单元,第一列代表每四个像素的第一个像素映射,第二列代表每四个像素的第二个像素映射,以此类推。 如上的定义,像素的输出格式如下图所示。 LCD_RB_SWAP调换 TCON 模块 RGB 中的 R 分量和 B 分量。 code">0:不变1:调换R分量和B分量需要 gamma 校正,或色彩映射,在 sys_config.fex 中将相应模块的 enable 参数置 1,lcd_gamma_en, lcd_cmap_en,并且填充 3 个系数表,lcd_gamma_tbl, lcd_cmap_tbl,注意的是:gamma,模板提供了 18 段拐点值,然后再插值出所有的值(255 个)。可以往相应表格内添加子项以补充细节部分。cmap_tbl 的大小是固定的,不能减小或增加表的大小。最终生成的 gamma 表项是由 rgb 三个 gamma 值组成的,各占 8bit。目前提供的模板中,三个 gamma 值是相同的。 延时函数函数原型 (毫秒级别) code">s32 sunxi_lcd_delay_ms(u32 ms)(微秒级别) code">s32 sunxi_lcd_delay_us(u32 us)图像数据使能函数打开 LCD 控制器,开始刷新 LCD 显示 code">void sunxi_lcd_tcon_enable(u32 screen_id)关闭 LCD 控制器,停止刷新数据 code">void sunxi_lcd_tcon_disable(u32 screen_id)背光控制函数打开背光,操作的是 sys_config.fex 中 lcd_bl 配置的 gpio。 code">void sunxi_lcd_backlight_enable(u32 screen_id)关闭背光,操作的是 sys_config.fex 中 lcd_bl 配置的 gpio。 code">void sunxi_lcd_backlight_disable(u32 screen_id)打开PWM背光,打开时 pwm 将往外输出 pwm 波形。对应的是lcd_pwm_ch 所对应的那一路 pwm。 code">s32 sunxi_lcd_pwm_enable(u32 screen_id)关闭PWM背光,打开时 pwm 将往外输出 pwm 波形。对应的是 lcd_pwm_ch 所对应的那一路 pwm。 code">s32 sunxi_lcd_pwm_disable(u32 screen_id)电源控制函数打开 Lcd 电源,操作的是 sys_config.fex 中的 lcd_power/lcd_power1/lcd_power2。( pwr_id标识电源索引) code">void sunxi_lcd_power_enable(u32 screen_id, u32 pwr_id)关闭 Lcd 电源,操作的是 sys_config.fex 中的 lcd_power/lcd_power1/lcd_power2。( pwr_id标识电源索引) code">void sunxi_lcd_power_disable(u32 screen_id, u32 pwr_id)
函数原型 code">s32 sunxi_lcd_pin_cfg(u32 screen_id, u32 bon)配置 lcd 的 data/clk 等 pin,对应 sys_config.fex 中的 lcdd0‑lcdd23/lcddclk/lcdde/lcdhsync/lcdvsync。 参数:
SUNXI_LCD_CPU_WRITE设定 CPU 屏的指定寄存器为指定的值。 函数原型 code">void sunxi_lcd_cpu_write(__u32 sel, __u32 index, __u32 data){ sunxi_lcd_cpu_write_index(sel, index); sunxi_lcd_cpu_wirte_data(sel, data);}实现了 8080 总线上的两个写操作
code">void sunxi_lcd_cpu_write_index(__u32 sel,__u32 index)参数:
code">void sunxi_lcd_cpu_write_data(__u32 sel, __u32 data)参数:
code">s32 tcon0_cpu_rd_24b_data(u32 sel, u32 index, u32 *data, u32 size)参数:
code">s32 sunxi_lcd_gpio_set_value(u32 screen_id, u32 io_index, u32 value)参数:
SUNXI_LCD_GPIO_SET_DIRECTION设置 LCD_GPIO PIN 脚为输入或输出模式 code">s32 sunxi_lcd_gpio_set_direction(u32 screen_id, u32 io_index, u32 direction)参数:
使用 SPI 初始化一般使用 GPIO 模拟的方式初始化 SPI 屏幕,其中 SPI 模拟如下所示 code">#define spi_scl_1 sunxi_lcd_gpio_set_value(0, 3, 1) // 配置 lcd_gpio_3 为 SCL#define spi_scl_0 sunxi_lcd_gpio_set_value(0, 3, 0)#define spi_sdi_1 sunxi_lcd_gpio_set_value(0, 2, 1) // 配置 lcd_gpio_2 为 SDI#define spi_sdi_0 sunxi_lcd_gpio_set_value(0, 2, 0)#define spi_cs_1 sunxi_lcd_gpio_set_value(0, 1, 1) // 配置 lcd_gpio_1 为 CS#define spi_cs_0 sunxi_lcd_gpio_set_value(0, 1, 0)static void spi_write_cmd(u8 value){ int i; spi_cs_0; spi_scl_0; spi_sdi_0; spi_scl_1; spi_scl_0; for (i = 0; i < 8; i++) { if (value & 0x80) spi_sdi_1; else spi_sdi_0; value <<= 1; spi_scl_1; spi_scl_0; } spi_cs_1;}static void spi_write_data(u8 value){ int i; spi_cs_0; spi_scl_0; spi_sdi_1; spi_scl_1; spi_scl_0; for (i = 0; i < 8; i++) { if (value & 0x80) spi_sdi_1; else spi_sdi_0; value <<= 1; spi_scl_1; spi_scl_0; } spi_cs_1;}然后就可以调用 spi_write_cmd(u8 value) 与 spi_write_data(u8 value) 函数写入初始化命令。 也可以使用 硬件 SPI 初始化屏幕,代码如下 code">static int spi_init(void){ int ret = ‑1; struct spi_master *master; master = spi_busnum_to_master(1); if (!master) { lcd_fb_wrn("fail to get mastern"); goto OUT } spi_device = spi_alloc_device(master); if (!spi_device) { lcd_fb_wrn("fail to get spi devicen"); goto OUT; } spi_device‑> bits_per_word = 8; spi_device‑> max_speed_hz = 50000000; /*50MHz*/ spi_device‑> mode = SPI_MODE_0; ret = spi_setup(spi_device); if (ret) { lcd_fb_wrn("Faile to setup spin"); goto FREE; } lcd_fb_inf("Init spi1:bits_per_word:%d max_speed_hz:%d mode:%dn", spi_device‑> bits_per_word, spi_device‑> max_speed_hz, spi_device‑> mode); ret = 0; goto OUT;FREE: spi_master_put(master); kfree(spi_device); spi_device = NULL;OUT: return ret;}static int comm_out(unsigned int sel, unsigned char cmd){ struct spi_transfer t; if (!spi_device) return ‑1; DC(sel, 0); memset(&t, 0, sizeof(struct spi_transfer)); t.tx_buf = &cmd; t.len = 1; t.bits_per_word = 8; t.speed_hz = 24000000; return spi_sync_transfer(spi_device, &t, 1);}首先调用 spi_init 函数对 spi 硬件进行初始化,spi_init 函数可以分为几个步骤,第一获取 master;根据实际的硬件连接,选择 spi(代码中选择了 spi1),如果这一步返回错误说 spi 没有配置好。第二步设置 spi device,这里包括最大速度,spi 传输模式,以及每个字包含的比特数。最后调用 spi_setup 完成 master 和 device 的关联。 comm_out 是一个 spi 传输的例子,核心就是 spi_sync_transfer 函数。 并行 RGB 接口当我们配置并行 RGB 接口时,在配置里面并不需要区分是 24 位,18 位和 16 位,最大位宽是哪种是参考 pin mux 表格,如果 LCD 屏本身支持的位宽比 SoC 支持的位宽少,当然只能选择少的一方。 因为不需要初始化,RGB 接口极少出现问题,重点关注 lcd 的 timing 的合理性,也就是lcd_ht,lcd_hspw,lcd_hbp,lcd_vt,lcd_vspw 和 lcd_vbp 这个属性的合理性。 下面是典型并行 RGB 接口 sys_config.fex 配置示例,其中用空行把配置分成几个部分 code">;--------------------------------------------------;Parallel RGB LCD;--------------------------------------------------[lcd0]; Part 1lcd_used = 1lcd_driver_name = "default_lcd"; Part 2lcd_if = 0; Part 3lcd_x = 480lcd_y = 480lcd_width = 150lcd_height = 94lcd_rb_swap = 0lcd_dclk_freq = 21lcd_hv_clk_phase = 1; Part 4lcd_backlight = 150lcd_pwm_used = 1lcd_pwm_ch = 5lcd_pwm_freq = 5000lcd_pwm_pol = 1; Part 5lcd_hbp = 80lcd_ht = 648lcd_hspw = 8lcd_vbp = 10lcd_vt = 522lcd_vspw = 2lcd_lvds_if = 0lcd_lvds_colordepth = 1lcd_lvds_mode = 0lcd_frm = 1lcd_io_phase = 0x0000lcd_gamma_en = 0lcd_bright_curve_en = 0lcd_cmap_en = 0deu_mode = 0lcdgamma4iep = 22smart_color = 90; Part 6;LCD_D2-LCD_D7lcd_gpio_4 = port:PA00<8><0><3><0>lcd_gpio_5 = port:PA01<8><0><3><0>lcd_gpio_6 = port:PA02<8><0><3><0>lcd_gpio_7 = port:PA03<8><0><3><0>lcd_gpio_8 = port:PA04<8><0><3><0>lcd_gpio_9 = port:PA05<8><0><3><0>;LCD_D10-LCD_D15lcd_gpio_10 = port:PA11<8><0><3><0>lcd_gpio_11 = port:PA10<8><0><3><0>lcd_gpio_12 = port:PA08<8><0><3><0>lcd_gpio_13 = port:PA07<8><0><3><0>lcd_gpio_14 = port:PA06<8><0><3><0>lcd_gpio_15 = port:PA09<8><0><3><0>;LCD_D18-LCD_D23lcd_gpio_16 = port:PA12<8><0><3><0>lcd_gpio_17 = port:PA13<8><0><3><0>lcd_gpio_18 = port:PA14<8><0><3><0>lcd_gpio_19 = port:PA15<8><0><3><0>lcd_gpio_20 = port:PB03<8><0><3><0>lcd_gpio_21 = port:PB02<8><0><3><0>;LCD_VSYNC, LCD_HSYNC, LCD_DCLK, LCD_DElcd_gpio_0 = port:PA18<8><0><3><0>lcd_gpio_1 = port:PA19<8><0><3><0>lcd_gpio_2 = port:PA20<8><0><3><0>lcd_gpio_3 = port:PA21<8><0><3><0>
同样与并行 RGB 接口一样,配置中并不需要也无法体现具体是哪种串行 RGB 接口,你要做的就是把硬件连接对就行。 这里需要注意的是,对于该接口,SoC 总共需要三个周期才能发完一个 pixel,所以我们配置时序的时候,需要满足 lcd_dclk_freq*3=lcd_ht*lcd_vt60,或者 lcd_dclk_freq=lcd_ht/3*lcd_vt*60 要么 3 倍 lcd_ht 要么 3 倍 lcd_dclk_freq。I8080 接口Intel 8080 接口屏 (又称 MCU 接口) 很老的协议,一般用在分辨率很小的屏上 管脚的控制脚有 6 种: 管脚作用说明 CS 片选信号决定该芯片是否工作。 RS 寄存器选择信号低表示选择 index 或者 status 寄存器,高表示选择控制寄存器。实际场景中一般接 SoC 的 LCD_DE 脚(数据使能脚)。 WR 数据命令区分信号即写时钟信号,一般接 SoC 的 LCD_CLK 脚。(低表示写数据) RD 数据读信号即读时钟信号,一般接 SoC 的 LCD_HSYNC 脚。(低表示读数据) RESET复位 LCD(用固定命令系列 0 1 0 来复位) Data双向数据 I8080 根据 Data 的数据位宽接口有 8/9/16/18,连哪些脚参考,即使位宽一样,连的管脚也不一样,还要考虑的因素是 rgb 格式。
|
|
相关推荐
|
|
只有小组成员才能发言,加入小组>>
983 浏览 0 评论
709 浏览 0 评论
832 浏览 0 评论
全志T113双核异构处理器的使用基于Tina Linux5.0——RTOS系统定制开发
1519 浏览 0 评论
全志T113双核异构处理器的使用基于Tina Linux5.0——RTOS编译开发说明
938 浏览 0 评论
全志V85x硬件设计大赛作品精选第二期,快来Pick你心目中的最佳方案
95692浏览 3评论
2883浏览 1评论
Yuzuki Lizard 全志V851S开发板 –移植 QT5.12.9教程
16456浏览 1评论
关于全志T113开发板接7寸LCD屏幕显示异常问题的解决方案
1176浏览 1评论
泰酷辣!基于全志R818的开源超迷你安卓手持终端CyberPad,芒果派惊喜之作
3301浏览 1评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-22 17:44 , Processed in 0.435283 second(s), Total 38, Slave 31 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号