眾所周知,一款優(yōu)秀的產(chǎn)品,不僅要有很高的性能,很好的穩(wěn)定性,而且還要具備對(duì)用戶非常友好和極具吸引力的圖形交互界面。
然而,運(yùn)行一個(gè)非常酷炫且極具吸引力的圖形用戶界面,就要求有一個(gè)高主頻,高性能,存儲(chǔ)資源豐富的MCU作為支撐。?
恩智浦擁有眾多高性能,低功耗,大容量存儲(chǔ)資源的MCU/MPU, 在這樣的MCU/MPU上,流暢地運(yùn)行圖形元素豐富,酷炫且富于吸引力的圖形用戶界面完全沒有壓力。
但是,在實(shí)際的客戶支持過程中,我發(fā)現(xiàn)有一些客戶基于成本的考慮,會(huì)選擇主頻相對(duì)低一些,存儲(chǔ)資源相對(duì)少一些的MCU。與此同時(shí),他們?nèi)匀幌Mo自己的產(chǎn)品賦予一個(gè)精美的圖形界面。
真實(shí)案例——電動(dòng)車屏幕
因此,本文通過一個(gè)運(yùn)行在LPC55S06上的,基于GUI Guider和LVGL的圖形界面設(shè)計(jì)項(xiàng)目——電動(dòng)車(簡(jiǎn)稱EBike)為例,說明如何在資源有限的MCU上進(jìn)行圖形應(yīng)用設(shè)計(jì)。
圖片與字體的存儲(chǔ)
在設(shè)計(jì)中, 電動(dòng)車的GUI使用了大小為1.18MB的26個(gè)圖片和大小為35KB的2種字體,共計(jì)約為1.22MB。
但事實(shí)上,LPC55S06的片上Flash容量為256KB,其中12KB為系統(tǒng)保留,可以為用戶使用的Flash容量只有244KB,不可能將全部圖片和字體存放到片上Flash中。
因此,為了能夠容納這些圖片和字體,可以考慮外擴(kuò)Flash。同時(shí),為了兼顧顯示性能,可以考慮將圖片存放到外部串行Flash中,而將字體存放到片上Flash中。
歸納一下,在資源有限的MCU上進(jìn)行圖形界面開發(fā),首先需要考慮的因素就是如何存儲(chǔ)圖片和字體。為了提高顯示性能,可以把圖片和字體盡可能放到片上Flash中存儲(chǔ)。但是,隨著開發(fā)的推進(jìn),用戶會(huì)不斷添加非圖形界面業(yè)務(wù)邏輯。這時(shí),如果遇到片上Flash存儲(chǔ)空間不夠的情況,可以將原本存放到片上Flash中的圖片和字體放到外部Flash中,從而節(jié)省片上Flash存儲(chǔ)空間給非圖形界面業(yè)務(wù)邏輯使用。
存儲(chǔ)區(qū)域的劃分與分配
那么,這里存在一個(gè)關(guān)鍵問題,如何為圖片和字體分配存儲(chǔ)空間呢,依據(jù)什么原則呢?換句話說,哪些圖片和字體存放到外部Flash,哪些圖片和字體存放到片上Flash。
第一點(diǎn),就是確保片上Flash可以容納全部用戶應(yīng)用邏輯。
第二點(diǎn),在滿足第一點(diǎn)的情況下,將需要頻繁刷新的圖片保存到片上Flash。例如,視頻所示界面中儀表盤的表針掃過的區(qū)域使用的圖片,隨著表針的轉(zhuǎn)動(dòng),這些圖片會(huì)不斷地從外部Flash進(jìn)行讀取并被顯示在屏幕上。
常見優(yōu)化手段
除了將消耗片上Flash資源的大戶放到外部Flash上,為了進(jìn)一步減少用戶應(yīng)用對(duì)存儲(chǔ)資源的消耗,一些優(yōu)化手段也是必要的。
常用的優(yōu)化手段包括如下幾點(diǎn):
將經(jīng)常需要調(diào)用的公共代碼段封裝成函數(shù)?
調(diào)整編譯優(yōu)化等級(jí)。使用不同的編譯優(yōu)化等級(jí)編譯生成的可執(zhí)行文件大小是不同的,如果所選的編譯器具有優(yōu)化代碼大小的編譯優(yōu)化選項(xiàng),則可以通過使用該編譯優(yōu)化選項(xiàng)壓縮可執(zhí)行文件的大小,從而減少對(duì)Flash和RAM存儲(chǔ)資源的占用。不同IDE中優(yōu)化代碼大小的編譯選項(xiàng)如下所示。
圖1 MCUXpresso IDE中的代碼大小編譯優(yōu)化選項(xiàng)
圖2?Keil uVision IDE中的代碼大小編譯優(yōu)化選項(xiàng)
圖3?IAR Embedded Workbench IDE中的代碼大小優(yōu)化選項(xiàng)
通過LVGL的配置文件lv_conf.h跳過設(shè)計(jì)中沒有使用的模塊的編譯。例如,在我們的設(shè)計(jì)中沒有用到控件,如SWICH, TABLE, TABVIEW和TILEVIEW, 就可以將相應(yīng)控件的開關(guān)宏定義為0,這樣沒有使用的控件對(duì)應(yīng)的C文件就不會(huì)編譯到最終的可執(zhí)行文件中,從而減少代碼的大小。
圖4?裁剪LVGL功能
選擇合理的屏幕加載策略
了解LVGL的小伙伴都清楚,GUI上的每一個(gè)圖形元素,如按鈕、圖片、標(biāo)簽、表格等,都是作為一個(gè)對(duì)象存在的,都是需要消耗一定的RAM資源。
如果我們的GUI設(shè)計(jì)包含多個(gè)屏幕,每個(gè)屏幕都包含大量的圖形元素,如果一次性的創(chuàng)建所有的圖形元素,很可能有限的RAM資源不足以容納這些圖形元素。因此,合理的選擇屏幕加載策略很有必要。
基于LVGL的GUI開發(fā)工具采用不同的屏幕加載策略。目前,屏幕加載策略有兩種:
第一種是以LVGL官方推出的SquareLine Studio為代表的靜態(tài)加載策略,即一次性地把所有屏幕上的圖形元素全部創(chuàng)建。這可以從其生成的代碼工程看到。
以SquareLine Studio的POS機(jī)界面示例為例,其UI初始化函數(shù)如下圖所示。我們可以看到其5個(gè)屏幕一次性創(chuàng)建,那么就意味著這種靜態(tài)屏幕加載策略消耗更多的RAM資源。
圖5?SquareLine Studio的UI初始化
第二種是以NXP官方推出的GUI Guider為代表的動(dòng)態(tài)加載策略,即只加載在系統(tǒng)啟動(dòng)后顯示的屏幕,后面如果需要顯示哪一個(gè)屏幕再動(dòng)態(tài)加載。
下圖所示是GUI Guider的官方示例ScreenTransition。這個(gè)示例總共有兩個(gè)屏幕,即screen1與screen2。函數(shù)setup_ui是UI初始化函數(shù)。
可以看到,在UI初始化函數(shù)setup_ui中只是靜態(tài)加載了屏幕screen1,沒有加載screen2。只有當(dāng)screen1的Next Screen按鈕按下時(shí),在事件回調(diào)函數(shù)screen_btn1_event_handler中才會(huì)調(diào)用setup_scr_screen2動(dòng)態(tài)加載screen2。
圖6?ScreenTransition示例的第一個(gè)屏幕
圖7?ScreenTransition示例的第二個(gè)屏幕
圖8?GUI Guider的UI初始化
圖9?Next Screen按鈕的事件回調(diào)函數(shù)
由此可見,NXP的GUI Guider的動(dòng)態(tài)屏幕加載策略,充分考慮了在資源有限的微控制器上從事GUI開發(fā)時(shí),遇到的存儲(chǔ)資源利用效率問題。
當(dāng)然,如果您所選擇的MCU或者M(jìn)PU的存儲(chǔ)資源豐富,可以采用第一種策略,那樣的話,可以能在一定程度上提高顯示性能。
總結(jié)
本篇文章以一個(gè)GUI示例——電動(dòng)車為例,重點(diǎn)關(guān)注如何在資源有限的微控制器上進(jìn)行GUI開發(fā),給出了圖片和字體的存儲(chǔ)策略,以及若干存儲(chǔ)資源優(yōu)化方法。
有關(guān)電動(dòng)車的技術(shù)細(xì)節(jié),可以參考AN13730: How to Develop LVGL GUI Demo on Memory-constrained MCU with GUI Guider.
編輯:黃飛
?
評(píng)論
查看更多