您好,欢迎来到年旅网。
搜索
您的当前位置:首页JXARM9-2410 UCOS实验教程

JXARM9-2410 UCOS实验教程

来源:年旅网
 JXARM9-2410 uC/OS-II课程设计实验 1

第1章 uC/OS-II内核移植和扩充实验........................................4 1.1 uC/OS-II移植实验..................................................4

1.1.1 实验目的........................................................4 1.1.2 实验内容........................................................4 1.1.3 预备知识........................................................4 1.1.4 实验设备........................................................4 1.1.5 基础知识........................................................4 1.1.6 实验步骤.......................................................12 1.1.7 实验报告要求...................................................12 1.2 uC/OS-II任务间通讯和同步实验.....................................13

1.2.1 实验目的.......................................................13 1.2.2 实验内容.......................................................13 1.2.3 预备知识.......................................................13 1.2.4 实验设备.......................................................13 1.2.5 基础知识.......................................................13 1.2.6 实验步骤.......................................................16 1.2.7 实验报告要求...................................................17 1.3 软件定时器实验....................................................18

1.3.1 实验目的.......................................................18 1.3.2 实验内容.......................................................18 1.3.3 预备知识.......................................................18 1.3.4 实验设备.......................................................18 1.3.5 实验步骤.......................................................18 1.4 内核裁减实验......................................................21

1.4.1 实验目的.......................................................21 1.4.2 实验内容.......................................................21 1.4.3 预备知识.......................................................21 1.4.4 实验设备.......................................................21 1.4.5 实验步骤.......................................................21

第2章 uC/OS-II驱动程序实验.............................................26 2.1 4X4小键盘驱动程序实验............................................26

2.1.1 实验目的.......................................................26 2.1.2 实验内容.......................................................26 2.1.3 预备知识.......................................................26 2.1.4 实验设备.......................................................26 2.1.5 实验步骤.......................................................26

JXARM9-2410 uC/OS-II课程设计实验 2

2.2 步进电机驱动程序实验..............................................32

2.2.1 实验目的.......................................................32 2.2.2 实验内容.......................................................32 2.2.3 预备知识.......................................................32 2.2.4 实验设备.......................................................32 2.2.5 实验步骤.......................................................32

第3章 uC/OS-II应用程序实验..............................................36 3.1 多任务编程实验....................................................36

3.1.1 实验目的.......................................................36 3.1.2 实验内容.......................................................36 3.1.3 预备知识.......................................................36 3.1.4 实验设备.......................................................36 3.1.5 实验步骤.......................................................36 3.2 图形用户界面uC/GUI移植实验.......................................40

3.2.1 实验目的.......................................................40 3.2.2 实验内容.......................................................40 3.2.3 预备知识.......................................................40 3.2.4 实验设备.......................................................40 3.2.5 实验步骤.......................................................40 3.3 图形用户界面(基本绘图功能/字符显示功能)编程实验..................53

3.3.1 实验目的.......................................................53 3.3.2 实验内容.......................................................53 3.3.3 预备知识.......................................................53 3.3.4 实验设备.......................................................53 3.3.5 实验步骤.......................................................53 3.4 图形用户界面(基本图形控件)编程实验..............................59

3.4.1 实验目的.......................................................59 3.4.2 实验内容.......................................................59 3.4.3 预备知识.......................................................59 3.4.4 实验设备.......................................................59 3.4.5 实验步骤.......................................................59

第4章 综合实验..........................................................63 4.1 多通道数据采集....................................................63

4.1.1 实验目的.......................................................63 4.1.2 实验内容.......................................................63 4.1.3 预备知识.......................................................63

JXARM9-2410 uC/OS-II课程设计实验 3

4.1.4 实验设备.......................................................63 4.1.5 实验步骤.......................................................63 4.2 贪食蛇游戏设计实验................................................68

4.2.1 实验目的.......................................................68 4.2.2 实验内容.......................................................68 4.2.3 预备知识.......................................................68 4.2.4 实验设备.......................................................68 4.2.5 实验步骤.......................................................68 4.3 俄罗斯方块游戏设计实验............................................80

4.3.1 实验目的.......................................................80 4.3.2 实验内容.......................................................80 4.3.3 预备知识.......................................................80 4.3.4 实验设备.......................................................80 4.3.5 实验步骤.......................................................80

JXARM9-2410 uC/OS-II课程设计实验 4

第1章 uC/OS-II内核移植和扩充实验

1.1 uC/OS-II移植实验

1.1.1 实验目的

1. 了解uC/OS-II内核的基本原理和主要结构;

2. 掌握将uC/OS-II内核移植到ARM处理器上的基本方法; 3. 掌握uC/OS-II下基本多任务应用程序的编写。

1.1.2 实验内容

1. 学习uC/OS-II再ARM处理器上的移植过程;

2. 编写简单的多任务应用程序,实现跑马灯和数码管显示的功能。

1.1.3 预备知识

1. 了解嵌入式操作系统的构架,以及具体的uC/OS-II的组成; 2. 了解操作系统的移植方法。

1.1.4 实验设备

1. 硬件:JX44B0教学实验箱、PC机;

2. 软件:PC机操作系统 Windows 98(2000、XP) + ADT IDE集成开发环境。

1.1.5 基础知识

1. uC/OS-II概述

uC/OS-II在特定处理器上的移植工作绝大部分集中在多任务切换的实现上,因为这部分代码主要是用来保存和恢复处理器现场,许多操作如读写寄存器操作不能用C语言,只能使用特定的处理器的汇编语言来完成。

将 uC/OS-II 移植到ARM处理器上,需要完成的工作非常简单,修改三个和体系结构相关的文件即可,代码量大约是500行。这三个文件是OS_CPU_C.c、OS_CPU_C.H以及OS_CPU_A.S,下面将分别说明。 2. OS_CPU.H的移植

1) 数据类型定义

该文件中定义了本系统中所使用的数据类型,这部分的修改是和所用的编译器相关的,不同的编译器会使用不同的字节长度来表示同一数据类型,比如int,同样在x86平台上,如果用GNU的gcc 编译器,则编译为4 bytes,而使用MS VC++则编译为2 bytes。我们这里使用的是

JXARM9-2410 uC/OS-II课程设计实验 5

GNU 的 gcc。此外,该文件还定义了堆栈单位,它定义了在处理器现场保存和恢复时所使用的数据类型,它必须和处理器的寄存器长度一致。相关的数据类型的定义如下:

typedef unsigned char BOOLEAN;

typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ typedef signed char INT8S; /* Signed 8 bit quantity */ typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ typedef signed int INT16S; /* Signed 16 bit quantity */ typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ typedef signed long INT32S; /* Signed 32 bit quantity */ typedef float FP32; /* Single precision floating point */ typedef double FP; /* Double precision floating point */

typedef unsigned int OS_STK; /* Each stack entry is 16-bit wide */

/* Define data types for backward compatibility ... */ #define BYTE INT8S

/* ... to uC/OS V1.xx. Not actually needed for ... */ #define UBYTE INT8U /* ... uC/OS-II. */ #define WORD INT16S #define UWORD INT16U #define LONG INT32S #define ULONG INT32U

2) ARM处理器相关宏定义

该文件还定义了ARM处理器中退出临界区和进入临界区的宏定义,如下图所示。

#define OS_ENTER_CRITICAL()

ARMDisableInt()

#define OS_EXIT_CRITICAL() ARMEnableInt()

3) 堆栈增长方向

堆栈增长方向也由该文件定义,堆栈由高地址向低地址增长,这个也是和编译器有关的,当进行函数调用时,入口参数和返回地址一般都会保存在当前任务的堆栈中,编译器的编译选项和由此生成的堆栈指令就会决定堆栈的增长方向。

#define OS_STK_GROWTH

1

3 .OS_CPU.c的移植

1) 任务堆栈初始化

该函数由OSTaskCreate()或OSTaskCreateExt()调用,用来初始化任务的堆栈并返回新的堆栈指针stk。初始状态的堆栈模拟发生一次中断后的堆栈结构。在ARM体系结构下,任务堆栈空间由高至低依次将保存着pc、lr、r12、r11、r10、… r1、r0、CPSR、SPSR,下图说明了

JXARM9-2410 uC/OS-II课程设计实验 6

OSTaskStkInit()初始化后的也是新创建任务的堆栈内容。堆栈初始化工作结束后,

OSTaskStkInit()返回新的堆栈栈顶指针,OSTaskCreate()或 OSTaskCreateExt()将指针保存在任务的OS_TCB中。

图6-4 OSTaskStkInit()初始化后的堆栈内容

任务堆栈初始化函数如下所示:

void *OSTaskStkInit(void (*task)(void *pd),void *pdata,void *ptos,INT16U opt) {

unsigned int *stk;

opt = opt; /* prevent warning */ stk = (unsigned int *)ptos; /* Load stack pointer*/

/* build a context for the new task */ *--stk = (unsigned int) task; /* pc */ *--stk = (unsigned int) task; /* lr */

*--stk = 0; /* r12 */ *--stk = 0; /* r11 */ *--stk = 0; /* r10 */ *--stk = 0; /* r9 */ *--stk = 0; /* r8 */ *--stk = 0; /* r7 */ *--stk = 0; /* r6 */ *--stk = 0; /* r5 */ *--stk = 0; /* r4 */ *--stk = 0; /* r3 */ *--stk = 0; /* r2 */ *--stk = 0; /* r1 */ *--stk = (unsigned int) pdata; /* r0 */ *--stk = (SVC32MODE|0x0);

/* cpsr IRQ, FIQ disable*/

JXARM9-2410 uC/OS-II课程设计实验 7

*--stk = (SVC32MODE|0x0);

return ((void *)stk); }

/* spsr IRQ, FIQ disable */

2) 系统hook函数

在这个文件里面还需要实现几个操作系统规定的hook函数,这些函数为用户定义函数,它将在相应的操作系统调用后执行由用户定义的这些hook函数,执行特定的用户操作,如果没有特殊需求,则只需要简单地将它们都实现为空函数就可以。这些函数包括:

OSSTaskCreateHook( ) OSTaskDelHook( ) OSTaskSwHook( ) OSTaskStatHook( ) OSTimeTickHook( )

3) 中断级任务切换函数

该函数由OSIntExit()和OSExIntExit()调用。它是在时钟中断ISR(中断服务例程)中发现有高优先级任务等待的时钟信号到来,则需要在中断退出后并不返回被中断任务,而是直接调度就绪的高优先级任务执行。这样做的目的主要是能够尽快地让高优先级的任务得到响应,保证系统的实时性能。该函数通过设置一个全局变量need_to_swap_context标志以表示在中断服务程序中进行任务切换,然后在OSTickISR()中判断该变量以进行正确的动作。其函数如下:

void OSIntCtxSw(void) { }

need_to_swap_context = 1;

4 . OS_CPU_A.S的移植

1) 时钟节拍中断服务函数

时钟节拍是特定的周期性中断。这个中断可以看作是系统心脏的脉动。时钟的节拍式中断使得内核可以将任务延时若干个整数时钟节拍,以及当任务等待事件发生时,提供等待超时的依据。时钟节拍率越快,系统的额外开销就越大。中断之间的时间间隔取决于不同的应用,本系统使用S3C44B0X的timer 0作为时钟节拍源,产生间隔10mS的时钟节拍。

OSTickISR()就是时钟节拍中断服务函数,也就是S3C44B0X的timer 0的中断处理函数。 OSTickISR()首先在被中断任务堆栈中保存CPU寄存器的值,然后调用OSIntEnter()。随后,OSTickISR()调用OSTimeTick(),检查所有处于延时等待状态的任务,判断是否有延时结束就绪的任务。OSTickISR()的最后调用OSIntExit(),如果在中断中(或其他嵌套的中断)有更高优先级的任务就绪,并且当前中断为中断嵌套的最后一层。OSIntExit()将进行任务调度。注意如果进行了任务调度,OSIntExit()将不再返回调用者,而是用新任务的堆栈中的寄存器数值恢复CPU现场,然后用IRET实现任务切换。如果当前中断不是中断嵌套的最后一层,或中断中没

JXARM9-2410 uC/OS-II课程设计实验 8

有改变任务的就绪状态,OSIntExit()将返回调用者OSTickISR(),最后OSTickISR()返回被中断的任务。

OSTickISR()先关闭中断,然后清除timer 0中断标记(只有清楚当前中断标记才能够引发下一次中断)。接着将调用IrqStart(),uC/OS-II要求在中断服务程序开头将记录中断嵌套层数的全局变量OSIntNesting加1。随后OSTickISR()调用OSTimeTick(),检查所有处于延时等待状态的任务,判断是否有延时结束就绪的任务。然后调用IrqFinish()函数,IrqFinish()将调用OSIntExit()函数,如果在中断中(或其他嵌套的中断)有更高优先级的任务就绪,并且当前中断为中断嵌套的最后一层,OSIntExit()将进行任务调度,并在OSIntCtxSw()函数中设置need_to_swap_context标记为1。接下来OSTickISR()判断need_to_swap_context标记是否为1,如果为1则进行任务调度,将不再返回被中断的任务,而是用新任务的堆栈中的寄存器数值恢复CPU现场,然后实现任务切换。如果当前中断不是中断嵌套的最后一层,或中断中没有改变任务的就绪状态,OSTickISR()将返回被中断的任务。

下面给出了OSTickISR()的完整代码。

.GLOBAL OSTickISR OSTickISR :

SB sp!,{r0-r11,lr} mrs orr msr

r0, CPSR r0, r0, #0x80 CPSR_cxsf, r0

@ and set IRQ disable flag

LDR r0, =I_ISPC LDR r1, =BIT_TIMER0 STR r1, [r0] BL IrqStart BL OSTimeTick BL IrqFinish LDR LDR CMP LDREQ

r0, =need_to_swap_context r2, [r0] r2, #1 pc, =_CON_SW

_NOT_CON_SW :

@not context switching LDMIA sp!,{r0-r11, lr} SUBS pc, lr, #4

@set need_to_swap_context is '0' MOV STR

r1, #0 r1, [r0]

_CON_SW:

@now context switching LDMIA sp!,{r0-r11,lr}

JXARM9-2410 uC/OS-II课程设计实验 9

LDMFD

sp!, {r4}

@ OSTCBCur = OSTCBHighRdy STR r6, [r4]

@ set new current task TCB address

@ Get highest priority task TCB address LDR r6, addr_OSTCBHighRdy LDR r6, [r6] LDR sp, [r6]

@ get new task's stack pointer

@ OSPrioCur = OSPrioHighRdy LDR r4, addr_OSPrioCur LDR r5, addr_OSPrioHighRdy LDRB r6, [r5] STRB r6, [r4]

@ Get current task TCB address LDR r4, addr_OSTCBCur LDR r5, [r4] STR sp, [r5]

@ store sp in preempted tasks's TCB

SUB STR

lr, lr, #4

lr, SAVED_LR

@Change Supervisor mode AND ORR

lr, lr, #0xFFFFFFE0 lr, lr, #0x13

MRS lr, SPSR

MSR CPSR_cxsf, lr

@Now Supervisor mode STR LDR STMFD SUB LDMIA STMFD STMFD MRS STMFD MRS STMFD

r12, [sp, #-8] r12, SAVED_LR sp!, {r12} sp, sp, #4 sp!, {r12} sp!, {lr} r4, CPSR sp!, {r4} r4, SPSR sp!, {r4}

@ save current PSR

@ save SPSR

@ r12 that PC of task @ inclease stack point @ restore r12 @ saved r12

@ save lr

sp!, {r0-r12} @ save register file and ret address

JXARM9-2410 uC/OS-II课程设计实验 10

MSR SPSR_cxsf, r4 LDMFD LDMFD

sp!, {r4}

MSR CPSR_cxsf, r4

sp!, {r0-r12, lr, pc}

2) 退出临界区和进入临界区函数

他们分别是退出临界区和进入临界区的宏指令实现。主要用于在进入临界区之前关闭中断,在退出临界区的时候恢复原来的中断状态。它的实现如下所示。

.GLOBAL ARMDisableInt ARMDisableInt:

.GLOBAL ARMEnableInt ARMEnableInt:

SB

sp!, {r0}

MRS r0, CPSR BIC r0, r0, #NoInt MSR CPSR_cxsf, r0 LDMIA

sp!, {r0}

MOV pc, lr SB MRS ORR MSR LDMIA

sp!, {r0} r0, CPSR r0, r0, #NoInt CPSR_cxsf, r0 sp!, {r0}

MOV pc, lr

3) 任务级上下文切换函数

任务级的上下文切换函数OS_TASK_SW(),它是当任务因为被阻塞而主动请求cpu调度时被执行,由于此时的任务切换都是在非异常模式下进行的,因此区别于中断级别的任务切换。它的工作是先将当前任务的cpu现场保存到该任务堆栈中,然后获得最高优先级任务的堆栈指针,从该堆栈中恢复此任务的cpu现场,使之继续执行。这样就完成了一次任务切换。其程序清单如下所示:

.GLOBAL OS_TASK_SW OS_TASK_SW:

STMFD STMFD STMFD STMFD STMFD

sp!, {lr} sp!, {lr}

@ save pc @ save lr

sp!, {r0-r12} @ save register file and ret address sp!, {r4}

sp!, {r4}

@ save current PSR

@ save SPSR

MRS r4, CPSR MRS r4, SPSR

JXARM9-2410 uC/OS-II课程设计实验 11

@ OSPrioCur = OSPrioHighRdy LDR r4, addr_OSPrioCur LDR r5, addr_OSPrioHighRdy LDRB r6, [r5] STRB r6, [r4]

@ Get current task TCB address LDR r4, addr_OSTCBCur LDR r5, [r4] STR sp, [r5]

@ store sp in preempted tasks's TCB

@ Get highest priority task TCB address LDR r6, addr_OSTCBHighRdy LDR r6, [r6] LDR sp, [r6] STR r6, [r4] LDMFD LDMFD LDMFD

@ get new task's stack pointer @ set new current task TCB address

@ OSTCBCur = OSTCBHighRdy

sp!, {r4} sp!, {r4}

MSR SPSR_cxsf, r4 MSR CPSR_cxsf, r4

sp!, {r0-r12, lr, pc}

4) OSStartHighRd

OSStartHighRd()函数是在OSStart()多任务启动之后,负责从最高优先级任务的TCB控制块中获得该任务的堆栈指针sp,通过sp依次将cpu现场恢复,这时系统就将控制权交给用户创建的该任务进程,直到该任务被阻塞或者被其他更高优先级的任务抢占cpu。该函数仅仅在多任务启动时被执行一次,用来启动第一个,也就是最高优先级的任务执行。

LDMFD LDMFD

sp!, {r4} sp!, {r4}

@ get new state from top of the stack @ CPSR should be SVC32Mode

MSR SPSR_cxsf, r4 MSR CPSR_cxsf, r4 STR r5, [r4]

@ set new current task TCB address

LDR r5, [r5] LDR sp, [r5]

@ get stack pointer @ switch to the new stack

.GLOBAL OSStartHighRdy LDR r4, addr_OSTCBCur

@ Get current task TCB address

OSStartHighRdy:

LDR r5, addr_OSTCBHighRdy @ Get highest priority task TCB address

JXARM9-2410 uC/OS-II课程设计实验 12

LDMFD

sp!, {r0-r12, lr, pc } @ start the new task

5. 多任务应用程序的编写

Eg1.c中是一个最基本的uC/OS-II多任务应用程序的范例,它主要包括如下两个部分: 1) C语言入口函数

函数Main为C语言入口函数,所有的C程序从这里开始运行。在该函数中将进行如下操作:

1、调用函数ARMTargetInit初始化ARM处理器; 2、调用OSInit进行操作系统初始化;

3、调用OSTaskCreate函数两个任务:TaskLED和TaskSEG; 4、调用ARMTargetStart函数启动时钟节拍中断; 5、调用OSStart启动系统任务调度。 2) 任务处理函数

1. 硬件:JX44B0教学实验箱、PC机;

2. 软件:PC机操作系统 Windows 98(2000、XP) + ADT IDE集成开发环境。

1.1.6 实验步骤

1. 使用创建好的模板工程Eg1,新建一个工程Eg1,并将模板中的Core(C source和Core(Assemble)文件夹中的文件加入到工程Eg1中,参照ModelEg修改Eg1的工程设置。

2. 新建一个文件Eg1.c,并将其添加到Eg1工程的App文件夹中。

3. 打开Eg1.c文件,参照Eg1.c添加两个任务,它们的任务处理函数分别为TaskLED和TaskSEG。

4. 在TaskLED函数中每隔200个时钟节拍使所有的跑马灯闪烁一次(一亮一灭)。 5. 在TaskSEG函数中每隔100个时钟节拍切换一次数码管显示(循环从“1”到“F”显示)。

6. 编译工程Eg1,如果出错,进行修改后再编译。

7. 将Eg1下载并运行,看结果,正确的结果将每隔1S切换一次数码管显示,每隔2S使所有的跑马灯闪烁一次。

1.1.7 实验报告要求

1. uC/OS-II是一个小型的操作系统,它由那些模块组成?具有哪些功能? 2. 简述uC/OS-II是如何进行任务调度的?

3. 修改uC/OS-II内核,实现在uC/OS-II中处理中断。

JXARM9-2410 uC/OS-II课程设计实验 13

1.2 uC/OS-II任务间通讯和同步实验

1.2.1 实验目的

1. 掌握uC/OS-II操作系统下使用信号量解决任务之间的同步问题; 2. 掌握uC/OS-II操作系统下任务间通讯的方法。

1.2.2 实验内容

1. 使用信号量实现任务间同步; 2. 使用邮箱实现任务之间的通讯。

1.2.3 预备知识

1. 了解操作系统任务调度的机制; 2. 了解操作系统任务间通讯的机制;

3. 学习uC/OS-II操作系统下多任务应用程序的编写方法。

1.2.4 实验设备

1. 硬件:JX44B0教学实验箱、PC机;

2. 软件:PC机操作系统 Windows 98(2000、XP) + ADT IDE集成开发环境。

1.2.5 基础知识

1. uC/OS-II任务之间的通讯与同步方式:

在µC/OS-II中,有多种方法可以保护任务之间的共享数据和提供任务之间的通讯。 1) 利用宏OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()来关闭中断和打开中断。当两个任务或者一个任务和一个中断服务子程序共享某些数据时,可以采用这种方法;

2) 利用函数OSSchedLock()和OSSchekUnlock()对µC/OS-II中的任务调度函数上锁和开锁; 3) 信号量; 4) 邮箱; 5) 队列。

2. uC/OS-II中使用信号量进行任务之间同步

通过调用OSSemCreate()建立信号量,并对信号量的初始计数值赋值。该初始值为0到65,535之间的一个数。如果信号量是用来表示一个或者多个事件的发生,那么该信号量的初始值应设为0。如果信号量是用于对共享资源的访问,那么该信号量的初始值应设为1(例如,把它当作二值信号量使用)。最后,如果该信号量是用来表示允许任务访问n个相同的资源,那么该初始值显然应该是n,并把该信号量作为一个可计数的信号量使用。

JXARM9-2410 uC/OS-II课程设计实验 14

通过调用OSSemPost()函数发送一个信号量,通过调用OSSemPend()函数等待一个信号量。如果信号量当前是可用的(信号量的计数值大于0),将信号量的计数值减1,然后函数将“无错”错误代码返回给它的调用函数。如果信号量的计数值为0,而OSSemPend()函数又不是由中断服务子程序调用的,则调用OSSemPend()函数的任务要进入睡眠状态,等待另一个任务(或者中断服务子程序)发出该信号量。

下面的代码使用两个信号量实现了两个任务之间的同步。信号量创建的代码如下,信号量Sem2初始为可用状态,而信号量Sem1初始为不可用状态。

Sem1 = OSSemCreate(0);

Sem2 = OSSemCreate(1);

任务TaskLED必须等待Sem2可用才能够继续往下运行,而Sem2在TaskSEG中发送。同样TaskSEG必须等待Sem1可用才能够继续往下运行,而Sem1在TaskLED中发送,这样就实现了程序中“…”之间代码的顺序执行,而不受OSTimeDly的延时值的影响。

void TaskLED(void *Id) {

INT8U Reply;

for (;;) {

OSSemPend(Sem2, 0, &Reply); …

OSSemPost(Sem1); OSTimeDly(200); } }

void TaskSEG(void *Id) {

INT8U Reply;

for (;;) {

OSSemPend(Sem1, 0, &Reply);

/* signal the semaphore */ /* wait a short while */

OSSemPost(Sem2); OSTimeDly(100); } }

/* wait for the semaphore */

/* signal the semaphore */ /* wait a short while */ /* wait for the semaphore */

JXARM9-2410 uC/OS-II课程设计实验 15

3. uC/OS-II中使用邮箱实现任务之间的通讯

邮箱可使一个任务或者中断服务子程序向另一个任务发送一个指针型的变量。该指针指向一个包含了特定“消息”的数据结构。通过调用OSMboxCreate()函数来创建邮箱,并指定指针的初始值。一般情况下,这个初始值是NULL,但也可以初始化一个邮箱,使其在最开始就包含一条消息。如果使用邮箱的目的是用来通知一个事件的发生(发送一条消息),那么就要初始化该邮箱为NULL,因为在开始时,事件还没有发生。如果用户用邮箱来共享某些资源,那么就要初始化该邮箱为一个非NULL的指针。在这种情况下,邮箱被当成一个二值信号量使用。使用邮箱同样可以实现上节中描述的任务间的同步。

通过OSMboxPost()函数发送一个消息到邮箱中,通过OSMboxPend()函数等待一个邮箱中的消息,如果邮箱中没有可用的消息,OSMboxPend()的调用任务就被挂起,直到邮箱中有了消息或者等待超时。

下面的代码每100个时钟节拍从TaskSEG中发送一个字符串,在TaskLED中接收并打印出来。

void TaskLED(void *Id) { }

void TaskSEG(void *Id) {

for (;;) {

/* post the input message to the output mailbox */ sprintf(Msg, \"TaskSEG %d\OSMboxPost(Mbox1, Msg);

char Msg[100]; INT8U

err;

int nCount = 0; for (;;) { }

/* wait for a message from the input mailbox */ Msg = (char *)OSMboxPend(Mbox1, 0, &err); uHALr_printf(Msg);

/* print task's id */

char *Msg; INT8U

err;

JXARM9-2410 uC/OS-II课程设计实验 16

}

}

OSTimeDly(100);

4. uC/OS-II中使用消息队列实现任务之间的通讯

消息队列是uC/OS-II中另一种通讯机制,它可以使一个任务或者中断服务子程序向另一个任务发送以指针方式定义的变量。因具体的应用有所不同,每个指针指向的数据结构变量也有所不同。

uC/OS-II提供了7个对消息队列进行操作的函数:创建消息队列函数OSQCreate(),等待消息队列函数OSQPend(),先进先出(FIFO)发送消息函数OSQPost(),后进先出(LIFO)发送消息函数OSQPostFront(),无等待获取消息函数OSQAccept(),清空消息队列函数OSQFlush()和查询消息队列函数OSQQuery()。

1.2.6 实验步骤

实验A 使用信号量进行任务之间的同步:

1. 使用创建好的模板工程Eg2,新建一个工程Eg2,并将模板中的Core(C source和Core(Assemble)文件夹中的文件加入到工程Eg2中,参照Eg2修改Eg2的工程设置。

2. 新建一个文件Eg2.c,并将其添加到Eg2工程的App文件夹中。

3. 打开Eg2.c文件,参照Eg2.c添加两个任务,它们的任务处理函数分别为TaskLED和TaskSEG。

4. 在TaskLED中打印字符串“[TaskLED]”,在TaskSEG中打印字符串“TaskSEG”,并使用信号量实现这两个字符串打印动作的顺序执行。

5. 编译工程Eg2,如果出错,进行修改后再编译。 6. 将Eg2下载并运行,观察结果。

7. 在TaskLED和TaskSEG中添加不同的延时,观察结果。

8. 去掉TaskLED和TaskSEG中的信号量操作,并修改延时值,观察结果。 实验B 使用邮箱实现任务之间的通讯

1. 使用创建好的模板工程Eg3,新建一个工程Eg3,并将模板中的Core(C source和Core(Assemble)文件夹中的文件加入到工程Eg3中,参照ModelEg修改Eg3的工程设置。

2. 新建一个文件Eg3.c,并将其添加到Eg3工程的App文件夹中。

3. 打开Eg3.c文件,参照Eg3.c添加两个任务,它们的任务处理函数分别为TaskLED和TaskSEG,创建一个邮箱Mbox1。

4. 在TaskSEG中申明一个int型变量nCount,并设置初始值为0,每隔100个时钟节拍累加一次nCount,并向邮箱中发送nCount的值。

5. 在TaskLED中申明一个int型变量nCount,接收邮箱Mbox1的值放到nCount中,并通过串口打印出来。

6. 编译工程Eg3,如果出错,进行修改后再编译。

JXARM9-2410 uC/OS-II课程设计实验 17

7. 将Eg3下载并运行,观察结果。

1.2.7 实验报告要求

1. 在一个操作系统中,任务间通讯有那些方法? 2. 简述邮箱和信号量的区别?

3. 简述邮箱和信号量的在uC/OS-II中的是如何实现的?

JXARM9-2410 uC/OS-II课程设计实验 18

1.3 软件定时器实验

1.3.1 实验目的

1. 扩充uC/OS-II内核,实现软件定时器功能。

1.3.2 实验内容

1. 实现软件定时器管理函数;

2. 在应用程序中添加软件定时器功能。

1.3.3 预备知识

1. C语言的基础知识;

2. 程序调试的基础知识和方法。

1.3.4 实验设备

1. 硬件:JXARM9-2410教学实验箱、PC机;

2. 软件:PC机操作系统 Windows 98(2000、XP) + ADT IDE集成开发环境。

1.3.5 实验步骤

软件定时器是许多操作系统提供的必备功能,它使得应用程序定时执行某一段代码。但是,在uC/OS-II的内核中没有提供软件定时器的功能。本实验采用一种简单的方法实现软件定时器功能。

1. 软件定时器管理函数

在UCOS-II\\Includes.h中包含了关于软件定时器管理的相关函数的声明,软件定时器管理函数在UCOS-II\\eg_tmr\\OS_TIMER.c文件中中提供,下面做个简单的介绍:

/* timer used function */ extern INT8U OSTmrInit(void);

extern INT8U OSCreateTimer(OS_TMR **tmr, void (* ImrFunc)(INT8U arg), INT8U TmrArg, INT8U Ticks, INT8U initStatus);

extern INT8U OSEnableTimer(OS_TMR *tmr); extern INT8U OSDisableTimer(OS_TMR *tmr); extern INT8U OSDeleteTimer(OS_TMR *tmr);

2. 定时器管理功能初始化

调用OSTmrInit函数完成定时器管理功能初始化,在该函数中将创建一个优先级为4的高优先级任务,它应该是系统中最高优先级的任务,在创建其它任务时请使用5或者过大的优先级

JXARM9-2410 uC/OS-II课程设计实验 19

数。这个任务每个时钟节拍都将运行,在其中检查是否有定时器就绪,如果就绪将执行相应的定时器函数,否则将进行任务调度。

采用这种方法实现软件定时器有一个前提,就是定时器管理任务的优先级应该比任何其它应用任务优先级高,另外,这种方式实现的定时器精度有限,在本系统中,定时器精度小于10ms,且由于需要频繁进行任务切换,CPU开销较大。但是这种方法实现起来比较简单,而且对于一般应用已经足够,如果要求更高要求的定时器功能,可以考虑直接采用硬件定时器实现。 3. 编写定时器应用程序

定时器编程非常简单,首先调用OSTmrInit初始化,请在任务函数中调用该函数,尽量避免然后就可以调用OSCreateTimer创建软件定时器,

/*

* Task entry function.

* this task blink the led every 200 ticks * that is 2s. */

void TaskLED(void *Id) {

INT8U err;

uHALr_printf(\"Task1() called\\n\");

for (;;) {

OSTimeDly(100); } }

/* init timers */ OSTmrInit();

err = OSCreateTimer( &Tmr1, TmrFunc1, 1, 200, OS_TMR_ENABLE); err = OSCreateTimer( &Tmr2, TmrFunc1, 2, 200, OS_TMR_DISABLE); err = OSCreateTimer( &Tmr3, TmrFunc1, 3, 200, OS_TMR_DISABLE);

在Main函数中调用。

第二个参数为定时器服务函数,也就是定时器时间到后执行的动作,在本实验中创建了三个

定时器,但是它们都使用同一个定时器服务函数TmrFunc1函数,并通过由OSCreateTimer的第三个参数判别是哪一个定时器引发。OSCreateTimer的第四个参数为定时器定时时钟节拍的个数,此处三个定时器均为200,即为2秒钟。最后一个参数为定时器初始状态。

/* 定时器1、2、3 */ OS_TMR *Tmr1; OS_TMR *Tmr2;

JXARM9-2410 uC/OS-II课程设计实验 20

OS_TMR *Tmr3;

下面为本实验使用的定时器服务函数,过程中使用了OSEnableTimer和OSDisableTimer函

/* 定时器服务函数,三个定时器公用一个定时器服务函数 */ void TmrFunc1(INT8U arg);

void TmrFunc1(INT8U arg) { }

switch(arg) { case 1: }

OSEnableTimer(Tmr2); OSDisableTimer(Tmr1); User_LED_Blink(); break;

OSEnableTimer(Tmr3); OSDisableTimer(Tmr2); break;

OSEnableTimer(Tmr1); OSDisableTimer(Tmr3); break;

数使能和关闭某个定时器。

case 2:

case 3:

4. 编译

选择“Build”->“Rebuild All”功能编译工程,如果出现错误,修改代码,然后重新编译,直到成功。 5. 下载、调试

将该程序下载到JXARM9-2410教学系统中调试,并观察结果,实验效果应该为每6秒钟(三个定时器,每个2秒钟,请查看代码)将跑马灯闪烁一次。

JXARM9-2410 uC/OS-II课程设计实验 21

1.4 内核裁减实验

1.4.1 实验目的

1. 本实验的目的让学生了解如何在uC/OS-II下裁减内核。

1.4.2 实验内容

1. 裁减uC/OS-II内核。

1.4.3 预备知识

1. C语言的基础知识;

2. 程序调试的基础知识和方法。

1.4.4 实验设备

1. 硬件:JXARM9-2410教学实验箱、PC机;

2. 软件:PC机操作系统 Windows 98(2000、XP) + ADT IDE集成开发环境。

1.4.5 实验步骤

嵌入式操作系统的裁减的一个直接的目标是使得在满足现有功能的前提下,去掉一些不必要的功能,并对现有程序进行优化使得目标系统运行的代码尺寸尽可能小。 代码尺寸不仅仅和程序编程有关,而且也和所使用的库文件相关,不同的编译器编译uC/OS-II得到的代码尺寸通常都是不相同的。在ARM系统中,硬件资源,尤其是存储器资源通常都比较丰富,而且uC/OS-II本省已经是比较小型化的一个操作系统。因此,裁减功能在嵌入式操作系统中体现的并不是非常迫切。本实验的目的就是在JXARM9-2410上进行uC/OS-II的裁减,以学习和理解操作系统裁减的概念和方法,这对于其它操作系统的移植都是很有帮助的。 本实验是在Eg2的基础上进行的,Eg2是用于任务间通讯和同步实验的,其中用到uC/OS-II的信号量,因此首先从裁减该功能开始。 1. 观察当前uC/OS-II的大小

打开ucos工作区,并设置Eg2为当前活动工程,然后编译,编译成功后将在UCOS-II\\debug目录下有一个Eg2.elf文件。然后点击“Tools”->“elf to binary”菜单项,屏幕将出现一个Windows控制台窗口后立即消失,此时通过在Windows资源管理器中查看UCOS-II\\debug目录,可以看到生成了一个Eg2.bin的文件,在该文件上点击右键菜单的“属性”选项,可以看到该文件的大小,这个大小就是Eg2过程生成的代码大小,本例大小如下图所示,为62444字节:

JXARM9-2410 uC/OS-II课程设计实验 22

2. 裁减信号量功能(功能裁减)

打开UCOS-II\\os_cfg.h文件 将其中的

#define OS_SEM_EN 1 /* Include code for SEMAPHORES */

修改为:

#define OS_SEM_EN 0 /* Include code for SEMAPHORES */

然后选择“Build”->“Clean”和“Build”->“Build”菜单,在output窗口的build提示栏中提示编译错误,如下所示:

-------------------- Configuration : Eg2 - DEBUG -------------------- OS_CPU_C.c UCOS_II.c 44blib.c uhal.c OS_CPU_A.S ramstart.s eg2.c

E:/UCOS-II/UCOS-II/eg2.c: In function `Main':

E:/UCOS-II/UCOS-II/eg2.c:134: warning: assignment makes pointer from integer without a cast E:/UCOS-II/UCOS-II/eg2.c:135: warning: assignment makes pointer from integer without a cast Link ......

.\\debug\\eg2.o(.text+0xd4): In function `TaskLED':

E:/UCOS-II/UCOS-II/eg2.c:74: undefined reference to `OSSemPend'

JXARM9-2410 uC/OS-II课程设计实验 23

.\\debug\\eg2.o(.text+0xf4):E:/UCOS-II/UCOS-II/eg2.c:81: undefined reference to `OSSemPost' .\\debug\\eg2.o(.text+0x138): In function `TaskSEG':

E:/UCOS-II/UCOS-II/eg2.c:100: undefined reference to `OSSemPend'

.\\debug\\eg2.o(.text+0x158):E:/UCOS-II/UCOS-II/eg2.c:107: undefined reference to `OSSemPost' .\\debug\\eg2.o(.text+0x198): In function `Main':

E:/UCOS-II/UCOS-II/eg2.c:134: undefined reference to `OSSemCreate'

.\\debug\\eg2.o(.text+0x1a8):E:/UCOS-II/UCOS-II/eg2.c:135: undefined reference to `OSSemCreate'

Eg2.elf - build uncompleted.

上面的提示显示在eg2.c文件中调用的OSSemPend和OSSemPost函数没有定义,它们是信号量函数,由于在UCOS-II\\os_cfg.h文件中将OS_SEM_EN定义为0,也就是将信号量功能屏蔽掉了,因此也就没有OSSemPend和OSSemPost函数实现,所以报错。解决的方法是,在应用程序中不要使用信号量相关函数。

在eg2.c的Main函数中

/*

* create the semaphores */

// Sem1 = OSSemCreate(0); // Sem2 = OSSemCreate(1);

在任务函数中:

/*

* Task entry function.

* this task blink the led every 200 ticks * that is 2s. */

void TaskLED(void *Id) {

INT8U Reply;

for (;;) {

/* wait for the semaphore */ // OSSemPend(Sem2, 0, &Reply);

uHALr_printf(\"[\"); User_LED_Blink(); uHALr_printf(\"TaskLED]\");

/* signal the semaphore */ // OSSemPost(Sem1);

/* wait a short while */

JXARM9-2410 uC/OS-II课程设计实验 24

} /*

* Task entry function.

* this task blink the seg every 200 ticks * that is 1s. */

void TaskSEG(void *Id) {

INT8U Reply;

for (;;) {

/* wait for the semaphore */ // OSSemPend(Sem1, 0, &Reply);

uHALr_printf(\"[\");

User_SEG_Blink(); uHALr_printf(\"TaskSEG]\");

/* signal the semaphore */ // OSSemPost(Sem2);

/* wait a short while */ }

OSTimeDly(100);

}

OSTimeDly(200);

}

然后重新编译,提示成功。此时已经去掉信号量功能,uC/OS-II以功能来换取少量的代码空间,这也是裁减的一种方法。然后重新生成Eg2.bin并查看其大小,本实验从62444裁减到61380,约1K字节。

JXARM9-2410 uC/OS-II课程设计实验 25

然后请恢复上述修改。

JXARM9-2410 uC/OS-II课程设计实验 26

第2章 uC/OS-II驱动程序实验

2.1 4X4小键盘驱动程序实验

2.1.1 实验目的

1. 本实验的目的是在uC/OS-II下设计4X4小键盘的驱动程序。

2.1.2 实验内容

1. 设计uC/OS-II下的键盘驱动程序;

2. 编写一个简单的测试程序以测试uC/OS-II下的键盘驱动程序。

2.1.3 预备知识

1. C语言的基础知识;

2. 程序调试的基础知识和方法。

2.1.4 实验设备

1. 硬件:JXARM9-2410教学实验箱、PC机;

2. 软件:PC机操作系统 Windows 98(2000、XP) + ADT IDE集成开发环境。

2.1.5 实验步骤

1. 键盘驱动程序设计

JXARM9-2410的键盘采用矩阵式键盘,必须采取定时轮询的方式对键盘状态进行扫描,为了达到键盘信号的及时采集,本实验采用时钟节拍HOOK函数,该函数在时钟节拍中断中调用,每10ms调用一次,在该函数中调用扫描一次键盘扫描程序。该函数在UCOS-II\\OS_CPU_C.c文件中实现,如果不定义KBD_SCAN宏则不起动键盘扫描。

void OSTimeTickHook (void) {

#ifdef KBD_SCAN }

Kbd_Scan(); #endif

Kbd_Scan函数扫描键盘,获取到的键值通过调用key_recv_key函数加入到键值缓冲区key_recv_buf中,代码如下所示:

/******************************************************************** // Function name : Kbd_Scan // Description

: 定时器1中断服务程序,用于扫描键盘,每隔10ms一次中断

JXARM9-2410 uC/OS-II课程设计实验 27

// Return type

: void

// Argument : void

*********************************************************************/ void Kbd_Scan(void) { 值*/

*/

} break;

if (((*keyboard_port_value) & key_mask) != input_key[temp]) {

keyboard_scan_status[temp] = KEYBOARD_SCAN_FIRST; else

bexit = 1;

if(input_key[temp] == key_mask) */ else {

keyboard_scan_status[temp] = KEYBOARD_SCAN_THIRD;

/* 有按键

keyboard_scan_status[temp] = KEYBOARD_SCAN_FIRST;

/* 没有按键,回

// 键盘扫描

for( loopcnt = row; loopcnt < row + 4; loopcnt ++) {

if(loopcnt >= 4) {

case KEYBOARD_SCAN_FIRST:

*keyboard_port_scan = output_0x10000000 & (~(0x00000001<input_key[temp] = (*keyboard_port_value) & key_mask;

/*并获取第一次扫描

temp = loopcnt - 4; temp = loopcnt; else

switch(keyboard_scan_status[temp]) int loopcnt = row, bexit = 0; int temp;

将row列置低电平 */

case KEYBOARD_SCAN_SECOND:

到开始状态

case KEYBOARD_SCAN_THIRD:

JXARM9-2410 uC/OS-II课程设计实验 28

值*/

}

}

row = temp;

}

if(input_key1[temp] == key_mask) { { } break;

*keyboard_port_scan = output_0x10000000 & (~(0x00000001<keyboard_scan_status[temp] = KEYBOARD_SCAN_FIRST;

} break;

input_key1[temp] = (*keyboard_port_value) & key_mask;

/*并获取第一次扫描

ascii_key = key_get_char(temp, input_key[temp]); keyboard_scan_status[temp] = KEYBOARD_SCAN_FOURTH;

*keyboard_port_scan = output_0x10000000 & (~(0x00000001</*将row列置低电平 */

case KEYBOARD_SCAN_FOURTH:

}else

/*将row列置低电平 */

if(bexit)

break;

键盘驱动程序的接口函数定义了如下两个函数(在UCOS-II\\eg_kbd\\keyboard.c文件中实现):

/******************************************************************** // Function name : Key_GetKey // Description // Return type

: 如果有键按下返回键,否则返回0

: char

// Argument :

*********************************************************************/ char Key_GetKey() {

char ch;

JXARM9-2410 uC/OS-II课程设计实验 29

}

if(key_recv_write == key_recv_read) { { }

return ch;

ch = key_recv_buf[key_recv_read]; key_recv_read ++;

if(key_recv_read >= RECV_CMD_MAX_BUF)

key_recv_read = 0; /* no key found */ ch = 0;

}else

该函数用于获取键值,如果当前没有键按下将返回0。该函数是直接从键值缓冲区key_recv_buf中获取。 2. 键盘应用设计

首先必须定义KBD_SCAN宏。如下图所示在ADTIDE中定义KBD_SCAN宏。

键盘应用程序非常简单,不断调用Key_GetKey查询键值就可以,如下代码所示,在创建的TaskLED任务中获取键值并定义四个键:

‘1’ – LED1 亮或灭 ‘2’ – LED2 亮或灭

JXARM9-2410 uC/OS-II课程设计实验 30

‘3’ – LED3 亮或灭 ‘4’ – LED4 亮或灭

/*

* Task entry function.

* this task blink the led every 200 ticks * that is 2s. */

void TaskLED(void *Id) {

/* Start the (uHAL based ARM system) system running */ ARMTargetStart();

/* Turn off all leds */ Led_Display(led_status);

char key_press; char led_status = 0x0;

uHALr_printf(\"Task1() called\\n\");

for (;;) {

key_press = Key_GetKey();

switch(key_press) {

case '1':

led_status ^= 0x01; Led_Display(led_status);

break; case '2':

led_status ^= 0x02; Led_Display(led_status);

break; case '3':

led_status ^= 0x04; Led_Display(led_status);

break; case '4':

led_status ^= 0x08; Led_Display(led_status);

JXARM9-2410 uC/OS-II课程设计实验 31

}

break;

OSTimeDly(10); } }

3. 编译

选择“Build”->“Rebuild All”功能编译工程,如果出现错误,修改代码,然后重新编译,直到成功。 4. 下载、调试

将该程序下载到JXARM9-2410教学系统中调试,按下键盘的’1’, ’2’, ’3’, ’4’键将分别控制四个LED跑马灯。

JXARM9-2410 uC/OS-II课程设计实验 32

2.2 步进电机驱动程序实验

2.2.1 实验目的

1. 本实验的目的是在uC/OS-II下设计步进电机的驱动程序,要求能够控制步进电机转动和停止、电机正反转、电机转速等。

2.2.2 实验内容

1. 设计uC/OS-II下的步进电机驱动程序;

2. 编写一个简单的测试程序以测试uC/OS-II下的步进电机驱动程序。

2.2.3 预备知识

1. C语言的基础知识;

2. 程序调试的基础知识和方法。

2.2.4 实验设备

1. 硬件:JXARM9-2410教学实验箱、PC机;

2. 软件:PC机操作系统 Windows 98(2000、XP) + ADT IDE集成开发环境。

2.2.5 实验步骤

本实验采用时钟节拍HOOK函数,该函数在时钟节拍中断中调用,每10ms调用一次,在该函数中调用发送步进电机驱动脉冲。该函数在UCOS-II\\OS_CPU_C.c文件中实现,对于此次实验需要定义KBD_SCAN宏和STEPPER_PULSE宏。宏的设置方法请参考2.1节。

void OSTimeTickHook (void) {

#ifdef KBD_SCAN

#ifdef STEPPER_PULSE }

DRVStepperPulse(); #endif

Kbd_Scan(); #endif

1. 步进电机驱动函数

步进电机初始化函数,在系统初始化时调用,另外由于要用到定时器1中断和键盘作为控制因此,在初始化时也需要初始化键盘驱动。

void DRVStepperInit();

JXARM9-2410 uC/OS-II课程设计实验 33

步进电机使能控制函数,启动或者停止步进电机运行。其参数可以为STEP_MOTOR_ENABLE或STEP_MOTOR_DISABLE。

void DRVStepperControl(INT8U benable); #define STEP_MOTOR_ENABLE 1 #define STEP_MOTOR_DISABLE 0

步进电机方向控制函数。其参数可以为STEP_MOTOR_CLOCKWISE或STEP_MOTOR_ANTICLOCKWISE。

void DRVStepperSetDirect(INT8U direct); #define STEP_MOTOR_CLOCKWISE 0 #define STEP_MOTOR_ANTICLOCKWISE 1

步进电机速度控制函数。设置步进电机转速,单位为每步speedx10ms,1<=s<=100,值越小速度越快。

void DRVStepperSetSpeed(INT8U speed);

另外还提供了两个步进电机加速和减速函数。

void DRVStepperSpeedUp(void); void DRVStepperSpeedDown(void);

2. 步进电机控制

步进电机应用程序非常简单,先调用DRVKeyInit初始化键盘接口并调用DRVStepperInit初始化步进电机接口,然后不断调用DRVKeyGet查询键值并根据键值进行相应得处理,如下代码所示,通过键盘得“1”键控制方向,“2”键控制速度,“UP”键加速,“DOWN”键减速。

/*

* Task entry function.

* this task blink the led every 200 ticks * that is 2s. */

void TaskLED(void *Id) {

INT8U err;

/* Start the (uHAL based ARM system) system running */ ARMTargetStart();

uHALr_printf(\"Task1() called\\n\");

uHALr_printf(\"步进电机测试!\\n\"); uHALr_printf(\"1 -- 正反转 2 -- 起停\\n\"); uHALr_printf(\"UP -- 加速 DOWN -- 减速\\n\"); int benable = STEP_MOTOR_ENABLE; int direct = STEP_MOTOR_CLOCKWISE;

/* 初始化步进电机 */

JXARM9-2410 uC/OS-II课程设计实验 34

DRVStepperInit();

/* 开始启动步进电机 */ DRVStepperSetDirect(direct); DRVStepperControl(benable);

for (;;) {

INT8U ch;

/* 获取键值 */ ch = Key_GetKey(); if(ch == 0) {

case 'C': // 加速

uHALr_printf(\"\\r加速\"); DRVStepperSpeedUp(); break;

uHALr_printf(\"\\r减速\"); DRVStepperSpeedDown(); break;

if(direct == STEP_MOTOR_CLOCKWISE) { } else { }

DRVStepperSetDirect(direct); break;

if(benable == STEP_MOTOR_ENABLE) {

uHALr_printf(\"\\r停止\"); uHALr_printf(\"\\r反转\"); direct = STEP_MOTOR_CLOCKWISE; uHALr_printf(\"\\r正转\");

direct = STEP_MOTOR_ANTICLOCKWISE;

continue; switch( ch )

case 'D': // 减速

case '1': // 正反转控制

case '2': // 使能控制

JXARM9-2410 uC/OS-II课程设计实验 35

}

} else { }

DRVStepperControl(benable); break;

uHALr_printf(\"\\r启动\"); benable = STEP_MOTOR_ENABLE; benable = STEP_MOTOR_DISABLE;

OSTimeDly(10); } }

JXARM9-2410 uC/OS-II课程设计实验 36

第3章 uC/OS-II应用程序实验

3.1 多任务编程实验

3.1.1 实验目的

1. 本实验的目的是让学生了解uC/OS-II中怎样创建一个任务以及了解uC/OS-II的多任务调度机制。

3.1.2 实验内容

1. 在Eg1的基础上新建一个任务; 2. 在该任务函数中打印提示信息。

3.1.3 预备知识

1. C语言的基础知识;

2. 程序调试的基础知识和方法。

3.1.4 实验设备

1. 硬件:JXARM9-2410教学实验箱、PC机;

2. 软件:PC机操作系统 Windows 98(2000、XP) + ADT IDE集成开发环境。

3.1.5 实验步骤

本章将以Eg1为基础,在其上添加一个任务。 1. 打开Eg1工程

打开examples/ucos工作区,并设置Eg1工程为活动工程。然后打开App目录下的eg1.C文件。 2. 声明任务栈

在eg1.c文件中声明任务堆栈,下面代码中黑体字表示的为新添加的代码:

/* task stack */

OS_STK StackLED[STACKSIZE]= {0, }; OS_STK StackSEG[STACKSIZE]= {0, }; OS_STK StackTEST[STACKSIZE]= {0, };

任务栈以全局变量的方式静态分配,然后在创建任务时使用。 3. 添加任务ID

/* task name string */

JXARM9-2410 uC/OS-II课程设计实验 37

char IdLED = '1'; char IdSEG = '2'; char IdTEST = '3';

4. 任务函数声明

/* task entry function */ void TaskLED(void *Id); void TaskSEG(void *Id); void TaskTEST(void *Id);

5. 任务函数实现

在TaskSEG函数后添加如下函数:

/*

* Task entry function.

* this task blink the seg every 200 ticks * that is 1s. */

void TaskTEST(void *Id) {

uHALr_printf(\"Task3() called\\n\");

for (;;) {

uHALr_printf(\"Task%c() turned\\n\ User_SEG_Blink();

OSSchedUnlock();

OSTimeDly(100); } }

OSSchedLock();

在该函数中实现数码管显示,由于在TaskSEG中也进行了数码管显示,因此,请先将TaskSEG中的数码管显示功能关闭,以更好地看到效果,修改后的TaskSEG函数如下:

void TaskSEG(void *Id) {

uHALr_printf(\"Task2() called\\n\");

for (;;) {

OSSchedLock();

JXARM9-2410 uC/OS-II课程设计实验 38

uHALr_printf(\"Task%c() turned\\n\// User_SEG_Blink();

OSSchedUnlock();

OSTimeDly(100); } }

6. 创建任务

然后在Main函数中创建任务,添加TaskTEST的创建代码,如下所示:

/*

* create the tasks in uC/OS and assign increasing * priorities to them so that Task3 at the end of * the pipeline has the highest priority. */

OSTaskCreate(TaskLED, (void *)&IdLED, (OS_STK *)&StackLED[STACKSIZE - 1], 5); /* Create seg blink tasks */

OSTaskCreate(TaskSEG, (void *)&IdSEG, (OS_STK *)&StackSEG[STACKSIZE - 1], 13); /* Create test tasks */

OSTaskCreate(TaskTEST, (void *)&IdTEST, (OS_STK *)&StackTEST[STACKSIZE - 1], 15);

7. 编译

选择“Build”->“Rebuild All”功能编译工程,如果出现错误,修改代码,然后重新编译,直到成功。 8. 下载、调试

将该程序下载到JXARM9-2410教学系统中调试,并观察结果,原来在TaskSEG中进行数码管闪烁的功能转移到TaskTEST中。如果将串口0连接到PC,在超级终端中还可以看到显示。 9. 修改

TaskTEST的优先级在所创建的任务中为最低,根据uC/OS-II的多任务调度策略,总是保证优先级最高的任务先执行,因此,高优先级的任务如果不主动让出CPU(在此程序中调用OSTimeDly将让出其参数中指定个数时钟节拍的CPU资源)资源,则更低优先级的任务将无法获得CPU资源,在此程序中,如果将TaskSEG的OSTimeDly函数注释掉,那么TaskTEST将无法获得执行,数码管也不会闪烁,修改后的TaskSEG函数如下:

void TaskSEG(void *Id) {

uHALr_printf(\"Task2() called\\n\");

for (;;) {

JXARM9-2410 uC/OS-II课程设计实验 39

uHALr_printf(\"Task%c() turned\\n\// User_SEG_Blink();

OSSchedUnlock();

// OSTimeDly(100); } }

OSSchedLock();

观察实验结果。

如果将TaskTEST的任务优先级修改为比TaskSEG更高的话,TaskTEST将重新获得执行权,数码管将闪烁,如下所示:

/*

* create the tasks in uC/OS and assign increasing * priorities to them so that Task3 at the end of * the pipeline has the highest priority. */

OSTaskCreate(TaskLED, (void *)&IdLED, (OS_STK *)&StackLED[STACKSIZE - 1], 5); /* Create seg blink tasks */

OSTaskCreate(TaskSEG, (void *)&IdSEG, (OS_STK *)&StackSEG[STACKSIZE - 1], 13); /* Create test tasks */

OSTaskCreate(TaskTEST, (void *)&IdTEST, (OS_STK *)&StackTEST[STACKSIZE - 1], 12);

JXARM9-2410 uC/OS-II课程设计实验 40

3.2 图形用户界面uC/GUI移植实验

3.2.1 实验目的

1. 本实验的目的是让学生了解uC/OS-II中图形用户界面的移植过程。

3.2.2 实验内容

1. 移植uC/GUI到JXARM9-2410中;

3.2.3 预备知识

1. C语言的基础知识;

2. 程序调试的基础知识和方法。

3.2.4 实验设备

1. 硬件:JXARM9-2410教学实验箱、PC机;

2. 软件:PC机操作系统 Windows 98(2000、XP) + ADT IDE集成开发环境。

3.2.5 实验步骤

图形用户界面(GUI)是嵌入式系统中软件设置的一个常用的需求。在uC/OS-II内核中没有支持图形用户界面,但是可以通过移植uC/GUI实现GUI。本实验讲述如何在JXARM9-2410中的uC/OS-II中移植uC/GUI。 1、uC/GUI简介:

uC/GUI是Micrium公司开发的通用的嵌入式用户图形界面软件。它给任何使用图形LCD的应用程序提供于处理器和LCD控制器之外的有效的图形用户接口。可以应用于单一任务环境,也可以应用于多任务环境中。uC/GUI能够应用于任何LCD控制器和CPU的任何尺寸的物理显示或者模拟显示中。

uC/GUI具有如下特点:

1)适用于任何8位/16位/32位CPU,可允许于支持ANSI C的任何编译器 2)适用于任何控制器驱动任何LCD(单色,灰度,或者彩色) 3)通过配置宏,可支持任何接口 4)可配置显示尺寸

5)可在LCD的任何一点上显示字符和画位图

6)对于显示尺寸和速度提供优化进程,编译时间依赖于采用的优化进程 7)支持虚拟显示,虚拟显示的尺寸比实际显示大。 8)uC/GUI的窗口管理

JXARM9-2410 uC/OS-II课程设计实验 41

2、uC/GUI源代码文件组织:

uC/GUI目录下的文件有配置文件目录Config,GUI库函数目录,以及为GUI编写的应用程序目录。下面分别简要介绍相应目录下的函数。

1)uC-GUI\\Config\\目录:

GUICONF.h: 配置GUI移植到不同操作系统的选项。在本系统中配置移植到uC/OSII中,允许多任务调用uC/GUI函数。

GUITouchConf.h:配置触摸屏的选项以及编写触摸屏的驱动。

LCDConf.h: LCD显示屏的选项文件,包括bpp,调试板模式,水平、竖直方向的分辨率等等。为了支持不同的LCD,在本系统中定义了宏进行LCD配置选择,详细代码参见下一小节。

2)uC/GUI\\GUI\\ConvertColor\\目录:

这个目录中包含14个.C文件,涉及调色板模式。uC\\GUI的调色板模式支持111模式,222模式,223,323,332,444,555,565,8666等相关模式。

3)uC/GUI\\GUI\\ConvertMono\\目录:

此目录下的文件描述单色显示的不同模式,包含4个文件。 4)uC/GUI\\GUI\\Core

此目录下包含129个文件,是uC/GUI的核心部分。包括GUI头文件,GUI显示各种文本,二进制,十进制,十六进制,字符型文本,字符串,在不同的位置显示二进制,十进制,十六进制,字符型文本,字符串等;GUI设置各种字体;GUI的2-D图形库,GUI绘图函数,在各种位置绘各种点,线,位图,多边形,长方形,圆等等;GUI获取函数,获取当前点,线,位图,多边形,长方形,圆,当前字体,当前二进制,十进制,十六进制,字符型文本,字符串等函数;设置GUI画笔函数;GUI支持的鼠标函数;GUI支持的键盘函数,GUI支持的触摸屏函数;GUI设置LCD函数等等。这些函数,在uC/GUI系统中都是必须的函数。正是这些函数的组合,使得uC/GUI具有复杂而且完备的图形用户接口。而且,这些函数的组合,使得uC/GUI可以单独的使用,也可以通过配置文件,移植到各种操作系统中使用。

5)uC/GUI\\GUI\\Font

此目录下包含的是uC/GUI支持的字体。 6)uC/GUI\\GUI\\LCDDriver

LCD API目录。该目录下包含很多已经完备的LCD控制器的驱动程序以及API函数。 7)uC/GUI\\GUI\\MemDev

MemDev主要用于防止在画交迭图时产生的抖动。uC/GUI函数绘图不使用MemDev时,画图操作直接写到终端上显示,交迭绘图执行时刷新屏幕,多次刷新时就会出现抖动。例如,要在背景色中画图,且在前景中写一些透明的文字,实现的步骤就是先画图,然后写文字,那么结果就会出现文字的抖动。如果在程序中使用MemDev,则所有的执行操作都在MemDev中执行,当所有的操作都执行完毕之后,最后的结果才会送到屏幕上显示,因而可以避免多次刷新,从而避免抖动。

JXARM9-2410 uC/OS-II课程设计实验 42

此目录下包含这MemDev的所有函数,包括创建MemDev函数,激活MemDev,执行画图操作,显示到终端,删除MemDev函数等等。

8)uC/GUI\\GUI\\Widget

此目录包含窗口控件函数,总共46个函数。UC/GUI中窗口控件机制时uC/GUI的实现难点,也是应用难点。运用窗口管理和回调机制,运用窗口控件函数,可以任意在LCD屏幕上实现类似于windows的界面,这样完备的功能在工业自动化控制和触摸屏应用上有着深远而积极的意义。

此目录下的函数主要包括uC/GUI的窗口控件,如按钮BUTTON,校验窗CHECKBOX,编辑区EDIT,窗口框FRAMEWIN,列表LISTBOX,进度条PROGBAR,音频按钮RADIOBUTTON,滚动条SCROLLERBAR,改变值的灰度条SLIDER,以及文本框TEXT相关的各种函数。

9)uC/GUI\\GUI\\WM

此目录包括窗口管理函数,总共52个函数。UC/GUI中,窗口管理中的消息传递机制和回调机制,也是uC/GUI的实现难点和应用难点。

此目录下的函数主要包括设置、返回、建立背景窗口、父窗口、各种子窗口以及相应的尺寸、窗口句柄,起点x,y坐标,窗口宽度,高度,位置等等,还包括改变窗口的大小,以及最关键的窗口的回调函数,窗口重绘函数等等。 3、uC/GUI在JXARM9-2410中的移植:

1)源代码组织和编译

在uC/GUI的源代码组织如下图所示,我们讲uC/GUI相关的代码编译成为的库文件uC/GUI.a文件,该文件编译成功后位于UCOS-II\\LIB目录下。其它的应用程序则通过使用这个库文件使用uC/GUI。该库工程名称为UC-GUI,其组织方式与上小节中的介绍相同。

2)LCDConf.h文件

的修改

JXARM9-2410 uC/OS-II课程设计实验 43

在该文件中需要针对不同的LCD配置其屏幕尺寸以及BPP(位每点)值。本系统配置如下,由于JXARM9-2410支持三种不同的LCD显示器,分别为320*240 5.7英寸STN、240*320 3.5英寸TFT以及0*480 8英寸TFT。它们通过LCD_TFT_3_5、LCD_TFT_8_0宏的定义进行选择,如下图所示设置UC-GUI支持8英寸TFT LCD显示器,如果使用3.5英寸TFT请设置LCD_TFT_3_5,如果使用STN LCD则不用设置任何值。因此,如果改变了当前的LCD设置,您必须重新编译UC-GUI库文件,否则将不会生效。

#ifdef LCD_TFT_3_5

#define LCD_XSIZE (240) /* X-resolution of LCD, Logical coor. */ #define LCD_YSIZE (320) /* Y-resolution of LCD, Logical coor. */ #define LCD_BITSPERPIXEL (16) #ifdef LCD_TFT_8_0

#define LCD_XSIZE (0) /* X-resolution of LCD, Logical coor. */ #define LCD_YSIZE (480) /* Y-resolution of LCD, Logical coor. */ #define LCD_BITSPERPIXEL (16)

#define LCD_XSIZE (320) /* X-resolution of LCD, Logical coor. */ #define LCD_YSIZE (240) /* Y-resolution of LCD, Logical coor. */ #define LCD_BITSPERPIXEL (8)

#else

#else

#endif

#endif

在该文件中需要针对不同的LCD配置其屏幕尺寸以及BPP(位每点)值。本系统配置如下,

JXARM9-2410 uC/OS-II课程设计实验 44

3)uC/GUI\\GUI\\ConvertColor\\目录

这个目录移植时不用修改,但是这里进行以下简单介绍。由于uC/GUI应用程序颜色采用统一的16比特颜色值表示,而对于不同的LCD显示器,颜色表示有的为8比特,有的为16比特。因此在填写显示缓冲区时必须在这两种颜色值之间进行转换。

根据在上一步中定义的BPP值组要进行调色板模式选择,在本系统中,320*240 5.7英寸STN使用332模式,转换文件为LCDPM332.c,240*320 3.5英寸TFT以及0*480 8英寸TFT均使用565模式,转换文件为LCDPM565.c。如下所示为LCDPM565.c的代码。其中

LCD_Color2Index_M565实现将16比特系统颜色值转换为565格式颜色。LCD_Index2Color_M565则将565格式颜色转换成16比特系统颜色。

int LCD_Color2Index_M565(LCD_COLOR Color) {

}

LCD_COLOR LCD_Index2Color_M565(int Index) {

int r,g,b;

b = (Index&(0x1f<<0)) << ( 3); g = (Index&(0x3f<<5)) >> (5-2); r = 255*((Index>>11)&31)/31; return r+(g<<8)+(((U32)b)<<16); }

int r,g,b;

r = (Color>> (0+3)) &0x1f; g = (Color>> (8+2)) &0x3f; b = (Color>>(16+3)) &0x1f;

return b+(g<<5)+(r<<11);

4)UCOS-II\\UC-GUI\\gui\\LCDDriver\\LCD_X_S3C2410.c文件

本系统中,在LCDDriver中使用LCD_X_S3C2410.c文件中的驱动程序。在该文件中有几个重要函数需要修改或者添加,下面将一一说明。

LCD_L0_Init函数将在应用程序中由GUI_Init一步步调用下来,在该函数中进行LCD驱动的初始化。

int LCD_L0_Init(void) { int x,y;

s3c2410x_lcd_init(); }

return 0;

在该函数中调用了s3c2410x_lcd_init初始化S3C2410X的LCD控制器。s3c2410x_lcd_init的实现如下所示,同样的对于不同的LCD通过宏进行控制。

/***************************************************************************** // Function name : s3c2410x_lcd_init // Description // Return type

: LCD显示驱动初始化函数

: void

JXARM9-2410 uC/OS-II课程设计实验 45

// Argument : 无

*****************************************************************************/ void s3c2410x_lcd_init() { }

Lcd_Port_Init();

Lcd_Init(MODE_TFT_16BIT_240320); #ifdef LCD_TFT_8_0

Lcd_PowerEnable(0, 1); Lcd_EnvidOnOff(1); #else

Lcd_Init(MODE_CSTN_8BIT); #endif

Lcd_Init(MODE_TFT_16BIT_0480); rGPCCON &= ~(3<<8); rGPCCON |= (2<<8);

#ifdef LCD_TFT_3_5 #else

#endif

其中,Lcd_Port_Init用于LCD端口的初始化,因为LCD使用的端口有可能被复用为GPIO口或者其它用途,因此在开启LCD之前必须将其端口初始化为LCD使用。主要包括VD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND等信号的配置。

void Lcd_Port_Init(void) {

save_rGPCCON=rGPCCON; save_rGPCDAT=rGPCDAT; save_rGPCUP=rGPCUP; save_rGPDCON=rGPDCON; save_rGPDDAT=rGPDDAT; save_rGPDUP=rGPDUP;

rGPCUP=0xffffffff; // Disable Pull-up register

rGPCCON=0xaaaaaaaa; //Initialize VD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND rGPDUP=0xffffffff; // Disable Pull-up register rGPDCON=0xaaaaaaaa; //Initialize VD[23:8] }

Lcd_Init函数用于初始化LCD控制器,该函数支持各种分辨率的LCD显示器,通过参数进行选择。

void Lcd_Init(int type) {

switch(type)

JXARM9-2410 uC/OS-II课程设计实验 46

{

case MODE_STN_1BIT:

frameBuffer1Bit=(U32 (*)[SCR_XSIZE_STN/32])LCDFRAMEBUFFER;

case MODE_STN_2BIT:

frameBuffer2Bit=(U32 (*)[SCR_XSIZE_STN/16])LCDFRAMEBUFFER; rLCDCON1=(CLKVAL_STN_GRAY<<8)|(MVAL_USED<<7)|(1<<5)|(1<<1)|0; // 4-bit single scan,2bpp STN,ENVID=off

rLCDCON2=(0<<24)|(LINEVAL_STN<<14)|(0<<6)|(0<<0);

rLCDCON3=(WDLY_STN<<19)|(HOZVAL_STN<<8)|(LINEBLANK_GRAY<<0); rLCDCON4=(MVAL<<8)|(WLH_STN<<0); rLCDCON5=0;

//BPP24BL:x,FRM565:x,INVVCLK:x,INVVLINE:x,INVVFRAME:x,INVVD:x, //INVVDEN:x,INVPWREN:x,INVLEND:x,PWREN:x,ENLEND:x,BSWP:x,HWSWP:x rLCDCON3=(WDLY_STN<<19)|(HOZVAL_STN<<8)|(LINEBLANK_MONO<<0); rLCDCON4=(MVAL<<8)|(WLH_STN<<0); rLCDCON5=0;

//BPP24BL:x,FRM565:x,INVVCLK:x,INVVLINE:x,INVVFRAME:x,INVVD:x, //INVVDEN:x,INVPWREN:x,INVLEND:x,PWREN:x,ENLEND:x,BSWP:x,HWSWP:x

rLCDSADDR1=(((U32)frameBuffer1Bit>>22)<<21)|M5D((U32)frameBuffer1Bit>>1); rLCDSADDR2=M5D( ((U32)frameBuffer1Bit+(SCR_XSIZE_STN*LCD_YSIZE_STN/8))>>1 ); rLCDSADDR3=(((SCR_XSIZE_STN-LCD_XSIZE_STN)/16)<<11)|(LCD_XSIZE_STN/16);

rLCDCON1=(CLKVAL_STN_MONO<<8)|(MVAL_USED<<7)|(1<<5)|(0<<1)|0;

rLCDCON2=(0<<24)|(LINEVAL_STN<<14)|(0<<6)|(0<<0); // It is not TFT LCD. So,..... // 4-bit single scan,1bpp STN,ENVID=off

break;

rLCDSADDR1=(((U32)frameBuffer2Bit>>22)<<21)|M5D((U32)frameBuffer2Bit>>1); rLCDSADDR2=M5D( ((U32)frameBuffer2Bit+(SCR_XSIZE_STN*LCD_YSIZE_STN/4))>>1); rLCDSADDR3=(((SCR_XSIZE_STN-LCD_XSIZE_STN)/8)<<11)|(LCD_XSIZE_STN/8);

rDITHMODE=0x0;

rBLUELUT =0xf950; // 4-Gray only

break;

case MODE_STN_4BIT:

frameBuffer4Bit=(U32 (*)[SCR_XSIZE_STN/8])LCDFRAMEBUFFER; rLCDCON1=(CLKVAL_STN_GRAY<<8)|(MVAL_USED<<7)|(1<<5)|(2<<1)|0; // 4-bit single scan,4bpp STN,ENVID=off

rLCDCON2=(0<<24)|(LINEVAL_STN<<14)|(0<<6)|(0<<0);

rLCDCON3=(WDLY_STN<<19)|(HOZVAL_STN<<8)|(LINEBLANK_GRAY<<0); rLCDCON4=(MVAL<<8)|(WLH_STN<<0); rLCDCON5=0;

//BPP24BL:x,FRM565:x,INVVCLK:x,INVVLINE:x,INVVFRAME:x,INVVD:x,

JXARM9-2410 uC/OS-II课程设计实验 47

case MODE_CSTN_8BIT:

frameBuffer8Bit=(U32 (*)[SCR_XSIZE_CSTN/4])LCDFRAMEBUFFER;

rLCDCON1=(CLKVAL_CSTN<<8)|(MVAL_USED<<7)|(2<<5)|(3<<1)|0; rLCDCON2=(0<<24)|(LINEVAL_CSTN<<14)|(0<<6)|(0<<0);

rLCDCON3=(WDLY_CSTN<<19)|(HOZVAL_CSTN<<8)|(LINEBLANK_CSTN<<0); rLCDCON4=(MVAL<<8)|(WLH_CSTN<<0); rLCDCON5=0;

//BPP24BL:x,FRM565:x,INVVCLK:x,INVVLINE:x,INVVFRAME:x,INVVD:x, //INVVDEN:x,INVPWREN:x,INVLEND:x,PWREN:x,ENLEND:x,BSWP:x,HWSWP:x

rLCDSADDR1=(((U32)frameBuffer8Bit>>22)<<21 )|M5D((U32)frameBuffer8Bit>>1); rLCDSADDR2=M5D( ((U32)frameBuffer8Bit+(SCR_XSIZE_CSTN*LCD_YSIZE_CSTN/1))>>1 ); rLCDSADDR3=(((SCR_XSIZE_CSTN-LCD_XSIZE_CSTN)/2)<<11)|(LCD_XSIZE_CSTN/2); rDITHMODE=0x0; rREDLUT =0xfdb920; rGREENLUT=0xfdb920; rBLUELUT =0xfb40;

// 8-bit single scan,8bpp CSTN,ENVID=off

//INVVDEN:x,INVPWREN:x,INVLEND:x,PWREN:x,ENLEND:x,BSWP:x,HWSWP:x

rLCDSADDR1=(((U32)frameBuffer4Bit>>22)<<21)|M5D((U32)frameBuffer4Bit>>1); rLCDSADDR2=M5D( ((U32)frameBuffer4Bit+(SCR_XSIZE_STN*LCD_YSIZE_STN/2))>>1 ); rLCDSADDR3=(((SCR_XSIZE_STN-LCD_XSIZE_STN)/4)<<11)|(LCD_XSIZE_STN/4); rDITHMODE=0x0;

break;

break;

case MODE_CSTN_12BIT:

frameBuffer12Bit=(U32 (*)[SCR_XSIZE_CSTN*3/8])LCDFRAMEBUFFER; // Packed Type : The L.C.M of 12 and 32 is 96.

rLCDCON1=(CLKVAL_CSTN<<8)|(MVAL_USED<<7)|(2<<5)|(4<<1)|0; // 8-bit single scan,12bpp CSTN,ENVID=off rLCDCON2=(0<<24)|(LINEVAL_CSTN<<14)|(0<<6)|0;

rLCDCON3=(WDLY_CSTN<<19)|(HOZVAL_CSTN<<8)|(LINEBLANK_CSTN<<0); rLCDCON4=(MVAL<<8)|(WLH_CSTN<<0); rLCDCON5=0;

//BPP24BL:x,FRM565:x,INVVCLK:x,INVVLINE:x,INVVFRAME:x,INVVD:x,

//INVVDEN:x,INVPWREN:x,INVLEND:x,PWREN:x,ENLEND:x,BSWP:x,HWSWP:x

rLCDSADDR1=(((U32)frameBuffer12Bit>>22)<<21)|M5D((U32)frameBuffer12Bit>>1); rLCDSADDR2=M5D(((U32)frameBuffer12Bit+((SCR_XSIZE_CSTN*3/2)*LCD_YSIZE_CSTN))>>1); rLCDSADDR3=(((SCR_XSIZE_CSTN-LCD_XSIZE_CSTN)*3/4)<<11)|(LCD_XSIZE_CSTN*3/4);

rDITHMODE=0; break;

JXARM9-2410 uC/OS-II课程设计实验 48

case MODE_TFT_8BIT_240320: );

rLCDSADDR2=M5D( ((U32)frameBuffer8BitTft240320+(SCR_XSIZE_TFT_240320*LCD_YSIZE_TFT_240320rLCDSADDR3=(((SCR_XSIZE_TFT_240320-LCD_XSIZE_TFT_240320)/2)<<11)|(LCD_XSIZE_TFT_240320/2); rLCDINTMSK|=(3); // MASK LCD Sub Interrupt rLPCSEL&=(~7); // Disable LPC3600 rTPAL=0; // Disable Temp Palette

/1))>>1 );

frameBuffer8BitTft240320=(U32 (*)[SCR_XSIZE_TFT_240320/4])LCDFRAMEBUFFER; rLCDCON1=(CLKVAL_TFT_240320<<8)|(MVAL_USED<<7)|(3<<5)|(11<<1)|0;

rLCDCON2=(VBPD_240320<<24)|(LINEVAL_TFT_240320<<14)|(VFPD_240320<<6)|(VSPW_240320); rLCDCON3=(HBPD_240320<<19)|(HOZVAL_TFT_240320<<8)|(HFPD_240320); rLCDCON4=(MVAL<<8)|(HSPW_240320);

rLCDCON5=(1<<11)|(1<<9)|(1<<8); //FRM5:6:5,HSYNC and VSYNC are inverted

rLCDSADDR1=(((U32)frameBuffer8BitTft240320>>22)<<21)|M5D((U32)frameBuffer8BitTft240320>>1

// TFT LCD panel,8bpp TFT,ENVID=off

break; >1);

case MODE_TFT_16BIT_0480:

frameBuffer16BitTft0480=(U32 (*)[SCR_XSIZE_TFT_0480/2])LCDFRAMEBUFFER;

rLCDCON1=(CLKVAL_TFT_0480<<8)|(MVAL_USED<<7)|(3<<5)|(12<<1)|0;

rLCDCON2=(VBPD_0480<<24)|(LINEVAL_TFT_0480<<14)|(VFPD_0480<<6)|(VSPW_0480); rLCDCON3=(HBPD_0480<<19)|(HOZVAL_TFT_0480<<8)|(HFPD_0480); rLCDCON4=(MVAL<<8)|(HSPW_0480); // TFT LCD panel,16bpp TFT,ENVID=off

rLCDSADDR2=M5D( ((U32)frameBuffer16BitTft240320+(SCR_XSIZE_TFT_240320*LCD_YSIZE_TFT_24032rLCDSADDR3=(((SCR_XSIZE_TFT_240320-LCD_XSIZE_TFT_240320)/1)<<11)|(LCD_XSIZE_TFT_240320/1); rLCDINTMSK|=(3); // MASK LCD Sub Interrupt rLPCSEL&=(~7); // Disable LPC3600 rTPAL=0; // Disable Temp Palette

0*2))>>1 );

case MODE_TFT_16BIT_240320:

frameBuffer16BitTft240320=(U32 (*)[SCR_XSIZE_TFT_240320/2])LCDFRAMEBUFFER; rLCDCON1=(CLKVAL_TFT_240320<<8)|(MVAL_USED<<7)|(3<<5)|(12<<1)|0;

rLCDCON2=(VBPD_240320<<24)|(LINEVAL_TFT_240320<<14)|(VFPD_240320<<6)|(VSPW_240320); rLCDCON3=(HBPD_240320<<19)|(HOZVAL_TFT_240320<<8)|(HFPD_240320); rLCDCON4=(MVAL<<8)|(HSPW_240320);

rLCDCON5=(1<<11)|(0<<9)|(0<<8); //FRM5:6:5,HSYNC and VSYNC are inverted

rLCDSADDR1=(((U32)frameBuffer16BitTft240320>>22)<<21)|M5D((U32)frameBuffer16BitTft240320>

// TFT LCD panel,12bpp TFT,ENVID=off

break;

JXARM9-2410 uC/OS-II课程设计实验 49

>1);

case MODE_TFT_1BIT_0480:

frameBuffer1BitTft0480=(U32 (*)[SCR_XSIZE_TFT_0480/32])LCDFRAMEBUFFER; );

case MODE_TFT_8BIT_0480:

frameBuffer8BitTft0480=(U32 (*)[SCR_XSIZE_TFT_0480/4])LCDFRAMEBUFFER; );

rLCDSADDR2=M5D( ((U32)frameBuffer8BitTft0480+(SCR_XSIZE_TFT_0480*LCD_YSIZE_TFT_0480rLCDSADDR3=(((SCR_XSIZE_TFT_0480-LCD_XSIZE_TFT_0480)/2)<<11)|(LCD_XSIZE_TFT_0480/2); rLCDINTMSK|=(3); // MASK LCD Sub Interrupt

/1))>>1 );

rLCDCON1=(CLKVAL_TFT_0480<<8)|(MVAL_USED<<7)|(3<<5)|(11<<1)|0;

rLCDCON2=(VBPD_0480<<24)|(LINEVAL_TFT_0480<<14)|(VFPD_0480<<6)|(VSPW_0480); rLCDCON3=(HBPD_0480<<19)|(HOZVAL_TFT_0480<<8)|(HFPD_0480); rLCDCON4=(MVAL<<8)|(HSPW_0480);

rLCDCON5=(1<<11)|(1<<9)|(1<<8); //FRM5:6:5,HSYNC and VSYNC are inverted

rLCDSADDR1=(((U32)frameBuffer8BitTft0480>>22)<<21)|M5D((U32)frameBuffer8BitTft0480>>1 // TFT LCD panel,8bpp TFT,ENVID=off

rLCDSADDR2=M5D( ((U32)frameBuffer1BitTft0480+(SCR_XSIZE_TFT_0480*LCD_YSIZE_TFT_0480rLCDSADDR3=(((SCR_XSIZE_TFT_0480-rLCDINTMSK|=(3); // MASK LCD Sub Interrupt rLPCSEL&=(~7); // Disable LPC3600 rTPAL=0; // Disable Temp Palette

/8))>>1 );

LCD_XSIZE_TFT_0480)/16)<<11)|(LCD_XSIZE_TFT_0480/16);

rLCDCON1=(CLKVAL_TFT_0480<<8)|(MVAL_USED<<7)|(3<<5)|(8<<1)|0;

rLCDCON2=(VBPD_0480<<24)|(LINEVAL_TFT_0480<<14)|(VFPD_0480<<6)|(VSPW_0480); rLCDCON3=(HBPD_0480<<19)|(HOZVAL_TFT_0480<<8)|(HFPD_0480); rLCDCON4=(MVAL<<8)|(HSPW_0480);

rLCDCON5=(1<<11)|(1<<9)|(1<<8); //FRM5:6:5,HSYNC and VSYNC are inverted

rLCDSADDR1=(((U32)frameBuffer1BitTft0480>>22)<<21)|M5D((U32)frameBuffer1BitTft0480>>1rLCDSADDR2=M5D( ((U32)frameBuffer16BitTft0480+(SCR_XSIZE_TFT_0480*LCD_YSIZE_TFT_048rLCDSADDR3=(((SCR_XSIZE_TFT_0480-LCD_XSIZE_TFT_0480)/1)<<11)|(LCD_XSIZE_TFT_0480/1); rLCDINTMSK|=(3); // MASK LCD Sub Interrupt rLPCSEL&=(~7); // Disable LPC3600 rTPAL=0; // Disable Temp Palette

0*2))>>1 );

rLCDCON5=(1<<11)|(1<<9)|(1<<8)/*|(1<<0)*/;

//FRM5:6:5,HSYNC and VSYNC are inverted

rLCDSADDR1=(((U32)frameBuffer16BitTft0480>>22)<<21)|M5D((U32)frameBuffer16BitTft0480>

break;

break;

JXARM9-2410 uC/OS-II课程设计实验 50

rLPCSEL&=(~7); // Disable LPC3600 rTPAL=0; // Disable Temp Palette

break;

case MODE_TFT_24BIT_0480:

frameBuffer24BitTft0480=(U32 (*)[SCR_XSIZE_TFT_0480])LCDFRAMEBUFFER; >1);

break;

case MODE_TFT_1BIT_800600:

frameBuffer1BitTft800600=(U32 (*)[SCR_XSIZE_TFT_800600/32])LCDFRAMEBUFFER; rLCDCON1=(CLKVAL_TFT_800600<<8)|(MVAL_USED<<7)|(3<<5)|(8<<1)|0; // TFT LCD panel,1bpp TFT,ENVID=off );

rLCDSADDR2=M5D( ((U32)frameBuffer1BitTft800600+(SCR_XSIZE_TFT_800600*LCD_YSIZE_TFT_800600rLCDSADDR3=(((SCR_XSIZE_TFT_800600-rLCDINTMSK|=(3); // MASK LCD Sub Interrupt rLPCSEL&=(~7); // Disable LPC3600 rTPAL=0; // Disable Temp Palette

/8))>>1 );

LCD_XSIZE_TFT_800600)/16)<<11)|(LCD_XSIZE_TFT_800600/16);

rLCDCON2=(VBPD_800600<<24)|(LINEVAL_TFT_800600<<14)|(VFPD_800600<<6)|(VSPW_800600); rLCDCON3=(HBPD_800600<<19)|(HOZVAL_TFT_800600<<8)|(HFPD_800600); rLCDCON4=(MVAL<<8)|(HSPW_800600); rLCDCON5=(1<<9)|(1<<8);

//INVVDEN:x,INVPWREN:x,INVLEND:x,PWREN:x,ENLEND:x,BSWP:x,HWSWP:x

rLCDSADDR1=(((U32)frameBuffer1BitTft800600>>22)<<21)|M5D((U32)frameBuffer1BitTft800600>>1rLCDSADDR2=M5D( ((U32)frameBuffer24BitTft0480+(SCR_XSIZE_TFT_0480*LCD_YSIZE_TFT_048rLCDSADDR3=(((SCR_XSIZE_TFT_0480-LCD_XSIZE_TFT_0480)*2)<<11)|(LCD_XSIZE_TFT_0480*2); rLCDINTMSK|=(3); // MASK LCD Sub Interrupt rLPCSEL&=(~7); // Disable LPC3600 rTPAL=0; // Disable Temp Palette

0*4))>>1 );

rLCDCON1=(CLKVAL_TFT_0480<<8)|(MVAL_USED<<7)|(3<<5)|(13<<1)|0;

rLCDCON2=(VBPD_0480<<24)|(LINEVAL_TFT_0480<<14)|(VFPD_0480<<6)|(VSPW_0480); rLCDCON3=(HBPD_0480<<19)|(HOZVAL_TFT_0480<<8)|(HFPD_0480); rLCDCON4=(MVAL<<8)|(HSPW_0480);

rLCDCON5=(1<<12)|(1<<9)|(1<<8); // BPP24:MSB,HSYNC and VSYNC are inverted

rLCDSADDR1=(((U32)frameBuffer24BitTft0480>>22)<<21)|M5D((U32)frameBuffer24BitTft0480> // TFT LCD panel,24bpp TFT,ENVID=off

//BPP24BL:x,FRM565:x,INVVCLK:x,INVVLINE:o,INVVFRAME:o,INVVD:x,

JXARM9-2410 uC/OS-II课程设计实验 51

break;

case MODE_TFT_8BIT_800600:

frameBuffer8BitTft800600=(U32 (*)[SCR_XSIZE_TFT_800600/4])LCDFRAMEBUFFER; rLCDCON1=(CLKVAL_TFT_800600<<8)|(MVAL_USED<<7)|(3<<5)|(11<<1)|0; // TFT LCD panel,8bpp TFT,ENVID=off );

rLCDSADDR2=M5D( ((U32)frameBuffer8BitTft800600+(SCR_XSIZE_TFT_800600*LCD_YSIZE_TFT_800600rLCDSADDR3=(((SCR_XSIZE_TFT_800600-LCD_XSIZE_TFT_800600)/2)<<11)|(LCD_XSIZE_TFT_800600/2); rLCDINTMSK|=(3); // MASK LCD Sub Interrupt rLPCSEL&=(~7); // Disable LPC3600 rTPAL=0; // Disable Temp Palette

/1))>>1 );

rLCDCON2=(VBPD_800600<<24)|(LINEVAL_TFT_800600<<14)|(VFPD_800600<<6)|(VSPW_800600); rLCDCON3=(HBPD_800600<<19)|(HOZVAL_TFT_800600<<8)|(HFPD_800600); rLCDCON4=(MVAL<<8)|(HSPW_800600); rLCDCON5=(1<<9)|(1<<8);

//BPP24BL:x,FRM565:x,INVVCLK:x,INVVLINE:o,INVVFRAME:o,INVVD:x, //INVVDEN:x,INVPWREN:x,INVLEND:x,PWREN:x,ENLEND:x,BSWP:x,HWSWP:x

rLCDSADDR1=(((U32)frameBuffer8BitTft800600>>22)<<21)|M5D((U32)frameBuffer8BitTft800600>>1

break;

case MODE_TFT_16BIT_800600:

frameBuffer16BitTft800600=(U32 (*)[SCR_XSIZE_TFT_800600/2])LCDFRAMEBUFFER; rLCDCON1=(CLKVAL_TFT_800600<<8)|(MVAL_USED<<7)|(3<<5)|(12<<1)|0; // TFT LCD panel,16bpp TFT,ENVID=off >1);

break;

rLCDSADDR2=M5D( ((U32)frameBuffer16BitTft800600+(SCR_XSIZE_TFT_800600*LCD_YSIZE_TFT_80060rLCDSADDR3=(((SCR_XSIZE_TFT_800600-LCD_XSIZE_TFT_800600)/1)<<11)|(LCD_XSIZE_TFT_800600/1); rLCDINTMSK|=(3); // MASK LCD Sub Interrupt rLPCSEL&=(~7); // Disable LPC3600 rTPAL=0; // Disable Temp Palette

0*2))>>1 );

rLCDCON2=(VBPD_800600<<24)|(LINEVAL_TFT_800600<<14)|(VFPD_800600<<6)|(VSPW_800600); rLCDCON3=(HBPD_800600<<19)|(HOZVAL_TFT_800600<<8)|(HFPD_800600); rLCDCON4=(MVAL<<8)|(HSPW_800600); rLCDCON5=(1<<11)|(1<<10)|(1<<9)|(1<<8);

//BPP24BL:x,FRM565:o,INVVCLK:x,INVVLINE:o,INVVFRAME:o,INVVD:x, //INVVDEN:x,INVPWREN:x,INVLEND:x,PWREN:x,ENLEND:x,BSWP:x,HWSWP:x

rLCDSADDR1=(((U32)frameBuffer16BitTft800600>>22)<<21)|M5D((U32)frameBuffer16BitTft800600>

JXARM9-2410 uC/OS-II课程设计实验 52

default: break; } }

另外一个重要函数就是lcd_put_pixel点输出函数,用于显示点。

void lcd_put_pixel(int x,int y,int c) {

#ifdef LCD_TFT_3_5

_PutTft16Bit_240320(x, y, c); #else }

#ifdef LCD_TFT_8_0 #else

_PutCstn8Bit(x, y, c); #endif

_PutTft16Bit_0480(x, y, c);

#endif

5)应用程序调用

应用程序在使用uC/GUI之前必须调用GUI_Init函数初始化uC/GUI。请在任务函数体中调用该函数。

GUI_Init();

JXARM9-2410 uC/OS-II课程设计实验 53

3.3 图形用户界面(基本绘图功能/字符显示功能)编程实验

3.3.1 实验目的

1. 本实验的目的是让学生了解uC/OS-II下图形用户界面的编程方法,包括绘图函数、图形用户界面编程。

3.3.2 实验内容

1. 编写程序实现基本的类Windows菜单和对话框界面。

3.3.3 预备知识

1. C语言的基础知识;

2. 程序调试的基础知识和方法。

3.3.4 实验设备

1. 硬件:JXARM9-2410教学实验箱、PC机;

2. 软件:PC机操作系统 Windows 98(2000、XP) + ADT IDE集成开发环境。

3.3.5 实验步骤

本实验的程序在ucos-ii的APP1工程中。

uC/GUI是uC/OS-II下的图形用户界面,本实验介绍基本uC/GUI的基本绘图函数和字符显示函数。这些函数声明在UC-GUI\\gui\\core\\GUI.h文件中。 1、设置背景颜色函数:

void GUI_SetBkColor (GUI_COLOR);

设置背景颜色,在uC/GUI中定义了如下颜色:

#define GUI_BLACK 0x000000 #define GUI_BLUE 0xFF0000 #define GUI_GREEN 0x00ff00 #define GUI_CYAN 0xffff00 #define GUI_RED 0x0000FF #define GUI_MAGENTA 0x8b008b #define GUI_BROWN 0x2a2aa5 #define GUI_DARKGRAY 0x404040 #define GUI_GRAY 0x808080 #define GUI_LIGHTGRAY 0xd3d3d3 #define GUI_LIGHTBLUE 0xff8080 #define GUI_LIGHTGREEN 0x80ff80 #define GUI_LIGHTCYAN 0x80ffff #define GUI_LIGHTRED 0x8080ff

JXARM9-2410 uC/OS-II课程设计实验

#define GUI_LIGHTMAGENTA 0xff80ff #define GUI_YELLOW 0x00ffff #define GUI_WHITE 0xffffff

#define GUI_INVALID_COLOR 0xfffffff /* Invalid color - more than 24 bits */

2、基本绘图函数:

清除屏幕函数,使用背景颜色清除,背景颜色由GUI_SetBkColor函数进行设置。

void GUI_Clear (void);

清除(x0, y0) (x1, y1)矩形区域内的屏幕,使用背景颜色清除,背景颜色由GUI_SetBkColor函数进行设置。

void GUI_ClearRect (int x0, int y0, int x1, int y1);

绘制以(x0, y0)为圆心,r为半径的圆。

void GUI_DrawCircle (int x0, int y0, int r);

绘制直线相关函数。

void GUI_DrawHLine (int y0, int x0, int x1); // 绘制水平线,(x0, y0)为起点,x1为终点的水平坐标

void GUI_DrawVLine (int x0, int y0, int y1); void GUI_DrawLine (int x0, int y0, int x1, int y1); void GUI_DrawLineRel (int dx, int dy); void GUI_MoveTo (int x, int y); void GUI_DrawLineTo (int x, int y);

void GUI_DrawPie (int x0, int y0, int r, int a0, int a1, int Type);

画点函数。

void GUI_DrawPixel (int x, int y); void GUI_DrawPoint (int x, int y);

绘制矩形函数。

void GUI_DrawRect (int x0, int y0, int x1, int y1); void GUI_DrawRectEx (const GUI_RECT *pRect);

图形填充函数。

void GUI_FillCircle (int x0, int y0, int r);

void GUI_FillEllipse (int x0, int y0, int rx, int ry);

void GUI_FillPolygon (const GUI_POINT*, int NumPoints, int x0, int y0); void GUI_FillRect (int x0, int y0, int x1, int y1); void GUI_FillRectEx (const GUI_RECT* pRect);

图形绘制函数。下面的函数在(x0, y0)起始处绘制位图。位图数据保存在pBM中。

void GUI_DrawBitmap (const GUI_BITMAP* pBM, int x0, int y0);

其中pBM定义如下:Xsize和Ysize分别为位图大小,BytesPerLine为每行字节数,BitsPerPixel为每个点所占比特数。PDate为图形数据,它显示使用pPal剪贴板。

typedef struct { U16P XSize; U16P YSize; U16P BytesPerLine;

JXARM9-2410 uC/OS-II课程设计实验 55

U16P BitsPerPixel; const U8* pData;

const GUI_LOGPALETTE* pPal; tfDrawSpecialBitmap* pfDraw; } GUI_BITMAP;

3、文本相关函数:

字符显示相关函数:

void GUI_DispChar (U16 c);

void GUI_DispChars (U16 c, int Cnt); void GUI_DispCharAt(U16 c, I16P x, I16P y);

显示字符串函数:

void GUI_DispString(const char GUI_FAR *s);

void GUI_DispStringAt(const char GUI_FAR *s, int x, int y); void GUI_DispStringAtCEOL(const char GUI_FAR *s, int x, int y);

void GUI_DispStringInRect(const char GUI_FAR *s, GUI_RECT* pRect, int Flags); void GUI_DispStringLen(const char GUI_FAR *s, int Len); char GUI_GotoXY(int x, int y); char GUI_GotoX(int x); char GUI_GotoY(int y);

4、示例程序说明:

下面为本实验示例程序的代码,在Main函数中创建一个任务LCD_Task_Main,所有的LCD操作都在该任务中进行:

/*

* Main function. */

void Main(void) { /*

* do target (uHAL based ARM system) initialisation */

ARMTargetInit();

uHALr_printf(\"#########Example 1#########\\n\"); /*

* needed by uC/OS */ /*

* create the tasks in uC/OS and assign increasing

OSInit();

JXARM9-2410 uC/OS-II课程设计实验 56

* priorities to them so that Task3 at the end of * the pipeline has the highest priority. */

OSTaskCreate(TaskLED, (void *)&IdLED, (OS_STK *)&StackLED[STACKSIZE - 1], 15); /* Create seg blink tasks */

OSTaskCreate(TaskSEG, (void *)&IdSEG, (OS_STK *)&StackSEG[STACKSIZE - 1], 13); /* Create LCD tasks */

OSTaskCreate(LCD_Task_Main, (void *)&IdLCD, (OS_STK *)&StackLCD[LCD_STACKSIZE - 1], 12);

/*

* start the task */ OSStart(); /*

* never reached */

return; }

LCD_Task_Main代码如下所示,首先调用uC/GUI初始化函数完成uC/GUI的初始化,然后调用ARMTargetStart启动时钟节拍定时器,开始任务调度,然后在循环中进行如下动作:

1) 显示红屏; 2) 显示兰屏; 3) 显示红屏;

4) 每10列显示一条直线,并在行首打印行数; 5) 使用GUI_DrawHLine显示一个三角形; 6) 然后显示一副位图; 7) 显示字符串。

/*

******************************************************************* *

* LCD_Task_Main() *

******************************************************************* */

void LCD_Task_Main(void *Id) {

int Cnt =0; int i,YPos;

int LCDXSize = LCD_GET_XSIZE(); int LCDYSize = LCD_GET_YSIZE(); GUI_BITMAP *pBitmap;

JXARM9-2410 uC/OS-II课程设计实验 57

GUI_Init();

ARMTargetStart(); while(1) {

GUI_SetBkColor(GUI_RED); GUI_Clear(); GUI_Delay(100);

GUI_SetBkColor(GUI_BLUE); GUI_Clear(); GUI_Delay(100);

GUI_SetColor(GUI_WHITE); for (i=0; i<1000; i+=10) {

GUI_DrawHLine(i,0,100); GUI_DispStringAt(\"Line \ GUI_DispDecMin(i); }

GUI_Delay(200); GUI_SetColor(0x0); GUI_SetBkColor(0xffffff); for (i=0; i<160; i++) {

int len = (i<80) ? i : 160-i; GUI_DrawHLine(i,20,len+20); }

GUI_Delay(200); GUI_Clear();

if (LCD_GET_YSIZE()>(100+bmMicriumLogo_1bpp.YSize)) {

pBitmap=&bmMicriumLogo; }else {

GUI_SetColor(GUI_BLUE); pBitmap=&bmMicriumLogo_1bpp; }

GUI_DrawBitmap(pBitmap,(LCDXSize-pBitmap->XSize)/2,10); YPos=20+pBitmap->YSize;

GUI_SetFont(&GUI_FontComic24B_1);

GUI_DispStringHCenterAt(\"www.micrium.com\ GUI_Delay(200); GUI_SetColor(GUI_RED);

JXARM9-2410 uC/OS-II课程设计实验 58

}

GUI_DispStringHCenterAt(\"?2002\\n\ GUI_SetFont(&GUI_Font10S_1);

GUI_DispStringHCenterAt(\"Micri祄 Inc.\ GUI_Delay(200); }

JXARM9-2410 uC/OS-II课程设计实验 59

3.4 图形用户界面(基本图形控件)编程实验

3.4.1 实验目的

1. 本实验的目的是让学生了解uC/OS-II下基本图形控件的编程方法。

3.4.2 实验内容

1. 编程实现显示一个对话框。

3.4.3 预备知识

1. C语言的基础知识;

2. 程序调试的基础知识和方法。

3.4.4 实验设备

1. 硬件:JXARM9-2410教学实验箱、PC机;

2. 软件:PC机操作系统 Windows 98(2000、XP) + ADT IDE集成开发环境。

3.4.5 实验步骤

本实验的程序在ucos-ii的APP3工程中。

和其它图形界面一样,支持资源,在uC/GUI中,资源采用全局/局部变量直接定义,如下面

为本实验使用的对话框控件的资源的定义_aDialogCreate。

/********************************************************************* *

* Dialog resource *

* This table conatins the info required to create the dialog.

* It has been created manually, but could also be created by a GUI-builder. */

static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = {

{ FRAMEWIN_CreateIndirect, \"Dialog\0 },

{ BUTTON_CreateIndirect, \"OK\ { BUTTON_CreateIndirect, \"Cancel\

{ TEXT_CreateIndirect, \"LText\ { TEXT_CreateIndirect, \"RText\ { EDIT_CreateIndirect, NULL, GUI_ID_EDIT0, 60, 55, 100, 15, 0, 50 }, { EDIT_CreateIndirect, NULL, GUI_ID_EDIT1, 60, 80, 100, 15, 0, 50 }, { TEXT_CreateIndirect, \"Hex\ { EDIT_CreateIndirect, NULL, GUI_ID_EDIT2, 60, 100, 100, 15, 0, 6 },

{ TEXT_CreateIndirect, \"Bin\

JXARM9-2410 uC/OS-II课程设计实验 60

{ EDIT_CreateIndirect, NULL, GUI_ID_EDIT3, 60, 120, 100, 15 }, { LISTBOX_CreateIndirect, NULL, GUI_ID_LISTBOX0,10, 10, 60, 40 }, { CHECKBOX_CreateIndirect, NULL, GUI_ID_CHECK0, 10, 140, 0, 0 }, { CHECKBOX_CreateIndirect, NULL, GUI_ID_CHECK1, 30, 140, 0, 0 }, { SLIDER_CreateIndirect, NULL, GUI_ID_SLIDER0, 60, 140, 100, 20 }, { SLIDER_CreateIndirect, NULL, GUI_ID_SLIDER1, 10, 170, 150, 30 } };

下面为一个列表框中显示的数据。

/********************************************************************* *

* Initializers for listbox */

static const GUI_ConstString _apListBox[] = {

\"English\鏰is\ };

对话框接收到消息后调用相应的回调函数进行处理,如下面的_cbCallback函数,这是对话框处理的主要函数,下面的函数处理了WM_INIT_DIALOG、WM_KEY、WM_NOTIFY_PARENT等多种消息。

/********************************************************************* *

* Dialog callback routine */

static void _cbCallback(WM_MESSAGE * pMsg) { int NCode, Id;

WM_HWIN hEdit0, hEdit1, hEdit2, hEdit3, hListBox; WM_HWIN hWin = pMsg->hWin; switch (pMsg->MsgId) { case WM_INIT_DIALOG:

/* Get window handles for all widgets */ hEdit0 = WM_GetDialogItem(hWin, GUI_ID_EDIT0); hEdit1 = WM_GetDialogItem(hWin, GUI_ID_EDIT1); hEdit2 = WM_GetDialogItem(hWin, GUI_ID_EDIT2); hEdit3 = WM_GetDialogItem(hWin, GUI_ID_EDIT3); hListBox = WM_GetDialogItem(hWin, GUI_ID_LISTBOX0); /* Initialize all widgets */

EDIT_SetText(hEdit0, \"EDIT widget 0\"); EDIT_SetText(hEdit1, \"EDIT widget 1\"); EDIT_SetTextAlign(hEdit1, GUI_TA_LEFT); EDIT_SetHexMode(hEdit2, 0x1234, 0, 0xffff); EDIT_SetBinMode(hEdit3, 0x1234, 0, 0xffff);

JXARM9-2410 uC/OS-II课程设计实验 61

LISTBOX_SetText(hListBox, _apListBox);

WM_DisableWindow (WM_GetDialogItem(hWin, GUI_ID_CHECK1)); CHECKBOX_Check( WM_GetDialogItem(hWin, GUI_ID_CHECK0)); CHECKBOX_Check( WM_GetDialogItem(hWin, GUI_ID_CHECK1)); SLIDER_SetWidth( WM_GetDialogItem(hWin, GUI_ID_SLIDER0), 5); SLIDER_SetValue( WM_GetDialogItem(hWin, GUI_ID_SLIDER1), 50); SCROLLBAR_CreateAttached(hListBox, SCROLLBAR_CF_VERTICAL); break; case WM_KEY:

switch (((WM_KEY_INFO*)(pMsg->Data.p))->Key) { case GUI_KEY_ESCAPE: GUI_EndDialog(hWin, 1); break;

case GUI_KEY_ENTER: GUI_EndDialog(hWin, 0); break; } break;

case WM_NOTIFY_PARENT:

Id = WM_GetId(pMsg->hWinSrc); /* Id of widget */ NCode = pMsg->Data.v; /* Notification code */ switch (NCode) {

case WM_NOTIFICATION_RELEASED: /* React only if released */ if (Id == GUI_ID_OK) { /* OK Button */ GUI_EndDialog(hWin, 0); }

if (Id == GUI_ID_CANCEL) { /* Cancel Button */ GUI_EndDialog(hWin, 1); } break; } break; default:

WM_DefaultProc(pMsg); } }

对话框的主函数如下所示,通过调用GUI_ExecDialogBox创建对话框,并将对话框资源和回调函数等参数传递进去。

/********************************************************************* *

* main *

JXARM9-2410 uC/OS-II课程设计实验 62

********************************************************************** */

void Dialog_Main(void) { GUI_Init();

WM_SetDesktopColor(GUI_RED); /* Automacally update desktop window */

WM_SetCreateFlags(WM_CF_MEMDEV); /* Use memory devices on all windows to avoid flicker */ GUI_ExecDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), &_cbCallback, 0, 0, 0); }

JXARM9-2410 uC/OS-II课程设计实验 63

第4章 综合实验

4.1 多通道数据采集

4.1.1 实验目的

1. 本实验的目的是设计一个双通道A/D采集程序,将采集到的数据以图形的方式进行显示。

4.1.2 实验内容

1. 编程实现数据采集; 2. 将采集数据显示到LCD上。

4.1.3 预备知识

1. C语言的基础知识;

2. 程序调试的基础知识和方法。

4.1.4 实验设备

1. 硬件:JXARM9-2410教学实验箱、PC机;

2. 软件:PC机操作系统 Windows 98(2000、XP) + ADT IDE集成开发环境。

4.1.5 实验步骤

/*

* Main function. */

void Main(void) { /*

* do target (uHAL based ARM system) initialisation */

ARMTargetInit();

uHALr_printf(\"#########Example 1#########\\n\"); /*

* needed by uC/OS */

本实验的程序在ucos-II的APP4工程中。

Main函数如下所示,在其中创建了一个任务LCD_Task_Main。

JXARM9-2410 uC/OS-II课程设计实验

/*

* start the task */ OSStart(); /*

* never reached */

return; }

/* Create LCD tasks */

OSTaskCreate(LCD_Task_Main, (void *)&IdLCD, (OS_STK *)&StackLCD[LCD_STACKSIZE - 1], 12); OSInit();

/*

在CD_Task_Main中调用Dialog_Main显示图形并采集AD数据然后显示。

******************************************************************* *

* LCD_Task_Main() *

******************************************************************* */

void LCD_Task_Main(void *Id) {

GUI_Init();

Dialog_Main(); }

ARMTargetStart();

AD数据以及数据的显示在ADC_Get函数中进行,在LCD上显示了两个通道的AD数据,并以条码的方式进行显示,同时,分别在七段数码管上显示两个通道的AD数据。

void ADC_Get(void) {

int ch0, ch1;

ch0=Adc_Get_Data(0, ADC_FREQ); ch1=Adc_Get_Data(1, ADC_FREQ);

// 重绘

AD_Draw_Data(1, ch0);

JXARM9-2410 uC/OS-II课程设计实验 65

}

#define CH1_BACK_COLOR GUI_WHITE #define CH1_COLOR GUI_RED

#define CH2_BACK_COLOR GUI_WHITE #define CH2_COLOR GUI_GREEN

#define CH1_TOP_X 100 #define CH1_TOP_Y 30 #define CH1_BOT_X 310 #define CH1_BOT_Y 130 #define CH2_TOP_X 100 #define CH2_TOP_Y 135 #define CH2_BOT_X 310 #define CH2_BOT_Y 235

#define AD_ACQUIRE_POINT 209 //(CH1_BOT_X - CH1_TOP_X - 1)

INT32U ch1_acq_pt[AD_ACQUIRE_POINT] = {0, }; INT32U ch2_acq_pt[AD_ACQUIRE_POINT] = {0, };

void AD_Draw_Data(INT8U ch, INT32U data) {

char str[20]; INT32U loopcnt;

data &= 0x3ff;

sprintf(str, \"%03d\switch(ch) {

case 1:

GUI_SetBkColor(GUI_WHITE); GUI_SetColor(CH1_COLOR);

GUI_DispStringAt(str, 20,CH1_TOP_Y + 50); GUI_SetBkColor(CH1_BACK_COLOR); GUI_SetColor(CH1_BACK_COLOR);

GUI_FillRect(CH1_TOP_X, CH1_TOP_Y, CH1_BOT_X, CH1_BOT_Y); for(loopcnt = 0; loopcnt < AD_ACQUIRE_POINT - 1; loopcnt ++)

ch1_acq_pt[loopcnt] = ch1_acq_pt[loopcnt + 1];

ch1_acq_pt[AD_ACQUIRE_POINT - 1] = data*1.0*(CH1_BOT_Y - CH1_TOP_Y)/ADC_MAX_VALUE; AD_Draw_Data(2, ch1);

JXARM9-2410 uC/OS-II课程设计实验 66

GUI_SetColor(CH1_COLOR);

for(loopcnt = CH1_TOP_X + 1; loopcnt < CH1_BOT_X; loopcnt ++)

GUI_DrawVLine(loopcnt, CH1_BOT_Y - ch1_acq_pt[loopcnt - CH1_TOP_X - 1], CH1_BOT_Y); break; case 2:

GUI_SetBkColor(GUI_WHITE); GUI_SetColor(CH2_COLOR);

GUI_DispStringAt(str, 20,CH2_TOP_Y + 50); GUI_SetBkColor(CH2_BACK_COLOR); GUI_SetColor(CH2_BACK_COLOR);

GUI_FillRect(CH2_TOP_X, CH2_TOP_Y, CH2_BOT_X, CH2_BOT_Y); for(loopcnt = 0; loopcnt < AD_ACQUIRE_POINT - 1; loopcnt ++)

ch2_acq_pt[loopcnt] = ch2_acq_pt[loopcnt + 1];

ch2_acq_pt[AD_ACQUIRE_POINT - 1] = data*1.0*(CH2_BOT_Y - CH2_TOP_Y)/ADC_MAX_VALUE; GUI_SetColor(CH2_COLOR);

for(loopcnt = CH2_TOP_X + 1; loopcnt < CH2_BOT_X; loopcnt ++)

GUI_DrawVLine(loopcnt, CH2_BOT_Y - ch2_acq_pt[loopcnt - CH2_TOP_X - 1], CH2_BOT_Y); break;

}

}

/******************************************************************** // Function name : Dialog_Main // Description // Return type

: 对话框主函数

: void

// Argument : void

*********************************************************************/ void Dialog_Main(void) {

int loopcnt = 0;

GUI_SetBkColor(GUI_BLUE); GUI_Clear();

GUI_SetColor(GUI_WHITE);

GUI_SetFont(&GUI_FontComic24B_1);

// 画边框

GUI_SetBkColor(CH1_BACK_COLOR);

GUI_FillRect(CH1_TOP_X, CH1_TOP_Y, CH1_BOT_X, CH1_BOT_Y); GUI_SetBkColor(CH2_BACK_COLOR);

GUI_DispStringAt(\"Two-channel A/D data acquire system\GUI_DispStringAt(\"Channel One\GUI_DispStringAt(\"Channel Two\ GUI_SetFont(&GUI_FontComic18B_1);

JXARM9-2410 uC/OS-II课程设计实验 67

}

while(1) { }

ADC_Get(); OSTimeDly(20);

GUI_FillRect(CH2_TOP_X, CH2_TOP_Y, CH2_BOT_X, CH2_BOT_Y);

// 初始化

for(loopcnt = 0; loopcnt <= AD_ACQUIRE_POINT - 1; loopcnt ++) { }

ch1_acq_pt[loopcnt] = 0; ch2_acq_pt[loopcnt] = 0;

JXARM9-2410 uC/OS-II课程设计实验 68

4.2 贪食蛇游戏设计实验

4.2.1 实验目的

1. 本实验的目的是设计一个基于uC/OS-II的贪食蛇游戏。

4.2.2 实验内容

1. 编程实现贪食蛇游戏。

4.2.3 预备知识

1. C语言的基础知识;

2. 程序调试的基础知识和方法; 3. uC/OS-II的键盘驱动方法; 4. uC/OS-II基本的图形编程方法。

4.2.4 实验设备

1. 硬件:JXARM9-2410教学实验箱、PC机;

2. 软件:PC机操作系统 Windows 98(2000、XP) + ADT IDE集成开发环境。

4.2.5 实验步骤

本实验的程序在UCOS-II的Snake工程中。 贪食蛇游戏是一个很普通的游戏,设计算法也比较简单。在嵌入式系统上实现贪食蛇游戏需要正确处理以下几个方面的问题: 1、人机交互的问题。 贪食蛇游戏是一个交互式的游戏,必须接收用户输入,对于JXARM9-2410输入方式可以有多种,如触摸屏、小键盘等。考虑操作的方便,通常使用小键盘,此处我们也使用小键盘进行操作,并定义如下键值(在snake.c文件中定义):

#define VK_LEFT ('4') // 4键左转 #define VK_RIGHT ('6') // 6键右转 #define VK_UP ('2') // 2键上转 #define VK_DOWN ('8') // 8键下转 #define VK_ESC ('E') // Cancel键退出 #define VK_SPEED_UP ('C') // UP键加速 #define VK_SPEED_DOWN ('D') // DOWN键减速

2、小键盘控制的实现

小键盘的实现在2.1节进行了介绍,请参考该节,并且正确的设置KBD_SCAN宏。在uC/GUI

中具有键盘驱动的接口,因此,在本实验讲键盘操作加入到uC/GUI的键盘驱动接口中,该接口主要函数为GUI_GetKey,它的实现如下所示。通过调用Key_GetKey,将其保存起来并返回,在

JXARM9-2410 uC/OS-II课程设计实验 69

应用程序中就可以直接调用GUI_GetKey获取键值,如果为0表示没有键按下,否则分析键值。GUI_GetKey函数在UC-GUI\\gui\\core\\GUI_OnKey.c文件中实现。

int GUI_GetKey(void) { int r = Key_GetKey(); _Key = r; return r; }

3、贪食蛇的主控函数

贪食蛇的主控函数如下所示:

/******************************************************************** // Function name : Snake_Main // Description // Return type

: 贪食蛇游戏主控程序

: void

// Argument : void

*********************************************************************/ void Snake_Main(void) {

int i=0;

init();

while(1)

{

key = GUI_GetKey();

if(key != 0) /*检索按键*/ {

if(key==VK_ESC) break;

switch(key) {

case VK_LEFT: turn(DIRE_LEFT); break; case VK_UP: turn(DIRE_UP); break; case VK_DOWN: turn(DIRE_DOWN); break; case VK_RIGHT: turn(DIRE_RIGHT); break; case VK_SPEED_UP: speed --; if(speed < 1)

speed = 1;

draw_speed(); break;

case VK_SPEED_DOWN: speed ++;

JXARM9-2410 uC/OS-II课程设计实验 70

if(speed >= 10)

speed = 10;

draw_speed(); break; };

};

if(i = (++i) % 2) if(check()) break;

OSTimeDly(speed * 4); };

gameover(); }

首先调用init()初始化函数,在该函数中主要进行初始界面的绘制,并等待用户按下任意键开始游戏。 紧接着是一个死循环,在该循环中不断调用GUI_GetKey函数获取键值,并进行键值分析,当按下向上、向下、向左、向右键时调用turn函数调转蛇头方向。当按下加速和减速键时,更新speed速度变量并重绘界面。该循环在检测到Cancel键时直接从while(1)循环中退出,并调用gameover函数,提示游戏结束。

4、贪食蛇界面的绘制

界面绘制的代码如下所示,请注意该界面设置采用320*240 LCD设计,因此,在0*480的TFT显示器上界面只有左上角位置有。

#include \"gui.h\"

/* LATIN CAPITAL LETTER A */

static const unsigned char acFontSnake13_0000[ 13] = { /* code 0000 */ ________, ________, ________, ________, ________, ________, ________, ________, ________, ________, ________, ________, ________};

/* LATIN CAPITAL LETTER B */

JXARM9-2410 uC/OS-II课程设计实验 71

static const unsigned char acFontSnake13_0001[ 13] = { /* code 0001 */ XXXXXXXX, XXXXXXXX, XXXXXXXX, XXXXXXXX, XXXXXXXX, XXXXXXXX, XXXXXXXX, XXXXXXXX, XXXXXXXX, XXXXXXXX, XXXXXXXX, XXXXXXXX, XXXXXXXX};

static const GUI_CHARINFO GUI_FontSnake13_CharInfo[2] = { { 8, 8, 1, (void *)&acFontSnake13_0000 } /* code 0000 */ ,{ 8, 8, 1, (void *)&acFontSnake13_0001 } /* code 0001 */ };

static const GUI_FONT_PROP GUI_FontSnake13_Prop1 = { 0x0000 /* first character */ ,0x0001 /* last character */

,&GUI_FontSnake13_CharInfo[ 0] /* address of first character */ ,(void*)0 /* pointer to next GUI_FONT_PROP */ };

static const GUI_FONT GUI_FontSnake13 = { GUI_FONTTYPE_PROP_SJIS /* type of font */ ,8 /* height of font */ ,8 /* space of font y */ ,1 /* magnification x */ ,1 /* magnification y */ ,(void *)&GUI_FontSnake13_Prop1 };

/******************************************************************** // Function name : is_xy_inbody // Description // Return type

: 检查点(x, y)是否已被占用

: int

// Argument : int x // Argument : int y

*********************************************************************/ int is_xy_inbody(int x, int y) /*检查点(x, y)的是否已被占用*/ {

JXARM9-2410 uC/OS-II课程设计实验 72

int i; if(head>tail) {

for(i=tail; iif(nodes[i][0]==x && nodes[i][1]==y) return 1; } else {

for(i=tail; i<=MAX_NODE; i++)

if(nodes[i][0]==x && nodes[i][1]==y) return 1;

for(i=0; iif(nodes[i][0]==x && nodes[i][1]==y) return 1; };

return 0; /*正常返回0*/ }

/******************************************************************** // Function name : drawfood // Description // Return type

: 绘制食物

: void

// Argument :

*********************************************************************/ void drawfood() {

while(!(food_value = rand() % 10)); /*获取一个从1至9的随机整数,并放至food_value*/ GUI_SetFont(&GUI_Font8_ASCII); do {

while(!(food_x = rand() % (SCREEN_WIDTH - CHAR_WIDTH))); while(!(food_y = rand() % (SCREEN_HEIGHT - CHAR_HIGH)));

food_x = (food_x / CHAR_WIDTH) * CHAR_WIDTH; food_y = (food_y / CHAR_HIGH) * CHAR_HIGH;

}while(food_x < CHAR_WIDTH || food_y < CHAR_HIGH || is_xy_inbody(food_x, food_y) || food_x == nodes[head][0] || food_y == nodes[head][1]);

GUI_GotoXY(food_x, food_y); GUI_DispChar(food_value + 48); }

/******************************************************************** // Function name : do_draw

JXARM9-2410 uC/OS-II课程设计实验 73

// Description // Return type

: 绘制蛇身

: void

// Argument : int x // Argument : int y // Argument : int type

*********************************************************************/ void do_draw(int x, int y, int type) {

GUI_GotoXY(x, y);

GUI_SetFont(&GUI_FontSnake13);

switch(type) {

case 1: GUI_DispChar(CH_HEAD); break; case 2: GUI_DispChar(CH_BODY); break; case 3: GUI_DispChar(CH_TAIL); break;

case 4: GUI_DispChar(CH_BKG); /*用背景擦除尾巴*/ }; }

/******************************************************************** // Function name : draw // Description // Return type

: 绘制贪食蛇

: void

// Argument :

*********************************************************************/ void draw() {

int i;

do_draw(nodes[tail][0], nodes[tail][1], 3); /*画尾巴*/ if(head>tail) {

for(i = tail + 1; i < head; i++ ) do_draw(nodes[i][0], nodes[i][1], 2); /*画蛇身*/ }

else /*因为在check()中保证head不可能等于tail,即首尾不会重叠.*/ {

for(i = tail + 1; i < MAX_NODE - 1; i++ ) do_draw(nodes[i][0], nodes[i][1], 2); /*分两步画蛇身*/

for(i = 0; i < head; i++ ) do_draw(nodes[i][0], nodes[i][1], 2); };

do_draw(nodes[head][0], nodes[head][1], 1); /*画蛇头*/ }

/******************************************************************** // Function name : turn

JXARM9-2410 uC/OS-II课程设计实验 74

// Description // Return type

: 变换方向

: int

// Argument : int dire

*********************************************************************/ int turn(int dire) {

switch(nodes[head][2]) {

case DIRE_LEFT:

case DIRE_RIGHT: switch(dire) {

case DIRE_UP: nodes[head][2] = DIRE_UP; break; case DIRE_DOWN: nodes[head][2] = DIRE_DOWN; }; break; case DIRE_UP:

case DIRE_DOWN: switch(dire) {

case DIRE_LEFT: nodes[head][2] = DIRE_LEFT; break; case DIRE_RIGHT:nodes[head][2] = DIRE_RIGHT; }; } }

/******************************************************************** // Function name : step // Description // Return type

: 行进一步

: void

// Argument : int increased

*********************************************************************/ void step(int increased) {

int newhead;

newhead = (head + 1) % MAX_NODE; /*计算蛇头的偏移量*/

nodes[newhead][0] = nodes[head][0]; nodes[newhead][1] = nodes[head][1]; nodes[newhead][2] = nodes[head][2]; head = newhead;

switch(nodes[head][2]) {

case 1: nodes[head][0]-=CHAR_WIDTH; break;

JXARM9-2410 uC/OS-II课程设计实验 75

case 2: nodes[head][1]-=CHAR_HIGH; break; case 3: nodes[head][0]+=CHAR_WIDTH; break; case 4: nodes[head][1]+=CHAR_HIGH; break; };

if(!increased) /*当蛇处于增长状态时,不擦除尾巴*/ {

do_draw(nodes[tail][0], nodes[tail][1], 4); /*擦除尾巴*/ tail = (tail + 1) % MAX_NODE; /*计算蛇尾的偏移量*/ };

draw(); /*重画蛇*/ }

/******************************************************************** // Function name : draw_frame // Description // Return type

: 绘制边框

: void

// Argument :

*********************************************************************/ void draw_frame() {

GUI_GotoXY(320 - 8, loopcnt * 8); GUI_DispChar(0x1);

GUI_GotoXY(240 - 8, loopcnt * 8); GUI_DispChar(0x1);

for(loopcnt = 0; loopcnt < 30; loopcnt ++ ) {

GUI_GotoXY(0, loopcnt * 8); GUI_DispChar(0x1); }

GUI_GotoXY(loopcnt * 8, 240 - 8); GUI_DispChar(0x1); int loopcnt;

for(loopcnt = 0; loopcnt < 40; loopcnt ++ ) {

GUI_GotoXY(loopcnt * 8, 0); GUI_DispChar(0x1);

GUI_SetFont(&GUI_FontSnake13);

JXARM9-2410 uC/OS-II课程设计实验 76

}

/******************************************************************** // Function name : draw_level // Description // Return type

: 打印当前级别

: void

for(loopcnt = 30; loopcnt < 40; loopcnt ++ ) { }

GUI_DispStringAt(\"Snake 1.0\GUI_DispStringAt(\"2 - UP\GUI_DispStringAt(\"8 - DOWN\GUI_DispStringAt(\"4 - LEFT\GUI_DispStringAt(\"6 - RIGHT\GUI_DispStringAt(\"UP - FAST\GUI_DispStringAt(\"DOWN - SLOW\

GUI_GotoXY(loopcnt * 8, 15 * 8); GUI_DispChar(0x1); }

GUI_SetFont(&GUI_Font8_ASCII);

// Argument :

*********************************************************************/ void draw_level() {

char str[20];

GUI_SetFont(&GUI_Font8_ASCII);

sprintf(str, \"LEVEL:%d\ }

/******************************************************************** // Function name : draw_score // Description // Return type

: 打印当前得分数

: void

GUI_DispStringAt(str, 242, 21 * 8);

// Argument :

*********************************************************************/ void draw_score() {

char str[20];

GUI_SetFont(&GUI_Font8_ASCII); sprintf(str, \"SCORE:%d\

GUI_DispStringAt(str, 242, 17 * 8); draw_level();

JXARM9-2410 uC/OS-II课程设计实验 77

}

/******************************************************************** // Function name : draw_speed // Description // Return type

: 打印游戏速度提示信息

: void

// Argument :

*********************************************************************/ void draw_speed() {

char str[20];

GUI_SetFont(&GUI_Font8_ASCII); sprintf(str, \"SPEED:%d\ }

/******************************************************************** // Function name : draw_info // Description // Return type

: 打印提示信息

: void

GUI_DispStringAt(str, 242, 19 * 8);

// Argument : char *info

*********************************************************************/ void draw_info(char *info) {

GUI_SetFont(&GUI_Font8_ASCII); }

/******************************************************************* // Function name : init // Description // Return type

: 初始化函数

: void

GUI_DispStringAt(info, 242, 23 * 8);

// Argument :

*********************************************************************/ void init() {

int i; score =0; length = 10; speed = 4;

GUI_SetFont(&GUI_FontSnake13);

for(i=0; i <= length - 1; i++) /*蛇身各节坐标及运动方向,共有6节,且蛇头向左.*/ {

nodes[i][0] = 25*CHAR_WIDTH - i*CHAR_WIDTH; /* X坐标 */ nodes[i][1] = 12*CHAR_HIGH; /* Y坐标 */

JXARM9-2410 uC/OS-II课程设计实验 78

nodes[i][2] = DIRE_LEFT; /* 方向 */ };

head = length - 1; tail = 0;

GUI_SetBkColor(GUI_BLUE); GUI_SetColor(GUI_WHITE); GUI_Clear(); draw_frame(); draw_speed(); draw_score();

draw_info(\"Press any key\");

while(GUI_GetKey() == 0) OSTimeDly(1); draw_info(\"Playing \"); draw(); drawfood(); }

/******************************************************************** // Function name : check // Description // Return type

: 检查游戏是否结束,为0表示可以继续进行

: int

// Argument :

*********************************************************************/ int check() /*返回0表示游戏可以继续进行*/ {

if(nodes[head][0]==food_x && nodes[head][1]==food_y) /*吃到食物后的处理*/ {

score = score + food_value; draw_score(); length++; step(1); drawfood(); } else {

step(0); {

int x, y;

x = nodes[head][0]; y = nodes[head][1];

if(xSCREEN_WIDTH || ySCREEN_HEIGHT || is_xy_inbody(x, y)) return 1; } };

JXARM9-2410 uC/OS-II课程设计实验 79

return 0; /*正常返回0*/ }

/******************************************************************** // Function name : gameover // Description // Return type

: 游戏结束

: void

// Argument :

*********************************************************************/ void gameover() {

draw_info(\"Game Over!!! \"); }

JXARM9-2410 uC/OS-II课程设计实验 80

4.3 俄罗斯方块游戏设计实验

4.3.1 实验目的

1. 本实验的目的是设计一个基于uC/OS-II的俄罗斯方块游戏。

4.3.2 实验内容

1. 编程实现俄罗斯方块游戏。

4.3.3 预备知识

1. C语言的基础知识;

2. 程序调试的基础知识和方法; 3. uC/OS-II的键盘驱动方法; 4. uC/OS-II基本的图形编程方法。

4.3.4 实验设备

1. 硬件:JXARM9-2410教学实验箱、PC机;

2. 软件:PC机操作系统 Windows 98(2000、XP) + ADT IDE集成开发环境。

4.3.5 实验步骤

本实验的程序在ucos-ii的Terris工程中。 俄罗斯方块游戏是一个很普通的游戏,设计算法也比较简单。在嵌入式系统上实现俄罗斯方块游戏需要正确处理以下几个方面的问题: 1、人机交互的问题。 俄罗斯方块游戏是一个交互式的游戏,必须接收用户输入,对于JXARM9-2410输入方式可以有多种,如触摸屏、小键盘等。考虑操作的方便,通常使用小键盘,此处我们也使用小键盘进行操作,并定义如下键值(在snake.c文件中定义):

#define LEFT ('4') // 4键左移 #define RIGHT ('6') // 6键右移 #define UP ('2') // 2键变形 #define DOWN ('8') // 8键下落 #define ESC ('E') // Cancel键退出 #define SPEEDUP ('C') // UP键加速 #define SPEEDDOWN ('D') // DOWN键减速

2、小键盘控制的实现

小键盘的实现在2.1节进行了介绍,请参考该节,并且正确的设置KBD_SCAN宏。在uC/GUI

中具有键盘驱动的接口,因此,在本实验讲键盘操作加入到uC/GUI的键盘驱动接口中,该接口主要函数为GUI_GetKey,它的实现如下所示。通过调用Key_GetKey,将其保存起来并返回,在

JXARM9-2410 uC/OS-II课程设计实验 81

应用程序中就可以直接调用GUI_GetKey获取键值,如果为0表示没有键按下,否则分析键值。GUI_GetKey函数在UC-GUI\\gui\\core\\GUI_OnKey.c文件中实现。

int GUI_GetKey(void) { int r = Key_GetKey(); _Key = r; return r; }

3、俄罗斯方块的主控函数

俄罗斯方块的主控函数如下所示:

/******************************************************************** // Function name : Terris_Main // Description // Return type

: 俄罗斯方块游戏主控程序

: void

// Argument : void

*********************************************************************/ void Terris_Main(void) {

unsigned c;

int CurrentShape,x=6,y=0,Status=0; NewShape[0]=rand()%7; gameover = 0; init();

memcpy(back, back1, 22*14 * sizeof(unsigned));

DrawFace();

CurrentShape=CreateNewShape(); show(x,y,CurrentShape,Status); while(gameover == 0) {

c=getch(); if(c != 0) {

if(c==0) {

case DOWN :GoDown(&x,&y,&CurrentShape,&Status);break; case LEFT :GoLeft(&x,&y,&CurrentShape,&Status);break; case RIGHT :GoRight(&x,&y,&CurrentShape,&Status);break; case CHANGE :ChageShape(&x,&y,&CurrentShape,&Status);break;

c=getch(); switch(c)

JXARM9-2410 uC/OS-II课程设计实验 82

}

}

}

if(counter == (speed)) { }

counter ++; OSTimeDly(1);

GoDown(&x,&y,&CurrentShape,&Status); counter=0;

case SPEEDUP: speed --; if(speed <= 0) speed =1; draw_speed(); break; case SPEEDDOWN: speed ++; if(speed > 10) speed =10; draw_speed(); break; counter=0; }

首先调用init()初始化函数,在该函数中主要进行初始界面的绘制,并等待用户按下任意键开始游戏。 紧接着是一个死循环,在该循环中不断调用GUI_GetKey函数获取键值,并进行键值分析。

4、俄罗斯方块界面的绘制

界面绘制的代码如下所示,请注意该界面设置采用320*240 LCD设计,因此,在0*480的TFT显示器上界面只有左上角位置有。

/*

*********************************************************************************************************

* uC/GUI

* Universal graphic software for embedded applications *

* (c) Copyright 2002, Micrium Inc., Weston, FL

* (c) Copyright 2002, SEGGER Microcontroller Systeme GmbH *

* 礐/GUI is protected by international copyright laws. Knowledge of the * source code may not be used to write a similar product. This file may * only be used in accordance with a license and should not be redistributed * in any way. We appreciate your understanding and fairness. *

----------------------------------------------------------------------

File : Terris.c

Purpose : 俄罗斯方块游戏

----------------------------------------------------------------------

JXARM9-2410 uC/OS-II课程设计实验 83

*/

#include \"gui.h\"

#include #include #include #include #include

#define LEFT '4' #define RIGHT '6' #define DOWN '8' #define CHANGE '2' #define ESC 'E' #define SPEEDUP 'C' #define SPEEDDOWN 'D'

#define DefaultX 5 #define DefaultY 1

/* LATIN CAPITAL LETTER A */

static const unsigned char acFontSnake13_0000[ 13] = { /* code 0000 */ ________, ________, ________, ________, ________, ________, ________, ________, ________, ________, ________, ________, ________};

/* LATIN CAPITAL LETTER B */

JXARM9-2410 uC/OS-II课程设计实验 84

static const unsigned char acFontSnake13_0001[ 13] = { /* code 0001 */ XXXXXXXX, XXXXXXXX, XXXXXXXX, XXXXXXXX, XXXXXXXX, XXXXXXXX, XXXXXXXX, XXXXXXXX, XXXXXXXX, XXXXXXXX, XXXXXXXX, XXXXXXXX, XXXXXXXX};

static const GUI_CHARINFO GUI_FontSnake13_CharInfo[2] = { { 8, 8, 1, (void *)&acFontSnake13_0000 } /* code 0000 */ ,{ 8, 8, 1, (void *)&acFontSnake13_0001 } /* code 0001 */ };

static const GUI_FONT_PROP GUI_FontSnake13_Prop1 = { 0x0000 /* first character */ ,0x0001 /* last character */

,&GUI_FontSnake13_CharInfo[ 0] /* address of first character */ ,(void*)0 /* pointer to next GUI_FONT_PROP */ };

static const GUI_FONT GUI_FontSnake13 = { GUI_FONTTYPE_PROP_SJIS /* type of font */ ,8 /* height of font */ ,8 /* space of font y */ ,1 /* magnification x */ ,1 /* magnification y */ ,(void *)&GUI_FontSnake13_Prop1 };

int speed = 4; /*游戏速度*/ int gameover;

static unsigned counter=0; static unsigned shape[7][4][4][4]= {

{

{{0,1,1,0},{0,1,1,0},{0,0,0,0},{0,0,0,0}},

JXARM9-2410 uC/OS-II课程设计实验 85

{ { { { { {

{{0,1,0,0},{0,1,0,0},{1,1,0,0},{0,0,0,0}}, {{0,0,0,0},{1,0,0,0},{1,1,1,0},{0,0,0,0}}, {{1,1,0,0},{1,0,0,0},{1,0,0,0},{0,0,0,0}}, {{0,0,0,0},{1,1,1,0},{0,0,1,0},{0,0,0,0}}, {{1,0,0,0},{1,0,0,0},{1,1,0,0},{0,0,0,0}}, {{0,0,0,0},{1,1,1,0},{1,0,0,0},{0,0,0,0}}, {{1,1,0,0},{0,1,0,0},{0,1,0,0},{0,0,0,0}}, {{0,0,0,0},{0,0,1,0},{1,1,1,0},{0,0,0,0}}, {{0,1,0,0},{1,1,0,0},{1,0,0,0},{0,0,0,0}}, {{0,0,0,0},{1,1,0,0},{0,1,1,0},{0,0,0,0}}, {{0,1,0,0},{1,1,0,0},{1,0,0,0},{0,0,0,0}}, {{0,0,0,0},{1,1,0,0},{0,1,1,0},{0,0,0,0}}, {{1,0,0,0},{1,1,0,0},{0,1,0,0},{0,0,0,0}}, {{0,0,0,0},{0,1,1,0},{1,1,0,0},{0,0,0,0}}, {{1,0,0,0},{1,1,0,0},{0,1,0,0},{0,0,0,0}}, {{0,0,0,0},{0,1,1,0},{1,1,0,0},{0,0,0,0}}, {{0,1,0,0},{1,1,1,0},{0,0,0,0},{0,0,0,0}}, {{0,1,0,0},{0,1,1,0},{0,1,0,0},{0,0,0,0}}, {{0,0,0,0},{1,1,1,0},{0,1,0,0},{0,0,0,0}}, {{0,1,0,0},{1,1,0,0},{0,1,0,0},{0,0,0,0}}, {{0,0,0,0},{1,1,1,1},{0,0,0,0},{0,0,0,0}}, {{0,0,1,0},{0,0,1,0},{0,0,1,0},{0,0,1,0}}, {{0,0,0,0},{1,1,1,1},{0,0,0,0},{0,0,0,0}}, {{0,0,1,0},{0,0,1,0},{0,0,1,0},{0,0,1,0}}, {{0,1,1,0},{0,1,1,0},{0,0,0,0},{0,0,0,0}}, {{0,1,1,0},{0,1,1,0},{0,0,0,0},{0,0,0,0}}, {{0,1,1,0},{0,1,1,0},{0,0,0,0},{0,0,0,0}},

},

},

},

},

},

},

},

};

JXARM9-2410 uC/OS-II课程设计实验 86

unsigned back[22][14]= {

unsigned back1[22][14]= {

{1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,1,1,1,1,1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1,1,1,1,1,1,1}

};

JXARM9-2410 uC/OS-II课程设计实验 87

int ShapeColor[7]={GUI_RED,GUI_GREEN,GUI_BLUE,GUI_LIGHTRED,GUI_BLUE,GUI_YELLOW,GUI_BLUE}; char DigitalShape[10]={128+119,3,62,31,128+75,128+93,128+125,19,128+127,128+95}; int

ZodiacBack[11]={GUI_RED,GUI_BROWN,GUI_LIGHTRED,GUI_LIGHTMAGENTA,GUI_LIGHTCYAN,GUI_LIGHTGREEN,GUI_GREEN,GUI_CYAN,GUI_LIGHTBLUE,GUI_BLUE,GUI_DARKGRAY};

char ZodiacSoft[18][14]={

unsigned long score=0;

unsigned int Erasered=0,ETimes=0; int CEr=0;

{0,0,0,0,96,0,0,0,0,0,0,0,60,0}, {255,248,0,0,96,0,0,0,0,248,0,0,124,0}, {255,248,0,0,97,128,0,0,3,248,0,0,192,0}, {0,112,0,0,97,128,0,0,7,0,0,1,128,48}, {0,224,0,0,96,0,0,0,14,0,0,1,128,48}, {1,192,0,0,96,0,0,0,12,0,0,1,128,48},

{3,128,120,15,97,128,240,60,12,0,15,15,249,255}, {7,0,252,31,225,131,248,127,14,0,31,143,249,255}, {7,1,142,48,225,135,24,227,7,240,49,193,128,48}, {14,3,134,96,97,142,24,192,3,252,112,193,128,48}, {28,3,6,96,97,140,25,192,0,28,96,193,128,48}, {56,3,6,96,97,140,25,128,0,6,96,193,128,48}, {56,3,6,96,97,140,25,128,0,6,96,193,128,48}, {120,3,6,96,97,140,25,128,0,6,96,193,128,48}, {224,1,140,48,225,142,25,195,24,14,49,129,128,48}, {255,249,252,63,225,135,252,255,28,28,63,129,128,48}, {255,248,240,15,97,131,236,60,15,248,30,1,128,48}, {0,0,0,0,0,0,0,0,7,224,0,1,128,0} {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0,0,0,0,0,1,1}, {1,1,1,1,1,1,1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1,1,1,1,1,1,1}

};

};

JXARM9-2410 uC/OS-II课程设计实验 88

int NumOfLev[5]={0,0,0,0,0};

int TimeDelay[10]={21,18,17,15,13,11,9,7,5,3}; char NewShape[2]; unsigned PerOnce[4];

void setcolor(int c);

void game_over() { }

void DrawShape(int x,int y,int color) { }

void DrawNull(int x,int y) { }

void show(int x,int y,int CurrentShape,int Status) {

int temp, i, j, l, p; for(i=0;i<20;i++) int i;

setcolor(GUI_WHITE); for(i=0;i<20/*16*/;i++)

line(x*20,(y*20)+i,(x*20)+19/*15*/,(y*20)+i); int i;

setcolor(color); for(i=0;i<19/*15*/;i++)

line(x*20,(y*20)+i,(x*20)+18/*14*/,(y*20)+i); setcolor(GUI_DARKGRAY);

line((x*20)+19/*15*/,(y*20)+1,(x*20)+19/*15*/,(y*20)+19/*15*/); line((x*20)+1,(y*20)+15,(x*20)+19/*15*/,(y*20)+19/*15*/); setcolor(color-8);

line((x*20)+2,(y*20)+2,(x*20)+16/*12*/,(y*20)+2); line((x*20)+2,(y*20)+2,(x*20)+2,(y*20)+16/*12*/); int i, j;

gameover = 1;

draw_info(\"Game Over!!!\"); clrscr();

JXARM9-2410 uC/OS-II课程设计实验

}

int CreateNewShape() { }

int Possible(int x,int y,int CurrentShape,int Status) {

NewShape[1]=NewShape[0]; NewShape[0]=rand()%7; for(l=0;l<4;l++)

for(p=0;p<4;p++)

if(shape[NewShape[0]][0][p][l]==1)

DrawShape(26+l,8+p,GUI_GREEN/*ShapeColor[7]*/); return NewShape[1];

int l, p;

setcolor(GUI_DARKGRAY); bar(493, 141, 613, 235);

for(j=2;j<12;j++) {

if(back[i][j]==1)

DrawShape(6+j,2+i,GUI_BLUE); DrawNull(6+j,2+i); else

} //no matter what the status be,I will draw the background for(l=0;l<4;l++)

for(p=0;p<4;p++) { }

if(l+x<2||x+l>11||p+y>19)

continue;

//if(shape[CurrentShape][Status][p][l]+back[y+p][x+l]==1) // DrawShape(3+l+x,3+p+y,8+CurrentShape); //else //cout<<'O';

// DrawNull(3+j,3+i);

if(shape[CurrentShape][Status][p][l]==1)

DrawShape(6+l+x,2+p+y,ShapeColor[CurrentShape]); DrawShape(6+l+x,2+p+y,GUI_BLUE); if(back[y+p][x+l]==1)

JXARM9-2410 uC/OS-II课程设计实验 90

}

void GoLeft(int *x,int *y,int *CurrentShape,int *Status) { }

void GoRight(int *x,int *y,int *CurrentShape,int *Status) { }

void GoDown(int *x,int *y,int *CurrentShape,int *Status) {

int AllAreOne=1,temp=0; int i, j, r, l, rr, ll;

if(Possible(*x,(*y)+1,*CurrentShape,*Status)) { }

score+=3*(*CurrentShape);

*y = (*y)+1;

show(*x,*y,*CurrentShape,*Status); return;

if(Possible(*x+1,*y,*CurrentShape,*Status))

*x = (*x) + 1;

show(*x,*y,*CurrentShape,*Status);

if(Possible(*x-1,*y,*CurrentShape,*Status))

*x = (*x)-1;

show(*x,*y,*CurrentShape,*Status); int i, j;

for(i=0;i<4;i++) { } return 1;

for(j=0;j<4;j++) { }

if(shape[CurrentShape][Status][i][j]+back[y+i][x+j]==2)

//this line can also write as the following type: //if(shape[CurrentShape][Status][i][j]&&back[y+i][x+j]) return 0;

JXARM9-2410 uC/OS-II课程设计实验 91

for(i=0;i<4;i++)

for(j=0;j<4;j++) { }

*CurrentShape=CreateNewShape(); *x=DefaultX;*y=DefaultY;*Status=0; NumOfLev[temp]++; score+=5*temp;

show(*x,*y,*CurrentShape,*Status); counter=0;

if(!Possible(*x,*y,*CurrentShape,*Status)) { }

if(CEr>=30) { } if(temp)

ETimes++; draw_score(); return;

speed=(speed+1)%10; CEr/=30; getch(); game_over(); for(l=2;l<13;l++) { }

if(AllAreOne==1) { }

AllAreOne=1;

for(rr=r;rr>0;rr--)

for(ll=2;ll<13;ll++)

back[rr][ll]=back[rr-1][ll]; Erasered++; CEr++; temp++; if(back[r][l]==0)

AllAreOne=0;

back[i+(*y)][j+(*x)]+=shape[*CurrentShape][*Status][i][j]; for(r=1;r<20;r++)

JXARM9-2410 uC/OS-II课程设计实验 92

}

void ChageShape(int*x,int*y,int*CurrentShape,int*Status) { }

void DrawFace() { }

/******************************************************************** // Function name : draw_frame // Description // Return type

: 绘制边框

: void

int temp, i; setcolor(GUI_WHITE); line(491,139,615,139); line(491,140,614,140); line(491,139,491,236); line(492,139,492,235); setcolor(GUI_LIGHTGRAY); line(614,141,614,234); line(615,140,615,234); line(493,235,615,235); line(492,236,615,236); setcolor(GUI_DARKGRAY); bar(493, 141, 613, 235); setcolor(GUI_LIGHTGRAY);

if(Possible(*x,*y,*CurrentShape,(*Status+1)%4))

*Status=(*Status+1)%4; show(*x,*y,*CurrentShape,*Status);

// Argument :

*********************************************************************/ void draw_frame() {

int loopcnt;

for(loopcnt = 0; loopcnt < 40; loopcnt ++ ) {

GUI_GotoXY(loopcnt * 8, 0); GUI_DispChar(0x1);

GUI_SetFont(&GUI_FontSnake13);

JXARM9-2410 uC/OS-II课程设计实验 93

}

/******************************************************************** // Function name : draw_level // Description // Return type

: 打印当前级别

: void

for(loopcnt = 30; loopcnt < 40; loopcnt ++ ) { }

GUI_DispStringAt(\"Terris 1.0\GUI_DispStringAt(\"2 - CHANGE\GUI_DispStringAt(\"8 - SPEED\GUI_DispStringAt(\"4 - LEFT\GUI_DispStringAt(\"6 - RIGHT\GUI_DispStringAt(\"UP - FAST\GUI_DispStringAt(\"DOWN - SLOW\

GUI_GotoXY(loopcnt * 8, 15 * 8); GUI_DispChar(0x1); }

GUI_GotoXY(320 - 8, loopcnt * 8); GUI_DispChar(0x1);

GUI_GotoXY(240 - 8, loopcnt * 8); GUI_DispChar(0x1);

for(loopcnt = 0; loopcnt < 30; loopcnt ++ ) {

GUI_GotoXY(0, loopcnt * 8); GUI_DispChar(0x1); }

GUI_GotoXY(loopcnt * 8, 240 - 8); GUI_DispChar(0x1);

GUI_SetFont(&GUI_Font8_ASCII);

// Argument :

*********************************************************************/ void draw_level() {

char str[20];

JXARM9-2410 uC/OS-II课程设计实验 94

GUI_SetBkColor(GUI_BLACK); GUI_SetColor(GUI_WHITE);

GUI_SetFont(&GUI_Font8_ASCII);

sprintf(str, \"LEVEL:%d\ }

/******************************************************************** // Function name : draw_score // Description // Return type

: 打印当前得分数

: void

GUI_DispStringAt(str, 242, 21 * 8);

// Argument :

*********************************************************************/ void draw_score() {

char str[20];

GUI_SetBkColor(GUI_BLACK); GUI_SetColor(GUI_WHITE);

GUI_SetFont(&GUI_Font8_ASCII); sprintf(str, \"SCORE:%d\ }

/******************************************************************** // Function name : draw_speed // Description // Return type

: 打印游戏速度提示信息

: void

GUI_DispStringAt(str, 242, 17 * 8); draw_level();

// Argument :

*********************************************************************/ void draw_speed() {

char str[20];

GUI_SetBkColor(GUI_BLACK); GUI_SetColor(GUI_WHITE);

GUI_SetFont(&GUI_Font8_ASCII); sprintf(str, \"SPEED:%d\ }

/******************************************************************** // Function name : draw_info // Description // Return type

: 打印提示信息

: void

GUI_DispStringAt(str, 242, 19 * 8);

JXARM9-2410 uC/OS-II课程设计实验 95

// Argument : char *info

*********************************************************************/ void draw_info(char *info) { }

/******************************************************************* // Function name : init // Description // Return type

: 初始化函数

: void

GUI_SetBkColor(GUI_BLACK); GUI_SetColor(GUI_WHITE);

GUI_DispStringAt(info, 242, 23 * 8);

GUI_SetFont(&GUI_Font8_ASCII);

// Argument :

*********************************************************************/ void init() {

int i; score =0; speed = 4;

GUI_SetBkColor(GUI_BLACK); GUI_SetColor(GUI_WHITE); GUI_Clear(); draw_frame(); draw_speed(); draw_score();

draw_info(\"Press any key\"); while(GUI_GetKey() == 0); draw_info(\"Playing \"); }

void setcolor(int c) { }

int line(int x1, int y1, int x2, int y2) {

if(x1 == x2) {

GUI_DrawVLine(x1/2, y1/2, y2/2); GUI_SetColor(c);

JXARM9-2410 uC/OS-II课程设计实验 96

}

int getbkcolor() { }

int outtextxy(int x, int y, char *s) { }

int gotoxy(int x, int y) { }

int getch() { }

int clrscr() { }

int setbkcolor(int c) { }

int putpixel(int x, int y, int c) { }

int bar(int x1, int y1, int x2, int y2)

GUI_SetBkColor(c); GUI_Clear(); return GUI_GetKey(); GUI_GotoXY(x, y);

GUI_DispStringAt(s, x/2, y/2); return GUI_GetBkColor(); }else if(y1 == y2) { }

GUI_DrawHLine(y1/2, x1/2, x2/2);

JXARM9-2410 uC/OS-II课程设计实验 97

{ }

int circle(int x0, int y0, int r) { }

GL_DrawCircle(x0, y0, r); GUI_SetBkColor(GUI_RED);

GUI_FillRect(x1/2, y1/2, x2/2, y2/2);

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- oldu.cn 版权所有 浙ICP备2024123271号-1

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务