【ESP32】打造全网最强esp-idf基础教程——11.LVGL移植(基于ST7789芯片)

使用ESP32驱动ST7789,效果很好的IPS显示屏 前言 在平台上面购买了这一种模块,然后这种模块是IPS液晶屏,显示效果会比早期那种好一些。显示屏的控制芯片是ST7789 我准备使用ESP32进行驱动,测试上使用简单的Arduino IDE,那么具体要怎么样让这一屏幕正常的显示? 应用库与具体配置 如果是使用avr的MCU例如Arduino UNO一类可以使用这一个库,GitHub - cbm80amiga/Arduino_ST7789_Fast: Fast SPI library for the ST7789 IPS 阅读详情
AI摘要

本文详细介绍了LVGL图形用户界面库的移植过程,以及如何在ESP32上使用SPI接口驱动ST7789显示屏。内容涵盖LVGL源码获取、显示驱动初始化、SPI配置与ST7789初始化命令,适合嵌入式系统开发者学习。

LVGL移植(基于ST7789芯片)

       风吹又日晒的打工日暂且告一段落,又到本公主的周末闲暇时光,在琐碎的日子里发发我的博客,看到有那么多支持我的小伙伴们点赞,心里乐开了花❀话不多说,且看以下:

一、前言
       本课内容涵盖了SPI、LCD、LVGL知识,每一个点单独来讲都是比较丰富的内容,尤其是LVGL,LVGL(Light and Versatile Graphics Library)是一个开源的图形用户界面(GUI)库,专为嵌入式系统设计,旨在提供轻量级、高度可移植、灵活且易于使用的图形界面解决方案。该库支持在不同的操作系统、微控制器以及图形加速器上运行,非常适合资源有限的嵌入式设备,其源码较多,功能较为庞大,可以单独的开一门课程去讲。那么本节课只涉及到LVGL的移植、SPI和LCD驱动接口的使用、以及demo演示。
       本节课内容也不少,因为SPI、LCD、LVGL显示三者在这节课中关系密切,因此我这边合起来一起描述。

二、LVGL源码获取和移植
       大家可以从https://github.com/lvgl/lvgl.git上获取LVGL最新的源码,LVGL目前最新的源码已更新到9.X,不同的版本之间接口基本难以兼容,因此我们需要选定一个版本,在这个版本基础上再去开发我们的显示程序,在本例程中使用的是8.3.10版本。大家先看esp32-board/display目录结构是这样的:

       被我标红的就是lvgl仓库的源码,目前我用git子仓库的形式引入,里面的内容我没有改动,只是把版本切换到了8.3.10,同时大家可能注意到,lvgl是以组件形式引入到这个工程的(目录解析具体可看第3个教程),路径在display/components/lvgl,另外我们也添加了一个bsp组件,bsp组件中用于存放与板相关的代码,我们把lvgl移植相关的代码也放在这里,具体的移植代码位于lv_port.c中。现在我们看下lv_port.c中具体有什么内容。
       先看一下与LVGL显示直接相关的初始化函数 

/**
 * @brief 注册LVGL显示驱动
 *
 */
static void lv_port_disp_init(void)
{
    static lv_disp_draw_buf_t draw_buf_dsc;
    size_t disp_buf_height = 40;

    /* 必须从内部RAM分配显存,这样刷新速度快 */
    lv_color_t *p_disp_buf1 = heap_caps_malloc(LCD_WIDTH * disp_buf_height * sizeof(lv_color_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA);
    lv_color_t *p_disp_buf2 = heap_caps_malloc(LCD_WIDTH * disp_buf_height * sizeof(lv_color_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA);
    ESP_LOGI(TAG, "Try allocate two %u * %u display buffer, size:%u Byte", LCD_WIDTH, disp_buf_height, LCD_WIDTH * disp_buf_height * sizeof(lv_color_t) * 2);
    if (NULL == p_disp_buf1 || NULL == p_disp_buf2) {
        ESP_LOGE(TAG, "No memory for LVGL display buffer");
        esp_system_abort("Memory allocation failed");
    }
    /* 初始化显示缓存 */
    lv_disp_draw_buf_init(&draw_buf_dsc, p_disp_buf1, p_disp_buf2, LCD_WIDTH * disp_buf_height);
    /* 初始化显示驱动 */
    lv_disp_drv_init(&disp_drv);
    /*设置水平和垂直宽度*/
    disp_drv.hor_res = LCD_WIDTH;
    disp_drv.ver_res = LCD_HEIGHT;
    /* 设置刷新数据函数 */
    disp_drv.flush_cb = disp_flush;
    /*设置显示缓存*/
    disp_drv.draw_buf = &draw_buf_dsc;
    /*注册显示驱动*/
    lv_disp_drv_register(&disp_drv);
}

       在LVGL中,要想显示内容,首先得告诉LVGL你的显示驱动信息,显示驱动信息包含显示刷新缓存、显示屏的宽高、显示输出函数这三个信息。 

       lv_disp_draw_buf_init函数用于初始化显示缓存,把用户定义的缓存设置到draw_buf_dsc显示缓存描述结构体上,这里要注意,我们使用esp-idf内存管理接口heap_caps_malloc申请的缓存一定要用MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA修饰,因为SPI传输RGB数据用的是DMA方式,这种方式无法应用于外部PSRAM,只能从内部IRAM进行申请。

       lv_disp_drv_init函数用于按默认配置初始化一个显示驱动disp_drv。 

       之后我们对disp_drv这个驱动进行设置,包括显示宽高、缓存、显示数据输出函数,显示数据输出函数disp_flush是需要我们实现的,当LVGL进行完界面的绘画后,最终是要调用这个函数将RGB显示数据输出到LCD屏上,实现如下:

 

/**
 * @brief 写入显示数据
 *
 * @param disp_drv  对应的显示器
 * @param area      显示区域
 * @param color_p   显示数据
 */
static void disp_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p)
{
    (void) disp_drv;
    st7789_flush(area->x1, area->x2 + 1, area->y1,area->y2 + 1, color_p);
}

       在disp_flush函数中,实际是调用了st7789驱动里面的刷新函数,将数据写入到st7789中,关于st7789的驱动我们在后面一节会讲到。 

      最后调用lv_disp_drv_register把这个显示驱动注册到LVGL中。
除了要设置显示驱动之外,还需要给LVGL设置一个定时器,这个定时器的功能是给LVGL做一些动画效果的,比如平移、缩放等,都需要用到这个定时器来进行计时操作。

/**
 * @brief LVGL定时器时钟
 *
 * @param pvParam 无用
 */
static void lv_tick_inc_cb(void *data)
{
    uint32_t tick_inc_period_ms = *((uint32_t *) data);
    lv_tick_inc(tick_inc_period_ms);
}
/**
 * @brief 创建LVGL定时器
 *
 * @return esp_err_t
 */
static esp_err_t lv_port_tick_init(void)
{
    static uint32_t tick
stm32驱动st7789 TFT-LCD屏幕显示 stm32驱动tft-lcd显示图片、文字、字符串 阅读详情

相关推荐

快速入门ESP32——移植LVGL(保姆级教程)

在上一期我们移植了TFT_eSPI库成功点亮了LCD,本期就教大家怎么在platform上移植LVGL。温馨提醒:请确保你的LCD能正常使用快速入门ESP32——点亮你的第一个LCD屏幕ESP32S3+1.69LCD(无触摸),

mucherry的博客 1万+

ESP32基础应用之使用ESP-IDF自带程序实现LVGL

必填

while(1) 4952

STM32(HAL库)驱动st7789LCD屏幕(7引脚240*240)

屏幕厂家提供的都是标准库,网上找了找没看到好用的HAL库屏幕驱动,因此本文对HAL库驱动TFT屏幕进行详细讲解。

weixin_44597885的博客 6059

ArduPilot + Gazebo + Mavros + QGC + 遥控器:从仿真到实机的自主轨迹控制实践

本文详细介绍了基于ArduPilot、Gazebo、Mavros和QGC的无人机自主轨迹控制全流程实践。从仿真环境搭建、多终端协同配置,到遥控器集成与自主圆形轨迹算法实现,提供了完整的代码示例和实机迁移要点,帮助开发者快速掌握无人机自主控制技术。

corn8的博客 940

STM32G474片内运放实战:从独立模式到PGA与ADC采样链路

在嵌入式控制系统中,运放是连接模拟信号与数字处理的关键环节。传统方案依赖外部分立运放搭建放大电路,存在成本高、PCB布局敏感、一致性差等痛点。STM32G474在MCU内部集成多路可编程运放(OPAMP),支持独立模式、跟随器、PGA以及比较器模式,配合内部ADC和DMA可构成完整模拟采集链路。通过片内互联,信号路径大幅缩短,抗干扰性和通道一致性显著提升,尤其适用于电机电流采样、数字电源等场景。本文以STM32G474为例,详解从独立模式到PGA增益配置,再到ADC与DMA联动调试的完整过程,并给出采样时间

weixin_29194255的博客 245

SAP ABAP CO核心扩展-ZCKMLQS 多物料工厂的评估数量结构报表(CKMLQS)

CKMLQS 只能查看单一物料工厂的评估数量结构,SAP 没有提供多物料工厂的评估数量结构报表。这篇文章将实现 CO核心扩展-ZCKMLQS 多物料工厂的评估数量结构报表。

SAP李斌,本人承诺所有原创文章均不使用任何AI生成技术,请大家放心阅读。 1089

如何使用Github创建一个完全免费的个人网站

摘要: 本文详细介绍如何利用Github Pages免费搭建个人静态网站,适合零基础用户。首先需注册Github账号并创建特定命名的仓库(格式:用户名.github.io),然后通过网页或命令行创建index.html文件作为网站首页。完成后可通过"仓库设置- Pages"获取网站链接。文章还包含GitHub Desktop的安装使用、代码提交指南及常见问题自检方法,并说明即使Github被墙也可迁移至国内平台(如码云)。整个过程无需编程基础,仅需15分钟即可完成基础网站搭建。

安德洛夫 1513

亿图机床采集数据

这个数控系统的英文名是HUST,在台湾知名度还可以,但大陆这边我做这么多年项目也只接触过屈指可数的几次,可见市场占有率并不大,联网采集不复杂。

若云流风的专栏 2487

时间序列预测 — 预测数据集(负荷、风电、光伏、销量等)

GEFCom2014 “负荷预测数据”为竞赛的公共数据集,GEFCom2014 的负荷预测轨迹为概率负荷预测。

几度春风里的博客 2万+

YOLOv8改进策略【卷积层】| DEConv: 强度信息与梯度特征融合的细节增强 适用于小目标与细节目标检测任务

本文记录的是利用 模块优化 的目标检测网络模型。(Detail-Enhanced Convolution,细节增强卷积)的设计旨在,解决 目标检测网络中传统普通卷积缺乏目标细节相关先验、对小目标边缘、目标与背景边界等关键细节捕捉能力不足的问题,同时避免引入额外参数量与计算开销,以适配 对实时推理性能与检测精度的双重需求。DEA-Net: Single image dehazing based on detail-enhanced convolution and content-guided atte

Limiiiing的博客 346

LVGL 丝滑菜单3(Silk Menu)

h。

摸鱼专家 88

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

上一篇: 【ESP32】打造全网最强esp-idf基础教程——10.SDIO读写TF卡
下一篇: 【ESP32】打造全网最强esp-idf基础教程——12.ESP32中的分区表
盛夏的小公举
博客等级 码龄2年 484粉丝 18原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值