嵌入式课程实现Linux操作系统LVGL移植操作

简介: 嵌入式课程实现Linux操作系统LVGL移植操作

1、介绍

上次我们完成了在Windows上移植LVGL到一个LCD工程当中,感兴趣的小伙伴可以到博主的主页当中去自行查找即可,然后接下来,我们进入到今天的正题,实现LInux操作系统的LVGL移植的操作过程!

2、移植

2.1 需要一个带有LCD代码的工程

下载源码:


LVGL官网:LVGL - Light and Versatile Embedded Graphics Library

LVGL代码库地址(Simulator、Source、Examples、Esp32、MicroPython):https://github.com/lvgl

LVGL源码下载地址:https://github.com/lvgl/lvgl  


拿到之后目录分支:

2.2 在自己工程目录下新建LVGL文件

在源码目录下复制:

复制后:

添加文件到工程:

工程目录新建2个分组:

Prot:

LVGLSRC:

还要添加CPU支持文件:

进去themes添加:

添加完成后要添加其他路径:

添加完编译报错:

.\Objects\NewProject.axf: Error: L6218E: Undefined symbol __aeabi_assert (referred from lv_tlsf.o).  

解决方法:取消微库

然后进行编译:

2.3 修改底层驱动

GUI ---跟屏幕的关系

打开驱动文件的条件编译 1 使能

选择显示方式:

有些单片机内存小的要用方式1

想要显示更新快那么选择2 DMA刷新  ------用这个屏幕是SPI屏 SPI使用DMA搬运显示提高速度 内存大---1M

这时候会发现方式二的东西没有定义许哟自己定义数组:

添加LCD头文件;

添加一个全局变量static lv_disp_drv_t *disp_drv_p;

此时我们定义的数组报错跳到这个头文件:打开编译

修改屏幕大小:

修改后:

复制使用DMA显示代码:

/*********************************************************************************************************
* 函 数 名 : DisPlay_SPI_DMA_Init
* 功能说明 : SPI3 DMA1初始化
* 形    参 : 无
* 返 回 值 : 无
* 备    注 : DMA1_Stream7搬运显示数据到SPI3的DR寄存器
*********************************************************************************************************/ 
static void DisPlay_SPI_DMA_Init()
{
    DMA_InitTypeDef  DMA_InitStructure  = {0};
  NVIC_InitTypeDef NVIC_InitStruct  = {0};
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); //DMA1时钟使能
    DMA_DeInit(DMA1_Stream7);
    while(DMA_GetCmdStatus(DMA1_Stream7) != DISABLE) {}  //等待DMA可配置
    /* 配置 DMA Stream */
    DMA_InitStructure.DMA_Channel         = DMA_Channel_0;          //通道选择
    DMA_InitStructure.DMA_PeripheralBaseAddr  = (unsigned int)&SPI3->DR;    //DMA外设地址
    DMA_InitStructure.DMA_Memory0BaseAddr     = (unsigned int)buf_2_1;    //DMA 存储器0地址
    DMA_InitStructure.DMA_DIR           = DMA_DIR_MemoryToPeripheral; //存储器到外设模式
    DMA_InitStructure.DMA_BufferSize      = sizeof(buf_2_2);        //数据传输量
    DMA_InitStructure.DMA_PeripheralInc     = DMA_PeripheralInc_Disable;  //外设非增量模式
    DMA_InitStructure.DMA_MemoryInc       = DMA_MemoryInc_Enable;     //存储器增量模式
    DMA_InitStructure.DMA_PeripheralDataSize  = DMA_PeripheralDataSize_Byte;  //外设数据长度:8位
    DMA_InitStructure.DMA_MemoryDataSize    = DMA_MemoryDataSize_Byte;    //存储器数据长度:8位
    DMA_InitStructure.DMA_Mode          = DMA_Mode_Normal;        //使用普通模式
    DMA_InitStructure.DMA_Priority        = DMA_Priority_High;      //中等优先级
    DMA_InitStructure.DMA_FIFOMode        = DMA_FIFOMode_Disable;     //不使用fifo
    DMA_InitStructure.DMA_FIFOThreshold     = DMA_FIFOThreshold_Full;   //fifo全容量
    DMA_InitStructure.DMA_MemoryBurst       = DMA_MemoryBurst_Single;   //存储器突发单次传输
    DMA_InitStructure.DMA_PeripheralBurst     = DMA_PeripheralBurst_Single; //外设突发单次传输
    DMA_Init(DMA1_Stream7, &DMA_InitStructure);                 //初始化DMA Stream
    SPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Tx, ENABLE); // SPI3使能DMA发送
  NVIC_InitStruct.NVIC_IRQChannel = DMA1_Stream7_IRQn;
  NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
  NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
  NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;
  NVIC_Init(&NVIC_InitStruct);
    DMA_ITConfig(DMA1_Stream7, DMA_IT_TC, ENABLE);
  DMA_Cmd(DMA1_Stream7, DISABLE);
}
/*********************************************************************************************************
* 函 数 名 : DisPlay_SPI_DMA_Enable
* 功能说明 : 配置DMA并启动一次传输
* 形    参 : buf:需要搬运的数据的指针;size:搬运的数据量
* 返 回 值 : 无
* 备    注 : 无
*********************************************************************************************************/ 
void DisPlay_SPI_DMA_Enable(void *buf, unsigned int size)
{
  DMA1_Stream7->CR &= ~(0x01);
  while((DMA1_Stream7->CR&0X1)){}
    DMA1_Stream7->M0AR = (unsigned int)buf;
    DMA1_Stream7->NDTR = size;
  DMA1_Stream7->CR |= (0x01); 
}
/*********************************************************************************************************
* 函 数 名 : DMA1_Stream7_IRQHandler
* 功能说明 : DMA1_Stream7发送完成中断
* 形    参 : 无
* 返 回 值 : 无
* 备    注 : 无
*********************************************************************************************************/ 
void DMA1_Stream7_IRQHandler(void)
{
    if(DMA_GetITStatus(DMA1_Stream7, DMA_IT_TCIF7) != RESET)
  //if(DMA1->HISR & (1<<27))
    {
    DMA_ClearITPendingBit(DMA1_Stream7, DMA_IT_TCIF7);
    //DMA1->HIFCR |= (1<<27);
    LCD_CS = 1;
    SPI3->DR; 
     lv_disp_flush_ready(disp_drv_p); /* tell lvgl that flushing is done */
    }
}

把DMA初始化放到disp_init初始化当中:

修改底层显示:

/* Flush the content of the internal buffer the specific area on the display
 * You can use DMA or any hardware acceleration to do this operation in the background but
 * 'lv_disp_flush_ready()' has to be called when finished. */
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
    /*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/
//    int32_t x;
//    int32_t y;
//    for(y = area->y1; y <= area->y2; y++) {
//        for(x = area->x1; x <= area->x2; x++) {
//            /* Put a pixel to the display. For example: */
//            /* put_px(x, y, *color_p)*/
//            color_p++;
//        }
//    }
    unsigned int size = (area->x2 - area->x1 + 1) * (area->y2 - area->y1 + 1) * 2;
    disp_drv_p = disp_drv;
    LCD_Address_Set(area->x1, area->y1, area->x2, area->y2+1);  
    LCD_CS = 0;
    DisPlay_SPI_DMA_Enable(color_p, size);
  /*不使用DMA的显示方法*/
//  LCD_Color_Fill(area->x1, area->y1, area->x2-area->x1, area->y2-area->y1+1, (unsigned short *)color_p);
    /* IMPORTANT!!!
     * Inform the graphics library that you are ready with the flushing*/
//    lv_disp_flush_ready(disp_drv);
}

2.4 心跳

初始化:

要使用图形库,必须对其进行初始化并设置所需的组件。初始化的顺序:

1、叫lv_init();

2、初始化驱动程序;

3、在LVGL中注册显示和输入设备驱动程序。详细了解显示和输入设备注册;

4、在终端中每隔一毫秒调试一次,向LVGL报告经过的时间。

5、每隔几毫秒调用一次,以处理与LVGL相关的任务。

使用定时器:

现在的LCD乱码的:

修改以下堆栈大小:否则代码一大直接崩溃

打开配置文件:

3、对象

LVGL使用的编程思想就是分类,按键是一个类,图片(按键模块)

 


相关文章
|
24天前
|
安全 Linux 数据安全/隐私保护
Vanilla OS:下一代安全 Linux 发行版
【10月更文挑战第30天】
44 0
Vanilla OS:下一代安全 Linux 发行版
|
2月前
|
人工智能 分布式计算 大数据
Linux操作系统:开源力量的崛起与影响###
一场技术革命的火种,如何燎原? 本文将带您深入探索Linux操作系统的诞生背景、核心特性及其对现代科技世界的深远影响。从1991年芬兰学生Linus Torvalds的一个小众项目,到如今成为支撑全球无数服务器、超级计算机及物联网设备的基石,Linux的发展既是一部技术创新史,也是开源文化胜利的见证。通过剖析其设计哲学、安全性、灵活性等关键优势,结合实例展示Linux在云计算、大数据处理等领域的广泛应用,本文旨在揭示Linux为何能在众多操作系统中脱颖而出,以及它如何塑造了我们今天的数字生活。 ###
|
2月前
|
安全 Linux 编译器
探索Linux内核的奥秘:从零构建操作系统####
本文旨在通过深入浅出的方式,带领读者踏上一段从零开始构建简化版Linux操作系统的旅程。我们将避开复杂的技术细节,以通俗易懂的语言,逐步揭开Linux内核的神秘面纱,探讨其工作原理、核心组件及如何通过实践加深理解。这既是一次对操作系统原理的深刻洞察,也是一场激发创新思维与实践能力的冒险。 ####
|
4天前
|
人工智能 安全 Linux
Linux操作系统的演变与未来趋势###
本文深入探讨了Linux操作系统从诞生至今的发展历程,分析了其开源模式对技术创新和IT行业的影响,并展望了Linux在未来技术生态中的角色。通过历史回顾、现状分析和未来预测,本文旨在为读者提供一个关于Linux操作系统全面而深入的视角。 ###
|
4天前
|
缓存 网络协议 Linux
深入探索Linux操作系统的内核优化策略####
本文旨在探讨Linux操作系统内核的优化方法,通过分析当前主流的几种内核优化技术,结合具体案例,阐述如何有效提升系统性能与稳定性。文章首先概述了Linux内核的基本结构,随后详细解析了内核优化的必要性及常用手段,包括编译优化、内核参数调整、内存管理优化等,最后通过实例展示了这些优化技巧在实际场景中的应用效果,为读者提供了一套实用的Linux内核优化指南。 ####
16 1
|
17天前
|
缓存 资源调度 安全
深入探索Linux操作系统的心脏——内核配置与优化####
本文作为一篇技术性深度解析文章,旨在引领读者踏上一场揭秘Linux内核配置与优化的奇妙之旅。不同于传统的摘要概述,本文将以实战为导向,直接跳入核心内容,探讨如何通过精细调整内核参数来提升系统性能、增强安全性及实现资源高效利用。从基础概念到高级技巧,逐步揭示那些隐藏在命令行背后的强大功能,为系统管理员和高级用户打开一扇通往极致性能与定制化体验的大门。 --- ###
47 9
|
17天前
|
缓存 运维 网络协议
深入Linux内核架构:操作系统的核心奥秘
深入Linux内核架构:操作系统的核心奥秘
36 2
|
21天前
|
缓存 网络协议 Linux
Linux操作系统内核
Linux操作系统内核 1、进程管理: 进程调度 进程创建与销毁 进程间通信 2、内存管理: 内存分配与回收 虚拟内存管理 缓存管理 3、驱动管理: 设备驱动程序接口 硬件抽象层 中断处理 4、文件和网络管理: 文件系统管理 网络协议栈 网络安全及防火墙管理
38 4
|
20天前
|
安全 网络协议 Linux
Linux操作系统的内核升级与优化策略####
【10月更文挑战第29天】 本文深入探讨了Linux操作系统内核升级的重要性,并详细阐述了一系列优化策略,旨在帮助系统管理员和高级用户提升系统的稳定性、安全性和性能。通过实际案例分析,我们展示了如何安全有效地进行内核升级,以及如何利用调优技术充分发挥Linux系统的潜力。 ####
44 1
|
23天前
|
物联网 Linux 云计算
Linux操作系统的演变与未来趋势####
【10月更文挑战第29天】 本文深入探讨了Linux操作系统从诞生至今的发展历程,分析了其在服务器、桌面及嵌入式系统领域的应用现状,并展望了云计算、物联网时代下Linux的未来趋势。通过回顾历史、剖析现状、预测未来,本文旨在为读者提供一个全面而深入的视角,以理解Linux在当今技术生态中的重要地位及其发展潜力。 ####