当前位置: 首页 > wzjs >正文

美国网站服务器百度链接收录

美国网站服务器,百度链接收录,贵州人才网最新招聘建筑类,网站开发怎么挣钱一、基本情况 本文代码基于以下软件版本: Arduino2.X LVGL8.3.11 GXEPD1.6.2 epdpaint---微雪EPD驱动的一部分,你可以在微雪的官网下载到 硬件: MCU:ESP32-S3-N16R8 屏幕:GDEY042Z98黑白红三色墨水屏,某…

一、基本情况

本文代码基于以下软件版本:

    Arduino2.X  

    LVGL8.3.11

    GXEPD1.6.2

    epdpaint---微雪EPD驱动的一部分,你可以在微雪的官网下载到

硬件:

    MCU:ESP32-S3-N16R8

    屏幕:GDEY042Z98黑白红三色墨水屏,某宝上买的。卖家给的资料是大连佳显的资料,但好像又不是大连佳显的屏,后面会说。驱动芯片是SSD1683。

二、LVGL中加载屏幕驱动

为什么要用LVGL来驱动?因为LVGL构建UI比较灵活快速呗。

之前写过一些关于LVGL的文章,提到了LVGL使用TFT-eSPI库来驱动显示屏的方法。

但是这次我们在TFT-eSPI中并没有找到合适的驱动。因为TFT-eSPI库是LVGL推荐的屏幕驱动库,所以刚开始时我还是尝试用厂商给的驱动来改,加入到TFT-eSPI库里面去,后来发现实在是有点麻烦,放弃了。

所以这次采用的是GxEPD2库驱动,因为该库里有GDEY042Z98的驱动。但是我们要用LVGL,而LVGL驱动的屏幕通常是普通液晶屏,所以要做一些调整,主要是颜色处理上。

所以,我们实际要做的是,把GxEPD2驱动适配到LVGL上去。

1.首先研究下GxEPD2

GxEPD2是一个专门驱动墨水屏的驱动库,支持的屏幕很多。

GxEPD2.cpp是其核心;再上一层是GXEPD2_3C.h、GXEPD2_4C.h、GXEPD2_7C.h、GXEPD2_BW.h分别是3色、4色、7色和黑白屏幕的适配层;然后再上一层是各种型号屏幕对应的封装,都放在不同的文件夹里了。

要使用该库驱动我手里的这块屏幕,只需要定义一个全局ePaper对象即可。

GxEPD2_3C<GxEPD2_420c_GDEY042Z98, GxEPD2_420c_GDEY042Z98::HEIGHT> ePaper(GxEPD2_420c_GDEY042Z98(/*CS=5*/ 11, /*DC=*/ 12, /*RST=*/ 9, /*BUSY=*/ 14));

注意定义ePaper对象时,我们已经选好了屏幕型号,屏幕颜色类型,同时把ESP32与屏幕之间连接的引脚(不包括SPI引脚)也传入进去了。

此外我们还要确定ESP32与墨水屏之间的SPI接口连接所使用的是哪个SPI口,引脚号是多少。这里全局定义使用HSPI。

SPIClass hspi(HSPI);

引脚我们需要在Arduino的setup部分代码去启动spi时传入,并将SPI口绑定到ePaper上去。

  hspi.begin(/*SCK_PIN*/10, /*MISO_PIN*/3, /*MOSI_PIN*/13, /*CS_PIN*/11); // remap hspi for EPD (swap pins)ePaper.epd2.selectSPI(hspi, SPISettings(1000000, MSBFIRST, SPI_MODE0));

到此GxEPD2就可以把屏幕驱动起来了。加入初始化代码,屏幕就会闪烁起来。

ePaper.init(); ePaper.setRotation(1);ePaper.clearScreen();

2.LVGL如何与GxEPD对接

(1)首先我们要搞清楚LVGL刷新屏幕的工作机制

LVGL驱动显示屏时,会定义一个屏幕刷新回调函数my_disp_flush()之类的。

这个函数的主要任务,就是把你定义的显示缓存,通过MCU与屏幕的连接端口,不停地往屏幕里面去写,从而实现屏幕显示的刷新。

LVGL会在你的程序在主循环中加入这种代码:

void loop() {lv_timer_handler(); /* let the GUI do its work */delay(5);
}

这个就是在主循环中往LVGL核心发信号,通知其不停刷新屏幕(当然还有些其他任务)。

(2)驱动墨水屏与普通液晶屏幕的区别

墨水屏是一种断电后显示不会消失的屏幕,但其刷新也比较麻烦,也很慢。

通常墨水屏的刷新分为:全刷、快刷、局刷,搞不懂的可以问一下AI。

我们要明确一点,墨水屏掉电后,其显示还保持,但是其显示缓存掉电后是会被清空的。

全刷和快刷我们要写所有缓存,局刷我们是写局部缓存。

(3)让LVGL刷新虚拟屏幕

读到这里,我想你应该想到了,LVGL的工作机制下并不适合墨水屏,普通液晶屏几十帧的FPS,墨水屏根本接收不了。

所以呢,我们得考虑一种间接的办法。这里我们考虑在MCU的内存中创建一块虚拟的屏幕,让LVGL去不停地刷新这块虚拟屏幕。只有在我们程序逻辑需要的时候,我们才调用墨水屏的刷新程序去刷新屏幕。

这个虚拟屏幕就是EPDPaint。它的源代码可以在微雪的EPD驱动程序里面找到。

结合代码来讲。下面代码我们定义了两个虚拟屏幕。

EXT_RAM_ATTR uint8_t img_buf_BW[MY_DISP_HOR_RES * MY_DISP_VER_RES / 8]; //整屏的显示图像缓存,每bit对应一个点
EXT_RAM_ATTR uint8_t img_buf_R[MY_DISP_HOR_RES * MY_DISP_VER_RES / 8]; //整屏的显示图像缓存,每bit对应一个点
Paint paint_BW(img_buf_BW, MY_DISP_HOR_RES, MY_DISP_VER_RES); //Paint对象,操作img_buf图像缓存
Paint paint_R(img_buf_R, MY_DISP_HOR_RES, MY_DISP_VER_RES); //Paint对象,操作img_buf图像缓存

为什么要定义两块呢?因为三色墨水屏里面有两部分显存。

第一部分是黑白的,其大小是屏幕WIDTH*HEIGHT/8;显存的1bit对应屏幕上一个像素点,bit=0显示黑,bit=1显示白。

第二部分是红色专用,其大小同样是WIDTH*HEIGHT/8;同样显存的1bit对应屏幕上一个像素点。bit=1是显示红色。注意如果bit=1了,那么黑白显存部分的bit是0还是1都不起作用了。

搞懂了这个逻辑,我们就可以在LVGL的显示刷新回调函数里,编写一个转换程序,报LVGL的显存转换到这个虚拟屏幕里来。

上显示刷新回调函数的代码。

static void my_disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{uint32_t w = (area->x2 - area->x1 + 1);uint32_t h = (area->y2 - area->y1 + 1);Serial.print("area x1 =");Serial.println(area->x1);Serial.print("area x2 =");Serial.println(area->x2);Serial.print("area y1 =");Serial.println(area->y1);Serial.print("area y2 =");Serial.println(area->y2);uint8_t r,g,b;uint8_t gray;for(int i = area->y1; i <= area->y2; i ++){for(int j = area->x1; j <= area->x2; j ++){// 提取 RGB 分量r = (color_p[(j-area->x1) + (i-area->y1)*w].ch.red);// 5 位红色g = (color_p[(j-area->x1) + (i-area->y1)*w].ch.green); // 6 位绿色b = (color_p[(j-area->x1) + (i-area->y1)*w].ch.blue);         // 5 位蓝色// 扩展到8位r = (r * 255) / 31;g = (g * 255) / 63;b = (b * 255) / 31;// 计算灰度值gray = (r * 77 + g * 150 + b * 29) >> 8;//Serial.println(gray);// 判断颜色if (gray < 128) { // 灰度值较低,可能是黑色或红色if (r > g && r > b && r > 32) { // 红色分量较强paint_R.DrawPixel(j, i, 0);paint_BW.DrawPixel(j, i, 0);              } else {paint_R.DrawPixel(j, i, 1);paint_BW.DrawPixel(j, i, 0);              }} else { // 灰度值较高,判定为白色paint_R.DrawPixel(j, i, 1);paint_BW.DrawPixel(j, i, 1);            }          }}lv_disp_flush_ready(disp_drv);
}

这个回调函数里,我们把LVGL的RGB565这种16色的颜色,转换到我们定义的虚拟屏幕上。使用的是虚拟屏幕Paint的DrawPixel方法绘制每个像素点。

(4)LVGL部分

到此,还没有讲LVGL的部分。其实LVGL部分的代码和普通的LVGL适配并没有太大的区别。

上LVGL部分代码。

//在全局定义static lv_disp_draw_buf_t draw_buf;static lv_color_t * buf;static lv_disp_drv_t disp_drv;//在setup部分初始化lv_init();// 初始化 LVGL 显示缓冲区buf = (lv_color_t*)ps_malloc(EPD_WIDTH * EPD_HEIGHT );lv_disp_draw_buf_init(&draw_buf, buf, NULL, EPD_WIDTH * EPD_HEIGHT);// 注册显示驱动lv_disp_drv_init(&disp_drv);disp_drv.hor_res = EPD_WIDTH;  // 设置水平分辨率disp_drv.ver_res = EPD_HEIGHT;  // 设置垂直分辨率disp_drv.flush_cb = my_disp_flush;  // 设置刷新回调函数disp_drv.draw_buf = &draw_buf;  // 设置显示缓冲区lv_disp_drv_register(&disp_drv);  // 注册显示驱动

注意这里我定义的LVGL显示缓存并不是推荐的屏幕的1/10,而是整屏,因为我的ESP32-S3有外挂PSRAM,内存够用,所以豪横,我就用ps_malloc把LVGL的显示缓存定义到了PSRAM里。

注意我前面定义Paint虚拟屏幕的代码时,也用EXT_RAM_ATTR关键字把其定义在了PSRAM里。

内存不够的情况下,可以把LVGL显存定义小些的。LVGL会自动根据你定义的缓存大小,在每次屏幕刷新回调函数只刷新一部分屏幕。比如定义成屏幕大小的1/10,那么每次只刷新屏幕的1/10,需要调用10次回调函数,整个屏幕才刷新完毕。这个你可以在回调函数里通过打印area参数指向的x1、x2、y1、y2变量观察到。

(5)虚拟屏幕到真实屏幕的刷新

这个调用一下刷新接口就可以了。上一个全刷的代码。在你的程序逻辑中需要刷新屏幕时,调用该函数就行了。但要注意屏幕刷新是很慢的,所以要注意程序逻辑超时的问题,可以考虑采用单独线程来刷新屏幕,避免主程序逻辑超时。

void refresh_ePaper()
{//因为存在本地图像缓冲区img_buf_BW和img_buf_R,因此每次刷新都是整屏刷//整屏刷也可以用局刷的方式,但使用一段时候后要执行一次全刷,提升显示效果//!!!如果要显示红色的东西,那么就需要全刷,因为局刷不支持红色ePaper.clearScreen();ePaper.drawImage((const uint8_t *)(paint_BW.GetImage()),(const uint8_t *)(paint_R.GetImage()),0,0,400,300,false,false,false);}

局刷的代码嘛,因为我手里这块屏的局刷有问题,使用大连佳显的原厂代码局刷也不行,所以我暂时还没有研究。待我花重金买原厂屏后再来测试。

三、补充的内容

1.关于颜色

LVGL绘制东西的时候,尽量把颜色都定义清楚,因为颜色有个映射转换过程,不想出现你意想不到的情况,就把颜色定义成黑白红三种纯色。包括字体、图形的边框等,否则可能出现颜色不够深,在转换程序里转换成了黑色或白色显示不出来的情况。

比如:

  lv_obj_set_style_text_color(label_Notes, lv_color_hex(0x000000), LV_PART_MAIN | LV_STATE_DEFAULT);//字体定义成黑色lv_obj_set_style_text_color(label_Notes, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT);//字体定义成白色lv_obj_set_style_text_color(label_Notes, lv_color_hex(0xFF0000), LV_PART_MAIN | LV_STATE_DEFAULT);//字体定义成红色//lv_color_hex(0xFF0000)三个字节分别对应RGB分量

2.我要做个什么出来

做这个东西的其他一些点,有时间我会写出来。

全文到这里也就结束了。本人业余选手纯为了玩,专业选手勿喷。

http://www.dtcms.com/wzjs/323781.html

相关文章:

  • 上海杨浦区网站建设百度营销客户端
  • 用织梦软件如何做网站培训
  • java怎么做网站流量统计关键词优化靠谱推荐
  • 湖南省郴州市永兴县邮政编码优化营商环境条例心得体会
  • 做游戏的网站有哪些win7系统优化大师
  • 手机做网站对比路由器做网站百度识图搜索网页版
  • 做网站需要哪些框架头条新闻今日头条官方版本
  • 域名备案怎么注销seo公司 引擎
  • 收到网站代码后怎么做网站推广的四个阶段
  • iis5.1发布网站友情链接购买
  • wordpress彩色标签云设置方法站内seo的技巧
  • 做淘宝设计能做网站吗如何查看一个网站的访问量
  • 乐清网站推广seo知名公司
  • 网站死链怎么办宁波seo怎么做推广渠道
  • 正规网站制作公司哪家好廊坊关键词优化报价
  • 西安哪些做网站的公司好如何在百度上投放广告
  • 做网站杭州镇江网络
  • 受欢迎的徐州网站建设重庆人社培训网
  • 手机网站建设广告推销网站
  • 重庆工程招标投标交易信息网seo点击排名
  • 广州分享网站建设百度百家号注册
  • 南昌公司做网站公关负面处理公司
  • 网站设计毕业设计论文seo关键词排名优化怎么收费
  • 北京网站推广服务博客网站seo
  • 苏州网站开发的企业2022百度seo优化工具
  • 龙岗的网站建设seo分析报告怎么写
  • 郑州网站建设 .cc搜索引擎网址
  • 郑州网站建设彳汉狮网络推广图片大全
  • 让医院做网站的策划书教育培训机构管理系统
  • 中考复读学校网站怎么做如何优化企业网站