郭健忠,耿 屹,謝 斌,閔 銳
(1.武漢科技大學 汽車與交通工程學院,湖北 武漢 430065; 2.武漢保華顯示科技有限公司,湖北 武漢 430081)
隨著智能網聯汽車、高級輔助駕駛等技術的發展,數字儀表作為車況信息顯示終端被廣泛應用于汽車電子系統中[1-2]。作為數字儀表的一種,組合式儀表由低成本微處理單元(MPU)、5至8英寸液晶顯示屏、機械指針或斷碼屏組合而成,相較于全液晶儀表,其顯示效果與信息呈現形式存在一定差距[3]。人機交互界面(HMI)是汽車數字儀表的核心功能之一,承擔駕駛員與汽車信息交互的功能[4-5]。傳統HMI軟件通常借助MiniGUI[6-7]、Qt/Embedded[8]等嵌入式圖形用戶界面(GUI)框架開發,應用于窗口化而非全屏模式的應用場景,UI界面響應鼠標、鍵盤等輸入信號,未針對汽車HMI以總線信號為觸發源的信號環境進行優化。在移植方式上,傳統框架需要將自身框架源碼跨平臺編譯至目標平臺,移植方式較為繁瑣[9]。Cairo圖形庫具備跨平臺、輕量化、可定制性強等特性[10],本設計基于Cairo圖形庫構建虛擬HMI平臺和嵌入式平臺,創新跨平臺開發方式,簡化開發與移植流程,針對低成本嵌入式平臺,從多維度設計并優化HMI軟件,提高軟硬件運行效率,以更低成本實現可靠的功能性及更佳的顯示效果。
汽車儀表HMI一般由圖1左側所示的背景圖層、儀表盤指針圖層、狀態指示燈圖層和報警/菜單顯示圖層組成,由于圖層結構相對固定,圖形庫渲染時按照從下至上的順序對圖層進行堆疊渲染。圖層由如圖1右側所示的一個或多個場景組成,場景中包含圖片、文字以及動畫效果等元素,場景中包含的元素內容、顯示內容及觸發方式均與總線數據逐一對應,例如儀表盤指針圖層與背景圖層根據總線信號中關于當前駕駛模式的數據,分別顯示ECO、SPORT和標準模式場景以提供不同的主題色彩和顯示效果;報警/菜單圖層則根據總線信號中當前菜單的索引數據和報警數據觸發相應的菜單或報警場景。

圖1 汽車儀表HMI圖層及場景示意圖
HMI圖層與場景采用Fairy GUI軟件進行設計和導出,Fairy GUI是一款用于軟件或游戲的UI設計軟件,可提供跨平臺UI設計解決方案[11]。該軟件支持在工程設計樹中以包和組件的方式管理HMI圖層和場景,可在場景中導入界面元素,為每個場景內元素設定顯示坐標、旋轉角度、旋轉錨點、縮放比例、透明度等信息。設計完成后可通過軟件中的發布功能生成包含當前圖層和場景布局信息的XML文件,用于后期圖形渲染。為簡化設計流程,HMI中靜態文字、按鈕等控件元素均使用支持透明背景(支持Alpha通道)的PNG圖片資源,動態文字通過預留空位,在程序中調用Cairo圖形庫中的矢量字庫接口繪制文字。
在嵌入式GUI框架中,圖片資源通過資源文件路徑加載,而資源文件通常儲存在存儲器不同扇區中,此方式會增加文件隨機讀寫次數,不適用于圖片資源較多且讀寫速度有限的Flash存儲器上。汽車HMI單一場景內的元素內容數量較少、重復性小且元素搭配相對固定,因此以場景為單位,封裝場景內的元素為單個二進制(bin)文件,將多次隨機讀寫轉換為單次順序讀寫,可有效提高場景資源文件加載效率,封裝后的二進制文件格式及相關描述如表1所示。為進一步提升Flash存儲器的讀寫效率,文件中數據以四字節對齊的方式排列,元素數據域內圖片數據按照設計的堆疊順序依次收尾相連,數據加載時通過文件頭中元素地址索引定位。

表1 場景元素封裝二進制文件格式
Cairo是基于C語言編寫的跨平臺2D圖形庫,支持Windows、Linux等主流操作系統和部分嵌入式平臺,支持將渲染好的像素數據導出為多種格式的文件或與各平臺圖形底層結合顯示圖像,其圖形應用程序接口(API)和畫面輸出效果在任意平臺下均保持一致,擁有優秀的跨平臺開發特性[12]。基于Cairo圖形庫搭建虛擬HMI開發平臺和嵌入式平臺,可確保雙平臺下HMI軟件代碼的一致性,便于后期程序跨平臺移植。
虛擬HMI平臺本質是在Windows操作系統環境下運行的窗口應用程序,其編譯與運行分別依賴靜態庫cairo.lib和動態庫cairo.dll,上述庫文件可從Gtk+框架中提取或通過編譯圖形庫源碼獲得[13-14]。由于Gtk+中的Cairo庫文件版本較低,對Win32平臺支持性較差,而通過編譯最新版本源碼生成的庫文件具有良好的兼容性并支持完整的新特性。Cairo源碼編譯依賴PNG圖片解碼庫libpng和像素處理函數庫pixman,而libpng庫依賴zlib函數庫提供對PNG圖片數據壓縮與解壓的支持[15],因此編譯順序如圖2所示。編譯完成后,將生成的靜態庫文件添加到工程鏈接器配置屬性中的附加依賴項中,將動態庫文件移動至生成的程序執行文件根目錄下,即可完成虛擬HMI開發平臺運行環境搭建。

圖2 Cairo圖形庫編譯順序
目前市場主流全液晶儀表采用恩智浦i.MX系列[16-17]、瑞芯微RK系列等高性能處理器,此類處理器硬件采購成本、電路設計及電路板印制成本較高,無法滿足組合式儀表對成本的限制需求。普通MCU由于性能較弱無法兼顧數據處理與畫面顯示,采用雙芯片設計能有效均衡算力從而降低成本[18]。文中采用如圖3所示的S32K144 MCU處理總線數據及IO信號,F1c100s MPU用于畫面顯示,二者通過高速串口進行數據交互。

圖3 雙芯片架構示意圖
其中全志F1c100s是基于ARM9架構設計默認主頻為400 MHz的微處理器,集成DDR內存,可運行XBOOT、精簡版Linux等操作系統。
XBOOT是一款功能強大、可移植性強、代碼復用率高的嵌入式系統Bootloader,同時也是片上系統應用程序執行引擎,可為應用程序提供啟動及運行環境。由于XBOOT系統具備體積小,功能完善的特點,且內置Cairo圖形庫與文件系統,無需用戶額外配置,適合跨平臺輕量化HMI開發。XBOOT源碼可從開源項目網站上獲取,解壓后需編輯源碼目錄中的Makefile文件,添加編譯選項,指定目標編譯平臺和交叉編譯器:
CROSS_COMPILE?=arm-eabi-
PLATFORM ?=arm32-f1c100s
再將源碼工程添加至集成CDT插件的Ecllipse IDE中編譯,將生成的二進制bin文件通過sunxi_tools燒寫工具燒寫至板載閃存中運行。
由于跨平臺軟件開發存在編譯速度慢、資源燒寫過程繁瑣甚至無法調試等問題,極大影響軟件開發速度。虛擬HMI平臺依托Visual Studio集成開發環境(IDE),具備完善的編譯與調試環境,無需燒寫資源,使HMI軟件開發流程更為簡化,從而提高開發效率。
虛擬HMI平臺由圖4所示的五個部分組成:(1)窗口程序主框架;(2)虛擬總線數據模塊;(3)虛擬按鍵模塊;(4)數據緩沖區;(5)HMI模塊。窗口程序主框架負責初始化程序各模塊,創建可視化窗口,監聽響應系統消息和用戶操作和任務調度;虛擬總線數據模塊與虛擬按鍵模塊為非模態對話框子程序,負責轉換用戶鼠標操作為虛擬總線數據并發送至數據緩沖區,HMI模塊掃描緩沖區中的數據進行實時畫面顯示。
HMI模塊包含數據解析、事件隊列、XML文件解析和圖形抽象四個單元,模塊的數據接口與平臺類型無關,圖形抽象接口可根據當前運行環境適配,因此在虛擬HMI平臺中構建的HMI模塊可整體移植至目標嵌入式平臺,使移植步驟更簡化。
3.2.1 HMI模塊工作流程
數據解析單元負責掃描緩沖區中數據的異動情況,根據當前數據異動情況向事件隊列單元發送相應事件,事件是一個包含當前事件信息的結構體DisplayEvent:
typedef struct __DisplayEvent
{
scr_id_t ScrId; //場景ID,與二進制文件頭中ID對應
scr_time_t ScrDisplayTime; //場景顯示時長
priority_t ePriority; //事件優先級
bool isInterrupt; //是否能被打斷
bool isRedisplay; //打斷后是否重新顯示
payload_t ePayload; //當前場景數據負載
}DisplayEvent;
事件隊列單元中的事件按照優先級從高到底以鏈表形式排列,事件插入函數依據傳入結構體中的ePriority值向鏈表中插入事件,事件響應函數優先響應鏈表頭部事件,再調用XML解析單元和圖形抽象單元繪制場景元素。XML文件解析依賴libxml2庫,場景布局數據以鍵值對的形式存儲在XML文件中,解析時將鍵值對數據逐一拷貝至PngInfo結構體數組中相應的位置,解析流程如圖5所示。
typedef struct __PngInfo
{
uint32_t pIndex; //場景元素編號
float x; //x軸坐標
float y; //y軸坐標
float scale_x; //x軸縮放比
float scale_y; //y軸縮放比
int rotation; //旋轉角度
float rot_x; //旋轉錨點x軸坐標
float rot_y; //旋轉錨點y軸坐標
uint8_t* pPngFileData; //文件數據指針
uint8_t* pPngRawData; //元素數據指針
cairo_surface_t PNGSurface; //圖形庫Surface指針
} PngInfo;

圖5 XML解析單元流程
3.2.2 圖形抽象單元
圖形抽象單元負責場景元素加載、解析和渲染,虛擬HMI平臺中的圖形抽象單元基于Windows系統下的圖形設備接口(GDI)與Cairo圖形庫搭建,由于Cairo圖形庫無法直接在應用程序窗口上繪制圖形,依賴GDI為Cairo圖形庫提供設備上下文環境(device context,DC)。使用GetDC()函數可基于當前窗口創建DC,若直接在窗口DC上渲染圖形會造成畫面撕裂和閃爍,使用雙重緩沖區可解決上述問題。調用CreateCompatibleDC()和CreateCompatibleBitmap()函數在內存中分別創建基于窗口DC的兼容DC和兼容位圖數據緩沖區,待Cairo圖形庫繪制完成后,使用BitBlt()函數將兼容DC中的像素數據逐字節拷貝至窗口DC,可在窗口中實現穩定的畫面顯示。
Cairo圖形庫為GDI提供了cairo_win32_surface_create()接口,該接口可將兼容DC轉換成類型為cairo_surface_t的抽象繪制平面(Surface),后續圖形均在此上下文繪制。圖形繪制流程由資源加載、圖形變換、圖形繪制、資源銷毀四個階段組成:
階段一,資源加載:圖片資源從對應場景的bin文件中加載,一種方式是通過libpng庫將bin文件數據域中的圖片數據解析為像素數據,傳入Cairo圖形庫中的cairo_image_surface_create_for_data()接口創建類型為cairo_t的上下文目標。第二種方式無需顯式地讓libpng庫參與圖片加載過程,而是向Cairo圖形庫中的cairo_image_surface_create_from_png_stream()接口傳入事先讀取好的圖片數據創建上下文目標。以上兩種方案均需重載用于讀取PNG文件的回調函數,并將函數指針傳遞至png_set_read_fn()接口調用。
階段二,圖形變換:汽車儀表HMI中涉及到的基本變換操作包含平移、縮放和旋轉,變換參數已由XML解析單元解析至PngInfo結構體中,為簡化變換流程,將所需的變換步驟封裝為如下所示單一函數中:
void Paint_PNG_Element(cairo_t* cr, PngInfo* info)
{
cairo_save(cr);
if (!(info->rotation == 0)) //旋轉
{
cairo_translate(cr, info->rot_x, info->rot_y);
cairo_rotate(cr, info->rotation);
cairo_translate(cr, -info->rot_x, -info->rot_y);
}
if (!(info->scale_x == 1.0&&info->scale_y == 1.0)) //縮放并平移
{
cairo_scale(cr, info->scale_x, info->scale_y);
cairo_set_source_surface(cr, info->PNGSurface,
(int)info->x / info->scale_x,
(int)info->y / info->scale_y);
}
else //僅平移
{
cairo_set_source_surface(cr, info->PNGSurface,info->x,info->y);
}
}
階段三,圖形繪制:圖形的加載和變換將圖片位圖數據置于內存中處理,并未與最初創建的Cairo抽象繪制平面綁定,因此可使用cairo_paint()或cairo_paint_with_alph()函數將內存中的數據渲染在上下文上,后者支持透明背景渲染。cairo_paint()不僅可以繪制圖片,還可以繪制實時矢量圖形和矢量文字,增加了HMI軟件設計的靈活性。
階段四,資源銷毀:受嵌入式平臺內存或顯存因素的制約,當場景內的某一元素不再顯示或發生場景切換等情況,需及時銷毀當前資源或場景在內存中的數據,釋放內存。Cairo圖形庫提供了cairo_surface_destroy()和cairo_destroy()接口,分別用于銷毀內存中的圖片數據和抽象繪制平面。
由于XBOOT系統為嵌入式平臺提供了包含Cairo圖形庫在內的完整的運行環境,虛擬HMI平臺與嵌入式平臺圖形環境基本一致,不同之處在于數據解析單元的總線數據來源、圖形抽象層與設備底層之間的接口以及部分設備驅動接口。因此移植過程更為簡化,僅需將虛擬HMI平臺中的代碼進行部分修改后拷貝至嵌入式平臺工程中編譯即可,移植詳情如表2所示。

表2 HMI模塊各單元移植方式
首先要向工程中注入資源文件,將各場景的bin文件及xml文件分別拷貝至./xboot/src/romdisk/framework/asset/scr和./xboot/src/romdisk/framework/asset/cfg目錄下,此目錄在編譯階段會自動生成虛擬文件系統,便于程序通過文件路徑調用文件。由于XBOOT內存結構及空間申請方式與Linux系統類似,采用雙向鏈表的形式管理,設備上下文環境需要調用list_for_each_entry_safe函數在鏈表中尋找足夠的內存空間,并在此內存空間上創建Cairo圖形庫的抽象繪制平面作為上下文,具體代碼如下,后續繪圖階段代碼則與虛擬HMI平臺保持一致。
cairo_surface_t * cs;
cairo_t * cr;
struct framebuffer_t * fb;
list_for_each_entry_safe(pos, n, &__device_head[DEVICE_TYPE_FRAMEBUFFER], head)
fb = (struct framebuffer_t *)(pos->priv))
cs = cairo_xboot_surface_create(fb);
cr = cairo_create(cs);
Cairo圖形庫渲染后的像素數據關聯在cs指針中,還需通過cairo_xboot_surface_present()函數將數據傳遞至硬件底層,交由LVDS驅動傳輸至顯示屏顯示。
本節采用虛擬HMI平臺與嵌入式平臺聯合實驗的方式驗證HMI軟件的可行性與可靠性。首先測試HMI軟件對總線信號響應的準確度,由于雙平臺中總線數據解析、事件隊列及XML解析單元中代碼一致,因此可在虛擬HMI平臺中測試驗證。根據如表3所示的汽車儀表HMI軟件測試用例對HMI軟件中指示燈顯示狀態、優先級打斷邏輯、報警場景觸發準確性等方面進行全功能測試,結果表明,儀表能準確響應總線信號并顯示正確的提示信息,具備可靠的功能性。

表3 汽車儀表HMI軟件測試用例部分測試項目
軟件性能方面,HMI軟件在嵌入式設備上的每秒顯示幀數(fps)是畫面流暢度的重要評價指標之一,fps值受當前設備內存、FLASH讀寫速度與MCU算力的制約,在汽車儀表HMI軟件中,場景資源的加載、解析及圖形變換對fps值影響較大。為測試上述問題對fps值的影響,本節使用包含120張分辨率為480*800動畫序列圖片的場景作為測試目標,在虛擬HMI中平臺測試,目的是記錄單幀渲染時長和內存占用情況。對照組采用以文件路徑作為形參調用圖形庫接口對圖片逐一加載的方式,方式一和方式二為3.2.2節中提出的兩種方式,方式三則是先將場景資源全部解析到內存中,再調用圖形庫從內存中讀取數據,此方式對內存占用較大,不適用嵌入式平臺,僅供參考。測試結果如圖6和表4所示,方式二相比于傳統方式平均單幀渲染時間降低4 ms,平均幀率提升5 fps,而方式三由于渲染時無需加載圖片資源,其單幀渲染時間僅為1 ms,但內存占用為常規方式的5.6倍,上述結果說明方式二為更加合理的圖片資源加載方式。

圖6 單幀渲染時間測試

表4 測試詳情
軟件方面,方式三單幀渲染時間極低,但需要圖片數據常駐內存,因此可應用于變化不大且需長期顯示的場景,例如背景、儀表盤及指針所處的模式場景,其他場景則繼續采用方式二加載。經測試,嵌入式平臺HMI軟件運行在480*800分辨率的主界面下,混合加載模式相較于僅采用方式二的模式,平均幀率由27.2 fps提升至35.7 fps,提升幅度為31.25%。
硬件方面,全志F1c100s主頻默認400 MHz,通過修改時鐘配置文件,可將主頻提升至720 MHz從而提升幀率。由于Flash閃存在HMI軟件運行時為只讀狀態,將SPI驅動變更為雙線只讀模式,能提升一定的讀取速率。經測試驗證,平均幀率由軟件優化后的35.7 fps提升至42.7 fps,提升幅度為19.6%,軟硬件聯合優化后的實時幀率滿足汽車組合儀表HMI流暢顯示的設計需求。
介紹了面向低成本組合式汽車儀表的HMI系統設計,提出了以圖層與場景為單位的界面元素結構,搭建了基于Cairo圖形庫的虛擬HMI平臺和嵌入式平臺,簡化了界面設計、軟件編譯及調試的繁瑣步驟,同時雙平臺圖形環境的一致性使開發效率得以提升,從而降低了軟件的研發成本。HMI程序設計針對汽車信號環境進行了優化,通過監聽數據緩沖區中的數據異動情況,根據當前觸發事件的優先級響應繪圖事件,調用XML解析單元和圖形抽象單元完成畫面繪制。試驗表明,組合式儀表能在保證可靠功能性的同時,通過虛擬HMI平臺的仿真實驗和軟硬件的聯合優化,大幅提升HMI實時幀率,保證了儀表顯示的流暢性,達成了以低成本實現更佳顯示效果的設計目的。