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

1,LVGL(V8.3.10版本)裸机移植教程

        最近在学习NXP的Guider软件,图形化设计LVGL并导入到自己的STM32_LVGL工程中。由于LVGL版本问题导致很多的API函数不同,报错很多。(STM32工程是正点原子的例程LVGL 版本为 V8.2、而Guider设计软件的LVGL版本为V8.3.10)。

        为了适用Guider(LVGL版本V8.3.10)的设计,本教程将从头带领我们一起移植LVGL到STM32工程中。

一、移植前准备资料

        移植前我们需要准备STM32工程(包含内存管理、LCD显示、触摸屏、定时器中断这四种功能),我这里是均采用正点原子的例程。以及LVGL源码版本为V8.3.10,可以在官网找到或者GitHub仓库找到。

https://github.com/lvgl/lvgl/releaseshttp://LVGL的GitHub仓库

1.1 STM32裸机工程

        将内存管理、LCD显示、触摸屏、定时器中断这四种相关文件添加到裸机移植\Drivers\BSP位置。

        并在keil5中添加相关的.c文件和头文件路径。

1.2 LVGL源码

        官网下载的LVGL源码有许多是用不上的,我们需要进行裁剪再添加到STM32裸机工程中。下面是解压缩的LVGL源码:

1.2.1  文件夹裁剪

        将.github、docs、env_support、scripts、tests文件夹删除,仅保留如下三个文件夹:

1.2.2  文件裁剪

        再此页面仅保留lvgl.h、lv_conf_template.h,其余文件均删除,并且将lv_conf_template.h重命名为lv_conf.h。裁剪完毕后如下:

1.2.3 裁剪examples文件夹

        examples文件夹仅保留porting文件夹,其余文件夹均删除掉。

1.2.4 复制文件夹、文件到工程目录

        首先创建如下LVGL目录:

将demos文件夹复制到如下目录:工程名称\Middlewares\LVGL\GUI_APP

再将其他文件和文件夹复制到如下目录:工程名称\Middlewares\LVGL\GUI\lvgl

         ​​​​​​​     

二、Keil V5添加LVGL文件

2.1 .c文件的添加

        在Keil V5中添加工程目录,在目录下分别添加如下的.c源文件。

        在Keil V5中添加工程目录:

2.2 头文件路径添加

        根据如下图片选择头文件路径进行添加:

三、修改代码

3.1 LVGL时基

        在btime.c文件中添加lvgl的1ms心跳节拍。

添加lvgl头文件:

#include "lvgl.h"

在定时器中断回调函数中添加lvgl心跳函数:

/*** @brief       回调函数,定时器中断服务函数调用* @param       无* @retval      无*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{if (htim->Instance == BTIM_TIMX_INT){lv_tick_inc(1);                 /*lvgl的1ms心跳*/}
}

mian.c中初始化BTIM定时器为1ms周期:

    btim_timx_int_init(10-1,8400-1);    /* 初始化定时器1ms */

3.2 开启配置文件

        打开lvgl_conf.h文件,将#if 0 改为 #if 1,开启配置文件:

#if 1 /*Set it to "1" to enable content*/

3.3 配置显示屏

        配置显示屏主要与两个文件有关:lv_port_disp_template.c和lv_port_disp_template.h。两个文件目录位置在:工程名称/Middlewares/lvgl/examples/porting。

3.3.1 开启文件

        将lv_port_disp_template.c和lv_port_disp_template.h中的#if 0 改为 #if 1:

3.3.2 在.c文件添加头文件

               主要是将控制LCD的头文件添加到lv_port_disp_template.c。

/* 导入lcd驱动头文件 */
#include "./BSP/LCD/lcd.h"

3.3.3 设置屏幕分辨率

        我这里使用的是正点原子4.3寸的屏幕。分辨率为800x480:

#define MY_DISP_HOR_RES (800)   /* 屏幕宽度 */
#define MY_DISP_VER_RES (480)   /* 屏幕高度 */

3.3.4 定义正点原子LCD绘制函数

        此函数用于刷新显示函数disp_flush()中,原有LVGL自带的刷新绘制效率较低。

/*** @brief       LCD加速绘制函数* @param       (sx,sy),(ex,ey):填充矩形对角坐标,区域大小为:(ex - sx + 1) * (ey - sy + 1)* @param       color:要填充的颜色* @retval      无*/
void lcd_draw_fast_rgb_color(int16_t sx, int16_t sy,int16_t ex, int16_t ey, uint16_t *color)
{uint16_t w = ex-sx+1;uint16_t h = ey-sy+1;lcd_set_window(sx, sy, w, h);uint32_t draw_size = w * h;lcd_write_ram_prepare();for(uint32_t i = 0; i < draw_size; i++){lcd_wr_data(color[i]);}
}

3.3.5  修改显示屏初始化函数

        将lcd的初始化函数传入lvgl初始化显示中。

/*Initialize your display and the required peripherals.*/
static void disp_init(void)
{/*You code here*/lcd_init();         /* 初始化LCD */lcd_display_dir(1); /* 设置横屏 */
}

3.3.6 修改刷新显示函数

        添加3.3.4 定义正点原子LCD绘制函数。

/*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)
{
//    if(disp_flush_enabled) {
//        /*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++;
//            }
//        }
//    }lcd_draw_fast_rgb_color(area->x1,area->y1,area->x2,area->y2,(uint16_t*)color_p);/*IMPORTANT!!!*Inform the graphics library that you are ready with the flushing*/lv_disp_flush_ready(disp_drv);
}

3.4 配置触摸输入

        配置触摸输入主要与两个文件有关:lv_port_indev_template.c和lv_port_indev_template.h。两个文件目录位置在:工程名称/Middlewares/lvgl/examples/porting。

3.4.1 开启文件

        将lv_port_disp_template.c和lv_port_disp_template.h中的#if 0 改为 #if 1:

3.4.2 在.c文件添加头文件

               主要是将控制触摸的头文件添加到lv_port_indev_template.c。

/* 导入驱动头文件 */
#include "./BSP/TOUCH/touch.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"

3.4.3 屏蔽其他静态原型

        除触摸屏外,其他输入均注释掉。

/***********************  STATIC PROTOTYPES**********************/static void touchpad_init(void);
static void touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data);
static bool touchpad_is_pressed(void);
static void touchpad_get_xy(lv_coord_t * x, lv_coord_t * y);//static void mouse_init(void);
//static void mouse_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data);
//static bool mouse_is_pressed(void);
//static void mouse_get_xy(lv_coord_t * x, lv_coord_t * y);//static void keypad_init(void);
//static void keypad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data);
//static uint32_t keypad_get_key(void);//static void encoder_init(void);
//static void encoder_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data);
//static void encoder_handler(void);//static void button_init(void);
//static void button_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data);
//static int8_t button_get_pressed_id(void);
//static bool button_is_pressed(uint8_t id);

3.4.4 屏蔽其他静态变量

        除触摸屏外,其他输入均注释掉。

/***********************  STATIC VARIABLES**********************/
lv_indev_t * indev_touchpad;
//lv_indev_t * indev_mouse;
//lv_indev_t * indev_keypad;
//lv_indev_t * indev_encoder;
//lv_indev_t * indev_button;//static int32_t encoder_diff;
//static lv_indev_state_t encoder_state;

 3.4.5 屏蔽其他初始化函数

        除触摸屏外,其他输入均注释掉。

/***********************   GLOBAL FUNCTIONS**********************/void lv_port_indev_init(void)
{/*** Here you will find example implementation of input devices supported by LittelvGL:*  - Touchpad*  - Mouse (with cursor support)*  - Keypad (supports GUI usage only with key)*  - Encoder (supports GUI usage only with: left, right, push)*  - Button (external buttons to press points on the screen)**  The `..._read()` function are only examples.*  You should shape them according to your hardware*/static lv_indev_drv_t indev_drv;/*------------------* Touchpad* -----------------*//*Initialize your touchpad if you have*/touchpad_init();/*Register a touchpad input device*/lv_indev_drv_init(&indev_drv);indev_drv.type = LV_INDEV_TYPE_POINTER;indev_drv.read_cb = touchpad_read;indev_touchpad = lv_indev_drv_register(&indev_drv);/*------------------* Mouse* -----------------*//*Initialize your mouse if you have*/
//    mouse_init();//    /*Register a mouse input device*/
//    lv_indev_drv_init(&indev_drv);
//    indev_drv.type = LV_INDEV_TYPE_POINTER;
//    indev_drv.read_cb = mouse_read;
//    indev_mouse = lv_indev_drv_register(&indev_drv);//    /*Set cursor. For simplicity set a HOME symbol now.*/
//    lv_obj_t * mouse_cursor = lv_img_create(lv_scr_act());
//    lv_img_set_src(mouse_cursor, LV_SYMBOL_HOME);
//    lv_indev_set_cursor(indev_mouse, mouse_cursor);//    /*------------------
//     * Keypad
//     * -----------------*///    /*Initialize your keypad or keyboard if you have*/
//    keypad_init();//    /*Register a keypad input device*/
//    lv_indev_drv_init(&indev_drv);
//    indev_drv.type = LV_INDEV_TYPE_KEYPAD;
//    indev_drv.read_cb = keypad_read;
//    indev_keypad = lv_indev_drv_register(&indev_drv);//    /*Later you should create group(s) with `lv_group_t * group = lv_group_create()`,
//     *add objects to the group with `lv_group_add_obj(group, obj)`
//     *and assign this input device to group to navigate in it:
//     *`lv_indev_set_group(indev_keypad, group);`*///    /*------------------
//     * Encoder
//     * -----------------*///    /*Initialize your encoder if you have*/
//    encoder_init();//    /*Register a encoder input device*/
//    lv_indev_drv_init(&indev_drv);
//    indev_drv.type = LV_INDEV_TYPE_ENCODER;
//    indev_drv.read_cb = encoder_read;
//    indev_encoder = lv_indev_drv_register(&indev_drv);//    /*Later you should create group(s) with `lv_group_t * group = lv_group_create()`,
//     *add objects to the group with `lv_group_add_obj(group, obj)`
//     *and assign this input device to group to navigate in it:
//     *`lv_indev_set_group(indev_encoder, group);`*///    /*------------------
//     * Button
//     * -----------------*///    /*Initialize your button if you have*/
//    button_init();//    /*Register a button input device*/
//    lv_indev_drv_init(&indev_drv);
//    indev_drv.type = LV_INDEV_TYPE_BUTTON;
//    indev_drv.read_cb = button_read;
//    indev_button = lv_indev_drv_register(&indev_drv);//    /*Assign buttons to points on the screen*/
//    static const lv_point_t btn_points[2] = {
//        {10, 10},   /*Button 0 -> x:10; y:10*/
//        {40, 100},  /*Button 1 -> x:40; y:100*/
//    };
//    lv_indev_set_button_points(indev_button, btn_points);
}

3.4.6 修改触摸初始化函数

/*Initialize your touchpad*/
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();}
}

3.4.7 修改触摸检测相关函数

        触摸屏按下检测函数:

/*Return true is the touchpad is pressed*/
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;
}

        触摸屏获取坐标函数:

/*Get the x and y coordinates if the touchpad is pressed*/
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];
}

        触摸屏读取函数:

/*Will be called by the library to read the touchpad*/
static void touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
{static lv_coord_t last_x = 0;static lv_coord_t last_y = 0;/*Save the pressed coordinates and the state*/if(touchpad_is_pressed()) {touchpad_get_xy(&last_x, &last_y);data->state = LV_INDEV_STATE_PR;}else {data->state = LV_INDEV_STATE_REL;}/*Set the last pressed coordinates*/data->point.x = last_x;data->point.y = last_y;
}

3.4.8 屏蔽其他设备检测函数

        其他设备检测函数均注释掉。

/*------------------* Mouse* -----------------*////*Initialize your mouse*/
//static void mouse_init(void)
//{
//    /*Your code comes here*/
//}///*Will be called by the library to read the mouse*/
//static void mouse_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
//{
//    /*Get the current x and y coordinates*/
//    mouse_get_xy(&data->point.x, &data->point.y);//    /*Get whether the mouse button is pressed or released*/
//    if(mouse_is_pressed()) {
//        data->state = LV_INDEV_STATE_PR;
//    }
//    else {
//        data->state = LV_INDEV_STATE_REL;
//    }
//}///*Return true is the mouse button is pressed*/
//static bool mouse_is_pressed(void)
//{
//    /*Your code comes here*///    return false;
//}///*Get the x and y coordinates if the mouse is pressed*/
//static void mouse_get_xy(lv_coord_t * x, lv_coord_t * y)
//{
//    /*Your code comes here*///    (*x) = 0;
//    (*y) = 0;
//}///*------------------
// * Keypad
// * -----------------*////*Initialize your keypad*/
//static void keypad_init(void)
//{
//    /*Your code comes here*/
//}///*Will be called by the library to read the mouse*/
//static void keypad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
//{
//    static uint32_t last_key = 0;//    /*Get the current x and y coordinates*/
//    mouse_get_xy(&data->point.x, &data->point.y);//    /*Get whether the a key is pressed and save the pressed key*/
//    uint32_t act_key = keypad_get_key();
//    if(act_key != 0) {
//        data->state = LV_INDEV_STATE_PR;//        /*Translate the keys to LVGL control characters according to your key definitions*/
//        switch(act_key) {
//            case 1:
//                act_key = LV_KEY_NEXT;
//                break;
//            case 2:
//                act_key = LV_KEY_PREV;
//                break;
//            case 3:
//                act_key = LV_KEY_LEFT;
//                break;
//            case 4:
//                act_key = LV_KEY_RIGHT;
//                break;
//            case 5:
//                act_key = LV_KEY_ENTER;
//                break;
//        }//        last_key = act_key;
//    }
//    else {
//        data->state = LV_INDEV_STATE_REL;
//    }//    data->key = last_key;
//}///*Get the currently being pressed key.  0 if no key is pressed*/
//static uint32_t keypad_get_key(void)
//{
//    /*Your code comes here*///    return 0;
//}///*------------------
// * Encoder
// * -----------------*////*Initialize your keypad*/
//static void encoder_init(void)
//{
//    /*Your code comes here*/
//}///*Will be called by the library to read the encoder*/
//static void encoder_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
//{//    data->enc_diff = encoder_diff;
//    data->state = encoder_state;
//}///*Call this function in an interrupt to process encoder events (turn, press)*/
//static void encoder_handler(void)
//{
//    /*Your code comes here*///    encoder_diff += 0;
//    encoder_state = LV_INDEV_STATE_REL;
//}///*------------------
// * Button
// * -----------------*////*Initialize your buttons*/
//static void button_init(void)
//{
//    /*Your code comes here*/
//}///*Will be called by the library to read the button*/
//static void button_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
//{//    static uint8_t last_btn = 0;//    /*Get the pressed button's ID*/
//    int8_t btn_act = button_get_pressed_id();//    if(btn_act >= 0) {
//        data->state = LV_INDEV_STATE_PR;
//        last_btn = btn_act;
//    }
//    else {
//        data->state = LV_INDEV_STATE_REL;
//    }//    /*Save the last pressed button's ID*/
//    data->btn_id = last_btn;
//}///*Get ID  (0, 1, 2 ..) of the pressed button*/
//static int8_t button_get_pressed_id(void)
//{
//    uint8_t i;//    /*Check to buttons see which is being pressed (assume there are 2 buttons)*/
//    for(i = 0; i < 2; i++) {
//        /*Return the pressed button's ID*/
//        if(button_is_pressed(i)) {
//            return i;
//        }
//    }//    /*No button pressed*/
//    return -1;
//}///*Test if `id` button is pressed or not*/
//static bool button_is_pressed(uint8_t id)
//{//    /*Your code comes here*///    return false;
//}

3.5 修改main.c

        这里主要包括添加LVGL头文件、添加LVGL初始化、添加LVGL官方压力测试DEMO。

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/KEY/key.h"
#include "./BSP/SRAM/sram.h"
#include "./BSP/TIMER/btim.h"/* LVGL */
#include "lvgl.h"
#include "lv_port_indev_template.h"
#include "lv_port_disp_template.h"
#include "lv_demo_stress.h"int main(void)
{HAL_Init();                         /* 初始化HAL库 */sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */delay_init(168);                    /* 延时初始化 */usart_init(115200);                 /* 串口初始化为115200 */led_init();                         /* 初始化LED */key_init();                         /* 初始化按键 */sram_init();                        /* SRAM初始化 */btim_timx_int_init(10-1,8400-1);    /* 初始化定时器 *//* lvgl初始化 */lv_init();lv_port_disp_init();lv_port_indev_init();/* lvgl官方demo */lv_demo_stress();                   /* 官方例程测试 */while (1){lv_task_handler();delay_ms(5);}
}

注:为了运行官方压力测试DEMO还需要在lv_conf.h中开启压力测试DEMO的宏定义,如下所示。

/*Stress test for LVGL*/
#define LV_USE_DEMO_STRESS 1

四、烧录与显示

        编译无误进行烧录,成功后可以看到显示屏运行压力测试程序,裸机移植LVGL完成。

http://www.dtcms.com/a/398951.html

相关文章:

  • 重庆做网站 外包公司百度关键词收录
  • 探索TCP与TCP6连接的关系:netstat找不到tcp接口?
  • 商城网站建设哪家效益快产品推销文案
  • display vlan 概念及题目
  • Composer Deprecation Notice 警告:为什么会出现?如何解决?
  • Python 中常用的数据分析绘图库解析
  • 甜点网站里的新闻资讯怎么做如何做国际网站
  • 怎么知道Redis 6+ 是否启用 ACL
  • three.js ——文字
  • 中山市智能h5网站建设公司wordpress电视剧
  • 个人网站域名一级a做爰片免费网站黄
  • mac m4电脑运行 LLaMA Factory 微调
  • 基于Python的二手房价格数据分析预测系统
  • 【速成】快速掌握CMD
  • 网站建设找哪个网盟官方网站
  • NCL数据分析与处理实践技术应用
  • 莱阳 网站建设商城前端模板
  • 【APK安全】Receiver嗅探:Android广播组件的权限与UID安全防护及测试指南
  • (自用)vim的高级命令
  • ELK分析系统详解
  • 架构师成长之路06:缓存设计收官篇,缓存该放哪?写缓存怎么用?这篇讲透最后两个核心问题
  • 电子商务网站建设外包服务wordpress 教程
  • 简述Android应用程序结构包含哪些部分
  • 百度网站改版提交wordpress主题改中文版
  • 前端埋点(tracking)技术介绍(记录用户行为和页面性能数据)(埋点代码)ajax埋点、img埋点、navigator.sendBeacon埋点
  • 网站备案ps网站建设入门教程视频教程
  • 免费申请网站永久域名建设一个网站用什么软件下载
  • 内存泄漏可能由哪些原因导致?
  • 数据采集与同步
  • Weblogic T3 CVE-2018-2628漏洞复现