LVGL移植

基于正点原子LVGL教程

移植工程

examples文件夹下只保留porting文件夹

将lv_conf_template.h文件改为lv_conf.h

将lv_conf.h的#if 0改为#if 1 

注意:因为LVGL官方库引用头文件使用了相对路径,因此在移植官方文件时,要将文件放在名为lvgl文件下

 --diag_suppress=68,111,188,223,546,1295

问题1:添加完工程之后如果有很多的报错

解决:查看自己有没有将lv_conf_template.h文件改为lv_conf.h

问题2:断言函数错误

解决1:取消Use MicroLIB选项

解决2:有人说自己写一个断言函数,但是我很菜不会。 

问题3:取消使用微库(MicroLIB)选项之后没有报错但是程序无法运行,调试运行总是卡在BKPT        0XAB

解决:

 网上说由于没有引入微库,使用了printf,打开编译器提供的标准输入输出补丁、就是使用printf()等函数后是直接返回而不是进入一个断电。

经过实验确实是因为没有使用微库使用了printf函数导致系统停在BKPT        0xAB

添加输出设备(显示器)

1、把examples下的porting文件下的lv_port_disp_template.c/h的条件编译指令#if 0改为#if 1

2、包含输出设备驱动头文件

3、在disp_init函数中初始化屏幕设备,设置横屏

4、配置图形数据缓冲模式

        1、单缓冲

使用宏将屏幕宽度的像素输入 

        2、双缓冲

        3、全屏双缓冲

其他两种注释掉

5、设置屏幕尺寸

6、在disp_flush函数中配置打点输出

添加输入设备 

1、把lv_port_indev_template.c/h的条件编译指令#if 0改为#if 1

2、按需求裁剪输入设备

3、包含输入设备驱动头文件

4、在对应输入设备初始化函数中初始化输入设备驱动

5、添加获取输入设备状态

用编码器作为输入设备

待添加

用触摸屏作为输入设备


/**
 * @brief       初始化触摸屏
 * @param       无
 * @retval      无
 */
static void touchpad_init(void)
{
    /*Your code comes here*/
    tp_dev.init();
    
    /* 电阻屏坐标矫正 */
    if (key_scan(0) == KEY0_PRES)           /* KEY0按下,则执行校准程序 */
    {
        lcd_clear(WHITE);                   /* 清屏 */
        tp_adjust();                        /* 屏幕校准 */
        tp_save_adjust_data();
    }
}


/**
 * @brief       获取触摸屏设备的状态
 * @param       无
 * @retval      返回触摸屏设备是否被按下
 */
static bool touchpad_is_pressed(void)
{
    /*Your code comes here*/
    tp_dev.scan(0);//获取触摸状态并设置触摸标志

    if (tp_dev.sta & TP_PRES_DOWN)//根据触摸状态是否被触摸
    {
        return true;
    }

    return false;
}

/**
 * @brief       在触摸屏被按下的时候读取 x、y 坐标
 * @param       x   : x坐标的指针
 *   @arg       y   : y坐标的指针
 * @retval      无
 */
static void touchpad_get_xy(lv_coord_t * x, lv_coord_t * y)
{
    /*Your code comes here*/
    (*x) = tp_dev.x[0];
    (*y) = tp_dev.y[0];
}

用按钮作为输入设备

待添加

提供时基

裸机

1、添加定时器驱动

2、在定时器驱动中包含:#include "lvgl.h"

3、在定时器中断函数中调用:lv_tick_inc(x);

4、初始化定时器时,需保证:进入中断的时间间隔 = x(ms)

注意:裸机需要我们自己提供时基,宏LV_TICK_CUSTOM需要置0,如果使用RTOS宏LV_TICK_CUSTOM需要置1,RTOS下面再讲

FreeRTOS 

1、在工程中添加RTOS文件目录

2、根据FreeRTOS移植将rtos一直到工程中

3、修改LVGL相关

 (2)自定义时钟源

 删除裸机提供时基部分代码

main函数

1、包含头文件

timer,lvgl.h,lv_port_disp_template.h,lv_port_indev_template.h

2、初始化定时器,LVGL库,输入输出设备

3、在while(1)中每隔5ms调用一次lv_timer_handler();

4、编写测试代码:

int main()
{
    systick_config();//开启Tick中断
    delay_init(); //延时初始化   
    MyledInit();//系统led初始化
    drv_uart_init(115200);// nvic_irq_enable(s_uart_info.irq, 0, 0);
   // LCD_Init();
    timer5_config(199,999);//1ms
    lv_init();
    lv_port_disp_init();
    lv_port_indev_init();
    
    lv_obj_t*switch_obj = lv_switch_create(lv_scr_act());
    lv_obj_set_size(switch_obj,120,60);
    lv_obj_align(switch_obj,LV_ALIGN_CENTER,0,0);
    
    printf("继续学习编程FreeRTOS,加油jiejie\r\n");   
    while(1)
    {
        

        delay_ms(5);
        lv_timer_handler();
    }
    

}

 压力测试实验

int main()
{
    systick_config();//开启Tick中断
    delay_init(); //延时初始化   
    MyledInit();//系统led初始化
    drv_uart_init(115200);// nvic_irq_enable(s_uart_info.irq, 0, 0);
   // LCD_Init();
    timer5_config(199,999);//1ms
    lv_init();
    lv_port_disp_init();
    lv_port_indev_init();
    
    lv_demo_stress();//压力测试函数

//    lv_obj_t*switch_obj = lv_switch_create(lv_scr_act());
//    lv_obj_set_size(switch_obj,120,60);
//    lv_obj_align(switch_obj,LV_ALIGN_CENTER,0,0);
    
    printf("继续学习编程FreeRTOS,加油jiejie\r\n");   
    while(1)
    {
        

        delay_ms(5);
        lv_timer_handler();
    }
    

}

问题与解决

问题1:添加完工程之后如果有很多的报错

解决:查看自己有没有将lv_conf_template.h文件改为lv_conf.h

问题2:断言函数错误

解决1:取消Use MicroLIB选项

解决2:有人说自己写一个断言函数,但是我很菜不会。 

问题3:取消使用微库(MicroLIB)选项之后没有报错但是程序无法运行,调试运行总是卡在BKPT        0XAB

解决:

 网上说由于没有引入微库,使用了printf,打开编译器提供的标准输入输出补丁、就是使用printf()等函数后是直接返回而不是进入一个断电。

经过实验确实是因为没有使用微库使用了printf函数导致系统停在BKPT        0xAB

问题3:为什么调试的时候点击运行,我没有打断点,为什么代码自动停下来了?

解决:同问题2,这是因为取消了微库使用,还使用了printf函数导致的。

问题4:为什么按照正点原子教程,屏幕啥都没有

解决:

第一种:优化中景园电子的颜色填充函数

在头文件中加入#include “lvgl.h”

/******************************************************************************
      函数说明:在指定区域填充颜色
      入口数据:xsta,ysta   起始坐标
                xend,yend   终止坐标
								color       要填充的颜色
      返回值:  无
******************************************************************************/
#if !LVGL_SYSTEM
void LCD_Fill(u16 xsta,u16 ysta,u16 xend,u16 yend,u16 color)
{          
	u16 i,j; 
	LCD_Address_Set(xsta,ysta,xend-1,yend-1);//设置显示范围
	for(i=ysta;i<yend;i++)
	{													   	 	
		for(j=xsta;j<xend;j++)
		{
			LCD_WR_DATA16(color);
		}
	} 					  	    
}
#endif

void LCD_Fill(u16 sx, u16 sy, u16 ex, u16 ey, lv_color_t *color)
{

	uint32_t y=0; 
	u16 height, width;
	width = ex - sx + 1;            //得到填充的宽度
  height = ey - sy + 1;           //高度
	
	LCD_Address_Set(sx,sy,ex,ey);
	
	for(y = 0; y <width*height; y++) 
	{
		LCD_WR_DATA16(color->full);
		color++;
  }
}

修改官方颜色填充函数

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*/
#if 0
    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++;
        }
    }
#endif
    LCD_Fill(area->x1 ,area->y1,area->x2,area->y2,color_p);

    /*IMPORTANT!!!
     *Inform the graphics library that you are ready with the flushing*/
    lv_disp_flush_ready(disp_drv);
}

方法二:使用打点函数,不使用区域填充函数

/******************************************************************************
      函数说明:在指定位置画点
      入口数据:x,y 画点坐标
                color 点的颜色
      返回值:  无
******************************************************************************/
void LCD_DrawPoint(u16 x,u16 y,u16 color)
{
	LCD_Address_Set(x,y,x,y);//设置光标位置 
	LCD_WR_DATA16(color);
} 


//官方颜色填充函数

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*/
#if 1
    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)*/
            LCD_DrawPoint(x,y,color_p->full);//添加自己的打点函数即可
            color_p++;
        }
    }
#else
     LCD_Fill(area->x1 ,area->y1,area->x2,area->y2,color_p);
#endif
//    /*IMPORTANT!!!
//     *Inform the graphics library that you are ready with the flushing*/
    lv_disp_flush_ready(disp_drv);
}

问题5:如果使用SRAM比较小的会出现内存不足,报错

在lv_conf.h里将48改为20即可

 

参考文章:

LVGL移植stm8.3超详细【stm32移植lvgl】_stm32f429 lvgl 8.3.5-优快云博客

### 将LVGL图形库移植到特定平台或设备 #### 移植准备阶段 为了成功将LVGL移植至目标平台,前期准备工作至关重要。这不仅涉及到软件层面的考量,也包括硬件兼容性的评估。确保所选的目标平台具备足够的处理能力和内存空间来支持LVGL的操作是非常重要的[^1]。 #### 下载并熟悉源码结构 获取最新的LVGL版本可以从官方GitHub仓库进行克隆操作。该仓库内含有详尽的README.md文档,它不仅是理解整个项目的基础资料,同时也指引着开发者如何进一步探索其他重要资源,比如API参考、教程和用户手册等[^3]。 ```bash git clone https://github.com/littlevgl/lvgl.git cd lvgl ``` #### 配置编译环境 针对不同操作系统(如Windows, Linux),需设置相应的工具链以便能够顺利编译LVGL及其依赖项。对于嵌入式Linux系统而言,则特别需要注意交叉编译器的选择与配置,以适应具体处理器架构的需求[^2]。 #### 实现显示接口函数 LVGL通过定义一系列抽象化的绘图命令集来实现跨平台特性;因此,在新平台上部署时,首要任务之一就是编写这些底层绘制指令的具体实现方法——即所谓的“端口化”。通常情况下,这部分工作会集中在`disp_drv.c`文件中完成,其中涵盖了屏幕刷新机制的设计以及像素数据传输路径的确立[^4]。 #### 输入事件处理模块定制 除了视觉呈现外,交互体验同样不可或缺。为此,还需为选定平台量身定做一套输入事件解析逻辑,用以捕捉来自触摸屏或其他外围设备的动作反馈,并将其转换成可供GUI框架识别的形式传递给上层应用层去响应用户的操作意图。 #### 测试验证环节 最后一步是对上述各组件进行全面的功能性和稳定性测试。借助于预先构建好的示例工程可以快速搭建起初步的应用场景来进行调试优化直至达到预期效果为止。此外,利用PC端模拟器也能有效辅助这一过程中的问题排查工作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值