打印
[技术讨论]

全志R128点屏SPI LCD颜色相关问题

[复制链接]
441|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
神棍地海棠|  楼主 | 2023-12-6 10:10 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 神棍地海棠 于 2024-2-5 17:21 编辑

SPI LCD 颜色相关问题
[color=rgba(0, 0, 0, 0.87)]首先,得先确定显示屏使用的是SPI接口,还是DBI接口,不同的接口,输入数据的解析方式是不一样的。
[color=rgba(0, 0, 0, 0.87)]DBI接口的全称是 Display Bus Serial Interface ,在显示屏数据手册中,一般会说这是SPI接口,所以有人会误认为SPI屏可以使用 normal spi 去直接驱动。
[color=rgba(0, 0, 0, 0.87)]阅读lcd_dbi_if部分的介绍可以知道,在3线模式时,发送命令前有1位A0用于指示当前发送的是数据,还是命令。而命令后面接着的数据就没有这个A0位了,代表SPI需要在9位和8位之间来回切换,而在读数据时,更是需要延时 dummy clock 才能读数据,normal spi 都很难,甚至无法实现。所以 normal spi 只能模拟4 线的DBI的写操作。
[color=rgba(0, 0, 0, 0.87)]对于R128这类支持DBI接口的CPU,可以选择不去了解SPI。如果需要用到SPI去驱动显示屏,必须把显示屏设置成小端。
RGB565和RGB666
[color=rgba(0, 0, 0, 0.87)]SPI显示屏一般支持RGB444,RGB565和RGB666,RGB444使用的比较少,所以只讨论RGB565和RGB666.
[color=rgba(0, 0, 0, 0.87)]RGB565代表一个点的颜色由2字节组成,也就是R(红色)用5位表示,G(绿色)用6位表示,B(蓝色)用5位表示,如下图所示:
[color=rgba(0, 0, 0, 0.87)][color=var(--md-typeset-a-color)]
[color=rgba(0, 0, 0, 0.87)]RGB666一个点的颜色由3字节组成,每个字节代表一个颜色,其中每个字节的低2位会无视,如下图所示:
[color=rgba(0, 0, 0, 0.87)][color=var(--md-typeset-a-color)]
SPI 接口
[color=rgba(0, 0, 0, 0.87)]因为SPI接口的通讯效率不高,所以建议使用RGB565的显示,以 jlt35031c 显示屏为例,他的显示驱动芯片是 ST7789v,设置显示格式的方式是往 3a 寄存器写入0x55(RGB565)或者 0x66(RGB666),在 R128SDK 中,已经把 jlt35031c 的通讯格式写死为 0x55,lcd_pixel_fmt配置选项无效:
code" style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; font-size: inherit; font-family: inherit; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border-width: 0px; border-style: initial; border-color: initial; position: absolute; top: 0.5em; right: 0.5em; z-index: 1; width: 1.5em; height: 1.5em; border-radius: 0.1rem; outline: none; outline-offset: 0.1rem; cursor: pointer; transition: color 0.25s ease 0s;">sunxi_lcd_cmd_write(sel, 0x3a);sunxi_lcd_para_write(sel, 0x55);
[color=rgba(0, 0, 0, 0.87)]在例程中,输入的数据是 0xff,0x00,0xff,0x00,对于SPI接口,是按字节发送。实际上,例程只需要每次发送2字节即可,因为前后发送的都是相同的ff 00,所以没有看出问题。
[color=rgba(0, 0, 0, 0.87)]根据对 565 的数据解析,我们拆分 ff 00 就可以得到红色分量是 0b11111,也就是 31,绿色是0b111000,也就是 56,,蓝色是 0.我们等效转换成 RGB888,有:
code" style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; font-size: inherit; font-family: inherit; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border-width: 0px; border-style: initial; border-color: initial; position: absolute; top: 0.5em; right: 0.5em; z-index: 1; width: 1.5em; height: 1.5em; border-radius: 0.1rem; outline: none; outline-offset: 0.1rem; cursor: pointer; transition: color 0.25s ease 0s;">R = 31/31*255 = 255G = 56/63*255 = 226
[color=rgba(0, 0, 0, 0.87)]在调色板输入对应颜色,就可以得到黄色
[color=rgba(0, 0, 0, 0.87)][color=var(--md-typeset-a-color)]
[color=rgba(0, 0, 0, 0.87)]因为 DBI 通讯效率较高,所以可以使用 RGB565 或者 RGB666,使用 DBI 接口,也就是 lcd_if 设置为1时,驱动会根据 lcd_pixel_fmt 配置寄存器,以 SDK 中的 kld2844b.c 为例,这显示屏的显示驱动也是 ST7789,但是不同的屏幕,厂家封装时已经限制了通讯方式,所以即使是能使用 DBI 接口的驱动芯片的屏幕,或许也用不了DBI。
code" style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; font-size: inherit; font-family: inherit; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border-width: 0px; border-style: initial; border-color: initial; position: absolute; top: 0.5em; right: 0.5em; z-index: 1; width: 1.5em; height: 1.5em; border-radius: 0.1rem; outline: none; outline-offset: 0.1rem; cursor: pointer; transition: color 0.25s ease 0s;">sunxi_lcd_cmd_write(sel, 0x3A); /* Interface Pixel Format *//* 55----RGB565;66---RGB666 */if (info[sel.lcd_pixel_fmt == LCDFB_FORMAT_RGB_565 ||    info[sel.lcd_pixel_fmt == LCDFB_FORMAT_BGR_565) {    sunxi_lcd_para_write(sel, 0x55);    if (info[sel.lcd_pixel_fmt == LCDFB_FORMAT_RGB_565)        rotate &= 0xf7;    else        rotate |= 0x08;} else if (info[sel.lcd_pixel_fmt < LCDFB_FORMAT_RGB_888) {    sunxi_lcd_para_write(sel, 0x66);    if (info[sel.lcd_pixel_fmt == LCDFB_FORMAT_BGRA_8888 ||        info[sel.lcd_pixel_fmt == LCDFB_FORMAT_BGRX_8888 ||        info[sel.lcd_pixel_fmt == LCDFB_FORMAT_ABGR_8888 ||        info[sel.lcd_pixel_fmt == LCDFB_FORMAT_XBGR_8888) {        rotate |= 0x08;    }} else {    sunxi_lcd_para_write(sel, 0x66);}
[color=rgba(0, 0, 0, 0.87)]对于 DBI 格式,不再是以字节的形式去解析,而是以字的方式去解析,为了统一,软件已经规定了,RGB565 格式时,字大小是2字节,也就是16位,而 RGB666 格式时,字大小是4字节,也就是32位。
[color=rgba(0, 0, 0, 0.87)]对于 RGB565 格式,同样是设置为 0xff,0x00。因为屏幕是大端,而芯片存储方式是小端,所以芯片的 DBI 模块,会自动把数据从新排列,也就是实际上 DBI 发送数据时,会先发送0x00,再发送0xff,也就是红色分量为0,绿色分量为 0b000111,也就是7,蓝色分量是 0x11111,也就是31,我们同样转换成RGB888
code" style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; font-size: inherit; font-family: inherit; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border-width: 0px; border-style: initial; border-color: initial; position: absolute; top: 0.5em; right: 0.5em; z-index: 1; width: 1.5em; height: 1.5em; border-radius: 0.1rem; outline: none; outline-offset: 0.1rem; cursor: pointer; transition: color 0.25s ease 0s;">G = 7/63*255 = 28B= 31/31*255 = 255
[color=rgba(0, 0, 0, 0.87)]在调色板上输入,可以得到蓝色。
[color=rgba(0, 0, 0, 0.87)][color=var(--md-typeset-a-color)]
[color=rgba(0, 0, 0, 0.87)]如果是 RGB666,虽然占用的是3个字节,但是没有CPU是3字节对齐的,所以需要一次性输入4字节,然后 DBI 硬件模块,会自动舍弃1个字节,软件同意舍弃了最后一个字节。
[color=rgba(0, 0, 0, 0.87)]依旧以例程为例,例程输入了 0xff,0x00,0xff,0x00,为了方便说明,标准为 0xff(1),0x00(1),0xff(2),0x00(2),其中 0x00(2)会被舍弃掉,然后发送顺序是0xff(2),0x00(1),0xff(1),也就是 0xff(2) 是红色分量,0xff(1) 是蓝色分量,混合可以得到紫色。
[color=rgba(0, 0, 0, 0.87)][color=var(--md-typeset-a-color)]

使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

260

主题

268

帖子

0

粉丝