社区首页
技术讨论创新帖
全部新帖
资料区
社区活动
联系管理员
★ 社区积分制度
★ 新手必读
★ 申请版主★
请
登录
后使用快捷导航
没有帐号?
注册
首页
|
电子技术
|
嵌入式
模拟电子
单片机
电源管理
传感器
半导体
电子应用
|
工业控制
物联网
汽车电子
网络通信
医疗电子
手机便携
测试测量
安防电子
家用电子
机器人
新能源
电子头条
|
社区
|
论坛
测评
博客
大学堂
|
下载
|
下载中心
电路图
精品文集
电路图
|
参考设计
|
Datasheet
|
活动
|
直播
datasheet
datasheet
文章
搜索
登录
注册
论坛
切换旧版
电子工程世界-论坛
»
论坛
›
电子技术交流
›
国产芯片交流
›
全志R128应用开发案例——DBI驱动ST7789V1.3寸LCD屏
返回列表
发新帖
回复
阅
717
|
回
0
aleksib
当前离线
纯净的硅(中级)
最后登录
2024-12-2
在线时间
39 小时
威望
983分
芯积分
496分
(兑换)
E金币
0枚
(兑换)
(兑换)
好友
0
aleksib
282
帖子
0
TA的资源
纯净的硅(中级)
+ 好友
私信
楼主
发表于2023-11-6 11:14
只看该作者
全志R128应用开发案例——DBI驱动ST7789V1.3寸LCD屏
[复制链接]
# DBI驱动ST7789V1.3寸LCD 之前介绍了 R128 平台使用 SPI 驱动显示屏 ST7789V1.3寸 LCD,接下来介绍的是使用 DBI 接口驱动。 R128 平台提供了 SPI DBI 的 SPI TFT 接口,具有如下特点: - Supports DBI Type C 3 Line/4 Line Interface Mode - Supports 2 Data Lane Interface Mode - Supports data source from CPU or DMA - Supports RGB111/444/565/666/888 video format - Maximum resolution of RGB666 240 x 320@30Hz with single data lane - Maximum resolution of RGB888 240 x 320@60Hz or 320 x 480@30Hz with dual data lane - Supports tearing effect - Supports software flexible control video frame rate 同时,提供了 SPILCD 驱动框架以供 SPI 屏幕使用。 此次适配的SPI屏为 `ZJY130S0800TG01`,使用的是 DBI 进行驱动。 DBI接口的全称是 `Display Bus Serial Interface` ,在显示屏数据手册中,一般会说这是SPI接口,所以有人会误认为SPI屏可以使用 `normal spi` 去直接驱动。 SPI 接口就是俗称的4线模式,这是因为发送数据时需要额外借助`DC`线来区分命令和数据,与`sclk`,`cs`和`sda`共四线。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/2bf061f9058f4384b10449e81ca56230.png#pic_center) DBI 分为多种接口,包括 ``` 0:L3I1 1:L3I2 2:L4I1 3:L4I2 4:D2LI ``` `L3I1`和`L3I2`是三线模式(不需要`DC`脚),区别是读时序,也就是是否需要额外脚来读寄存器。读写时序图如下: - L3I1写时序 ![在这里插入图片描述](https://img-blog.csdnimg.cn/2937fb1145874221b312c428f54293d1.png#pic_center) - L3I1读时序 ![在这里插入图片描述](https://img-blog.csdnimg.cn/182969c8f27b4217b10ebe8441ace994.png#pic_center) `L4I1`和`L4I2`是四线模式,与spi接口协议一样,区别是DC脚的控制是否自动化控制,另外I2和I1的区别是读时序,也就是否需要额外脚来读取寄存器。 - L4I写时序 ![在这里插入图片描述](https://img-blog.csdnimg.cn/282ccecd91d24d1cb2d1c62113e98448.png#pic_center) - L4I读时序 ![在这里插入图片描述](https://img-blog.csdnimg.cn/d3ec27e28ee34920bc52cb4a8970232a.png#pic_center) `D2LI`是两data lane模式。发送命令部分时序与读时序与`L3I1`一致,下图是发送数据时的时序,不同像素格式时钟周期数量不一样。 - D2LI写时序 ![在这里插入图片描述](https://img-blog.csdnimg.cn/83d7ffd154624904bfafae2c3ac5a599.png#pic_center) 可以知道,在3线模式时,发送命令前有1位A0用于指示当前发送的是数据,还是命令。而命令后面接着的数据就没有这个A0位了,代表 SPI 需要在 9 位和 8 位之间来回切换,而在读数据时,更是需要延时 `dummy clock` 才能读数据,`normal spi` 都很难,甚至无法实现。所以 `normal spi` 只能模拟 4 线的 DBI 的写操作。读操作只能通过模拟IO来实现。 对于R128这类支持 DBI 接口的CPU,可以选择不去了解 SPI。直接选用 DBI 来驱动屏幕。由于不需要模拟延时和切换数据,屏幕驱动效率将有明显提升。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/5d787c7e7d31401e9ee913bdd4feaa69.png#pic_center) 引脚配置如下: | R128 Devkit | TFT 模块 | | :---------- | :------- | | PA12 | CS | | PA13 | SCL | | PA18 | SDA | | PA9 | BLK | | PA20 | RES | | PA19 | DC | | 3V3 | VCC | | GND | GND | ## 载入方案 我们使用的开发板是 R128-Devkit,需要开发 C906 核心的应用程序,所以载入方案选择 `r128s2_module_c906` ```bash $ source envsetup.sh $ lunch_rtos 1 ``` ![在这里插入图片描述](https://img-blog.csdnimg.cn/5ba16beab48840ab866721c19b0e887b.png#pic_center) ## 设置 DBI 驱动 屏幕使用的是SPI驱动,所以需要勾选SPI驱动,运行 `mrtos_menuconfig` 进入配置页面。前往下列地址找到 `SPI Devices` ```c Drivers Options---> soc related device drivers---> DBI Devices ---> -*- enable dbi driver ``` ![在这里插入图片描述](https://img-blog.csdnimg.cn/d5bc5bf7ed6d44e1bdbd21f8d1be28e8.png#pic_center) ### 配置 SPI 引脚 DBI同样使用 SPI 控制器,所以需要配置SPI的相关配置。打开你喜欢的编辑器,修改文件:`board/r128s2/module/configs/sys_config.fex`,在这里我们不需要用到SPI WP引脚,注释掉即可。SPI HOLD 需要作为 DC 脚接入LCD模块。 ``` ;---------------------------------------------------------------------------------- ;SPI controller configuration ;---------------------------------------------------------------------------------- ;Please config spi in dts [spi1] spi1_used = 1 spi1_cs_number= 1 spi1_cs_bitmap= 1 spi1_cs0 = port:PA12<6><0><3>
spi1_sclk = port:PA13<6><0><3>
spi1_mosi = port:PA18<6><0><3>
spi1_miso = port:PA21<6><0><3>
spi1_hold = port:PA19<6><0><2>
;spi1_wp = port:PA20<6><0><2>
``` ![在这里插入图片描述](https://img-blog.csdnimg.cn/e173340e96f64c3db1382a4189869732.png#pic_center) ## 设置 PWM 驱动 屏幕背光使用的是PWM驱动,所以需要勾选PWM驱动,运行 `mrtos_menuconfig` 进入配置页面。前往下列地址找到 `PWM Devices` ``` Drivers Options---> soc related device drivers---> PWM Devices ---> -*- enable pwm driver ``` ![在这里插入图片描述](https://img-blog.csdnimg.cn/a31faaa683e44da5a0b643a23866bbdf.png#pic_center) ### 配置 PWM 引脚 打开你喜欢的编辑器,修改文件:`board/r128s2/module/configs/sys_config.fex`,增加 PWM1 节点 ``` [pwm1] pwm_used = 1 pwm_positive = port:PA9<4><0><3>
``` ![在这里插入图片描述](https://img-blog.csdnimg.cn/015c551d74d2454a9daa32edfe09681e.png#pic_center) ## 设置 SPI LCD 驱动 SPI LCD 由专门的驱动管理。运行 `mrtos_menuconfig` 进入配置页面。前往下列地址找到 `SPILCD Devices` ,注意同时勾选 `spilcd hal APIs test` 方便测试使用。 ``` Drivers Options---> soc related device drivers---> [*] DISP Driver Support(spi_lcd) [*] spilcd hal APIs test ``` ![在这里插入图片描述](https://img-blog.csdnimg.cn/4e6ef8c188424aaa800a7d11c039ac34.png#pic_center) ## 编写 SPI LCD 显示屏驱动 ### 获取屏幕初始化序列 首先询问屏厂提供驱动源码 ![在这里插入图片描述](https://img-blog.csdnimg.cn/5446b054b2ac4a9f99424f97a6f69571.png#pic_center) 找到 LCD 的初始化序列代码 ![在这里插入图片描述](https://img-blog.csdnimg.cn/74d1dc0f2b4f4202a84c5fe0d55e1f85.png#pic_center) 找到屏幕初始化的源码 ![在这里插入图片描述](https://img-blog.csdnimg.cn/0839a635a555465ab8964655b9c5affe.png#pic_center) 整理后的初始化代码如下: ```c LCD_WR_REG(0x11); // Sleep out delay_ms(120); // Delay 120ms //************* Start Initial Sequence **********// LCD_WR_REG(0x36); LCD_WR_DATA8(0x00); LCD_WR_REG(0x3A); LCD_WR_DATA8(0x05); LCD_WR_REG(0xB2); LCD_WR_DATA8(0x1F); LCD_WR_DATA8(0x1F); LCD_WR_DATA8(0x00); LCD_WR_DATA8(0x33); LCD_WR_DATA8(0x33); LCD_WR_REG(0xB7); LCD_WR_DATA8(0x35); LCD_WR_REG(0xBB); LCD_WR_DATA8(0x20); // 2b LCD_WR_REG(0xC0); LCD_WR_DATA8(0x2C); LCD_WR_REG(0xC2); LCD_WR_DATA8(0x01); LCD_WR_REG(0xC3); LCD_WR_DATA8(0x01); LCD_WR_REG(0xC4); LCD_WR_DATA8(0x18); // VDV, 0x20:0v LCD_WR_REG(0xC6); LCD_WR_DATA8(0x13); // 0x13:60Hz LCD_WR_REG(0xD0); LCD_WR_DATA8(0xA4); LCD_WR_DATA8(0xA1); LCD_WR_REG(0xD6); LCD_WR_DATA8(0xA1); // sleep in后,gate输出为GND LCD_WR_REG(0xE0); LCD_WR_DATA8(0xF0); LCD_WR_DATA8(0x04); LCD_WR_DATA8(0x07); LCD_WR_DATA8(0x04); LCD_WR_DATA8(0x04); LCD_WR_DATA8(0x04); LCD_WR_DATA8(0x25); LCD_WR_DATA8(0x33); LCD_WR_DATA8(0x3C); LCD_WR_DATA8(0x36); LCD_WR_DATA8(0x14); LCD_WR_DATA8(0x12); LCD_WR_DATA8(0x29); LCD_WR_DATA8(0x30); LCD_WR_REG(0xE1); LCD_WR_DATA8(0xF0); LCD_WR_DATA8(0x02); LCD_WR_DATA8(0x04); LCD_WR_DATA8(0x05); LCD_WR_DATA8(0x05); LCD_WR_DATA8(0x21); LCD_WR_DATA8(0x25); LCD_WR_DATA8(0x32); LCD_WR_DATA8(0x3B); LCD_WR_DATA8(0x38); LCD_WR_DATA8(0x12); LCD_WR_DATA8(0x14); LCD_WR_DATA8(0x27); LCD_WR_DATA8(0x31); LCD_WR_REG(0xE4); LCD_WR_DATA8(0x1D); // 使用240根gate(N+1)*8 LCD_WR_DATA8(0x00); // 设定gate起点位置 LCD_WR_DATA8(0x00); // 当gate没有用完时,bit4(TMG)设为0 LCD_WR_REG(0x21); LCD_WR_REG(0x29); ``` ### 用现成驱动改写 SPI LCD 驱动 选择一个现成的 SPI LCD 改写即可,这里选择 `nv3029s.c` 驱动来修改 ![在这里插入图片描述](https://img-blog.csdnimg.cn/6b65147c6d2f4a1eb8fb41b23884eec5.png#pic_center) 复制这两个驱动,重命名为 `st7789v.c` ![在这里插入图片描述](https://img-blog.csdnimg.cn/e50875bbafa34cf7859491c0b012e611.png#pic_center) 先编辑 `st7789v.h` 将 `nv3029s` 改成 `st7789v` ![在这里插入图片描述](https://img-blog.csdnimg.cn/2c866abfe584485ba47f4f8ba397a7a7.png#pic_center) ```c #ifndef _ST7789V_H #define _ST7789V_H #include "panels.h" struct __lcd_panel st7789v_panel; #endif /*End of file*/ ``` 编辑 `st7789v.c` 将 `nv3029s` 改成 `st7789v` ![在这里插入图片描述](https://img-blog.csdnimg.cn/fc76a44819e74c64862163776d6b5af7.png#pic_center) ### 编写初始化序列 先删除 `static void LCD_panel_init(unsigned int sel)` 中的初始化函数。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/8404ecf67740453fa218782328c31f0a.png#pic_center) 然后将屏厂提供的初始化序列复制进来 ![在这里插入图片描述](https://img-blog.csdnimg.cn/f5371d7141564697950a186b48a0aab9.png#pic_center) 然后按照 `spi_lcd` 框架的接口改写驱动接口,具体接口如下 | 屏厂函数 | SPILCD框架接口 | | :------------- | :--------------------- | | `LCD_WR_REG` | `sunxi_lcd_cmd_write`| | `LCD_WR_DATA8` | `sunxi_lcd_para_write` | | `delay_ms` | `sunxi_lcd_delay_ms` | 可以直接进行替换 ![在这里插入图片描述](https://img-blog.csdnimg.cn/f462741b8ad74f91bd4ecbb56aaa6f02.png#pic_center) 完成后如下 ![在这里插入图片描述](https://img-blog.csdnimg.cn/760b1082ed4246f9815ec5d091e373bc.png#pic_center) 然后对照屏厂提供的驱动修改 `address` 函数 ![在这里插入图片描述](https://img-blog.csdnimg.cn/44c5bf4dea0b47fbaf6cfb183b20ae31.png#pic_center) 做如下修改 ```c static void address(unsigned int sel, int x, int y, int width, int height) { sunxi_lcd_cmd_write(sel, 0x2B); /* Set row address */ sunxi_lcd_para_write(sel, (y >> 8) & 0xff); sunxi_lcd_para_write(sel, y & 0xff); sunxi_lcd_para_write(sel, (height >> 8) & 0xff); sunxi_lcd_para_write(sel, height & 0xff); sunxi_lcd_cmd_write(sel, 0x2A); /* Set coloum address */ sunxi_lcd_para_write(sel, (x >> 8) & 0xff); sunxi_lcd_para_write(sel, x & 0xff); sunxi_lcd_para_write(sel, (width >> 8) & 0xff); sunxi_lcd_para_write(sel, width & 0xff); sunxi_lcd_cmd_write(sel, 0x2c); } ``` 完成驱动如下 ```c #include "st7789v.h" static void LCD_power_on(u32 sel); static void LCD_power_off(u32 sel); static void LCD_bl_open(u32 sel); static void LCD_bl_close(u32 sel); static void LCD_panel_init(u32 sel); static void LCD_panel_exit(u32 sel); #define RESET(s, v) sunxi_lcd_gpio_set_value(s, 0, v) #define power_en(sel, val) sunxi_lcd_gpio_set_value(sel, 0, val) static struct disp_panel_para info[LCD_FB_MAX]; static void address(unsigned int sel, int x, int y, int width, int height) { sunxi_lcd_cmd_write(sel, 0x2B); /* Set row address */ sunxi_lcd_para_write(sel, (y >> 8) & 0xff); sunxi_lcd_para_write(sel, y & 0xff); sunxi_lcd_para_write(sel, (height >> 8) & 0xff); sunxi_lcd_para_write(sel, height & 0xff); sunxi_lcd_cmd_write(sel, 0x2A); /* Set coloum address */ sunxi_lcd_para_write(sel, (x >> 8) & 0xff); sunxi_lcd_para_write(sel, x & 0xff); sunxi_lcd_para_write(sel, (width >> 8) & 0xff); sunxi_lcd_para_write(sel, width & 0xff); sunxi_lcd_cmd_write(sel, 0x2c); } static void LCD_panel_init(unsigned int sel) { if (bsp_disp_get_panel_info(sel, &info[sel])) { lcd_fb_wrn("get panel info fail!\n"); return; } sunxi_lcd_cmd_write(sel, 0x11); // Sleep out sunxi_lcd_delay_ms(120); // Delay 120ms //************* Start Initial Sequence **********// sunxi_lcd_cmd_write(sel, 0x36); sunxi_lcd_para_write(sel, 0x00); sunxi_lcd_cmd_write(sel, 0x3A); sunxi_lcd_para_write(sel, 0x05); sunxi_lcd_cmd_write(sel, 0xB2); sunxi_lcd_para_write(sel, 0x1F); sunxi_lcd_para_write(sel, 0x1F); sunxi_lcd_para_write(sel, 0x00); sunxi_lcd_para_write(sel, 0x33); sunxi_lcd_para_write(sel, 0x33); sunxi_lcd_cmd_write(sel, 0xB7); sunxi_lcd_para_write(sel, 0x35); sunxi_lcd_cmd_write(sel, 0xBB); sunxi_lcd_para_write(sel, 0x20); // 2b sunxi_lcd_cmd_write(sel, 0xC0); sunxi_lcd_para_write(sel, 0x2C); sunxi_lcd_cmd_write(sel, 0xC2); sunxi_lcd_para_write(sel, 0x01); sunxi_lcd_cmd_write(sel, 0xC3); sunxi_lcd_para_write(sel, 0x01); sunxi_lcd_cmd_write(sel, 0xC4); sunxi_lcd_para_write(sel, 0x18); // VDV, 0x20:0v sunxi_lcd_cmd_write(sel, 0xC6); sunxi_lcd_para_write(sel, 0x13); // 0x13:60Hz sunxi_lcd_cmd_write(sel, 0xD0); sunxi_lcd_para_write(sel, 0xA4); sunxi_lcd_para_write(sel, 0xA1); sunxi_lcd_cmd_write(sel, 0xD6); sunxi_lcd_para_write(sel, 0xA1); // sleep in后,gate输出为GND sunxi_lcd_cmd_write(sel, 0xE0); sunxi_lcd_para_write(sel, 0xF0); sunxi_lcd_para_write(sel, 0x04); sunxi_lcd_para_write(sel, 0x07); sunxi_lcd_para_write(sel, 0x04); sunxi_lcd_para_write(sel, 0x04); sunxi_lcd_para_write(sel, 0x04); sunxi_lcd_para_write(sel, 0x25); sunxi_lcd_para_write(sel, 0x33); sunxi_lcd_para_write(sel, 0x3C); sunxi_lcd_para_write(sel, 0x36); sunxi_lcd_para_write(sel, 0x14); sunxi_lcd_para_write(sel, 0x12); sunxi_lcd_para_write(sel, 0x29); sunxi_lcd_para_write(sel, 0x30); sunxi_lcd_cmd_write(sel, 0xE1); sunxi_lcd_para_write(sel, 0xF0); sunxi_lcd_para_write(sel, 0x02); sunxi_lcd_para_write(sel, 0x04); sunxi_lcd_para_write(sel, 0x05); sunxi_lcd_para_write(sel, 0x05); sunxi_lcd_para_write(sel, 0x21); sunxi_lcd_para_write(sel, 0x25); sunxi_lcd_para_write(sel, 0x32); sunxi_lcd_para_write(sel, 0x3B); sunxi_lcd_para_write(sel, 0x38); sunxi_lcd_para_write(sel, 0x12); sunxi_lcd_para_write(sel, 0x14); sunxi_lcd_para_write(sel, 0x27); sunxi_lcd_para_write(sel, 0x31); sunxi_lcd_cmd_write(sel, 0xE4); sunxi_lcd_para_write(sel, 0x1D); // 使用240根gate(N+1)*8 sunxi_lcd_para_write(sel, 0x00); // 设定gate起点位置 sunxi_lcd_para_write(sel, 0x00); // 当gate没有用完时,bit4(TMG)设为0 sunxi_lcd_cmd_write(sel, 0x21); sunxi_lcd_cmd_write(sel, 0x29); if (info[sel].lcd_x < info[sel].lcd_y) address(sel, 0, 0, info[sel].lcd_x - 1, info[sel].lcd_y - 1); else address(sel, 0, 0, info[sel].lcd_y - 1, info[sel].lcd_x - 1); } static void LCD_panel_exit(unsigned int sel) { sunxi_lcd_cmd_write(sel, 0x28); sunxi_lcd_delay_ms(20); sunxi_lcd_cmd_write(sel, 0x10); sunxi_lcd_delay_ms(20); sunxi_lcd_pin_cfg(sel, 0); } static s32 LCD_open_flow(u32 sel) { lcd_fb_here; /* open lcd power, and delay 50ms */ LCD_OPEN_FUNC(sel, LCD_power_on, 50); /* open lcd power, than delay 200ms */ LCD_OPEN_FUNC(sel, LCD_panel_init, 200); LCD_OPEN_FUNC(sel, lcd_fb_black_screen, 50); /* open lcd backlight, and delay 0ms */ LCD_OPEN_FUNC(sel, LCD_bl_open, 0); return 0; } static s32 LCD_close_flow(u32 sel) { lcd_fb_here; /* close lcd backlight, and delay 0ms */ LCD_CLOSE_FUNC(sel, LCD_bl_close, 50); /* open lcd power, than delay 200ms */ LCD_CLOSE_FUNC(sel, LCD_panel_exit, 10); /* close lcd power, and delay 500ms */ LCD_CLOSE_FUNC(sel, LCD_power_off, 10); return 0; } static void LCD_power_on(u32 sel) { /* config lcd_power pin to open lcd power0 */ lcd_fb_here; power_en(sel, 1); sunxi_lcd_power_enable(sel, 0); sunxi_lcd_pin_cfg(sel, 1); RESET(sel, 1); sunxi_lcd_delay_ms(100); RESET(sel, 0); sunxi_lcd_delay_ms(100); RESET(sel, 1); } static void LCD_power_off(u32 sel) { lcd_fb_here; /* config lcd_power pin to close lcd power0 */ sunxi_lcd_power_disable(sel, 0); power_en(sel, 0); } static void LCD_bl_open(u32 sel) { sunxi_lcd_pwm_enable(sel); /* config lcd_bl_en pin to open lcd backlight */ sunxi_lcd_backlight_enable(sel); lcd_fb_here; } static void LCD_bl_close(u32 sel) { /* config lcd_bl_en pin to close lcd backlight */ sunxi_lcd_backlight_disable(sel); sunxi_lcd_pwm_disable(sel); lcd_fb_here; } /* sel: 0:lcd0; 1:lcd1 */ static s32 LCD_user_defined_func(u32 sel, u32 para1, u32 para2, u32 para3) { lcd_fb_here; return 0; } static int lcd_set_var(unsigned int sel, struct fb_info *p_info) { return 0; } static int lcd_set_addr_win(unsigned int sel, int x, int y, int width, int height) { address(sel, x, y, width, height); return 0; } static int lcd_blank(unsigned int sel, unsigned int en) { return 0; } struct __lcd_panel st7789v_panel = { /* panel driver name, must mach the name of lcd_drv_name in sys_config.fex */ .name = "st7789v", .func = { .cfg_open_flow = LCD_open_flow, .cfg_close_flow = LCD_close_flow, .lcd_user_defined_func = LCD_user_defined_func, .blank = lcd_blank, .set_var = lcd_set_var, .set_addr_win = lcd_set_addr_win, }, }; ``` ### 对接驱动框架 完成了屏幕驱动的编写,接下来需要对接到 SPILCD 驱动框架。首先编辑 `Kconfig` ![在这里插入图片描述](https://img-blog.csdnimg.cn/6184177560d74796b273c74088a2e84a.png#pic_center) 增加 `st7789v` 的配置 ![在这里插入图片描述](https://img-blog.csdnimg.cn/5cad60f560124b44a529c6b70a1509b1.png#pic_center) ``` config LCD_SUPPORT_ST7789 bool "LCD support st7789v panel" default n ---help--- If you want to support st7789v panel for display driver, select it. ``` 然后编辑 `panels.c` 在 `panel_array` 里增加 `st7789` 驱动的引用 ![在这里插入图片描述](https://img-blog.csdnimg.cn/41660ee66cb744ceba491682e9be76d0.png#pic_center) 如下图 ![在这里插入图片描述](https://img-blog.csdnimg.cn/0578192dae08440b910b4fe960060001.png#pic_center) ```c #ifdef CONFIG_LCD_SUPPORT_ST7789V &st7789v_panel, #endif ``` 之后编辑 `panels.h` 同样增加引用 ![在这里插入图片描述](https://img-blog.csdnimg.cn/7019659b468d42cc89fb899f5411f74e.png#pic_center) 如下图 ![](https://img-blog.csdnimg.cn/3dd9d4bce6e9473496eac962ef1b568a.png#pic_center) ```c #ifdef CONFIG_LCD_SUPPORT_ST7789V extern struct __lcd_panel st7789v_panel; #endif ``` 最后编辑外层的 `Makefile` 增加编译选项 ![在这里插入图片描述](https://img-blog.csdnimg.cn/60ef8d1b3d3243f389e3f6cd495f074a.png#pic_center) 如下所示 ![在这里插入图片描述](https://img-blog.csdnimg.cn/2c35828b34a145388c987a5c330ca04a.png#pic_center) ```c obj-${CONFIG_LCD_SUPPORT_ST7789V} += panels/st7789v.o ``` ### 选择 ST7789V 驱动 在 SPILCD 驱动选择界面可以看到 `LCD_FB panels select` 选择 SPI 屏幕的驱动 进入 `LCD_FB panels select` 选项 ![在这里插入图片描述](https://img-blog.csdnimg.cn/a889ae1d29f6460583e632a551b6e093.png#pic_center) 选择并勾选 `[*] LCD support st7789v panel` ![](https://img-blog.csdnimg.cn/69d5d88a1649472dacff973a19a25545.png#pic_center) ### 配置 SPI LCD 引脚 这里是重点部分:打开你喜欢的编辑器,修改文件:`board/r128s2/module/configs/sys_config.fex` ``` [lcd_fb0] lcd_used = 1 lcd_model_name = "spilcd" lcd_driver_name = "st7789v" ; 屏幕规格配置 lcd_x = 240 lcd_y = 240 lcd_width = 48 lcd_height = 48 ; SPI 速率 lcd_data_speed = 50 ; PWM 背光配置项 lcd_pwm_used = 1 lcd_pwm_ch = 1 lcd_pwm_freq = 5000 lcd_pwm_pol = 0 lcd_backlight = 100 ; 配置 lcd_if = 1 为 DBI 模式,双缓冲 lcd_if = 1 fb_buffer_num = 2 ; 配置屏幕传输数据的像素格式,这里是 LCDFB_FORMAT_RGB_565 lcd_pixel_fmt = 10 ; 配置 DBI 接口像素格式,这里是 RGB565 lcd_dbi_fmt = 2 ; 配置 DBI 时钟的行为模式,这里是自动停止模式。有数据就有时钟,没发数据就没有时钟 lcd_dbi_clk_mode = 0 ; 屏幕没有 TE 脚,配置 TE 为 0 lcd_dbi_te = 0 ; 配置屏幕 DBI 格式 L4I1 lcd_dbi_if = 2 ; 输入图像数据 RGB 顺序识别设置,这里配置是 RGB 格式 lcd_rgb_order = 0 ; 设置屏的刷新率,单位Hz。当lcd_dbi_te使能时,这个值设置无效。 lcd_fps = 60 ; 使用 SPI1 作为通讯接口 lcd_spi_bus_num = 1 lcd_frm = 2 lcd_gamma_en = 1 lcd_power_num = 0 lcd_gpio_regu_num = 0 lcd_bl_percent_num= 0 ;RESET Pin lcd_gpio_0 = port:PA20<1><0><2><0> ``` ## 编译打包 运行命令 `mp` 编译打包,可以看到编译了 `st7789v.o` ![在这里插入图片描述](https://img-blog.csdnimg.cn/a8b7262375b54b7286a6ddb2b97d139e.png#pic_center) ## 测试 烧录启动之后,屏幕背光启动,但是屏幕全黑。 ![](https://img-blog.csdnimg.cn/3d714493e89a448f852fcb584dd028d4.png#pic_center) 输入 `test_spilcd` ,屏幕显示蓝色。 ![](https://img-blog.csdnimg.cn/c4d343a8c4424320b211ddcfefd5a4d0.png#pic_center) 输入 `lv_examples 1` 可以显示 `lvgl` 界面 ![在这里插入图片描述](https://img-blog.csdnimg.cn/f8b72153672644689b5586d7d5212e87.png#pic_center) ## 常见问题 ### LVGL 颜色异常 这是由于 LVGL 配置的 `LV_COLOR_DEPTH` 为 32,但是 SPI 屏配置为16位。请修改 `lv_conf.h`,也请注意 `LV_COLOR_16_SWAP` 仅有 SPI 需要设置为 1,在使用 DBI 驱动的时候不需要配置为 1。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/f3302889303e45a7897fe78aa6b3217a.png#pic_center) ### 出现部分花屏 ![在这里插入图片描述](https://img-blog.csdnimg.cn/bc31e070b4d244949b1bd8bb09ad3df1.png#pic_center) - 检查 `address` 函数是否正确 - 检查 `sys_config.fex` 屏幕配置分辨率是否正确 ### SPI LCD 颜色相关问题 首先,得先确定显示屏使用的是SPI接口,还是DBI接口,不同的接口,输入数据的解析方式是不一样的。 DBI接口的全称是 `Display Bus Serial Interface` ,在显示屏数据手册中,一般会说这是SPI接口,所以有人会误认为SPI屏可以使用 `normal spi` 去直接驱动。 阅读`lcd_dbi_if`部分的介绍可以知道,在3线模式时,发送命令前有1位A0用于指示当前发送的是数据,还是命令。而命令后面接着的数据就没有这个A0位了,代表SPI需要在9位和8位之间来回切换,而在读数据时,更是需要延时 `dummy clock` 才能读数据,`normal spi` 都很难,甚至无法实现。所以 `normal spi` 只能模拟4 线的DBI的写操作。 对于R128这类支持DBI接口的CPU,可以选择不去了解SPI。如果需要用到SPI去驱动显示屏,必须把显示屏设置成小端。 #### RGB565和RGB666 SPI显示屏一般支持RGB444,RGB565和RGB666,RGB444使用的比较少,所以只讨论RGB565和RGB666. RGB565代表一个点的颜色由2字节组成,也就是R(红色)用5位表示,G(绿色)用6位表示,B(蓝色)用5位表示,如下图所示: ![在这里插入图片描述](https://img-blog.csdnimg.cn/1b37132e522941fda0340b0205a32265.png#pic_center) RGB666一个点的颜色由3字节组成,每个字节代表一个颜色,其中每个字节的低2位会无视,如下图所示: ![在这里插入图片描述](https://img-blog.csdnimg.cn/268d13e7804a4729b5bf129ea1c6bfe5.png#pic_center) #### SPI 接口 因为SPI接口的通讯效率不高,所以建议使用RGB565的显示,以 `jlt35031c` 显示屏为例,他的显示驱动芯片是 `ST7789v`,设置显示格式的方式是往 `3a` 寄存器写入`0x55(RGB565`)或者 `0x66(RGB666)`,在 `R128SDK` 中,已经把 `jlt35031c` 的通讯格式写死为 `0x55`,`lcd_pixel_fmt`配置选项无效: ``` sunxi_lcd_cmd_write(sel, 0x3a); sunxi_lcd_para_write(sel, 0x55); ``` 在例程中,输入的数据是 `0xff,0x00,0xff,0x00`,对于SPI接口,是按字节发送。实际上,例程只需要每次发送2字节即可,因为前后发送的都是相同的ff 00,所以没有看出问题。 根据对 `565` 的数据解析,我们拆分 `ff 00` 就可以得到红色分量是 `0b11111`,也就是 `31`,绿色是`0b111000`,也就是 `56`,,蓝色是 `0`.我们等效转换成 `RGB888`,有: ``` R = 31/31*255 = 255 G = 56/63*255 = 226 ``` 在调色板输入对应颜色,就可以得到黄色 ![在这里插入图片描述](https://img-blog.csdnimg.cn/237d0993b6994ccdb71f1423801d0b7f.png#pic_center) 因为 `DBI` 通讯效率较高,所以可以使用 `RGB565` 或者 `RGB666`,使用 `DBI` 接口,也就是 `lcd_if` 设置为`1`时,驱动会根据 `lcd_pixel_fmt` 配置寄存器,以 `SDK` 中的 `kld2844b.c` 为例,这显示屏的显示驱动也是 `ST7789`,但是不同的屏幕,厂家封装时已经限制了通讯方式,所以即使是能使用 DBI 接口的驱动芯片的屏幕,或许也用不了DBI。 ```c 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); } ``` 对于 DBI 格式,不再是以字节的形式去解析,而是以字的方式去解析,为了统一,软件已经规定了,`RGB565` 格式时,字大小是2字节,也就是16位,而 `RGB666` 格式时,字大小是4字节,也就是32位。 对于 `RGB565` 格式,同样是设置为 `0xff,0x00`。因为屏幕是大端,而芯片存储方式是小端,所以芯片的 DBI 模块,会自动把数据从新排列,也就是实际上 DBI 发送数据时,会先发送`0x00`,再发送`0xff`,也就是红色分量为0,绿色分量为 `0b000111`,也就是7,蓝色分量是 `0x11111`,也就是31,我们同样转换成RGB888 ``` G = 7/63*255 = 28 B= 31/31*255 = 255 ``` 在调色板上输入,可以得到蓝色。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/2fd27af6103e459c863582701ebe8b28.png#pic_center) 如果是 `RGB666`,虽然占用的是3个字节,但是没有CPU是3字节对齐的,所以需要一次性输入4字节,然后 DBI 硬件模块,会自动舍弃1个字节,软件同意舍弃了最后一个字节。 依旧以例程为例,例程输入了 `0xff,0x00,0xff,0x00`,为了方便说明,标准为 `0xff(1),0x00(1),0xff(2),0x00(2)`,其中 `0x00(2)`会被舍弃掉,然后发送顺序是`0xff(2),0x00(1),0xff(1)`,也就是 `0xff(2)` 是红色分量,`0xff(1)` 是蓝色分量,混合可以得到紫色。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/44054a44b83f4e2a9773084e8394495d.png#pic_center)
此帖出自
国产芯片交流论坛
点赞
关注
(0)
回复
分享
扫一扫,分享给好友
复制链接分享
链接复制成功,分享给好友
举报
提升卡
变色卡
千斤顶
返回列表
发新帖
回复
您需要登录后才可以回帖
登录
|
注册
发表回复
回帖后跳转到最后一页
浏览过的版块
淘e淘
嵌入式系统
DSP 与 ARM 处理器
活动
更多>>
免费申请测评 | RDK X3机器人开发套件
中星联华直播 | 高速信号完整性分析与测试 — “码”上行动系列线上讲堂
新栏目器件口碑专辑上线~快来点评吧!
2024 DigiKey 应用说:大模型时代的智能汽车
有奖直播报名中!抢占工业4.1先机 文晔科技日等你来!
罗姆有奖直播 | 重点解析双极型晶体管的实用选型方法和使用方法
STM32N6终于要发布了,ST首款带有NPU的MCU到底怎么样,欢迎小伙们来STM32全球线上峰会寻找答案!
免费下载 | 安森美电动汽车充电白皮书,看碳化硅如何缓解“里程焦虑”!
开源项目
更多>>
ADM7150CP-EVALZ,用于评估 ADM7150 线性稳压器的评估板
SnaillPI_v3x
xl1583e1正负电源模块
WIFI Switch :ESP8266-01用于远程开关控制
LTC4214 负电压热插拔控制器的典型应用
AD8602WARZ-R7 符合 PC100 标准的线路输出放大器的典型应用
DC1935A-A,用于 LT4363-1 具有电流限制的高压浪涌抑制器的演示板,闩锁版本
(待验证) U2硬盘盒
LT3091HT7 并联器件使用 IMONN 消除镇流器电阻压降的典型应用
梳子lzq
随便看看
如下电路该如何分析?
[i=s]本帖最后由乱世煮酒论天下于2024-12-322:31编辑[/i]直流电压源幅值100V,正弦电流源幅值电压105V,以直流源负极为绝对零点针对这种交直流混有,而且含有非线性器件的电路该怎么分析?叠加定理只适用于线性电路[attach]867053[/attach][attach]867062[/at ...
建议谨慎采购美国芯片~~~
ADS7828,IIC信号线初始存在一定电平0.45,再正常升高至3.3V,会导致芯片初始状异常么
兼容DC
新编博士版“大腕”台词
开关电源的电磁干扰问题研究和解决方法
RoHS知识
电源芯片
查找数据手册?
搜索
EEWorld Datasheet 技术支持
热门标签
源代码
单片机
放大器
TI
ST
电源
分立器件
传感器
测试测量
模拟
无刷式测速发电机
窄线宽激光器
区域传感器
窗口比较器
模拟比较器
汽车线束
微波传输
串行接口
BLDC电机
双通道
相关文章
更多>>
首款NPU和首款64位,德州仪器C2000推出诚意满满的升级路线图
在刚刚过去的德国慕尼黑电子展上,德州仪器(TI)展示了最新的C2000 MCU新品, 包括支持NPU的F28P55X以及业界首款64位MCU F29H85X ,同时在慕展嵌入式论坛上,TI还发表了两
AMD Zen4处理器循环缓冲区功能被悄然禁用
12月3日消息,据媒体报道,近日在BIOS更新后,AMD在Zen 4架构的处理器中悄然禁用了循环缓冲区(Loop Buffer)功能,具体原因尚未公开。 循环缓冲区是CPU前端的一部分,用于存储少量
美国发布新半导体出口管制措施 光刻机巨头ASML:正在评估潜在影响
12月3日消息,日前,光刻机巨头ASML(阿斯麦)发布声明,称美国发布最新版先进计算和半导体制造设备规则,对出口芯片制造技术的供应商施加了更多限制。 这些规定将立即生效,其中一些变更的合规日期将延迟
消息称苹果有望2026下半年推出折叠iPhone,并重振折叠屏手机市场
美国升级对华半导体管制,140家中国半导体公司被列入“实体清单”
安森美二十五周年:唯有创新,才可持续
华为麒麟9020/9030/9040处理器曝光:小步快跑 四大方面升级
特斯拉FSD V13.2用户实测:表现惊艳,可实现“点对点”自动驾驶
AI助力探索癌症最佳诊疗方法
新型催化剂将水解制氢效率提高200倍
新帖速递
STM32和无源蜂鸣器播放声音的问题
车规级AECQ200介绍,混合铝电解电容器的选择
嵌入式教程_DSP技术_DSP实验箱操作教程:2-28 搭建轻量级WEB服务器实验
OPA847IDBVR运放器国产替代
AG32VF407测试UART
【得捷电子Follow Me第二期】第一章 收到货物的分享
请问这个红外接收头是什么型号?能用哪个型号代替?谢谢
出售全新未拆封ZYNQ 7Z020 FPGA核心板
用在锂电池供电的水表设置上的LORA模块,当有100块水表集中安装在一个楼道内时,节能
请问一下,当某个端口被设置为 RX0后,这个端口的输入输出方向还有必要设置吗
今年怎么这么难,比疫情时还难,三十了面临失业好迷茫
请教稳压管测试问题
【小华HC32F448测评】关于小华半导体的UART中断发送和PRINTF构造和重定向
【BIGTREETECH PI开发板】 HDMI输出测试
【BIGTREETECH PI开发板】+08.音频测试(zmj)
免费申请测评:RDK X3机器人开发套件
RDK X3是一款面向生态开发者的嵌入式AI开发板,具备5Tops的端侧推理能力,40pin接口兼容树莓派。搭载了伯努利2.0BPU和4核ARM A53处理器。拥有先进的ISP处理算法,使得在宽动态、低照度场景下,也能得到高质量的图像;同时具备强大的视频处理能力,可同时处理多路Camera Sensor的输入并支持H.264/H.265编解码。
查看 »
等待很久的STM32N6终于要发布了!
ST首款带有NPU的MCU到底怎么样,欢迎小伙们来STM32全球线上峰会寻找答案!报名峰会,还能赢【开发板、京东卡】呦~12月12日14:00不见不散!
查看 »
有奖直播报名| 高可靠性IGBT新选择 —— 安世半导体650V IGBT
【直播时间】12月19日(周四)下午15:00-16:30
【直播好礼】定制双肩商务包、30元京东卡、吸管玻璃杯
查看 »
安世半导体直播报名中
直播主题:安世半导体理想二极管与负载开关,保障物联网应用的稳健高效运行
直播时间:12月17日(周二)下午14:00
报名就有机会获得:定制双肩商务包、30元京东卡、吸管玻璃杯
查看 »
PI 电源小课堂 | 无 DC-DC 变换实现多路高精度输出反激电源
时间:即日起-12月15日
看视频学习电源干货,答题赢取京东卡!
查看 »
Littelfuse 新品赋能电子产品安全可靠并高效, 10+挑战等你探索!
Littelfuse 应用赋能星球,覆盖了诸多应用痛点及解决办法,邀请工程师一起探索,解锁更多设计力!
查看 »
下载资料赢好礼!看Vicor模块化电源解决方案如何推动创新
活动时间:即日起-2024年12月31日
如何参与:点击活动页内您想了解的模块,找到资料下载即可参与抽奖,活动结束后统一发奖!
查看 »
有奖活动|英飞凌高密度双相电源模块为高性能运算平台而生
活动时间:即日起-12月15日
活动奖励:蓝牙音箱、氮化镓充电器套装、黑色小背包
查看 »
本月精选下载推荐:
Vishay——选型-汽车级表面贴装和通孔超快整流器
查看 »
本周精选下载推荐:电源管理基础Dummies
本周小编给大家带来一本超简单、超干货的电子书——《电源管理基础Dummies》!内容深入浅出,排版舒服简洁,分分钟能get到电源管理最核心的知识内容。
查看 »
关闭
站长推荐
1
/10
电子工程世界版权所有
京B2-20211791
京ICP备10001474号-1
电信业务审批[2006]字第258号函
京公网安备 11010802033920号
Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复
返回顶部
返回列表
论坛首页
版块列表
专业技术中心
TI技术论坛
ST传感器与低功耗无线技术论坛
ADI参考电路
DigiKey得捷技术专区
ADI · 世健工业技术
电子技术交流
嵌入式系统
单片机
国产芯片交流
电机驱动控制
FPGA/CPLD
模拟电子
电源技术
PCB技术
RF/无线
传感器
综合技术交流
下载中心专版
大学堂专版
测评中心专版
创意与实践
电子竞赛
DIY/开源硬件专区
淘e淘
创意市集
行业应用
汽车电子
移动便携
医疗电子
工控电子
安防电子
休息一下
聊聊、笑笑、闹闹
工作这点儿事
为我们提意见&公告
EEWorld颁奖专区
信息发布
最新帖子
最新帖子
最新回复
精华
消灭零回复
测评中心
活动中心
积分兑换
E金币兑换
芯积分
厂商专区
TI技术论坛
ST传感器与低功耗无线技术论坛