如何新增一个屏幕驱动#
在本文档会演示如何新增一个 368(H) X 552(V) 的 mipi
屏幕。
使用屏幕调试助手#
在 CanMV-K230 工程中的子仓库 mpp 里增加了一个屏幕调试助手,用户可将该功能使能后,通过修改存储在 SDCard
中的配置文件快速的调试屏幕时序以及初始化序列,不再需要频繁的修改代码编译固件。
使能 DSI Debugger
#
在工程根目录执行 make menuconfig
,使能选项 Enable DSI Debuger
。
保存配置后,编译生成新的固件,烧录固件。
生成 display_debugger_config.txt
#
在工程中有一个配置文件的模板,路径为 src/rtsmart/mpp/userapps/src/connector/display_debugger_config.txt
。它的各项参数含义大概如下:
[config]
pclk_hz=33000000 # pclk in hz
fps=60 # target fps
lane_num=2 # mipi dsi lane number, choice in 1, 2, 4
buff_num=1
hactive=480
hsync=8
hbp=32
hfp=32
vactive=800
vsync=10
vbp=150
vfp=140
# !!! every line length should < 256
# cmd_type:
# 0x05 Command type: Single byte data (DCS Short Write, no parameters)
# 0x15 Command type: Two byte data (DCS Short Write, 1 parameter)
# 0x39 Command type: Multi byte data (DCS Long Write, n parameters n >= 2)
# format: cmd_type, delay_ms, cmd_data_length, cmd_data0 ... cmd_dataN
# 初始化序列的格式为:cmd_type, delay_ms, cmd_data_length, cmd_data0 ... cmd_dataN
#
# 现在支持3种Command type:
# 0x05 只写一个字节,不带参数
# 0x15 只写两个字节,带一个参数
# 0x39 可写多个字节,带大于两个参数
#
# 以 0x39,10,3,0xE8,0x00,0x0C 为例
# 0x39 0x39命令,代表我们现在要写多个字节数据
# 十进制数,代表我们执行完这个命令之后要延时10个毫秒才会执行下一条命令
# 十进制数,代表我们这次的0x39命令会写3个字节的数据
# 0xE8,0x00,0x0C 3个字节的数据里面,0xE8是命令,0x00,0x0C是参数,即这是一个带两个参数的命令
#
# 注意,0x39 和 0xE8 都是命令,但是要区分开。前者是MIPI显示接口协议中的一种命令类型,后者是屏幕初始化序列里面的一个特定的命令字节,通常在屏幕初始化过程中用来指定某些设置,具体而言,这个命令可能是用来启用或禁用某些功能(如显示模式、对比度、颜色配置等)。
[init-sequence]
0x05,0,1,0x01
0x05,10,1,0x11
0x39,0,6,0xFF,0x77,0x01,0x00,0x00,0x11
0x15,0,2,0xD1,0x11
0x15,0,2,0x55,0xB0
0x39,0,6,0xFF,0x77,0x01,0x00,0x00,0x10
0x39,0,3,0xC0,0x63,0x00
0x39,0,3,0xC1,0x04,0x02
0x39,0,3,0xC2,0x37,0x08
0x15,0,2,0xC7,0x00
0x15,0,2,0xCC,0x38
0x39,0,17,0xB0,0x00,0x11,0x19,0x0C,0x10,0x06,0x07,0x0A,0x09,0x22,0x04,0x10,0x0E,0x28,0x30,0x1C
0x39,0,17,0xB1,0x00,0x12,0x19,0x0D,0x10,0x04,0x06,0x07,0x08,0x23,0x04,0x12,0x11,0x28,0x30,0x1C
0x39,0,6,0xFF,0x77,0x01,0x00,0x00,0x11
0x15,0,2,0xB0,0x4D
0x15,0,2,0xB1,0x60
0x15,0,2,0xB2,0x07
0x15,0,2,0xB3,0x80
0x15,0,2,0xB5,0x47
0x15,0,2,0xB7,0x8A
0x15,0,2,0xB8,0x21
0x15,0,2,0xC1,0x78
0x15,0,2,0xC2,0x78
0x15,0,2,0xD0,0x88
0x39,0,4,0xE0,0x00,0x00,0x02
0x39,0,12,0xE1,0x01,0xA0,0x03,0xA0,0x02,0xA0,0x04,0xA0,0x00,0x44,0x44
0x39,0,12,0xE2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
0x39,0,5,0xE3,0x00,0x00,0x33,0x33
0x39,0,3,0xE4,0x44,0x44
0x39,0,17,0xE5,0x01,0x26,0xA0,0xA0,0x03,0x28,0xA0,0xA0,0x05,0x2A,0xA0,0xA0,0x07,0x2C,0xA0,0xA0
0x39,0,5,0xE6,0x00,0x00,0x33,0x33
0x39,0,3,0xE7,0x44,0x44
0x39,0,17,0xE8,0x02,0x26,0xA0,0xA0,0x04,0x28,0xA0,0xA0,0x06,0x2A,0xA0,0xA0,0x08,0x2C,0xA0,0xA0
0x39,0,8,0xEB,0x00,0x01,0xE4,0xE4,0x44,0x00,0x40
0x39,0,17,0xED,0xFF,0xF7,0x65,0x4F,0x0B,0xA1,0xCF,0xFF,0xFF,0xFC,0x1A,0xB0,0xF4,0x56,0x7F,0xFF
0x15,0,2,0xEE,0x42
0x39,0,6,0xFF,0x77,0x01,0x00,0x00,0x00
0x15,0,2,0x36,0x00
0x15,0,2,0x3A,0x55
0x05,10,1,0x11
0x05,0,1,0x29
接下来,我们根据自己的屏幕修改对应的屏幕时序和初始化序列,然后生成自己屏幕的 display_debugger_config.txt
,以本文档所调试的屏幕为例子,最后会调整出一个这样的文件。(记住将配置文件中的注释删掉)
[config]
pclk_hz=27000000
fps=60
lane_num=2
buff_num=1
hactive=368
hsync=8
hbp=16
hfp=16
vactive=552
vsync=48
vbp=250
vfp=250
[init-sequence]
0x39,0,6,0xFF,0x77,0x01,0x00,0x00,0x13
0x15,0,2,0xEF,0x08
0x39,0,6,0xFF,0x77,0x01,0x00,0x00,0x10
0x39,0,3,0xC0,0x44,0x00
0x39,0,3,0xC1,0x0B,0x02
0x39,0,3,0xC2,0x07,0x1F
0x15,0,2,0xCC,0x10
0x39,0,17,0xB0,0x0F,0x1E,0x25,0x0D,0x11,0x06,0x12,0x08,0x08,0x2A,0x05,0x12,0x10,0x2B,0x32,0x1F
0x39,0,17,0xB1,0x0F,0x1E,0x25,0x0D,0x11,0x05,0x12,0x08,0x08,0x2B,0x05,0x12,0x10,0x2B,0x32,0x1F
0x39,0,6,0xFF,0x77,0x01,0x00,0x00,0x11
0x15,0,2,0xB0,0x35
0x15,0,2,0xB1,0x45
0x15,0,2,0xB2,0x87
0x15,0,2,0xB3,0x80
0x15,0,2,0xB5,0x49
0x15,0,2,0xB7,0x85
0x15,0,2,0xB8,0x11
0x15,0,2,0xBB,0x03
0x15,0,2,0xC0,0x07
0x15,0,2,0xC1,0x78
0x15,0,2,0xC2,0x78
0x15,100,2,0xD0,0x88
0x39,0,4,0xE0,0x00,0x00,0x02
0x39,0,12,0xE1,0x03,0x30,0x07,0x30,0x02,0x30,0x06,0x30,0x00,0x44,0x44
0x39,0,12,0xE2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
0x39,0,5,0xE3,0x00,0x00,0x22,0x00
0x39,0,3,0xE4,0x22,0x00
0x39,0,17,0xE5,0x0A,0x34,0x30,0xE0,0x08,0x32,0x30,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
0x39,0,5,0xE6,0x00,0x00,0x22,0x00
0x39,0,3,0xE7,0x22,0x00
0x39,0,17,0xE8,0x09,0x33,0x30,0xE0,0x07,0x31,0x30,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
0x39,0,8,0xEB,0x00,0x01,0x10,0x10,0x11,0x00,0x00
0x39,0,17,0xED,0xFF,0xFF,0xF0,0x45,0xBA,0x2F,0xFF,0xFF,0xFF,0xFF,0xF2,0xAB,0x54,0x0F,0xFF,0xFF
0x39,0,7,0xEF,0x08,0x08,0x08,0x45,0x3F,0x54
0x39,0,6,0xFF,0x77,0x01,0x00,0x00,0x13
0x39,0,3,0xE8,0x00,0x0E
0x15,120,2,0x11,0x00
0x39,10,3,0xE8,0x00,0x0C
0x39,0,3,0xE8,0x00,0x00
0x39,0,6,0xFF,0x77,0x01,0x00,0x00,0x00
0x15,50,2,0x29,0x00
将配置文件放入SDCard
#
开机后,将配置文件放入SDCard
根目录
验证并调整配置#
在 CanMV IDE K230
打开 Display
相关的Sample#
修改Sample代码以使用 DSI Debugger
#
运行Sample,查看结果#
因为本文档给的参数是适配对应屏幕后的,所以屏幕会正确输出图像,如果读者得不到预期结果,那么需要修改SDCard的配置文件调整参数,重复运行Sample,查看结果,最后调整到合适的参数。
配置文件参数调整#
SDCard中配置文件的参数基本分为两部分,前半部分是屏幕时序相关,后半部分是屏幕厂家提供的初始化序列,接下来我们分别了解一下这两部分的具体含义。
屏幕时序#
[config]
pclk_hz=27000000 # 这个值是根据下面的参数,最后利用计算工具算出来的
fps=60 # 假定我想要这个帧率,等会写进去计算工具
lane_num=2
buff_num=1
# htotal = hactive + hsync + hbp + hfp
hactive=368 # 这个对应分辨率的宽
hsync=8 # hsync,hbp,hfp,根据对应的屏幕估算,调整
hbp=16
hfp=16
# vtotal = vactive + vsync + vbp +vfp
# 对于 vtotal 来说有个限制,主控只会在 2^N 行处发起中断,所以当 vtotal > 512 的时候,应该将 vtotal向上对齐到 1024,然后再给一点余量
# 给中断处理函数,所以预估 vtotal 应该为 1100,即 vactive + vsync + vbp +vfp 需要等于 1100,在这个限制下再去调整 vsync,vbp,vfp
vactive=552 # 这个对应分辨率的高
vsync=48 # vsync,vbp,vfp,根据对应的屏幕估算,调整
vbp=250
vfp=250
我们提供了一个协助计算时序的工具 K230 MIPI DSI Connector Info Generator,下面演示如何利用计算时序的工具来算出上面的值
初始化序列#
本文档示例的屏幕厂家提供了如下的初始化序列,我们根据需要转换为符合格式的 display_debugger_config.txt
文件即可。
{0xFF,5,{0x77,0x01,0x00,0x00,0x13}},
{0xEF,1,{0x08}},
{0xFF,5,{0x77,0x01,0x00,0x00,0x10}},
{0xC0,2,{0x44,0x00}},
{0xC1,2,{0x0B,0x02}},
{0xC2,2,{0x07,0x1F}},
{0xCC,1,{0x10}},
{0xB0,16,{0x0F,0x1E,0x25,0x0D,0x11,0x06,0x12,0x08,0x08,0x2A,0x05,0x12,0x10,0x2B,0x32,0x1F}},
{0xB1,16,{0x0F,0x1E,0x25,0x0D,0x11,0x05,0x12,0x08,0x08,0x2B,0x05,0x12,0x10,0x2B,0x32,0x1F}},
{0xFF,5,{0x77,0x01,0x00,0x00,0x11}},
{0xB0,1,{0x35}},
{0xB1,1,{0x45}},
{0xB2,1,{0x87}},
{0xB3,1,{0x80}},
{0xB5,1,{0x49}},
{0xB7,1,{0x85}},
{0xB8,1,{0x11}},
{0xBB,1,{0x03}},
{0xC0,1,{0x07}},
{0xC1,1,{0x78}},
{0xC2,1,{0x78}},
{0xD0,1,{0x88}},
{REGFLAG_DELAY,100,{}},
{0xE0,3,{0x00,0x00,0x02}},
{0xE1,11,{0x03,0x30,0x07,0x30,0x02,0x30,0x06,0x30,0x00,0x44,0x44}},
{0xE2,11,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
{0xE3,4,{0x00,0x00,0x22,0x00}},
{0xE4,2,{0x22,0x00}},
{0xE5,16,{0x0A,0x34,0x30,0xE0,0x08,0x32,0x30,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
{0xE6,4,{0x00,0x00,0x22,0x00}},
{0xE7,2,{0x22,0x00}},
{0xE8,16,{0x09,0x33,0x30,0xE0,0x07,0x31,0x30,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
{0xEB,7,{0x00,0x01,0x10,0x10,0x11,0x00,0x00}},
{0xED,16,{0xFF,0xFF,0xF0,0x45,0xBA,0x2F,0xFF,0xFF,0xFF,0xFF,0xF2,0xAB,0x54,0x0F,0xFF,0xFF}},
{0xEF,6,{0x08,0x08,0x08,0x45,0x3F,0x54}},
{0xFF,5,{0x77,0x01,0x00,0x00,0x13}},
{0xE8,2,{0x00,0x0E}},
{0x11,0,{0x00}},
{REGFLAG_DELAY,120,{}},
{0xE8,2,{0x00,0x0C}},
{REGFLAG_DELAY,10,{}},
{0xE8,2,{0x00,0x00}},
{0xFF,5,{0x77,0x01,0x00,0x00,0x00}},
{0x29,0,{0x00}},
{REGFLAG_DELAY,50,{}},
我们举两个例子:
{0xB0,16,{0x0F,0x1E,0x25,0x0D,0x11,0x06,0x12,0x08,0x08,0x2A,0x05,0x12,0x10,0x2B,0x32,0x1F}},
# 将多余的{}去掉
# 0xB0 是命令,其余的都是16个字节是参数,所以我们选择 0x39 命令,长度应该是 16 + 1 = 17
# 不需要延时,所以转化结果如下:
0x39,0,17,0xB0,0x0F,0x1E,0x25,0x0D,0x11,0x06,0x12,0x08,0x08,0x2A,0x05,0x12,0x10,0x2B,0x32,0x1F
{0x11,0,{0x00}},
{REGFLAG_DELAY,120,{}},
# 将多余的{}去掉
# 0x11 是命令,其余的1个字节是参数,所以我们选择 0x15 命令,长度应该是 1 + 1 = 2
# 后面的REGFLAG_DELAY代表还有120毫秒的延时,所以转化结果为如下:
0x15,120,2,0x11,0x00
# Tips: 因为每个厂家提供的初始化序列格式可能大有不同,所以这种转化的事情可以丢给ChatGPT去干就好
# PS: 其实第二个例子转换为 0x05,120,1,0x11,也是正确的,我们会发现厂家提供的初始化序列,自己在长度和数据这方面就没统一好
在工程代码中添加屏幕#
经过前面的调试,我们已经有了适配该款屏幕的参数了,可以在工程中添加一款屏幕了。
在 CanMV-K230 工程中的子仓库 mpp 里,仿造其他屏幕添加类似如下代码:(初始化序列来自屏幕厂家,屏幕时序是我们调整出来的,最后把计算工具生成的代码贴过去即可)
在 CanMV-K230 工程中的子仓库 canmv 里,仿造其他屏幕添加类似如下代码: