簡介linux
物聯網設備開發過程當中,嵌入式GUI(用戶圖形界面)的開發是一個重要的組成部分。許多智能設備如智能家電、智能手錶、智能儀表上都會涉及到GUI開發。AliOS Things集成開源圖形庫littlevGL,能夠在linux上進行圖形界面開發。開發完成後將代碼添加到相應的工程並完成顯示和輸入設備驅動的對接,程序便可在相應的硬件上運行,方便用戶進行嵌入式GUI開發。git
littlevGL是一個開源的嵌入式圖形庫,採用C語言開發,使用MIT協議,並在持續更新中。該圖形庫支持經常使用的控件,如按鈕、列表、滑塊、選擇框、儀表盤、鍵盤、波形等。並支持觸摸、鼠標、鍵盤等多種輸入方式。其官方網站爲:https://littlevgl.com。github
linux模擬開發步驟函數
一、環境安裝網站
a、按照AliOS Things Linux Environment Setup安裝基本環境。ui
b、按照以下命令安裝SDL2圖形庫。blog
sudo apt-get install libsdl2-2.0:i386事件
sudo apt-get install libxkbcommon-dev:i386ci
sudo apt-get install libmircommon-dev:i386開發
sudo apt-get install libmirclient-dev:i386
sudo apt-get install libegl1-mesa-dev:i386
sudo apt-get install libglib2.0-dev:i386
sudo apt-get install libpulse-dev:i386
sudo apt-get install libsdl2-dev:i386
二、拷貝代碼
git clone https://github.com/alibaba/AliOS-Things.git
三、模擬運行
編譯運行命令:aos make littlevgl_simulate@linuxhost
編譯經過以後會自動運行生成的可執行文件,界面以下
用戶能夠自行添加應用代碼,開發完成後將代碼添加到相應的工程並完成顯示和輸入設備驅動的對接,程序便可在相應的硬件上運行。
example/littlevgl_simulate/lv_examples目錄下包含demo程序以及各個控件使用的示例程序,可參考進行界面開發。
AliOS Things開發版開發步驟:
在starterkit的開發版上已經移植littlevgl,用戶直接運行命令便可編譯GUI工程。
編譯命令:aos make littlevgl_starterkit@starterkit
編譯完成後下載到starterkit便可。
其餘CPU開發步驟:
一、顯示驅動實現
a、使用內部緩衝區(lv_conf.h的LV_VDB_SIZE > 0)
必須實現以下函數,其功能爲對一片矩形區域填充顏色,注意該函數的最後必須調用lv_flush_ready()函數。
/*Write the internal buffer (VDB) to the display. 'lv_flush_ready()' has to be called when finished*/ void my_disp_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2, const lv_color_t * color_p) { /*TODO Copy 'color_p' to the specified area*/ /*Call 'lv_fluh_ready()' when ready*/ lv_flush_ready(); }
b、使用硬件加速(USE_LV_GPU = 1 且使用內部緩衝區)
必須實現以下函數:
/*Blend two memories using opacity (GPU only)*/ void my_mem_blend(lv_color_t * dest, const lv_color_t * src, uint32_t length, lv_opa_t opa) { /*TODO Copy 'src' to 'dest' but blend it with 'opa' alpha */ } /*Fill a memory with a color (GPU only)*/ void my_mem_fill(lv_color_t * dest, uint32_t length, lv_color_t color) { /*TODO Fill 'length' pixels in 'dest' with 'color'*/ }
c、不使用緩衝區
必須實現以下函數:
/*Fill an area with a color on the display*/ void my_disp_map(int32_t x1, int32_t y1, int32_t x2, int32_t y2, const lv_color_t * color_p) { /*TODO Copy 'color_p' to the specified area*/ } *Write pixel map (e.g. image) to the display*/ void my_disp_fill(int32_t x1, int32_t y1, int32_t x2, int32_t y2, lv_color_t color) { /*TODO Fill the specified area with 'color'*/ }
二、輸入驅動實現
a、觸摸或者鼠標等點輸入設備
必須使用以下函數,獲取點座標
bool my_input_read(lv_indev_data_t *data) { data->point.x = touchpad_x; data->point.y = touchpad_y; data->state = LV_INDEV_EVENT_PR or LV_INDEV_EVENT_REL; return false; /*No buffering so no more data read*/ }
b、鍵盤設備
必須使用以下函數:
bool keyboard_read(lv_indev_data_t *data) { data->key = last_key(); if(key_pressed()) { data->state = LV_INDEV_EVENT_PR; } else { data->state = LV_INDEV_EVENT_REL; } return false; /*No buffering so no more data read*/ }
三、初始化
a、將framework/GUI/littlevGL目錄下的文件添加到工程。
b、根據須要配置lv_conf.h中相應的宏定義。
c、調用lv_init()初始化littlevGL。
d、初始化顯示和輸入(鍵盤、鼠標、觸摸等)設備。
e、調用lv_disp_drv_init初始化顯示驅動,調用lv_disp_drv_register註冊顯示驅動。調用lv_indev_drv_init初始化輸入驅動,調用lv_indev_drv_register註冊輸入驅動,示例代碼見附錄。
f、在時鐘中斷中調用lv_tick_inc(1),爲littlevGL提供心跳。
g、建立一個低優先級任務,在其中重複調用lv_task_handler函數,進行圖像的刷新和輸入事件的響應。
四、APP編寫
用戶能夠自行添加相應的應用代碼。
其餘
AliOS Things也支持STemwin,在starterkit的開發版上已經移植STemwin,用戶直接運行命令便可編譯GUI工程。
編譯命令:aos make starterkitgui@starterkit
附錄
驅動初始化和註冊示例代碼以下:
lv_disp_drv_t dis_drv; lv_indev_drv_t indev_drv; void lvgl_drv_register(void) { lv_disp_drv_init(&dis_drv); dis_drv.disp_flush = my_disp_flush; dis_drv.disp_fill = my_disp_fill; dis_drv.disp_map = my_disp_map; lv_disp_drv_register(&dis_drv); lv_indev_drv_init(&indev_drv); indev_drv.type = LV_INDEV_TYPE_POINTER; indev_drv.read = my_input_read; lv_indev_drv_register(&indev_drv); } void my_disp_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2, const lv_color_t * color_p) { int32_t x = 0; int32_t y = 0; for (y = y1; y <= y2; y++) /*Pick the next row*/ { for (x = x1; x <= x2; x++) /*Pick the a pixel in the row*/ { BSP_LCD_DrawPixel(x,y, color_p); color_p++; } } lv_flush_ready(); } void my_disp_fill(int32_t x1, int32_t y1, int32_t x2, int32_t y2, lv_color_t color) { int32_t i =0; int32_t j =0; for (i = x1; i <= x2; i++) { for (j = y1; j <= y2; j++) { BSP_LCD_DrawPixel(i,j, color.full); } } } void my_disp_map(int32_t x1, int32_t y1, int32_t x2, int32_t y2, const lv_color_t * color_p) { int32_t i =0; int32_t j =0; for (i = x1; i <= x2; i++) { for (j = y1; j <= y2; j++) { BSP_LCD_DrawPixel(i,j, color_p->full); color_p++; } } } bool my_input_read(lv_indev_data_t *data) { __IO TS_StateTypeDef ts; BSP_TS_GetState((TS_StateTypeDef *)&ts); ts.touchX[0] = TouchScreen_Get_Calibrated_X(ts.touchX[0]); ts.touchY[0] = TouchScreen_Get_Calibrated_Y(ts.touchY[0]); if((ts.touchX[0] >= 240) ||(ts.touchY[0] >= 240) ) { ts.touchX[0] = 0; ts.touchY[0] = 0; } if((TS_State_cur.Pressed != ts.touchDetected )|| (TS_State_cur.x != ts.touchX[0]) || (TS_State_cur.y != ts.touchY[0])) { TS_State_cur.Pressed = ts.touchDetected; if(ts.touchDetected) { TS_State_cur.x = ts.touchX[0]; TS_State_cur.y = ts.touchY[0]; data->point.x = TS_State_cur.x; data->point.y = 240 - TS_State_cur.y; if(TS_State_cur.Pressed == ts.touchDetected) { data->state = 1; } else { data->state = 0; } } else { TS_State_cur.x = 0; TS_State_cur.y = 0; } } return false; /*No buffering so no more data read*/ }
閱讀更多幹貨好文,請關注掃描如下二維碼: