上一篇:[stm32][ucos] 1、基於ucos操作系統的LED閃爍、串口通信簡單例程
* 內容簡述:
本例程操作系統采用ucos2.86a版本, 建立了7個任務
任務名 優先級
APP_TASK_START_PRIO 2 主任務
APP_TASK_USER_IF_PRIO 13 ucgui界面任務
APP_TASK_KBD_PRIO 12 觸摸屏任務
Task_Com1_PRIO 4 COM1通信任務
Task_Led1_PRIO 7 LED1 閃爍任務
Task_Led2_PRIO 8 LED2 閃爍任務
Task_Led3_PRIO 9 LED3 閃爍任務
當然還包含了系統任務:
OS_TaskIdle 空閑任務-----------------優先級最低
OS_TaskStat 統計運行時間的任務-------優先級次低
*了解一下:
>_<" uCOSII介紹:
嵌入式實時操作系統uCosII是由美國工程師Jean J.Labrosse所創,它在中國的流行源於那本被邵貝貝引進翻譯的著名書籍《嵌入式實時操作系統uCos-II》,這本書是學習ucosII
的寶典,雖然很厚,但理解了關鍵概念,再結合實際應用例程,還是很容易看懂的。uCosII通過了美國航天管理局(FAA)的安全認證,可以用於飛機、航天器與人性命攸關的控制系統中。也就是說,用戶可以放心將uCosII用到自己的產品中,ucGUI也是Micrium公司的產品, 在本例程里使用了ucGUI3.90版本,它為嵌入式應用提供了功能強大的圖形用戶接口,使得用戶在開發具有人機界面的應用時,可以很方便做出復雜精致的用戶顯示界面。並提供了交互的接口。PS:現在邵貝貝的嵌入式實時操作系統已經到uCos-III了。
>_<" uCOSII特點:
- [1] 可移植性:uCosII源碼絕大部分是用移植性很強的ANSI C寫的。與微處理硬件相關的部分是用匯編語言寫的。uCOS可以在絕大多數8位、16位、32位以及64位處理器、微控制器及數字信號處理器(DSP)上運行。
- [2] 可裁剪性:可以通過開關條件編譯選項,來定義哪些uCosII的功能模塊用於用戶程序,方便控制代碼運行所占用的空間及內存。
- [3] 可剝奪性:uCOSII是完全可剝奪型的實時內核,它總是運行處於就緒狀態下的優先級最高的任務。
- [4] 多任務:uCOSII可以管理64個任務,每個任務對應一個優先級,並且是各不相同。其中8個任務保留給uCOSII。用戶的應用程序可以實際使用56個任務。
- [5] 可確定性:絕大多數uCosII的函數調用和服務的執行時間具有可確定性,也就是說用戶總是能知道函數調用與服務執行了多長時間。
- [6] 任務棧: 每個任務都有自己單獨的棧,uCOSII規定每個任務有不同的棧空間。
- [7] 系統服務:uCOSII 提供很多系統服務, 例如信號量、互斥信號量、事件標志、消息郵箱、消息隊列、內存的申請與釋放及時間管理函數等。
- [8] 中斷管理: 中斷可以使正在執行的任務暫時掛起,中斷嵌套層數可達255層。
>_<" uCGUI特點:
UCGUI 的設計目標是為使用 LCD 作為圖形顯示裝置的應用提供高效的與 LCD 控制器獨立及處理器獨立的圖形用戶接口。它適合於單任務環境及多任務環境,如私用的操作系統或是商業的RTOS(實時操做系統。UCGUI 以 C 源碼形式提供, 並適用於任意 LCD 控制器和 CPU 下任何尺寸的真實顯示或虛擬顯示。它包含以下特性(一般特性):
- [1] 適用任何 8/16/32 位 CPU, 只要有相對應的標准 C 編譯器.
- [2] 任何的控制器的 LCD 顯示器(單色,灰度,顏色), 只要有適合的 LCD 驅動可用.
- [3] 在小模式顯示時無須 LCD 控制器.
- [4] 所有接口支持使用宏進行配制.
- [5] 顯示尺寸可定制.
- [6] 字符和位圖可在 LCD 顯示器上的任意起點顯示,並不僅局限於偶數對齊的地址起點.
- [7] 程序在大小和速度上都進行了優化.
- [8] 編譯時允許進行不同的優化.
- [9] 對於緩慢一些的 LCD 控制器, LCD 顯存可以映射到內存當中, 從而減少訪問次數到最小並達到更高的顯示速度.
- [10]清晰的設計架構.
- [11]支持虛擬顯示, 虛擬顯示可以比實際尺寸大(即放大).
*概念須知:
>_<" 任務:
任務通常是一個無限的循環, 返回參數必須定義為void。 當任務開始執行時,會有一個參數傳遞給用戶任務代碼。uCosII可以管理64個任務, 其中系統保留了8個任務。開放給用戶的有56個任務,每個任務的優先級都不同, 任務的優先級號越低,任務的優先級越高,在這個版本的uCosII中,任務的優先級號就是任務編號。
任務的狀態一定是以下5種之一:
- [1] 睡眠態:就是任務沒有交給ucosII調度的,也就是沒用經過建立的任務。 只保存在存儲器空間里。
- [2] 就緒態:任務一旦建立,任務就進入就緒態。任務可以通過調用OSTasjDel()返回到睡眠態。
- [3] 運行態:任何時刻只能有一個任務處於運行態。
- [4] 等待狀態:正在運行的任務可以通過調用以下2 個函數之一,將自身延遲一段時間。 這2 個函數是OSTimeDly()或OSTimeDlyHMSM()。這個任務於是進入等待狀態,一直到函數中定義的延遲時間到。正在運行的任務可能在等待某一事件的發生,可以通過調用以下函數之一實現:OSFlagPend() , OSSemPend(),OSMutexPend(), OSMboxPend()或OSQPend()。如果某事件並未發生,調用上述函數的任務就進入了等待狀態,直到等待的事件發生了。當任務因等待事件被掛起時,下一個優先級最高的就緒任務就得到了CPU的使用權。當時間發生了或等待延時超時時,被掛起的任務就進入就緒態。
- [5] 中斷服務態:正在運行的任務是可以被中斷的,被中斷的任務於是進入了中斷服務態,響應中斷時,正在執行的任務被掛起,中斷服務程序控制了CPU的使用權。從中斷服務程序返回前,uCosII要判定被中斷的任務是否是目前就緒任務里優先級最高的,如果不是,就執行優先級最高的那個任務。 如果是,就執行被中斷的這個任務。
>_<" 消息郵箱:
這是uCosII中的一種通信機制,可以使一個任務或者中斷服務程序向另一個任務發送一個指針型的變量,通常該指針指向了一個包含了消息的特定數據結構。 在例程中需要建立郵箱,用到了函數OSMboxCreate(), 串口1中斷服務程序用到了向郵箱發送一則消息的函數OSMboxPost(), 串口接收任務用到了等待郵箱中消息的函數OSMboxPend()。
*核心代碼說明:
>_<" main():
1 int main(void) 2 { 3 CPU_INT08U os_err; 4 /* 禁止所有中斷 */ 5 CPU_IntDis(); 6 7 /* ucosII 初始化 */ 8 OSInit(); 9 10 /* 硬件平台初始化 */ 11 BSP_Init(); 12 13 //默認LED閃爍間隔500ms 14 milsec1=500,milsec2=500,milsec3=500; 15 16 USART_OUT(USART1,"*LED1閃爍間隔:1ms--65535ms 指令L1 1F--L1 65535F *\r\n");//向串口1發送開機字符。 17 USART_OUT(USART1,"*LED2閃爍間隔:1ms--65535ms 指令L2 1F--L1 65535F *\r\n"); 18 USART_OUT(USART1,"*LED3閃爍間隔:1ms--65535ms 指令L3 1F--L1 65535F *\r\n"); 19 USART_OUT(USART1,"\r\n"); 20 USART_OUT(USART1,"\r\n"); 21 //建立主任務, 優先級最高 建立這個任務另外一個用途是為了以后使用統計任務 22 os_err = OSTaskCreate((void (*) (void *)) App_TaskStart, //指向任務代碼的指針 23 (void *) 0, //任務開始執行時,傳遞給任務的參數的指針 24 (OS_STK *) &App_TaskStartStk[APP_TASK_START_STK_SIZE - 1], //分配給任務的堆棧的棧頂指針 從頂向下遞減 25 (INT8U) APP_TASK_START_PRIO); //分配給任務的優先級 26 27 OSTimeSet(0); //ucosII的節拍計數器清0 節拍計數器是0-4294967295 28 OSStart(); //啟動ucosII內核 29 return (0); 30 }
PS:經過啟動文件的初始化,首先在C代碼里,執行main(), 在啟動ucosII內核前先禁止CPU的中斷CPU_IntDis(),防止啟動過程中系統崩潰,然后對ucosII內核進行初始化OSInit(),以上兩個函數都不用特意修改,在STM32平台上已經被移植好了,對板子上的一些用到的外設進行初始化設置BSP_Init(), 這個函數包含了對系統時鍾的設置RCC_Configuration(),將系統時鍾設置為72MHz,對LED閃爍控制端口進行設置GPIO_Configuration(),對中斷源進行配置NVIC_Configuration(),對觸摸控制進行配置tp_config(),對顯示器接口FSMC進行配置, 板子上的外設初始化完畢。
>_<" 硬件相關初始化函數:
1 void BSP_Init(void) 2 { 3 RCC_Configuration(); //系統時鍾初始化及端口外設時鍾使能 4 NVIC_Configuration(); //中斷源配置 5 GPIO_Configuration(); //狀態LED1的初始化 6 USART_Config(USART1,115200); //串口1初始化 7 tp_Config(); //SPI1 觸摸電路初始化 8 FSMC_LCD_Init(); //FSMC TFT接口初始化 9 }
PS:BSP_Init(void)函數在BSP文件夾下的bsp.c文件里,其中包含了和硬件相關的初始化等驅動函數,會因不同的硬件平台而不同。
>_<" App_TaskStart()主任務:
如main函數的第22行調用的生成任務的函數:主任務的任務名為App_TaskStart, 主任務有自己的堆棧, 堆棧尺寸為APP_TASK_START_STK_SIZE*4(字節), 然后執行ucosII內部函數OSTimeSet(0),將節拍計數器清0,節拍計數器范圍是0-4294967295,對於節拍頻率100hz時, 每隔497天就重新計數, 調用內部函數OSStart(),啟動ucosII內核, 此時ucosII內核開始運行。對任務表進行監視,主任務因為已經處於就緒狀態,於是開始執行主任務App_TaskStart(),uCOSII的任務結構規定必須為無返回的結構,也就是無限循環模式。
1 static void App_TaskStart(void* p_arg) 2 { 3 (void) p_arg; 4 //初始化ucosII時鍾節拍 5 OS_CPU_SysTickInit(); 6 //使能ucos 的統計任務 7 #if (OS_TASK_STAT_EN > 0) 8 OSStatInit(); //----統計任務初始化函數 9 #endif 10 App_TaskCreate(); //建立其他的任務 11 while (1) 12 { 13 OSTimeDlyHMSM(0, 0, 1, 100); 14 } 15 }
>_<" 用戶級子任務:
在App_TaskStart()第10行調用App_TaskCreate()建立其他子任務,依次包括用戶界面任務、觸摸屏任務、串口通信任務、LED1~3閃爍任務:
1 /**************************************************************************** 2 * 名 稱:static void App_TaskCreate(void) 3 * 功 能:建立其余任務的函數 4 * 入口參數:無 5 * 出口參數:無 6 * 說 明: 7 * 調用方法:無 8 ****************************************************************************/ 9 static void App_TaskCreate(void) 10 { 11 12 Com1_MBOX=OSMboxCreate((void *) 0); //建立串口1中斷的郵箱 13 /* 建立用戶界面任務 */ 14 OSTaskCreateExt(AppTaskUserIF, //指向任務代碼的指針 15 (void *)0, //任務開始執行時,傳遞給任務的參數的指針 16 (OS_STK *)&AppTaskUserIFStk[APP_TASK_USER_IF_STK_SIZE-1], //分配給任務的堆棧的棧頂指針 從頂向下遞減 17 APP_TASK_USER_IF_PRIO, //分配給任務的優先級 18 APP_TASK_USER_IF_PRIO, //預備給以后版本的特殊標識符,在現行版本同任務優先級 19 (OS_STK *)&AppTaskUserIFStk[0], //指向任務堆棧棧底的指針,用於堆棧的檢驗 20 APP_TASK_USER_IF_STK_SIZE, //指定堆棧的容量,用於堆棧的檢驗 21 (void *)0, //指向用戶附加的數據域的指針,用來擴展任務的任務控制塊 22 OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR); //選項,指定是否允許堆棧檢驗,是否將堆棧清0,任務是否要 23 //進行浮點運算等等。 24 25 /* 建立觸摸驅動任務 */ 26 OSTaskCreateExt(AppTaskKbd, 27 (void *)0, 28 (OS_STK *)&AppTaskKbdStk[APP_TASK_KBD_STK_SIZE-1], 29 APP_TASK_KBD_PRIO, 30 APP_TASK_KBD_PRIO, 31 (OS_STK *)&AppTaskKbdStk[0], 32 APP_TASK_KBD_STK_SIZE, 33 (void *)0, 34 OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR); 35 //串口1接收及發送任務--------------------------------------------------------- 36 OSTaskCreateExt(Task_Com1,(void *)0,(OS_STK *)&Task_Com1Stk[Task_Com1_STK_SIZE-1],Task_Com1_PRIO,Task_Com1_PRIO,(OS_STK *)&Task_Com1Stk[0], 37 Task_Com1_STK_SIZE, 38 (void *)0, 39 OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR); 40 41 //LED1 閃爍任務------------------------------------------------------ 42 OSTaskCreateExt(Task_Led1,(void *)0,(OS_STK *)&Task_Led1Stk[Task_Led1_STK_SIZE-1],Task_Led1_PRIO,Task_Led1_PRIO,(OS_STK *)&Task_Led1Stk[0], 43 Task_Led1_STK_SIZE, 44 (void *)0, 45 OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR); 46 47 //LED2 閃爍任務------------------------------------------------------ 48 OSTaskCreateExt(Task_Led2,(void *)0,(OS_STK *)&Task_Led2Stk[Task_Led2_STK_SIZE-1],Task_Led2_PRIO,Task_Led2_PRIO,(OS_STK *)&Task_Led2Stk[0], 49 Task_Led2_STK_SIZE, 50 (void *)0, 51 OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR); 52 53 //LED3 閃爍任務------------------------------------------------------ 54 OSTaskCreateExt(Task_Led3,(void *)0,(OS_STK *)&Task_Led3Stk[Task_Led3_STK_SIZE-1],Task_Led3_PRIO,Task_Led3_PRIO,(OS_STK *)&Task_Led3Stk[0], 55 Task_Led3_STK_SIZE, 56 (void *)0, 57 OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR); 58 59 }
PS:6個用戶任務各自有自己的堆棧空間。
1 /**************************************************************************** 2 * 名 稱:static void AppTaskUserIF (void *p_arg) 3 * 功 能:用戶界面任務 4 * 入口參數:無 5 * 出口參數:無 6 * 說 明: 7 * 調用方法:無 8 ****************************************************************************/ 9 static void AppTaskUserIF (void *p_arg) 10 { 11 (void)p_arg; 12 GUI_Init(); //ucgui初始化 13 while(1) 14 { 15 Fun(); //界面主程序 16 } 17 } 18 /**************************************************************************** 19 * 名 稱:static void AppTaskKbd (void *p_arg) 20 * 功 能:觸摸屏坐標獲取任務 21 * 入口參數:無 22 * 出口參數:無 23 * 說 明: 24 * 調用方法:無 25 ****************************************************************************/ 26 static void AppTaskKbd (void *p_arg) 27 { 28 (void)p_arg; 29 while(1) 30 { 31 /* 延時10ms會讀取一次觸摸坐標 */ 32 OSTimeDlyHMSM(0,0,0,10); 33 GUI_TOUCH_Exec(); 34 } 35 } 36 /**************************************************************************** 37 * 名 稱:static void Task_Led1(void* p_arg) 38 * 功 能:LED1閃爍任務 39 * 入口參數:無 40 * 出口參數:無 41 * 說 明: 42 * 調用方法:無 43 ****************************************************************************/ 44 static void Task_Led1(void* p_arg) 45 { 46 47 48 49 (void) p_arg; 50 while (1) 51 { 52 LED_LED1_ON(); 53 OSTimeDlyHMSM(0, 0, 0, milsec1); 54 55 LED_LED1_OFF(); 56 OSTimeDlyHMSM(0, 0, 0, milsec1); 57 } 58 } 59 60 /**************************************************************************** 61 * 名 稱:static void Task_Led2(void* p_arg) 62 * 功 能:LED2閃爍任務 63 * 入口參數:無 64 * 出口參數:無 65 * 說 明: 66 * 調用方法:無 67 ****************************************************************************/ 68 static void Task_Led2(void* p_arg) 69 { 70 71 72 73 (void) p_arg; 74 while (1) 75 { 76 LED_LED2_ON(); 77 OSTimeDlyHMSM(0, 0, 0, milsec2); 78 79 LED_LED2_OFF(); 80 OSTimeDlyHMSM(0, 0, 0, milsec2); 81 } 82 } 83 84 /**************************************************************************** 85 * 名 稱:static void Task_Led3(void* p_arg) 86 * 功 能:LED3閃爍任務 87 * 入口參數:無 88 * 出口參數:無 89 * 說 明: 90 * 調用方法:無 91 ****************************************************************************/ 92 static void Task_Led3(void* p_arg) 93 { 94 95 96 97 (void) p_arg; 98 while (1) 99 { 100 LED_LED3_ON(); 101 OSTimeDlyHMSM(0, 0, 0, milsec3); 102 103 LED_LED3_OFF(); 104 OSTimeDlyHMSM(0, 0, 0, milsec3); 105 } 106 } 107 108 109 /**************************************************************************** 110 * 名 稱:static void Task_Com1(void *p_arg) 111 * 功 能:串口1任務 112 * 入口參數:無 113 * 出口參數:無 114 * 說 明: 115 * 調用方法:無 116 ****************************************************************************/ 117 static void Task_Com1(void *p_arg){ 118 INT8U err; 119 unsigned char * msg; 120 (void)p_arg; 121 while(1){ 122 msg=(unsigned char *)OSMboxPend(Com1_MBOX,0,&err); //等待串口接收指令成功的信號量 123 if(msg[0]=='L'&&msg[1]==0x31){ 124 milsec1=atoi(&msg[3]); //LED1 的延時毫秒 (mini and V3) 125 USART_OUT(USART1,"\r\n"); 126 USART_OUT(USART1,"LED1: %d ms 間隔閃爍",milsec1); 127 } 128 else if(msg[0]=='L'&&msg[1]==0x32){ 129 milsec2=atoi(&msg[3]); //LED2 的延時毫秒 (only V3) 130 USART_OUT(USART1,"\r\n"); 131 USART_OUT(USART1,"LED2: %d ms 間隔閃爍",milsec2); 132 } 133 else if(msg[0]=='L'&&msg[1]==0x33){ 134 milsec3=atoi(&msg[3]); //LED3 的延時毫秒 (only V3) 135 USART_OUT(USART1,"\r\n"); 136 USART_OUT(USART1,"LED3: %d ms 間隔閃爍",milsec3); 137 } 138 } 139 }
PS:這里串口通信要使用中斷來接收,並通過消息郵箱傳遞消息,如果不理解,請看上一節介紹(這里還可以把上一節知識說一遍,今后可能是想說都說不完啦說不完啦,親,我們才是ucos和ucgui的開篇之作呢~)
1 void USART1_IRQHandler(void) 2 { 3 unsigned int i; 4 unsigned char msg[50]; 5 OS_CPU_SR cpu_sr; 6 7 OS_ENTER_CRITICAL(); //保存全局中斷標志,關總中斷// Tell uC/OS-II that we are starting an ISR 8 OSIntNesting++; //用於中斷嵌套 9 OS_EXIT_CRITICAL(); //恢復全局中斷標志 10 11 if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //判斷讀寄存器是否非空 12 { 13 msg[RxCounter1++]= USART_ReceiveData(USART1); //將讀寄存器的數據緩存到接收緩沖區里 14 if(msg[RxCounter1-1]=='L'){msg[0]='L'; RxCounter1=1;} //判斷起始標志 15 if(msg[RxCounter1-1]=='F') //判斷結束標志是否是"F" 16 { 17 for(i=0; i< RxCounter1; i++){ 18 TxBuffer1[i] =msg[i]; //將接收緩沖器的數據轉到發送緩沖區,准備轉發 19 } 20 rec_f=1; //接收成功標志 21 TxBuffer1[RxCounter1]=0; //接收緩沖區終止符 22 RxCounter1=0; 23 OSMboxPost(Com1_MBOX,(void *)&msg); 24 } 25 } 26 if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET) 27 { 28 USART_ITConfig(USART1, USART_IT_TXE, DISABLE); 29 } 30 OSIntExit(); //在os_core.c文件里定義,如果有更高優先級的任務就緒了,則執行一次任務切換 31 }
*本節重點:
>_<" :用戶界面:
* 文件名: fun.c
* 內容簡述:
*
* 本例程圖形用戶接口基於ucgui3.90a,其中的MULTIEDIT窗口部件采用了ucgui3.98的窗口部件,
* 用到的ucgui窗口部件包括
* TEXT
* SLIDER
* EDIT
* FRAMEWIN
* MULTIEDIT
* 本例程實現的功能有:
* (1)通過界面上的滑動條控制板子上的LED1-LED3的閃爍間隔時間,范圍為50-5000ms
* (2)通過串口可以控制板子上的LED1-LED3的閃爍間隔時間,范圍為50-5000ms。
* 輔助軟件:PC機上需要運行串口調試助手軟件。
上面用戶級子任務中有一個是用戶界面任務,在任務中一直執行函數Fun(),這里的Fun其實就是界面顯示的核心函數。
1、對話框資源
1 /* 定義了對話框資源列表 */ 2 static const GUI_WIDGET_CREATE_INFO aDialogCreate[] = { 3 //建立窗體, 大小是800X480 原點在0,0 4 { FRAMEWIN_CreateIndirect, "LED Flash Config", 0, 0,0,800,480,FRAMEWIN_CF_ACTIVE}, //FRAMEWIN_CF_MOVEABLE}, 5 6 //建立TEXT控件,起點是窗體的10,20,大小180X30 文字左對齊 7 { TEXT_CreateIndirect, "Led Flash Rate", GUI_ID_TEXT3, 10, 20, 180, 30, TEXT_CF_LEFT }, 8 9 //建立TEXT控件,起點是窗體的200,20,大小39X30 文字左對齊 10 { TEXT_CreateIndirect, "ms", GUI_ID_TEXT4, 220, 20, 39, 30, TEXT_CF_LEFT }, 11 12 //建立EDIT控件,起點是窗體的191,60,大小47X25 文字右對齊 4個字符寬度 13 { EDIT_CreateIndirect, "", GUI_ID_EDIT0, 739, 60, 47, 25, EDIT_CF_RIGHT, 4 }, 14 //建立EDIT控件,起點是窗體的191,110,大小47X25 文字右對齊 4個字符寬度 15 { EDIT_CreateIndirect, "", GUI_ID_EDIT1, 739, 110, 47, 25, EDIT_CF_RIGHT, 4 }, 16 //建立EDIT控件,起點是窗體的191,160,大小47X25 文字右對齊 4個字符寬度 17 { EDIT_CreateIndirect, "", GUI_ID_EDIT2, 739, 160, 47, 25, EDIT_CF_RIGHT, 4 }, 18 19 //建立TEXT控件,起點是窗體的5,60,大小50X55 文字右對齊 20 { TEXT_CreateIndirect, "Led1", GUI_ID_TEXT0, 5, 60, 50, 55, TEXT_CF_RIGHT }, 21 //建立TEXT控件,起點是窗體的5,110,大小50X105 文字右對齊 22 { TEXT_CreateIndirect, "Led2", GUI_ID_TEXT1, 5, 110, 50, 105, TEXT_CF_RIGHT }, 23 //建立TEXT控件,起點是窗體的5,160,大小50X155 文字右對齊 24 { TEXT_CreateIndirect, "Led3", GUI_ID_TEXT2, 5, 160, 50, 155, TEXT_CF_RIGHT }, 25 26 //建立滑動條控件,起點是窗體的60,60,大小130X25 27 { SLIDER_CreateIndirect, NULL, GUI_ID_SLIDER0, 60, 60, 650, 25, 0, 0 }, 28 //建立滑動條控件,起點是窗體的60,110,大小130X25 29 { SLIDER_CreateIndirect, NULL, GUI_ID_SLIDER1, 60, 110, 650, 25, 0, 0 }, 30 //建立滑動條控件,起點是窗體的60,160,大小130X25 31 { SLIDER_CreateIndirect, NULL, GUI_ID_SLIDER2, 60, 160, 650, 25, 0, 0 }, 32 };
PS:包括控件類型,控件名稱,控件ID,位置大小等....具體參見eWin5中文手冊窗口管理器那章http://pan.baidu.com/s/1mgkKVFU
2、fun函數:
1 void Fun(void) { 2 unsigned char edit_cur; 3 GUI_CURSOR_Show(); 4 5 /* 建立窗體,包含了資源列表,資源數目, 並指定回調函數 */ 6 hWin = GUI_CreateDialogBox(aDialogCreate, GUI_COUNTOF(aDialogCreate), _cbCallback, 0, 0, 0); 7 8 /* 設置窗體字體 */ 9 FRAMEWIN_SetFont(hWin, &GUI_FontComic24B_1); 10 11 /* 獲得TEXT 部件的句柄 */ 12 text0 = WM_GetDialogItem(hWin, GUI_ID_TEXT0); 13 text1 = WM_GetDialogItem(hWin, GUI_ID_TEXT1); 14 text2 = WM_GetDialogItem(hWin, GUI_ID_TEXT2); 15 text3 = WM_GetDialogItem(hWin, GUI_ID_TEXT3); 16 text4 = WM_GetDialogItem(hWin, GUI_ID_TEXT4); 17 18 /* 獲得slider部件的句柄 */ 19 slider0 = WM_GetDialogItem(hWin, GUI_ID_SLIDER0); 20 slider1 = WM_GetDialogItem(hWin, GUI_ID_SLIDER1); 21 slider2 = WM_GetDialogItem(hWin, GUI_ID_SLIDER2); 22 23 /* 獲得edit 部件的句柄 */ 24 edit0 = WM_GetDialogItem(hWin, GUI_ID_EDIT0); 25 edit1 = WM_GetDialogItem(hWin, GUI_ID_EDIT1); 26 edit2 = WM_GetDialogItem(hWin, GUI_ID_EDIT2); 27 28 /* 設置TEXT部件的字體 */ 29 EDIT_SetFont(edit0,&GUI_FontComic18B_1); 30 EDIT_SetFont(edit1,&GUI_FontComic18B_1); 31 EDIT_SetFont(edit2,&GUI_FontComic18B_1); 32 33 /* 設置EDIT部件采用10進制 范圍50-20000*/ 34 EDIT_SetDecMode(edit0,milsec1,50,2000,0,0); 35 EDIT_SetDecMode(edit1,milsec2,50,2000,0,0); 36 EDIT_SetDecMode(edit2,milsec3,50,2000,0,0); 37 38 /* 設置TEXT部件的字體 */ 39 TEXT_SetFont(text0,pFont); 40 TEXT_SetFont(text1,pFont); 41 TEXT_SetFont(text2,pFont); 42 TEXT_SetFont(text3,pFont); 43 TEXT_SetFont(text4,pFont); 44 45 /* 設置TEXT部件的字體顏色 */ 46 TEXT_SetTextColor(text0,GUI_WHITE); 47 TEXT_SetTextColor(text1,GUI_WHITE); 48 TEXT_SetTextColor(text2,GUI_WHITE); 49 TEXT_SetTextColor(text3,GUI_WHITE); 50 TEXT_SetTextColor(text4,GUI_WHITE); 51 52 /* 設置slider部件的取值范圍50-2000 */ 53 SLIDER_SetRange(slider0,50,2000); 54 SLIDER_SetRange(slider1,50,2000); 55 SLIDER_SetRange(slider2,50,2000); 56 57 /* 設置slider部件的值*/ 58 SLIDER_SetValue(slider0,milsec1); 59 SLIDER_SetValue(slider1,milsec2); 60 SLIDER_SetValue(slider2,milsec3); 61 62 /* 在窗體上建立multiedit部件*/ 63 hmultiedit=MULTIEDIT_Create(5, 230, 790, 245, hWin, GUI_ID_MULTIEDIT0,WM_CF_SHOW, MULTIEDIT_CF_AUTOSCROLLBAR_V, 64 "",500); 65 /* 設置multiedit部件的字體 */ 66 MULTIEDIT_SetFont(hmultiedit,&GUI_FontHZ_SimSun_13); 67 /* 設置multiedit部件的背景色 */ 68 MULTIEDIT_SetBkColor(hmultiedit,MULTIEDIT_CI_EDIT,GUI_LIGHTGRAY); 69 /* 設置multiedit部件的字體顏色 */ 70 MULTIEDIT_SetTextColor(hmultiedit,MULTIEDIT_CI_EDIT,GUI_BLUE); 71 /* 設置multiedit部件的文字回繞 */ 72 MULTIEDIT_SetWrapWord(hmultiedit); 73 /* 設置multiedit部件的最大字符數 */ 74 MULTIEDIT_SetMaxNumChars(hmultiedit,500); 75 /* 設置multiedit部件的字符左對齊*/ 76 //MULTIEDIT_SetTextAlign(hmultiedit,GUI_TA_LEFT); 77 /* 獲得multiedit部件里光標位置 */ 78 edit_cur=MULTIEDIT_GetTextSize(hmultiedit); 79 /* 設置multiedit部件光標位置 */ 80 MULTIEDIT_SetCursorOffset(hmultiedit,edit_cur); 81 /* 設置multiedit部件的文本內容 */ 82 //MULTIEDIT_AddText(hmultiedit,"奮斗STM32開發板LED閃爍實驗"); 83 while (1) 84 { 85 if(rec_f==1){ //全局變量 rec_f 代表串口有數據接收到 86 rec_f=0; 87 edit_cur=MULTIEDIT_GetTextSize(hmultiedit); //獲得MULTIEDIT內容的長度 88 if(edit_cur<500){ //顯示區域字符長度小於500 繼續添加顯示 89 MULTIEDIT_SetCursorOffset(hmultiedit,edit_cur); 90 //MULTIEDIT_AddText(hmultiedit,&TxBuffer1[0]); //在內容的最后增加來自於串口的新的內容 91 } 92 else { //顯示區域字符長度大於等於500 清除顯示區。繼續重新顯示 93 94 MULTIEDIT_SetText(hmultiedit,&TxBuffer1[0]); 95 } 96 if(TxBuffer1[0]=='L'&&TxBuffer1[1]==0x31){ //讀取串口接收到的信息 97 milsec1=atoi(&TxBuffer1[3]); //LED1 的延時毫秒 (mini and V3) 98 SLIDER_SetValue(slider0,milsec1); //改變slider0的值 99 EDIT_SetValue(edit0,milsec1); //改變edit0的值 100 } 101 else if(TxBuffer1[0]=='L'&&TxBuffer1[1]==0x32){ //讀取串口接收到的信息 102 milsec2=atoi(&TxBuffer1[3]); //LED2 的延時毫秒 (mini and V3) 103 SLIDER_SetValue(slider1,milsec2); //改變slider1的值 104 EDIT_SetValue(edit1,milsec2); //改變edit1的值 105 } 106 else if(TxBuffer1[0]=='L'&&TxBuffer1[1]==0x33){ //讀取串口接收到的信息 107 milsec3=atoi(&TxBuffer1[3]); //LED3 的延時毫秒 (mini and V3) 108 SLIDER_SetValue(slider2,milsec3); //改變slider2的值 109 EDIT_SetValue(edit2,milsec3); //改變edit3的值 110 } 111 } 112 WM_Exec(); //屏幕刷新 113 } 114 }
PS:第6行hWin = GUI_CreateDialogBox(aDialogCreate, GUI_COUNTOF(aDialogCreate), _cbCallback, 0, 0, 0)是用上面設置好的對話框資源建立建立窗體並指定回調函數。
PS:下面為窗體回調函數(窗口產生變換時,會自動執行這個函數,該函數對窗體動作信息進行分析,最后調用_OnValueChanged(hDlg, Id); 修改對應控件的值。
1 static void _cbCallback(WM_MESSAGE * pMsg) { 2 int NCode, Id; 3 WM_HWIN hDlg; 4 hDlg = pMsg->hWin; 5 switch (pMsg->MsgId) { 6 case WM_NOTIFY_PARENT: 7 Id = WM_GetId(pMsg->hWinSrc); /*獲得窗體部件的ID*/ 8 NCode = pMsg->Data.v; /*動作代碼 */ 9 switch (NCode) { 10 case WM_NOTIFICATION_VALUE_CHANGED: /*窗體部件的值被改變 */ 11 _OnValueChanged(hDlg, Id); 12 break; 13 default: 14 break; 15 } 16 break; 17 default: 18 WM_DefaultProc(pMsg); 19 } 20 }
1 static void _OnValueChanged(WM_HWIN hDlg, int Id) { 2 3 if ((Id == GUI_ID_SLIDER0)) { //slider0 的值被改變 4 milsec1=SLIDER_GetValue(slider0); //獲得slider0的值 5 EDIT_SetValue(edit0,milsec1); //EDIT0 的值被改變 6 } 7 else if ((Id == GUI_ID_SLIDER1)) { //slider1 的值被改變 8 milsec2=SLIDER_GetValue(slider1); //獲得slider1的值 9 EDIT_SetValue(edit1,milsec2); //EDIT1 的值被改變 10 } 11 else if ((Id == GUI_ID_SLIDER2)) { //slider2 的值被改變 12 milsec3=SLIDER_GetValue(slider2); //獲得slider2的值 13 EDIT_SetValue(edit2,milsec3); //EDIT2 的值被改變 14 } 15 }
LZ說明及相關下載鏈接:
因為這里涉及uCos和uC-GUI的知識太多,在這里實在說不清,上面只是流程大致過了一下,如果想深入學習,建議看邵貝貝翻譯的關於uCos的書,以及eWin5中文手冊或者uC-GUI_user.pdf。這里建議看英文版的uc-GUI介紹,這個版本很全,講的深入淺出~
- 《嵌入式實時操作系統uCos-II》邵貝貝.pdf下載鏈接:http://pan.baidu.com/s/1pJBJiS7
- eWin5中文手冊下載鏈接:http://pan.baidu.com/s/1i39T6V7
- uC-GUI_user.pdf下載鏈接: http://pan.baidu.com/s/1qWM65kC
- uC-GUI中文手冊.pdf下載鏈接:http://pan.baidu.com/s/1c0cTH9e
- 上述工程代碼(keil4)選在鏈接:http://pan.baidu.com/s/1mg3bNJi
- LZ主頁[如果你是從其他地方看到這篇文章]:http://www.cnblogs.com/zjutlitao/
