[stm32][ucos][ucgui] 2、LED闪烁、串口、滑块、文本编辑框简单例程
上一篇:[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/