spi驱动st7789v1.47寸lcdr128 平台提供了 spi dbi 的 spi tft 接口,具有如下特点:
supports dbi type c 3 line/4 line interface modesupports 2 data lane interface modesupports data source from cpu or dmasupports rgb111/444/565/666/888 video formatmaximum resolution of rgb666 240 x 320@30hz with single data lanemaximum resolution of rgb888 240 x 320@60hz or 320 x 480@30hz with dual data lanesupports tearing effectsupports software flexible control video frame rate同时,提供了 spilcd 驱动框架以供 spi 屏幕使用。
此次适配的spi屏为 zjy147s0800tg01,使用的是 spi 进行驱动。
引脚配置如下:
r128 devkittft 模块pa12cspa13sclpa18sdapa9blkpa20respa19dc3v3vccgndgnd载入方案我们使用的开发板是 r128-devkit,需要开发 c906 核心的应用程序,所以载入方案选择 r128s2_module_c906
$ source envsetup.sh $ lunch_rtos 1
设置 spi 驱动屏幕使用的是spi驱动,所以需要勾选spi驱动,运行 mrtos_menuconfig 进入配置页面。前往下列地址找到 spi devices
drivers options --- > soc related device drivers --- > spi devices --- > -*- enable spi driver
配置 spi 引脚打开你喜欢的编辑器,修改文件:board/r128s2/module/configs/sys_config.fex,在这里我们不需要用到 spi hold与spi wp引脚,注释掉即可。
;----------------------------------------------------------------------------------;spi controller configuration;----------------------------------------------------------------------------------;please config spi in dts[spi1]spi1_used = 1spi1_cs_number = 1spi1_cs_bitmap = 1spi1_cs0 = port:pa12spi1_sclk = port:pa13spi1_mosi = port:pa18spi1_miso = port:pa21;spi1_hold = port:pa19;spi1_wp = port:pa20
设置 pwm 驱动屏幕背光使用的是pwm驱动,所以需要勾选pwm驱动,运行 mrtos_menuconfig 进入配置页面。前往下列地址找到 pwm devices
drivers options --- > soc related device drivers --- > pwm devices --- > -*- enable pwm driver
配置 pwm 引脚打开你喜欢的编辑器,修改文件:board/r128s2/module/configs/sys_config.fex,增加 pwm1 节点
[pwm1]pwm_used = 1pwm_positive = port:pa9
设置 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
编写 spi lcd 显示屏驱动获取屏幕初始化序列首先询问屏厂提供驱动源码
)
找到 lcd 的初始化序列代码
找到屏幕初始化的源码
整理后的初始化代码如下:
lcd_wr_reg(0x11);delay_ms(120);lcd_wr_reg(0x36);lcd_wr_data8(0x00);lcd_wr_reg(0x3a);lcd_wr_data8(0x05);lcd_wr_reg(0xb2);lcd_wr_data8(0x0c);lcd_wr_data8(0x0c);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(0x35);lcd_wr_reg(0xc0);lcd_wr_data8(0x2c);lcd_wr_reg(0xc2);lcd_wr_data8(0x01);lcd_wr_reg(0xc3);lcd_wr_data8(0x13);lcd_wr_reg(0xc4);lcd_wr_data8(0x20);lcd_wr_reg(0xc6);lcd_wr_data8(0x0f);lcd_wr_reg(0xd0);lcd_wr_data8(0xa4);lcd_wr_data8(0xa1);lcd_wr_reg(0xd6);lcd_wr_data8(0xa1);lcd_wr_reg(0xe0);lcd_wr_data8(0xf0);lcd_wr_data8(0x00);lcd_wr_data8(0x04);lcd_wr_data8(0x04);lcd_wr_data8(0x04);lcd_wr_data8(0x05);lcd_wr_data8(0x29);lcd_wr_data8(0x33);lcd_wr_data8(0x3e);lcd_wr_data8(0x38);lcd_wr_data8(0x12);lcd_wr_data8(0x12);lcd_wr_data8(0x28);lcd_wr_data8(0x30);lcd_wr_reg(0xe1);lcd_wr_data8(0xf0);lcd_wr_data8(0x07);lcd_wr_data8(0x0a);lcd_wr_data8(0x0d);lcd_wr_data8(0x0b);lcd_wr_data8(0x07);lcd_wr_data8(0x28);lcd_wr_data8(0x33);lcd_wr_data8(0x3e);lcd_wr_data8(0x36);lcd_wr_data8(0x14);lcd_wr_data8(0x14);lcd_wr_data8(0x29);lcd_wr_data8(0x32);lcd_wr_reg(0x21);lcd_wr_reg(0x11);delay_ms(120);lcd_wr_reg(0x29);用现成驱动改写 spi lcd 驱动选择一个现成的 spi lcd 改写即可,这里选择 nv3029s.c 驱动来修改
复制这两个驱动,重命名为 st7789v.c
先编辑 st7789v.h 将 nv3029s 改成 st7789v
#ifndef _st7789v_h#define _st7789v_h#include panels.hstruct __lcd_panel st7789v_panel;#endif /*end of file*/编辑 st7789v.c 将 nv3029s 改成 st7789v
编写初始化序列先删除 static void lcd_panel_init(unsigned int sel) 中的初始化函数。
然后将屏厂提供的初始化序列复制进来
然后按照 spi_lcd 框架的接口改写驱动接口,具体接口如下
屏厂函数
spilcd框架接口
lcd_wr_reg
sunxi_lcd_cmd_write
lcd_wr_data8
sunxi_lcd_para_write
delay_ms
sunxi_lcd_delay_ms
可以直接进行替换
完成后如下
然后对照屏厂提供的驱动修改 address 函数
做如下修改
static void address(unsigned int sel, int x, int y, int width, int height){ sunxi_lcd_cmd_write(sel, 0x2a); /* set coloum address */ sunxi_lcd_para_write(sel, (x + 34) > > 8); sunxi_lcd_para_write(sel, (x + 34)); sunxi_lcd_para_write(sel, (width + 34) > > 8); sunxi_lcd_para_write(sel, (width + 34)); sunxi_lcd_cmd_write(sel, 0x2b); /* set row address */ sunxi_lcd_para_write(sel, y > > 8); sunxi_lcd_para_write(sel, y); sunxi_lcd_para_write(sel, height > > 8); sunxi_lcd_para_write(sel, height); sunxi_lcd_cmd_write(sel, 0x2c);}完成驱动如下
#include st7789v.hstatic 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, 0x2a); /* set coloum address */ sunxi_lcd_para_write(sel, (x + 34) > > 8); sunxi_lcd_para_write(sel, (x + 34)); sunxi_lcd_para_write(sel, (width + 34) > > 8); sunxi_lcd_para_write(sel, (width + 34)); sunxi_lcd_cmd_write(sel, 0x2b); /* set row address */ sunxi_lcd_para_write(sel, y > > 8); sunxi_lcd_para_write(sel, y); sunxi_lcd_para_write(sel, height > > 8); sunxi_lcd_para_write(sel, height); 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); sunxi_lcd_delay_ms(120); 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, 0x0c); sunxi_lcd_para_write(sel, 0x0c); 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, 0x35); 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, 0x13); sunxi_lcd_cmd_write(sel, 0xc4); sunxi_lcd_para_write(sel, 0x20); sunxi_lcd_cmd_write(sel, 0xc6); sunxi_lcd_para_write(sel, 0x0f); 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); sunxi_lcd_cmd_write(sel, 0xe0); sunxi_lcd_para_write(sel, 0xf0); sunxi_lcd_para_write(sel, 0x00); sunxi_lcd_para_write(sel, 0x04); sunxi_lcd_para_write(sel, 0x04); sunxi_lcd_para_write(sel, 0x04); sunxi_lcd_para_write(sel, 0x05); sunxi_lcd_para_write(sel, 0x29); sunxi_lcd_para_write(sel, 0x33); sunxi_lcd_para_write(sel, 0x3e); sunxi_lcd_para_write(sel, 0x38); sunxi_lcd_para_write(sel, 0x12); sunxi_lcd_para_write(sel, 0x12); sunxi_lcd_para_write(sel, 0x28); sunxi_lcd_para_write(sel, 0x30); sunxi_lcd_cmd_write(sel, 0xe1); sunxi_lcd_para_write(sel, 0xf0); sunxi_lcd_para_write(sel, 0x07); sunxi_lcd_para_write(sel, 0x0a); sunxi_lcd_para_write(sel, 0x0d); sunxi_lcd_para_write(sel, 0x0b); sunxi_lcd_para_write(sel, 0x07); sunxi_lcd_para_write(sel, 0x28); sunxi_lcd_para_write(sel, 0x33); sunxi_lcd_para_write(sel, 0x3e); sunxi_lcd_para_write(sel, 0x36); sunxi_lcd_para_write(sel, 0x14); sunxi_lcd_para_write(sel, 0x14); sunxi_lcd_para_write(sel, 0x29); sunxi_lcd_para_write(sel, 0x32); sunxi_lcd_cmd_write(sel, 0x21); sunxi_lcd_cmd_write(sel, 0x11); sunxi_lcd_delay_ms(120); 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
增加 st7789v 的配置
config lcd_support_st7789v 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 驱动的引用
如下图
#ifdef config_lcd_support_st7789v &st7789v_panel,#endif之后编辑 panels.h 同样增加引用
如下图
#ifdef config_lcd_support_st7789vextern struct __lcd_panel st7789v_panel;#endif最后编辑外层的 makefile 增加编译选项
如下所示
obj-${config_lcd_support_st7789v} += panels/st7789v.o选择 st7789v 驱动在 spilcd 驱动选择界面可以看到 lcd_fb panels select 选择 spi 屏幕的驱动
进入 lcd_fb panels select 选项
选择并勾选 [*] lcd support st7789v panel
配置 spi lcd 引脚打开你喜欢的编辑器,修改文件:board/r128s2/module/configs/sys_config.fex
[lcd_fb0]lcd_used = 1 lcd_model_name = spilcd lcd_driver_name = st7789v lcd_x = 172 lcd_y = 320 lcd_width = 17 lcd_height = 32 lcd_data_speed = 50lcd_pwm_used = 1lcd_pwm_ch = 1lcd_pwm_freq = 5000 lcd_pwm_pol = 0 lcd_if = 0lcd_pixel_fmt = 11 lcd_dbi_fmt = 2lcd_dbi_clk_mode = 1lcd_dbi_te = 1fb_buffer_num = 2lcd_dbi_if = 4lcd_rgb_order = 0lcd_fps = 60lcd_spi_bus_num = 1lcd_frm = 2lcd_gamma_en = 1lcd_backlight = 100lcd_power_num = 0lcd_gpio_regu_num = 0lcd_bl_percent_num = 0lcd_spi_dc_pin = port:pa19;reset pinlcd_gpio_0 = port:pa20编译打包运行命令 mp 编译打包,可以看到编译了 st7789v.o
测试烧录启动之后,屏幕背光启动,但是屏幕全黑。
输入 test_spilcd ,屏幕显示黄色。
输入 lv_examples 1 可以显示 lvgl 界面
常见问题lvgl 出现 dma over size
这是由于 lvgl 配置的 lv_color_depth 为 32,但是 spi 屏配置为16位。请修改 lv_conf.h
滚珠螺杆螺母的加工方法
高压玻璃釉电阻简介
CI520读卡芯片兼容CV520支持ISO/IEC14443
简单的开关电源电路图分享 六款简单的开关电源电路设计方案
红米Note8评测 “宇宙良心”同价位无槽点
全志R128应用开发案例—适配SPI驱动ST7789V2.4寸LCD
基于ATECLOUD新能源汽车电机驱动电路测试方案
怎样去确保云存储的安全
是德科技发布高性能比特误码率测试解决方案
FPGA的优势和汽车电子主流需求吻合 利用FPGA提供灵活的解决方案
爆料称华为中国总部落户将丽泽SOHO
基于S3C2410微处理器和操作系统实现光电测量仿真检测系统的设计
中国芯片的全球并购投资该走向何方?
阳能发电原理及系统配置设置说明
仁寿第5代TFT-LCD高端显示器项目搬入首批设备
iOS10.2与10.2.1 Beta4相比怎么样?测试者:无明显性能差异
利用便携式功率记录仪进行负荷研究
将16x2显示器连接到树莓派
同步降压型DC/DC控制器LTC3858/-1的性能特点及功能应用
ivviV3评测 汇集时尚元素但性价比略低