一、環境說明
(1)開發板:STM32F401RCT6核心板(網上很多,價格只有幾塊錢)
(2)屏幕:2.8寸spi屏+gt911觸摸 + 轉接板(某寶有賣,沒有推廣自行搜索)
(3)開發工具:stm32 cubemx + Keil5
(4)開發庫:STM32 HAL庫
(5)LVGL版本:9.2.1(和nxp gui guider版本保持一致,可圖形化開發)
二、圖片展示
?效果圖:
?接線圖:
三、視頻展示
?【開源!在7塊錢的開發版上跑LVGL9.2?】 https://www.bilibili.com/video/BV1wQ8vz8EUG/?share_source=copy_web&vd_source=fe79bb5485e516d8c2620e2fed931723
說明:項目完整代碼可以在視頻評論區獲取
四、 移植流程
1、裁剪代碼
需要的代碼不多主要就是lvgl的src目錄和幾個配置文件,自己可以再創建一個porting目錄用來放自己的接口代碼,如下:
?lvgl.mk這個文件很重要可以查看所有的lvgl.c文件,根據自己需要包含進工程,或者干脆全部包含。
然后直接用官方的lv_conf_template.h文件修改為lv_conf.h,里面的配置項不要亂改,不改都可以,后面根據自己情況再調整。
2、清除報錯
不要著急去改lvgl配置和移植接口,先保證工程編譯不報錯為止,缺少函數定義就去找函數定義的文件包含進工程,代碼區超了就裁剪,內存超了就減少緩沖區定義大小。
3、lvgl移植
?(1)在main函數中調用lv_init(),然后如果有報錯就繼續解決報錯。在while循環中調用lv_timer_handler(),我是在自己寫的接口函數lv_porting中調用lv_init的,放lcd_init后面就行,都一樣。
gt911_init();LCD_Init();lv_porting();/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){lv_timer_handler();gt911_scan(>911_point);HAL_Delay(10);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}
?(2)在systick中斷中添加lv_tick_inc(1)函數,如下:
void SysTick_Handler(void)
{/* USER CODE BEGIN SysTick_IRQn 0 *//* USER CODE END SysTick_IRQn 0 */HAL_IncTick();/* USER CODE BEGIN SysTick_IRQn 1 */lv_tick_inc(1);/* USER CODE END SysTick_IRQn 1 */
}
?4、驅動移植
主要就是注冊顯示設備和輸入設備,代碼如下,lvgl9相比lvgl8驅動接口寫法簡單太多了。
int lv_porting(void)
{/*Initialize LVGL*/lv_init();/*Initialize the display, and the input devices*/hal_init(MY_DISP_HOR_RES, MY_DISP_VER_RES);/*Open a demo or an example*/gui_test();/*To hide the memory and performance indicators in the corners*disable `LV_USE_MEM_MONITOR` and `LV_USE_PERF_MONITOR` in `lv_conf.h`*/return 0;
}static void disp_flush(lv_display_t * disp_drv, const lv_area_t * area, uint8_t * px_map)
{/*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/uint16_t wr_color = RED;uint16_t * p_color = (uint16_t *)px_map;LCD_Color_Fill(area->x1,area->y1,area->x2,area->y2,p_color);/*IMPORTANT!!!*Inform the graphics library that you are ready with the flushing*/lv_display_flush_ready(disp_drv);
}static void tslib_read(lv_indev_t * drv, lv_indev_data_t * data)
{data->point.x = gt911_point.points.x1;data->point.y = gt911_point.points.y1;data->state = gt911_point.press ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED;
}lv_indev_t * lv_gt911_touchscreen_create(void)
{lv_indev_t * indev = lv_indev_create();lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);lv_indev_set_read_cb(indev, tslib_read);lv_indev_set_mode(indev, LV_INDEV_MODE_TIMER);return indev;
}/*** Initialize the Hardware Abstraction Layer (HAL) for the LVGL graphics* library*/static lv_display_t * hal_init(int32_t w, int32_t h)
{LV_ATTRIBUTE_MEM_ALIGNstatic uint8_t buf_2_1[MY_DISP_HOR_RES * 20 * BYTE_PER_PIXEL];LV_ATTRIBUTE_MEM_ALIGNstatic uint8_t buf_2_2[MY_DISP_HOR_RES * 20 * BYTE_PER_PIXEL];lv_display_t * disp;lv_group_set_default(lv_group_create());disp = lv_display_create(w, h);lv_display_set_flush_cb(disp, disp_flush);lv_display_set_buffers(disp, buf_2_1, buf_2_2, sizeof(buf_2_1)-MY_DISP_HOR_RES*3, LV_DISPLAY_RENDER_MODE_PARTIAL);lv_display_set_default(disp);lv_indev_t * touchscreen = lv_gt911_touchscreen_create();lv_indev_set_display(touchscreen, disp);lv_indev_set_group(touchscreen, lv_group_get_default());return disp;
}
五、總結
自己移植中間有很多坑不是三言兩句說得清楚的,后面有事件可以考慮出個視頻教程,有些我自己還沒完全搞明白,也在摸索當中,總之先把屏幕點起來,然后再考慮優化等等問題。
有興趣的可以從上面視頻關注我的b站賬號,視頻評論區也有完整項目工程代碼。