🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 点屏之SPI屏 ili9488 ili9488常用于480x320高清小屏应用。支持8080 8/16并行总线,3/4线SPI接口。 驱动手册在此下载:https://pan.baidu.com/s/1pLZchuF 这里以4线SPI驱动讲解。 ## 设备树修改 ~~~ &spi0 { status = "okay"; ili9488@0 { compatible = "ilitek,ili9488"; reg = <0>; spi-max-frequency = <50000000>; rotate = <270>; fps = <30>; buswidth = <8>; regwidth = <8>; reset-gpios = <&pio 1 7 GPIO_ACTIVE_LOW>; dc-gpios = <&pio 1 5 GPIO_ACTIVE_LOW>; debug = <0>; }; }; ~~~ ## 代码修改 因为ili9486手册内容类似9488,所以拷贝一份命名为fb_ili9488.c,并在Kconfig和Makefile中增加对应项目。 编译后下载,开机,发现全屏间隔显示灰度条纹,且执行fbv命令显示内容无任何改变。 ![](https://box.kancloud.cn/1088f9b941217b2544d6267fa8b513cc_766x1024.jpg) 这说明9488还是不兼容9486。 通过对初始化命令的调试发现,是0x3a指令的问题。 虽然寄存器列表中有16bit命令,但是实际上是不支持的。 切换到18bit指令: ![](https://box.kancloud.cn/8bc3e422513d93bfb5256e8e4d6c70e2_1920x1436.jpg) 可见可以看到图像内容,且显示区域只有2/3高度,推测是cpu端以16bit输出,屏幕以18bit(补全后为3byte 24bit)解析导致。 查看fbtft-core.c代码,发现确实只实现了16bit 565的方法。 所以我们需要增加666的显示方法。 ### 新增666显示 #### 初始化序列 ~~~ static const s16 default_init_sequence[] = { /* Interface Mode Control */ -1, 0xb0, 0x0, -1, MIPI_DCS_EXIT_SLEEP_MODE, -2, 250, /* Interface Pixel Format */ -1, MIPI_DCS_SET_PIXEL_FORMAT, 0x66, /* Power Control 3 */ -1, 0xC2, 0x44, /* VCOM Control 1 */ -1, 0xC5, 0x00, 0x00, 0x00, 0x00, -1, MIPI_DCS_EXIT_SLEEP_MODE, -1, MIPI_DCS_SET_DISPLAY_ON, /* end marker */ -3 }; ~~~ #### fbtft-core fbtft_framebuffer_alloc 这个函数只为RGB565编写,所以需要修改 这里只考虑了bpp=8和16的情况 ~~~ vmem_size = display->width * display->height * bpp / 8; info->fix.line_length = width * bpp / 8; ~~~ 修改为 ~~~ int byteperpix = ( bpp + 7 ) / 8; vmem_size = display->width * display->height * byteperpix; info->fix.line_length = width * byteperpix; ~~~ 同时在9488的文件里也加上bpp信息为24bit。 (因为fb只支持8,16,24,32) 下面这段只考虑了565排序, ~~~ /* RGB565 */ info->var.red.offset = 11; info->var.red.length = 5; info->var.green.offset = 5; info->var.green.length = 6; info->var.blue.offset = 0; info->var.blue.length = 5; info->var.transp.offset = 0; info->var.transp.length = 0; ~~~ 幸好后面可以使用自己的驱动覆盖: ~~~ fbtft_merge_fbtftops(&par->fbtftops, &display->fbtftops); ~~~ 所以在9488文件中修改set_var: 注意这里的var只影响mplayer等软件的颜色。 fbv等软件的颜色受dts里的bgr影响。 ~~~ par->info->var.red.offset = 16; par->info->var.red.length = 8; par->info->var.green.offset = 8; par->info->var.green.length = 8; par->info->var.blue.offset = 0; par->info->var.blue.length = 8; ~~~ #### 增加write_vmem方法 ~~~ /* 18/24 bit pixel over 8-bit databus */ int fbtft_write_vmem24_bus8(struct fbtft_par *par, size_t offset, size_t len) { u8 *vmem8; u8 *txbuf8 = par->txbuf.buf; size_t remain; size_t to_copy; size_t tx_array_size; int i; int ret = 0; size_t startbyte_size = 0; fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s(offset=%zu, len=%zu)\n", __func__, offset, len); remain = len / 3; vmem8 = (u8 *)(par->info->screen_buffer + offset); if (par->gpio.dc != -1) gpio_set_value(par->gpio.dc, 1); /* non buffered write */ if (!par->txbuf.buf) return par->fbtftops.write(par, vmem8, len); /* buffered write, /4*4 to faster */ tx_array_size = par->txbuf.len / 3 / 4 *4; if (par->startbyte) { txbuf8 = par->txbuf.buf + 1; tx_array_size -= 1; *(u8 *)(par->txbuf.buf) = par->startbyte | 0x2; startbyte_size = 1; } while (remain) { to_copy = min(tx_array_size, remain); dev_dbg(par->info->device, " to_copy=%zu, remain=%zu\n", to_copy, remain - to_copy); for (i = 0; i < to_copy/4; i++) { //faster copy *(u32*)(txbuf8+i*12) = *(u32*)(vmem8+i*12); *(u32*)(txbuf8+4+i*12) = *(u32*)(vmem8+4+i*12); *(u32*)(txbuf8+8+i*12) = *(u32*)(vmem8+8+i*12); } for(i = to_copy/4*4; i < to_copy; i++) { txbuf8[i*3] = vmem8[i*3]; txbuf8[i*3+1] = vmem8[i*3+1]; txbuf8[i*3+2] = vmem8[i*3+2]; } vmem8 = vmem8 + to_copy*3; ret = par->fbtftops.write(par, par->txbuf.buf, startbyte_size + to_copy * 3); if (ret < 0) return ret; remain -= to_copy; } return ret; } EXPORT_SYMBOL(fbtft_write_vmem24_bus8); ~~~ 然后在9488的文件里修改为: ~~~ static struct fbtft_display display = { .regwidth = 8, .width = WIDTH, .height = HEIGHT, .bpp = BPP, .init_sequence = default_init_sequence, .fbtftops = { .set_addr_win = set_addr_win, .set_var = set_var, .write_vmem = fbtft_write_vmem24_bus8, }, }; ~~~ ## 编译运行 显示效果如下: ![](https://box.kancloud.cn/b8d7b7ab59bc6b0bea9a06b29c27b048_1024x766.jpg) 播放视频效果如下: http://v.youku.com/v_show/id_XMzM5OTAyNjY5Mg==.html 视频中使用50MHz spi时钟,会显卡顿和撕裂。 实测60MHz以上时钟可以流畅播放,但是由于杜邦线过长,会出现水波纹,如果在实际产品中使用较短走线和地包围,应该没有问题。