,
(上海海事大學(xué) 信息工程學(xué)院,上海 201306)
伴隨著嵌入式技術(shù)的成熟,人性化圖形用戶界面在嵌入式系統(tǒng)中的應(yīng)用愈發(fā)廣泛[1]。圖形用戶界面(Graphical User Interface,簡稱GUI),是指采用圖形方式顯示的計(jì)算機(jī)操作用戶界面。與命令行界面相比,圖形界面對于大部分用戶來說更易于接受和操作。
RFID手持終端致力于解決當(dāng)前物流行業(yè)取貨、運(yùn)輸、配送等場合出現(xiàn)的問題。同時為了降低設(shè)備成本且方便一線員工使用,本文采用Cortex-M4內(nèi)核的STM32F407ZGT6作為處理器,輔以FreeRTOS操作系統(tǒng)和emWin GUI設(shè)計(jì)出簡單易操作的GUI界面用于人機(jī)交互,能夠很好地滿足實(shí)際需要。
隨著物聯(lián)網(wǎng)普及和物流行業(yè)的快速發(fā)展,RFID標(biāo)簽代替條碼標(biāo)簽的趨勢愈發(fā)明顯,為了方便物流運(yùn)輸環(huán)節(jié)運(yùn)輸員對RFID標(biāo)簽的操作,包括取貨環(huán)節(jié)輸入運(yùn)單號和送貨環(huán)節(jié)讀取商品信息,并與物流數(shù)據(jù)中心保持信息交互,本文設(shè)計(jì)的RFID終端包括硬件和軟件部分。
考慮到RFID手持終端需要對標(biāo)簽進(jìn)行讀寫,與物流數(shù)據(jù)中心保持信息交互,并有很好的可操作性,故設(shè)計(jì)一款采用ARM 32位Cortex-M4內(nèi)核的STM32F407ZGT6作為主控芯片,SIM800C作為數(shù)據(jù)傳輸模塊,MD3650A-HA 作為射頻讀寫模塊,且使用ATK-7’TFT LCD電容觸摸屏作為人機(jī)交互的RFID手持終端。另外,為了顯示快遞實(shí)時定位信息,給RFID手持終端增加GPS定位功能,以滿足快遞取貨送貨最后一公里的真實(shí)需求。
寫運(yùn)單號面設(shè)計(jì)圖如圖1所示。
圖1 寫運(yùn)單號面設(shè)計(jì)圖
綜合對RFID終端的使用場景、功能、成本、開發(fā)難度等方面考慮,采用輕量級FreeRTOS作為終端操作系統(tǒng),其具有最小的ROM、RAM和處理開銷且能提供任務(wù)管理、時間管理等一系列常用功能,其完全免費(fèi),源碼公開,同時具有可移植、可裁減、調(diào)度策略靈活的特點(diǎn)。二次開發(fā)簡單,可以方便地移植到各種單片機(jī)上運(yùn)行[2-3],能夠很好滿足終端的使用需求。
目前在嵌入式平臺上可用的GUI產(chǎn)品比較豐富,但大體上可分為如下幾類。
① 低端嵌入式GUI:包括emWin(μCGUI)、RT-Thread/GUI,此類GUI適用于單片機(jī)、ARM7、ARM Cortex-M等平臺,多與簡單的RTOS系統(tǒng)(比如FreeRTOS、μC/OS、RT-Thread)配合使用,開發(fā)語言為C語言。
② 中端嵌入式GUI:包括miniGUI、OpenGUI、Microwindows等等,主要適用于ATM7、ARM9、ARM11、ARM Cortex-R等平臺,多與嵌入式Linux、μCLinux操作系統(tǒng)配合使用,開發(fā)語言為C語言。
③ 高端嵌入式GUI:包括Qt/Embedded、Android、MFC等,主要適用于ARM9、ARM11、ARM Cortex-A等平臺,多與嵌入式Linux、Win CE/Win Phone操作系統(tǒng)配合使用,開發(fā)語言為C++和JAVA語言。
介于本文設(shè)計(jì)的物聯(lián)網(wǎng)終端主核芯片為ARM Cortex-M4架構(gòu)的STM32F407,且采用的操作系統(tǒng)為FreeRTOS,結(jié)合手持終端要求的功耗低、成本低、性價比高等要求,選定SEGGER公司授權(quán)給ST(意法半導(dǎo)體)的STemwin,使用ST芯片的用戶均可以免費(fèi)試用。emWin軟件架構(gòu)和功能成熟,通過調(diào)用emWin提供的函數(shù)接口,可為圖形LCD操作任何應(yīng)用程序提供方便有效且與處理器和LCD控制器無關(guān)的圖形用戶界面(GUI)。而且emWin對ROM和RAM的消耗并不高,這使得其在嵌入式人機(jī)交互場合廣受歡迎。
emWin是德國SEGGER公司的一個嵌入式GUI圖形庫,GUI圖形庫的概念就好像它是一個平臺,我們只需要在這個平臺上通過其提供的方法寫自己的用戶界面應(yīng)用程序,非常簡單、便捷。
emWin設(shè)計(jì)用于提供高效且獨(dú)立于處理器和顯示控制器的圖形用戶界面,用于任何使用圖形顯示進(jìn)行操作的應(yīng)用。它與單任務(wù)和多任務(wù)環(huán)境、專用操作系統(tǒng)或任何具有商業(yè)RTOS系統(tǒng)均兼容,同時由于其源代碼開放,使得開發(fā)難度大大降低。
在emWin界面應(yīng)用程序中,每個頁面都是由三部分組成:
① 控件結(jié)構(gòu)體數(shù)組:控件結(jié)構(gòu)體數(shù)組包括此頁面用到的所有控件。
② 回調(diào)函數(shù):每個頁面都對應(yīng)這著一個回調(diào)函數(shù),對界面進(jìn)行的任何操作都會跳轉(zhuǎn)到回調(diào)函數(shù)里面對對應(yīng)的消息函數(shù)進(jìn)行處理。
③ 頁面創(chuàng)建函數(shù):所有的頁面和控件都對應(yīng)一個句柄,通過句柄和ID可以找到并管理任意的頁面和控件。
另外,控件句柄、控件ID 、消息也是非常重要的三個元素。其具體實(shí)現(xiàn)如下:
static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] =//控件結(jié)構(gòu)體數(shù)組{
控件(ID_0)
控件(ID_1)
……
控件(ID_x)
};
static void _cbDialog(WM_MESSAGE* pMsg){ //回調(diào)函數(shù)
case WM_PAINT:
//窗口重繪消息,要在Framewin或Window窗口之中顯示文字
//或繪制直線、矩形、圓等在這里實(shí)現(xiàn)
……
case WM_INIT_DIALOG:
//初始化消息,創(chuàng)建窗口/控件時對其初始化參數(shù)進(jìn)行設(shè)置,即
//顯示的是未操作時的界面
……
case WM_NOTIFY_PARENT:
//操作觸發(fā)消息處理(操作屏幕程序會跑到這里),一般功能函
//數(shù)放在此消息下,比如點(diǎn)擊按鍵、點(diǎn)擊編輯框(任何的操作)所
//實(shí)現(xiàn)的功能
……
}
hWin= GUI_CreateDialogBox(控件結(jié)構(gòu)體數(shù)組, 回調(diào)函數(shù), 父窗口句柄); //頁面創(chuàng)建函數(shù),返回該頁面句柄,即hWin
移植包括對emWin進(jìn)行參數(shù)配置、LCD驅(qū)動程序、觸摸屏驅(qū)動程序編寫以及emWin與FreeRTOS操作系統(tǒng)接口修改等。
主要是針對實(shí)際情況進(jìn)行相應(yīng)的參數(shù)調(diào)整,本文采用LCD規(guī)格為800×480,控制器為GT811。
3.1.1 修改GUICong.c
在GUICong.c為emWin分配內(nèi)存,這里使用外部RAM。代碼如下:
//設(shè)置EMWIN內(nèi)存大小
#define GUI_NUMBYTES (500×1024)
#define GUI_BLOCKSIZE 0X80 //塊大小
void GUI_X_Config(void){
U32*aMemory=mymalloc(SRAMEX,GUI_NUMBYTES); //從外部RAM中分配內(nèi)存
GUI_ALLOC_AssignMemory((void*)aMemory, GUI_NUMBYTES); //為存儲管理系統(tǒng)分配存儲塊
GUI_ALLOC_SetAvBlockSize(GUI_BLOCKSIZE); //設(shè)置塊大小
GUI_SetDefaultFont(GUI_FONT_6X8); //設(shè)置字體
}
3.1.2 修改GUICong.h
在GUICong.h中進(jìn)行功能配置修改,設(shè)置如下:
#define GUI_NUM_LAYERS 10 //顯示的最大層數(shù)
#define GUI_OS (1) //使用操作系統(tǒng)
#define GUI_MAXTASK(5)
//最大可調(diào)用Emwin任務(wù)數(shù)
#define GUI_SUPPORT_TOUCH (1) //支持觸摸
#define GUI_DEFAULT_FONT &GUI_Font6x8 //默認(rèn)字體
#define GUI_SUPPORT_MOUSE (1) //支持鼠標(biāo)
#define GUI_WINSUPPORT (1) //窗口管理
#define GUI_SUPPORT_MEMDEV (1) //存儲設(shè)備
#define GUI_SUPPORT_DEVICES (1) //使用設(shè)備指針
3.1.3 配置LCDConf.h
根據(jù)觸摸屏的具體規(guī)格來修改LCDConf.h 文件里面的參數(shù),設(shè)置如下:
#define XSIZE_PHYS 800 //LCD 每一行的像素?cái)?shù)
#define YSIZE_PHYS 480 ///LCD 的行數(shù)
#define COLOR_CONVERSION GUICC_M565
//選擇RGB565色彩模式
#define TOUCH_AD_TOP160
//按下觸摸屏的頂部,寫下Y軸模擬輸入值
#define TOUCH_AD_BOTTOM3990
//按下觸摸屏的底部,寫下Y軸模擬輸入值
#define TOUCH_AD_LEFT160
//按下觸摸屏的左側(cè),寫下X軸模擬輸入值
#define TOUCH_AD_RIGHT3990
//按下觸摸屏的右側(cè),寫下X軸模擬輸入值
#define CT_EXCHG_XY 1 //調(diào)轉(zhuǎn) XY 坐標(biāo)
#define CT_MAX_TOUCH 5 //電容觸摸屏最大支持的點(diǎn)數(shù)
液晶驅(qū)動最核心的函數(shù)是畫點(diǎn)函數(shù),可以認(rèn)為幾乎所有的emWin顯示功能都是通過最終調(diào)用畫點(diǎn)函數(shù)來實(shí)現(xiàn)的[4],本設(shè)計(jì)畫點(diǎn)函數(shù)設(shè)計(jì)如下:
//畫點(diǎn),x,y:坐標(biāo),POINT_COLOR:此點(diǎn)顏色值
void LCD_DrawPoint(u16 x,u16 y){
LCD_SetCursor(x,y); //設(shè)置光標(biāo)位置
LCD_WriteRAM_Prepare(); //開始寫入GRAM
TFTLCD->LCD_RAM=POINT_COLOR;
}
STM32F407通過FSMC總線與觸摸屏模塊相連,首先調(diào)用GT811_Init()函數(shù)用于初始化電容觸摸屏驅(qū)動芯片GT811,并在其中開啟外部中斷1,使用GT811_Send_Cfg發(fā)送GT811的配置參數(shù)。初始化完成后,每當(dāng)GT811有數(shù)據(jù)可供讀取的時候,CPU就可以在CT_INT信號上接收到一個脈沖信號(100us左右的低電平脈沖),CPU只需要在接收到CT_INT中斷后,調(diào)用GT811_Scan()函數(shù)依次讀取GT811的輸出信息寄存器,將讀取到的數(shù)據(jù)組織起來,就可以獲得最多5個點(diǎn)的觸摸數(shù)據(jù)。
FreeRTOS移植成功后,便可以將emWin與CPU的相關(guān)部分交給FreeRTOS處理,即需要提供一些內(nèi)核接口函數(shù)來實(shí)現(xiàn)emWin在FreeRTOS上的運(yùn)行。任務(wù)調(diào)度相關(guān)接口函數(shù)實(shí)現(xiàn)如下:
//GUI延時函數(shù)
void GUI_X_Delay(int period) {
vTaskDelay(period);}
void GUI_X_InitOS(void){
osMutex=xSemaphoreCreateMutex();//創(chuàng)建互斥信號量
vSemaphoreCreateBinary(osSemaphore);//創(chuàng)建二值信號量
}
//等待信號量
void GUI_X_Lock(void){
xSemaphoreTake(osMutex,portMAX_DELAY);
//請求信號量
}
//發(fā)送信號量
void GUI_X_Unlock(void){
xSemaphoreGive(osMutex);//釋放信號量
}
//返回任務(wù)ID
U32 GUI_X_GetTaskId(void){
return((uint32_t)xTaskGetCurrentTaskHandle());
//獲取任務(wù)ID
}
至此,emWin GUI的移植基本上完成,需要編寫測試用例,如果顯示效果不理想,再對移植的GUI進(jìn)行底層配置優(yōu)化和改進(jìn)。
本項(xiàng)目利用emWin的配套工具GUIBuilder,允許不使用C語言的情況下,編程圖形創(chuàng)建對話框??梢詫Υ翱谛〔考M(jìn)行創(chuàng)建、拖曳、刪除和調(diào)整大小等操作,以實(shí)現(xiàn)組態(tài)、拖放式人機(jī)用戶界面設(shè)計(jì)[5]。GUIBuilder操作界面非常簡單、一目了然,生成的界面文件是標(biāo)準(zhǔn)C文件,將生成的C文件加到emWin工程中,并在emWin這個圖形庫平臺上運(yùn)行,即可顯示所設(shè)計(jì)的界面。
初步界面設(shè)計(jì)完成后,用CodeBlocks進(jìn)行模擬顯示,CodeBlocks是emWin脫機(jī)模擬仿真開發(fā)環(huán)境軟件,將emWin GUIBuilder保存的.c文件復(fù)制到Codeblocks示例文件的Application文件中,在LCDConf.c里面設(shè)置屏幕尺寸,GUIDEMO_Start.c里面創(chuàng)建主窗體,加入中文顯示庫和代碼并在對應(yīng)按鈕消息下添加界面轉(zhuǎn)換函數(shù),便可模擬出GUIBuilder所設(shè)計(jì)的界面。
通過C語言和API函數(shù)對照emWin使用手冊可對模擬界面進(jìn)行完善,以設(shè)計(jì)出更友善的人機(jī)交互界面。
最后將CodeBlocks中的C文件加入μVision工程中,并添加相應(yīng)的功能實(shí)現(xiàn)代碼,燒錄進(jìn)單片機(jī)之后便可進(jìn)行實(shí)際測試。
物聯(lián)網(wǎng)終端擬設(shè)計(jì)主界面和4個子界面,子界面分別為讀標(biāo)簽信息、寫入運(yùn)單號、設(shè)置、GPRS數(shù)據(jù)傳送。下面就主界面和RFID標(biāo)簽讀寫等三個界面進(jìn)行具體分析。
GUIBuilder設(shè)計(jì)界面如圖2所示。模擬圖如圖3所示。
圖2 主界面設(shè)計(jì)圖
圖3 主界面模擬圖
控件結(jié)構(gòu)體數(shù)組為:
static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = {
{FRAMEWIN_CreateIndirect, "TFT LCD", ID_FRAMEWIN_0, 0, 0, 800, 480, 0, 0x64, 0},
{ BUTTON_CreateIndirect, "read data", ID_BUTTON_0, 189, 126, 107, 33, 0, 0x0, 0 },
{ BUTTON_CreateIndirect, "write RFID", ID_BUTTON_1, 187, 240, 110, 35, 0, 0x0, 0 },
{ BUTTON_CreateIndirect, "send data", ID_BUTTON_2, 385, 241, 110, 37, 0, 0x0, 0 },
{ IMAGE_CreateIndirect, "Image", ID_IMAGE_0, 619, 318, 97, 99, 0, 0, 0 },
{ BUTTON_CreateIndirect, "Button", ID_BUTTON_3, 385, 123, 109, 33, 0, 0x0, 0 },
};
主要成員方法見表1。
表1 終端界面成員方法表
GUIBuilder設(shè)計(jì)界面如圖4所示。模擬圖如圖5所示。
圖4 寫運(yùn)單號面設(shè)計(jì)圖
圖5 寫運(yùn)單號面模擬圖
用12個按鈕來分別模擬數(shù)字0~9、空格和刪除鍵,其中數(shù)字和空格的按鈕操作觸發(fā)消息處理函數(shù)為:
void Button_trans(char k){
int i;
for(i=0;i<20;i++){
if(trans_number[i] == ' 黄梅县| 五原县| 石棉县| 楚雄市| 武功县| 沁源县| 连江县| 札达县| 万全县| 广东省| 新化县| 南涧| 苗栗县| 景泰县| 长葛市| 澳门| 济南市| 固始县| 渭南市| 康保县| 乌拉特后旗| 荃湾区| 平安县| 紫阳县| 青阳县| 东至县| 波密县| 偏关县| 广水市| 泗水县| 南部县| 九寨沟县| 台安县| 上栗县| 类乌齐县| 陆川县| 饶阳县| 澜沧| 峨山| 岢岚县| 花垣县|