1.LVGL快速移植和界面设计
一、拷贝lvgl 整个文件夹到工程中,lv_conf_template.h 文件要重命名为lv_conf.h,该文件里面#if 0改成#if 1 ,如下所示
二、工程里面添加所有文件和头文件路径,这一步过程比较长长,但还是要做好,
然后编译,可能报错.Undefined symbol __aeabi_assert (referred from qrcodegen.o).,需要添加NDEBUG到预处理,进行暂时屏蔽断言
三、注册屏幕驱动接口给lvgl
lv_port_disp.c是屏幕驱动接口,是移植重点,可以拷贝lvgl / env_support / rt_thread / lv_rt_thread_port.h进行修改
如下所示:
只有一个put_px()函数需要自己根据屏幕类型去实现,即画点函数
1 /** 2 * @file lv_port_disp_templ.c 3 * 4 */ 5 6 /*Copy this file as "lv_port_disp.c" and set this value to "1" to enable content*/ 7 #if 1 8 9 /********************* 10 * INCLUDES 11 *********************/ 12 #include "lv_port_disp.h" 13 #include "../../lvgl.h" 14 #include "main.h" 15 #include "custom.h" 16 17 /********************* 18 * DEFINES 19 *********************/ 20 #define ONE_BUFFER 1 21 #define TWO_BUFFER 0 22 23 #define COLOR_SIZE (CLCD_WIDTH * CLCD_HEIGHT) 24 /********************** 25 * TYPEDEFS 26 **********************/ 27 28 /********************** 29 * STATIC PROTOTYPES 30 **********************/ 31 static void disp_init(void); 32 33 static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p); 34 //static void gpu_fill(lv_disp_drv_t * disp_drv, lv_color_t * dest_buf, lv_coord_t dest_width, 35 // const lv_area_t * fill_area, lv_color_t color); 36 37 /********************** 38 * STATIC VARIABLES 39 **********************/ 40 41 /********************** 42 * MACROS 43 **********************/ 44 45 /********************** 46 * GLOBAL FUNCTIONS 47 **********************/ 48 49 void lv_port_disp_init(void) 50 { 51 /*------------------------- 52 * Initialize your display 53 * -----------------------*/ 54 disp_init(); 55 56 /*----------------------------- 57 * Create a buffer for drawing 58 *----------------------------*/ 59 60 /** 61 * LVGL requires a buffer where it internally draws the widgets. 62 * Later this buffer will passed to your display driver's `flush_cb` to copy its content to your display. 63 * The buffer has to be greater than 1 display row 64 * 65 * There are 3 buffering configurations: 66 * 1. Create ONE buffer: 67 * LVGL will draw the display's content here and writes it to your display 68 * 69 * 2. Create TWO buffer: 70 * LVGL will draw the display's content to a buffer and writes it your display. 71 * You should use DMA to write the buffer's content to the display. 72 * It will enable LVGL to draw the next part of the screen to the other buffer while 73 * the data is being sent form the first buffer. It makes rendering and flushing parallel. 74 * 75 * 3. Double buffering 76 * Set 2 screens sized buffers and set disp_drv.full_refresh = 1. 77 * This way LVGL will always provide the whole rendered screen in `flush_cb` 78 * and you only need to change the frame buffer's address. 79 */ 80 81 /* Example for 1) */ 82 static lv_disp_draw_buf_t draw_buf_dsc_1; 83 static lv_color_t buf_1[COLOR_SIZE]; /*A buffer for 10 rows*/ 84 lv_disp_draw_buf_init(&draw_buf_dsc_1, buf_1, NULL, COLOR_SIZE); /*Initialize the display buffer*/ 85 86 /* Example for 2) */ 87 //static lv_disp_draw_buf_t draw_buf_dsc_2; 88 //static lv_color_t buf_2_1[MY_DISP_HOR_RES * 10]; /*A buffer for 10 rows*/ 89 //static lv_color_t buf_2_2[MY_DISP_HOR_RES * 10]; /*An other buffer for 10 rows*/ 90 //lv_disp_draw_buf_init(&draw_buf_dsc_2, buf_2_1, buf_2_2, MY_DISP_HOR_RES * 10); /*Initialize the display buffer*/ 91 92 /* Example for 3) also set disp_drv.full_refresh = 1 below*/ 93 //static lv_disp_draw_buf_t draw_buf_dsc_3; 94 //static lv_color_t buf_3_1[MY_DISP_HOR_RES * MY_DISP_VER_RES]; /*A screen sized buffer*/ 95 //static lv_color_t buf_3_2[MY_DISP_HOR_RES * MY_DISP_VER_RES]; /*An other screen sized buffer*/ 96 //lv_disp_draw_buf_init(&draw_buf_dsc_3, buf_3_1, buf_3_2, MY_DISP_VER_RES * LV_VER_RES_MAX); /*Initialize the display buffer*/ 97 98 /*----------------------------------- 99 * Register the display in LVGL 100 *----------------------------------*/ 101 102 static lv_disp_drv_t disp_drv; /*Descriptor of a display driver*/ 103 lv_disp_drv_init(&disp_drv); /*Basic initialization*/ 104 105 /*Set up the functions to access to your display*/ 106 107 /*Set the resolution of the display*/ 108 disp_drv.hor_res = CLCD_HEIGHT; 109 disp_drv.ver_res = CLCD_WIDTH; 110 111 /*Used to copy the buffer's content to the display*/ 112 disp_drv.flush_cb = disp_flush; 113 114 /*Set a display buffer*/ 115 disp_drv.draw_buf = &draw_buf_dsc_1; 116 117 /*Required for Example 3)*/ 118 //disp_drv.full_refresh = 1 119 120 /* Fill a memory array with a color if you have GPU. 121 * Note that, in lv_conf.h you can enable GPUs that has built-in support in LVGL. 122 * But if you have a different GPU you can use with this callback.*/ 123 //disp_drv.gpu_fill_cb = gpu_fill; 124 125 /*Finally register the driver*/ 126 lv_disp_drv_register(&disp_drv); 127 } 128 129 /********************** 130 * STATIC FUNCTIONS 131 **********************/ 132 133 /*Initialize your display and the required peripherals.*/ 134 static void disp_init(void) 135 { 136 /*You code here*/ 137 drv_clcd_init(); 138 } 139 140 /*Flush the content of the internal buffer the specific area on the display 141 *You can use DMA or any hardware acceleration to do this operation in the background but 142 *'lv_disp_flush_ready()' has to be called when finished.*/ 143 static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p) 144 { 145 /*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/ 146 #if 1 147 int32_t x; 148 int32_t y; 149 for(y = area->y1; y <= area->y2; y++) 150 { 151 for(x = area->x1; x <= area->x2; x++) 152 { 153 /*Put a pixel to the display. For example:*/ 154 put_px(x, y, *((u16*)(color_p))); 155 color_p++; 156 } 157 } 158 #endif 159 160 //LCD_Color_Fill(area->x1, area->y1, area->x2, area->y2, (uint16_t*)color_p); 161 162 /*IMPORTANT!!! 163 *Inform the graphics library that you are ready with the flushing*/ 164 lv_disp_flush_ready(disp_drv); 165 } 166 #if LV_USE_LOG 167 static void lv_rt_log(const char *buf) 168 { 169 SYSTEM_DEBUG(buf); 170 } 171 #endif /* LV_USE_LOG */ 172 lv_ui guider_ui; 173 174 void lv_100ask_demo_course_2_1_1(void) 175 { 176 #if 0 177 lv_obj_t * obj = lv_obj_create(lv_scr_act()); 178 lv_obj_set_size(obj, LV_PCT(100), LV_PCT(10)); 179 lv_obj_align(obj, LV_ALIGN_CENTER, 0, 0); 180 #endif 181 setup_ui(&guider_ui); 182 183 lv_obj_t * label = lv_label_create(lv_scr_act()); 184 lv_label_set_text_fmt(label, "ver:%d.%d.%d\n",LVGL_VERSION_MAJOR, LVGL_VERSION_MINOR, LVGL_VERSION_PATCH); 185 lv_obj_align(label, LV_ALIGN_DEFAULT, 0, 0); 186 lv_label_set_recolor(label,1); 187 188 } 189 190 static void lvgl_thread_entry(void *parameter) 191 { 192 #if LV_USE_LOG 193 lv_log_register_print_cb(lv_rt_log); 194 #endif /* LV_USE_LOG */ 195 lv_init(); 196 lv_port_disp_init(); 197 //lv_port_indev_init(); 198 //lv_user_gui_init(); 199 //lv_disp_set_rotation(NULL,LV_DISP_ROT_90); 200 201 #if 0 202 lv_100ask_demo_course_2_1_1(); 203 #endif 204 205 /* handle the tasks of LVGL */ 206 while(1) 207 { 208 lv_task_handler(); 209 rt_thread_mdelay(1); 210 211 } 212 } 213 struct rt_thread lvgl_thread; 214 static rt_uint8_t task1_stack[4096]; 215 216 static int lvgl_thread_init(void) 217 { 218 rt_err_t err; 219 220 err = rt_thread_init(&lvgl_thread, "LVGL", lvgl_thread_entry, RT_NULL, &task1_stack[0], sizeof(task1_stack), 2, 0); 221 if(err != RT_EOK) 222 { 223 SYSTEM_DEBUG("Failed to create LVGL thread"); 224 return -1; 225 } 226 rt_thread_startup(&lvgl_thread); 227 228 return 0; 229 } 230 INIT_ENV_EXPORT(lvgl_thread_init); 231 232 233 /*OPTIONAL: GPU INTERFACE*/ 234 235 /*If your MCU has hardware accelerator (GPU) then you can use it to fill a memory with a color*/ 236 //static void gpu_fill(lv_disp_drv_t * disp_drv, lv_color_t * dest_buf, lv_coord_t dest_width, 237 // const lv_area_t * fill_area, lv_color_t color) 238 //{ 239 // /*It's an example code which should be done by your GPU*/ 240 // int32_t x, y; 241 // dest_buf += dest_width * fill_area->y1; /*Go to the first line*/ 242 // 243 // for(y = fill_area->y1; y <= fill_area->y2; y++) { 244 // for(x = fill_area->x1; x <= fill_area->x2; x++) { 245 // dest_buf[x] = color; 246 // } 247 // dest_buf+=dest_width; /*Go to the next line*/ 248 // } 249 //} 250 251 252 #else /*Enable this file at the top*/ 253 254 /*This dummy typedef exists purely to silence -Wpedantic.*/ 255 typedef int keep_pedantic_happy; 256 #endif
我的屏幕画点函数如下:
1 // 设置光标位置 2 void LCD_SetCursor(uint16_t x, uint16_t y) 3 { 4 LCD_WR_REG(0x2A); 5 LCD_WR_DATA(x); 6 //LCD_WR_DATA((CLCD_HEIGHT- 1) & 0xFF); 7 LCD_WR_DATA(x); 8 9 LCD_WR_REG(0x2B); 10 LCD_WR_DATA(y); 11 //LCD_WR_DATA((CLCD_WIDTH- 1) & 0xFF); 12 LCD_WR_DATA(y); 13 14 //LCD_WR_REG(0x2c);// 15 } 16 17 void put_px(u16 x,u16 y, u16 color) 18 { 19 LCD_SetCursor(x, y); 20 LCD_WR_REG(0x2C); 21 LCD_WR_DATA(color); 22 }
二、界面设计
https://zhuanlan.zhihu.com/p/687516934