首页 GEC2410B实验箱教学平台-uCOS教程

GEC2410B实验箱教学平台-uCOS教程

举报
开通vip

GEC2410B实验箱教学平台-uCOS教程 1 GEC2410B 实验箱教学平台 --uCOS--uCOS--uCOS --uCOS 教程 2 目 录 1. uC/OS-II系统的移植……………………………………………………2 1.1. uC/OS-II介绍…………………………………………………………3 1.2. uC/OS-II移植…………………………………………………………3 1.3. uC/OS-II 应用开发……………………………………………………3 2. uC/OS-II 实验介绍………………………………………………………11 2.1...

GEC2410B实验箱教学平台-uCOS教程
1 GEC2410B 实验箱教学平台 --uCOS--uCOS--uCOS --uCOS 教程 2 目 录 1. uC/OS-II系统的移植……………………………………………………2 1.1. uC/OS-II介绍…………………………………………………………3 1.2. uC/OS-II移植…………………………………………………………3 1.3. uC/OS-II 应用开发……………………………………………………3 2. uC/OS-II 实验介绍………………………………………………………11 2.1 BIOS界面………………………………………………………………11 2.2 主界面 ……………………………………………………………… 12 2.3 触摸屏,A/D实验………………………………………………………12 2.4 直流/步进电机实验……………………………………………………16 2.5 GPS/GPRS实验………………………………………………………20 2.6 音频输入/输出实验……………………………………………………25 2.7 蜂鸣器/数码管实验……………………………………………………30 2.8 2x2Keys/键盘实验……………………………………………………32 2.9 SD Card 读写实验……………………………………………………34 2.10 0RS-485收发实验…………………………………………………38 2.12 CAN 总线实验………………………………………………………40 2.13 以太网实验…………………………………………………………43 2.14 多任务实验…………………………………………………………46 3. 实验代码模块一览……………………………………………………48 4. 参考资料说明 ………………………………………………………49 3 111 1 uC/OS-IIuC/OS-IIuC/OS-II uC/OS-II 系统的移植和开发 1.11.11.1 1.1 uC/OS-IIuC/OS-IIuC/OS-II uC/OS-II 介绍 uC/OS-II是一种基于优先级的可抢先的专门为嵌入式设备设计的简单、 高效的嵌入式实时操作系统内核,被应用到各种嵌入式系统中。目前已经被移 植到40多种不同结构(如 x86、ARM、PowerPC、MIPS等众多体系结构) 的 CPU上,运行在从8位到64位的各种系统之上,并有上百个商业应用实 例,其稳定性和可用性是经过实践验证的。该系统自从2.51版本之后,就通过 了美国 FAA认证,可以运行在诸如航天器等对安全 要求 对教师党员的评价套管和固井爆破片与爆破装置仓库管理基本要求三甲医院都需要复审吗 极为苛刻的系统之 上。同时,它的源代码公开,可以从 www.ucos-ii.com网站上获得全部源码以及 其在各种体系结构平台上的移植范例。因此对于嵌入式 RTOS而言,选择 uC/OS无疑是最经济的选择。 最新的 uC/OS-II 2.0版以上的内核都具有可抢占的实时多任务调度功 能,另外它还提供了许多系统服务,例如信号量、消息队列、邮箱、内存管理、 时间函数等,这些功能可以根据不同的需求进行裁减。可以说,uC/OS-II是一 个具备现代操作系统特点的 RTOS,同时它结构清晰、注解详尽,具有良好的可 扩展性和可移植性,被广泛地应用于各种架构的微处理器上。 1.21.21.2 1.2 uC/OS-IIuC/OS-IIuC/OS-II uC/OS-II 移植 目前 uC/OS-II 已经被移植到40多种不同结构 (如 x86、ARM、 PowerPC、MIPS等众多体系结构)的 CPU上,可以从 www.ucos-ii.com网站上 获得全部源码以及其在各种体系结构平台上的移植范例。可以说对目前的各 种平台,基本上都有现成的移植 方案 气瓶 现场处置方案 .pdf气瓶 现场处置方案 .doc见习基地管理方案.doc关于群访事件的化解方案建筑工地扬尘治理专项方案下载 可用,但开发者也应当对移植的过程有所 了解,以使系统和自己的具体应用融合得更好,也可以根据基本的移植原理实 现新的移植方案。 实际上 uC/OS-II可以简单地看作是一个多任务调度器,在这个任务调度 器上完善地添加了与多任务操作系统相关的一些系统服务,如信号量、邮箱 等。其 90%的代码是用 C语言写的,可以直接移植到有 C语言编译器的处理 器上。移植工作主要都集中在多任务切换的实现上,因为这部分代码用来保存 和恢复 CPU现场(即写/读相关寄存器),不能用 C语言,只能使用汇编语言 完成。 uC/OS-II 的全部源代码量大约是 6000-7000 行 ,共 15 个文件。将 uC/OS-II 移植到ARM处理器上,需要修改三个与ARM体系结构相关的文件, 代码量大约是 500行。以下分别介绍这三个文件的移植工作。 1.2.1 OS_CPU.H 文件 4 ARM 体系结构的寄存器位置 ·数据类型定义 数据类型的修改与所用的编译器相关,不同的编译器使用不同的字节长度 关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf 示同 一数据类型,比如 int,同样在 x86 平台上,GNU 的 gcc 编译为 4bytes,而 MS VC+ +则编译为 2 bytes。本文使相关的数据类型定义如下: typedef unsigned int BOOLEAN; typedef unsigned int INT8U; typedef signed int INT8S; typedef unsigned int INT16U; typedef signed int INT16S; typedef unsigned long INT32U; typedef long INT32S; typedef float FP32; 5 typedef double FP64; ·堆栈单位 任务切换时,CPU 现场的寄存器将保存在当前运行任务的堆栈中,所以 OS_STK 数 据类型应该与 CPU 的寄存器长度一致。 typedef unsigned int OS_CPU_SR; typedef unsigned int OS_STK; ·堆栈增长方向 堆栈由高地址向低地址增长,也与编译器有关,在函数调用时,入口参数和返回地 址一般保存在当前任务的堆栈中,编译器的编译选项和由此生成的堆栈指令就会 决定堆栈的增长方向。 #define OS_STK_GROWTH 0 ·宏定义 包括开关中断的宏定义,以及进行任务切换的宏定义。 #define OS_ENTER_CRITICAL() asm(" SETC INTM") #define OS_EXIT_CRITICAL() asm(" CLRC INTM") #define OS_TASK_SW() asm(" INTR 31") 1.2.2 OS_CPU_C.C 文件 ·任务堆栈初始化 在此讨论任务初始化时的堆栈设计,也就是在堆栈增长方向上如何定义每个需要 保存的寄存器位置。在ARM体系结构下,任务堆栈空间由高至低依次将保存着pc、 lr、r12、r11、r10、... r1、r0、CPSR、SPSR,如图 1所示。 有两点需要说明:一是,当前任务堆栈初始化完成后,OSTaskStkInit 返回新的堆 栈指针STK,在 OSTaskCreate()执行时,将会调用 OSTaskStkInit的初始化过程, 然后通过 OSTCBInit()函数调用,将返回的 SP 指针保存到该任务的 TCB 块中。二 是,初始状态的堆栈是模拟了一次中断后的堆栈结构,因为任务创建后并不是直 接就获得执行,而是通过 OSSched()函数进行调度分配,满足执行条件后才能获 得执行。为了使这个调度简单一致,就预先将该任务的 PC 指针和返回地址 LR 都 指向函数入口,以便被调度时从堆栈中恢复刚开始运行时的 CPU 现场。 ·系统钩子函数 在该文件中需要实现几个操作系统规定的 hook 函数,如下: OSSTaskCreateHook( ) OSTaskDelHook( ) OSTaskSwHook( ) OSTaskStatHook( ) 6 OSTimeTickHook( ) 若无特殊需求,只需简单地将它们都实现为空函数即可。 1.2.3 OS_CPU_A.S 文件 ·OSStartHighRdy() 此函数是在 OSStart()多任务启动后,负责从最高优先级任务的 TCB 控制块中获 得该任务的堆栈指针 SP,通过 SP依次将 CPU现场恢复,这时系统就将控制权交给 用户创建的该任务进程,直到该任务被阻塞或者被其他更高优先级的任务抢占 C PU。该函数仅在多任务启动时被执行一次,即执行最高优先级任务,之后多任务的 调度和切换由以下函数实现。 ·OSCtxSw() 任务级的上下文切换,当任务因为被阻塞而主动请求 CPU 调度时被执行,由于此 时的任务切换在非异常模式下进行,因此区别于中断级别的任务切换。它的工作 是先将当前任务的 CPU 现场保存到该任务堆栈中,然后获得最高优先级任务的堆 栈指针,从该堆栈中恢复此任务的 CPU 现场,使之继续执行。这样就完成了一次任 务切换。 ·OSIntCtxSw() 中断级的任务切换,在时钟中断 ISR(中断服务例程)中发现有高优先级任务等 待的时钟信号到来,则在中断退出后并不返回被中断任务,而是直接调度就绪的 高优先级任务执行,从而能够尽快地让高优先级的任务得到响应,保证系统的实 时性能。其原理基本上与任务级的切换相同,但是由于进入中断时已经保存了被 中断任务的 CPU 现场,因此不用再进行类似的操作,只需对堆栈指针做相应调整。 ·OSTickISR() 时钟中断处理函数,其主要任务是负责处理时钟中断,调用系统实现的 OSTimeTi ck 函数,如果有等待时钟信号的高优先级任务,则需要在中断级别上调度其执 行。其他相关的两个函数是 OSIntEnter()和 OSIntExit(),都需要在 ISR 中执行。 ·OS_ENTER_CRITICAL() & OS_EXIT_CRITICAL() 分别是退出临界区和进入临界区的宏指令实现。主要用于在进入临界区之前关闭 中断,在退出临界区的时候恢复原来的中断状态。它的实现比较简单,可以直接开 关中断来实现,也可以通过保存关闭/恢复中断屏蔽位来实现。 1.31.31.3 1.3 uC/OS-IIuC/OS-IIuC/OS-II uC/OS-II 应用开发 1.3.11.3.11.3.1 1.3.1 uC/OS-IIuC/OS-IIuC/OS-II uC/OS-II 应用程序基本结构 每一个 uC/OS-II 应用至少要有一个任务。而每一个任务必须被写成无限循环的 形式。以下是推荐的结构: void task ( void* pdata ){ InitTimer(); // 可选,初始化系统时间中断等 7 while(1) { //你的应用程序代码 OSTimeDly(1); // 可选,主动释放 CPU 使用权 } } 以上就是基本结构,至于为什么要写成无限循环的形式呢?那是因为系统会为每 一个任务保留一个堆栈空间,由系统在任务切换的时候换恢复上下文,并执行一 条 reti 指令返回。如果允许任务执行到最后一个花括号(那一般都意味着一条 r et指令)的话,很可能会破坏系统堆栈空间从而使应用程序的执行不确定。换句 话说,就是“跑飞”了。所以,每一个任务必须被写成无限循环的形式。程序员一 定要相信,自己的任务是会放弃 CPU使用权的,而不管是系统强制(通过 ISR) 还是主动放弃(通过调用 OS API)。 现在来谈论上面程序中的 InitTimer()函数,这个函数应该由系统提供,程序员有 义务在优先级最高的任务内调用它而且不能在 for循环内调用。注意,这个函数 是和所使用的 CPU相关的,每种系统都有自己的 Timer初始化程序。在 uC/OS-I I的帮助手册内,作者特地强调绝对不能在OSInit()或者OSStart()内调用 Timer初 始化程序,那会破坏系统的可移植性同时带来性能上的损失。所以,一个折中的办 法就是象上面这样,在优先级最高的程序内调用,这样可以保证当 OSStart()调用 系统内部函数 OSStartHighRdy()开始多任务后,首先执行的就是 Timer初始化程 序。或者专门开一个优先级最高的任务,只做一件事情,那就是执行 Timer初始 化,之后通过调用 OSTaskSuspend()将自己挂起来,永远不再执行。不过这样会浪 费一个 TCB空间。对于那些 RAM吃紧的系统来说,还是不用为好。 1.3.2 一些重要的 uC/OS-II API 介绍 任何一个操作系统都会提供大量的 API供程序员使用,uC/OS-II 也不例外。由于 uC/OS-II 面向的是嵌入式开发,并不要求大而全,所以内核提供的 API也就大多 和多任务息息相关。主要的有以下几类: 任务类 消息类 同步类 时间类 临界区与事件类 对于程序员而言,任务类和时间类是必须要首先掌握的两种类型的 API。 1)OSTaskCreateOSTaskCreateOSTaskCreate OSTaskCreate 函数 8 这个函数应该至少再 main函数内调用一次,在 OSInit函数调用之后调用。作用 就是创建一个任务。目前有四个参数,分别是任务的入口地址,任务的参数,任务 堆栈的首地址和任务的优先级。调用本函数后,系统会首先从 TCB空闲列表内申 请一个空的 TCB指针,然后将会根据用户给出参数初始化任务堆栈,并在内部的 任务就绪表内标记该任务为就绪状态。最后返回,这样一个任务就创建成功了。 2)OSTaskSuspendOSTaskSuspendOSTaskSuspend OSTaskSuspend 函数 这个函数很简单,一看名字就该明白它的作用,它可以将指定的任务挂起。如果挂 起的是当前任务的话,那么还会引发系统执行任务切换先导函数 OSShed来进行 一次任务切换。这个函数只有一个参数,那就是指定任务的优先级。那为什么是 优先级呢?事实上在系统内部,优先级除了表示一个任务执行的先后次序外,还 起着分别每一个任务的作用,换句话说,优先级也就是任务的 ID。所以 uC/OS-II 不允许出现相同优先级的任务。 3)OSTaskResumeOSTaskResumeOSTaskResume OSTaskResume 函数 这个函数和上面的函数正好相反,它用于将指定的已经挂起的函数恢复成就绪状 态。如果恢复任务的优先级高于当前任务,那么还为引发一次任务切换。其参数 类似 OSTaskSuspend函数,为指定任务的优先级。需要特别说明是,本函数并不 要求和 OSTaskSuspend函数成对使用。 4)OS_ENTER_CRITICALOS_ENTER_CRITICALOS_ENTER_CRITICAL OS_ENTER_CRITICAL 宏 很多人都以为它是个函数,其实不然,仔细分析一下OS_CPU.H文件,它和下面马 上要谈到的 OS_EXIT_CRITICAL都是宏。他们都是涉及特定 CPU的实现。一 般都被替换为一条或者几条嵌入式汇编代码。由于系统希望向上层程序员隐藏内 部实现,故而一般都宣称执行此条指令后系统进入临界区。其实,它就是关个中断 而已。这样,只要任务不主动放弃 CPU使用权,别的任务就没有占用 CPU的机会 了,相对这个任务而言,它就是独占了。所以说进入临界区了。这个宏能少用还是 少用,因为它会破坏系统的一些服务,尤其是时间服务。并使系统对外界响应性能 降低。 5)OS_EXIT_CRITICALOS_EXIT_CRITICALOS_EXIT_CRITICAL OS_EXIT_CRITICAL 宏 这个是和上面介绍的宏配套使用另一个宏,它在系统手册里的说明是退出临界 区。其实它就是重新开中断。需要注意的是,它必须和上面的宏成对出现,否则会 带来意想不到的后果。最坏的情况下,系统会崩溃。我们推荐程序员们尽量少使 用这两个宏调用,因为他们的确会破坏系统的多任务性能。 6)OSTimeDlyOSTimeDlyOSTimeDly OSTimeDly 函数 9 这应该程序员们调用最多的一个函数了,这个函数完成功能很简单,就是先挂起 当起当前任务,然后进行任务切换,在指定的时间到来之后,将当前任务恢复为就 绪状态,但是并不一定运行,如果恢复后是优先级最高就绪任务的话,那么运行 之。简单点说,就是可以任务延时一定时间后再次执行它,或者说,暂时放弃 CPU 的使用权。一个任务可以不显式的调用这些可以导致放弃 CPU使用权的 API,但 那样多任务性能会大大降低,因为此时仅仅依靠时钟机制在进行任务切换。一个 好的任务应该在完成一些操作主动放弃使用权,好东西要大家分享嘛! 1.3.3 uC/OS-II 多任务实现机制分析 前面已经说过,uC/OS-II 是一种基于优先级的可抢先的多任务内核。那么,它的 多任务机制到底如何实现的呢?了解这些原理,可以帮助我们写出更加健壮的代 码来。 首先我们来看看为什么多任务机制可以实现?其实在单一 CPU的情况下,是不 存在真正的多任务机制的,存在的只有不同的任务轮流使用 CPU,所以本质上还 是单任务的。但由于 CPU执行速度非常快,加上任务切换十分频繁并且切换的很 快,所以我们感觉好像有很多任务同时在运行一样。这就是所谓的多任务机制。 由上面的描述,不难发现,要实现多任务机制,那么目标 CPU必须具备一种在运 行期更改 PC的途径,否则无法做到切换。不幸的使,直接设置 PC指针,目前还没 有哪个 CPU支持这样的指令。但是一般 CPU都允许通过类似 JMP,CALL这样 的指令来间接的修改 PC。我们的多任务机制的实现也正是基于这个出发点。事 实上,我们使用 CALL指令或者软中断指令来修改 PC,主要是软中断。但在一些 CPU上,并不存在软中断这样的概念,所以,我们在那些 CPU上,使用几条 PUSH 指令加上一条 CALL指令来模拟一次软中断的发生。 回想一下你在微机原理课程上学过的知识,当发生中断的时候,CPU保存当前的 PC和状态寄存器的值到堆栈里,然后将 PC设置为中断服务程序的入口地址,再 下来一个机器周期,就可以去执行中断服务程序了。执行完毕之后,一般都是执行 一条 RETI指令,这条指令会把当前堆栈里的值弹出恢复到状态寄存器和 PC 里 。 这样,系统就会回到中断以前的地方继续执行了。那么设想一下?如果再中断的 时候,人为的更改了堆栈里的值,那会发生什么?或者通过更改当前堆栈指针的 值,又会发生什么呢?如果更改是随意的,那么结果是无法预料的错误。因为我们 无法确定机器下一条会执行些什么指令,但是如果更改是 计划 项目进度计划表范例计划下载计划下载计划下载课程教学计划下载 好的,按照一定规 则的话,那么我们就可以实现多任务机制。事实上,这就是目前几乎所有的 OS的 核心部分。不过他们的实现不像这样简单罢了。 下面,我们来看看 uC/OS-II 再这方面是怎么处理的。再 uC/OS-II 里,每个任务都 有一个任务控制块(Task Control Block),这是一个比较复杂的数据结构。在任务控 制快的偏移为 0的地方,存储着一个指针,它记录了所属任务的专用堆栈地址。事 10 实上,再 uC/OS-II 内,每个任务都有自己的专用堆栈,彼此之间不能侵犯。这点要 求程序员再他们的程序中保证。一般的做法是把他们申明成静态数组。而且要申 明成 OS_STK类型。当任务有了自己的堆栈,那么就可以将每一个任务堆栈再那 里记录到前面谈到的任务控制快偏移为 0的地方。以后每当发生任务切换,系统 必然会先进入一个中断,这一般是通过软中断或者时钟中断实现。然后系统会先 把当前任务的堆栈地址保存起来,仅接着恢复要切换的任务的堆栈地址。由于哪 个任务的堆栈里一定也存的是地址(还记得我们前面说过的,每当发生任务切换, 系统必然会先进入一个中断,而一旦中断 CPU就会把地址压入堆栈),这样,就达 到了修改 PC为下一个任务的地址的目的。 1.3.41.3.41.3.4 1.3.4 多任务编程 APIAPIAPI API uC/OS-II 的多任务编程需要注意任务之间的协调和同步,这就需要用到 uC/OS 提供的任务通信和同步方面的 API,这里简介如下: 1)1)1) 1) 信号量管理 建立一个信号量, OSSemCreate 删除一个信号量,OSSemDel 等待一个信号量, OSSemPend 发出一个信号量, OSSemPost 无等待地请求一个信号量, OSSemAccept 查询一个信号量的当前状态, OSSemQuery 2)2)2) 2) 互斥型信号量管理 建立一个互斥型信号量,OSMutexCreate 删除一个互斥型信号量,OSMutexDel 等待一个互斥型信号量(挂起),OSMutexPend 释放一个互斥型信号量,OSMutexPost 无等待地获取互斥型信号量(任务不挂起), OSMutexAccept 获取互斥型信号量的当前状态,OSMutexQuery 3)3)3) 3) 事件标志组管理 深入事件标志组 建立一个事件标志组,OSFlagCreate 删除一个事件标志组,OSFlagDel 等待事件标志组的事件标志位,OSFlagPend 置位或清 0事件标志组中的事件标志, OSFlagPost 无等待地获得事件标志组中的事件标志, OSFlagAccept 查询事件标志组的状态,OSFlagQuery 4)4)4) 4) 消息邮箱管理 建立一个邮箱,OSMboxCreate 删除一个邮箱,OSMboxDel 等待邮箱中的消息,OSMboxPend 11 向邮箱发送一则消息,OSMboxPost 向邮箱发送一则消息,OSMboxPostOpt 无等待地从邮箱中得到一则消息, OSMboxAccept 查询一个邮箱 OSMboxQuery 222 2 uC/OS-IIuC/OS-IIuC/OS-II uC/OS-II 实验介绍 本实验平台的 uC/OS-II 支持串口模拟按键,触摸屏操作,板载小键盘操 作,LCD彩色界面显示,中英文显示,菜单操作等。实验请注意:  串口模拟按键 0-9,a-f,[,], 各代表菜单选择 0-9,10-15,菜单向上键,向下键。  在菜单操作中,小键盘 0-9,(BIOS里面还有 A,B),代表菜单选择 0-9,E,D代表 菜单向上键,向下键,A,B分别代码滚动框上翻下翻键。  触摸屏支持鼠标滑动和点击操作,菜单可通过触摸屏来控制。  在出现输入框时,若要输入数字以外的内容,需要通过串口输入  uC/OS-II下各个实验涉及的芯片资料,控制原理请参考 ”GEC2410实验箱- 基础实验”一文及相关的资料,此处不再赘述,仅对代码作简单介绍。 2.12.12.1 2.1 BIOSBIOSBIOS BIOS 界面 BIOS 是用来下载,配置,启动操作系统的,如下图所示 如图,可选择 Run uC/OS-II 来启动 uC/OS ,如下图 12 2.22.22.2 2.2 主界面 进入 uC/OS 后主界面如下图所示: 2.32.32.3 2.3 触摸屏,A/D,A/D,A/D ,A/D 实验 13 实验原理请参考 ”GEC2410GEC2410GEC2410 GEC2410 实验箱--- - 基础实验”一文及相关的资料。 (1) 触摸屏初始化 void Touch_Screen_Init(void) { rADCDLY = (30000); // ADC Start or Interval Delay rADCCON = (1<<14)|(ADCPRS<<6)|(0<<3)|(0<<2)|(0<<1)|(0); //Enable Prescaler,Prescaler,AIN5/7 fix,Normal,Disable read start,No operation rADCTSC = (0<<8)|(1<<7)|(1<<6)|(0<<5)|(1<<4)|(0<<3)|(0<<2)|(3);//tark // Down,YM:GND,YP:AIN5,XM:Hi-z,XP:AIN7,XP pullup En,Normal,Waiting for interrupt mode } (2) 触摸屏坐标获取 int GetMousePos(int* x,int* y) { int i; int s1,s2,sub1,sub2; int count = 1; //if( TouchFlag & 0x01 ) count = ITERATION; //Auto X-Position and Y-Position Read rADCTSC=(1<<7)|(1<<6)|(0<<5)|(1<<4)|(1<<3)|(1<<2)|(0); //[7] YM=GND, [6] YP is connected with AIN[5], [5] XM=Hi-Z, [4] XP is connected with AIN[7] //[3] XP pull-up disable, [2] Auto(sequential) X/Y position 14 conversion mode, [1:0] No operation mode for(i=0;i< count;i++) { rADCTSC = (1<<7)|(1<<6)|(0<<5)|(1<<4)|(1<<3)|(1<<2)|(0); rADCCON |= 0x1; //Start Auto conversion while(rADCCON & 0x1) //Check if Enable_start is low { } while(!(0x8000&rADCCON)) //Check ECFLG { } samplebuf[CurrSample][0] = (0x3ff&rADCDAT0); samplebuf[CurrSample][1] = (0x3ff&rADCDAT1); CurrSample++; if( CurrSample >= ITERATION ) CurrSample = 0; } // rADCTSC = (1<<7)|(1<<6)|(0<<5)|(1<<4)|(0<<3)|(0<<2)|(3); s1 = s2 = 0; for(i=0;i MAX_DIS || ABS(sub2) > MAX_DIS ) { if( Button > 0 ) Button = MS_RELEASING; else Button = MS_RELEASED; 15 *x = lx; *y = ly; return 0; } } sub1 = s1 - lx; sub2 = s2 - ly; if( (ABS(sub1) + ABS(sub2)) < 2 ) {// 去抖动 return 0; } if( Button <= 0 ) {// 原来释放状态,现在则为按下状态 Button = MS_PRESSING;// 第 1次按下 } else { Button = MS_PRESSED; // 第 N次按下 } lx = s1; ly = s2; *x = s1; *y = s2; return 1; } (3) 触摸屏和 LCD屏幕坐标转换 #define MIN_TX 45 #define MAX_TX 960 #define MIN_TY 75 #define MAX_TY 910 #define SW 800 #define SH 480 #define TW (MAX_TX-MIN_TX) #define TH (MAX_TY-MIN_TY) #define RX (TW*1.0/SW) #define RY (TH*1.0/SH) #define RVX(tx) (TW-((tx)-MIN_TX)) #define RVY(ty) (TH-((ty)-MIN_TY)) 16 #define TX2SX(tx) ((int)(RVX(tx)/RX)) #define TY2SY(ty) ((int)(RVY(ty)/RY)) // 触摸屏坐标 x,y转换到屏幕坐标 void Touch2Screen(int* x,int *y) { *x = TX2SX(*x); *y = TY2SY(*y); } (4)A/D初始化 void AD_init(void) { rCLKCON |= 1<<15; //enable the ADC clock } (5) 启动 A/D采样 void start_adc(unsigned int chanel) { int i; static int prevCh=-1; unsigned int preScaler; preScaler = 50000000/ADC_FREQ -1; rADCCON = (1<<14) | (preScaler<<6) | (chanel<<3); //setup channel rADCCON|=0x1; //start AD convert //while(rADCCON & 0x1); //check if Enable_start is low while(rADCCON & 0x1); //Check if Enable_start is low while(!(0x8000&rADCCON)); //Check ECFLG } (6) 读取 A/D值 unsigned int read_value(void) { unsigned int ad; ad = (unsigned int)rADCDAT0 & 0x3ff; return ad; } 2.42.42.4 2.4 直流/// / 步进电机实验 17 实验原理请参考 ”GEC2410GEC2410GEC2410 GEC2410 实验箱--- - 基础实验”一文及相关的资料。 (1) 电机测试初始化 void InitStepMotorTest(void) { // 步进电机控制口设置 rGPCCON = (rGPCCON & (~0x0000FC03)) | (0x00005401); // GPC0、 GPC5--7口设置为输出 rGPCUP = rGPCUP | 0x00E1; // 禁止 GPC0、GPC5--7口的上 拉电阻 rGPCDAT = rGPCDAT & (~0x00E1); // 设置 GPC0、GPC5--7口输 出低电平 } (2) 直流电机顺指针转动 void dcmotor_clockwise(void) { __raw_writel((__raw_readl(S3C2410_GPGCON) & (~(0x03 << 22))) | (0x01 << 22), S3C2410_GPGCON); // S3C2410_GPBCON[1:0] = 10b,设置 TOUT0功能 __raw_writel(__raw_readl(S3C2410_GPGUP) | (1<<11), S3C2410_GPGUP); // 禁止 TOUT0口的上拉电阻 __raw_writel(__raw_readl(S3C2410_GPGDAT)&(~(1<<11)), C2410_GPGDAT); // 输出 0电平 __raw_writel((__raw_readl(S3C2410_GPHCON) & (~(0x03 << 18))) | (0x01 << 18), S3C2410_GPHCON); // GPH9 __raw_writel(__raw_readl(S3C2410_GPGUP) | (1<<9), S3C2410_GPGUP); __raw_writel(__raw_readl(S3C2410_GPHDAT) | (1 << 9), S3C2410_GPHDAT); // 输出 1电平 } 18 (3) 直流电机逆指针转动 void dcmotor_anti_clockwise(void) { __raw_writel((__raw_readl(S3C2410_GPGCON) & (~(0x03 << 22)))| (0x01 << 22), S3C2410_GPGCON);// S3C2410_GPBCON[1:0] = 10b,设置 TOUT0功能 __raw_writel(__raw_readl(S3C2410_GPGUP) | (1<<11), S3C2410_GPGUP); // 禁止 TOUT0口的上拉电阻 __raw_writel(__raw_readl(S3C2410_GPGDAT) | (1<<11), S3C2410_GPGDAT); // 输出 1电平 __raw_writel((__raw_readl(S3C2410_GPHCON) & (~(0x03 << 18))) | (0x01 << 18), S3C2410_GPHCON); // GPH9 __raw_writel(__raw_readl(S3C2410_GPGUP) | (1<<9), S3C2410_GPGUP); __raw_writel(__raw_readl(S3C2410_GPHDAT) & (~(1 << 9)), S3C2410_GPHDAT); // 输出 0电平 } (4)直流电机停止 void dcmotor_stop(void) { __raw_writel(__raw_readl(S3C2410_GPGCON) & (~(0x03<<22)), S3C2410_GPGCON); //input __raw_writel(__raw_readl(S3C2410_GPGUP) | (1<<11), S3C2410_GPGUP); // 禁止 TOUT0口的上拉电阻 __raw_writel(__raw_readl(S3C2410_GPGDAT) & ( ~(1<<11)), S3C2410_GPGDAT); // 输出 0电平 __raw_writel((__raw_readl(S3C2410_GPHCON) & (~(0x03<<18))) | (0x01<<18), S3C2410_GPHCON); // GPH9 __raw_writel(__raw_readl(S3C2410_GPHUP) | (1<<9), S3C2410_GPHUP); __raw_writel(__raw_readl(S3C2410_GPHDAT) & (~(1<<9)), S3C2410_GPHDAT); // 输出 0电 } (5) 步进电机正转 /***************************************************************** **************************************** ** Function name: MOTO_Mode2 ** Descriptions : 步进电机双四拍运行 , 时序为 AB--BC--CD--DA--AB, 转 20*4步 ** 步距角为 18度,即,转动 80*18度=4*360度,转动 4圈 ** Input : dly, 每一步时延,即步进速度. ** Output: - ** Created Date: 2007-8-2 10:02上午 ****************************************************************** **************************************/ 19 void stepmotor_clockwise(unsigned char dly) { // uint32 i; // for(i=0; i<20; i++) { // AD GPIOSET(MOTOA); GPIOSET(MOTOD); DelayNS1(dly); GPIOCLR(MOTOA); // GPIOCLR(MOTOB); // DB GPIOSET(MOTOD); GPIOSET(MOTOB); DelayNS1(dly); GPIOCLR(MOTOD); // GPIOCLR(MOTOC); // BC GPIOSET(MOTOB); GPIOSET(MOTOC); DelayNS1(dly); GPIOCLR(MOTOB); // GPIOCLR(MOTOD); // CA GPIOSET(MOTOC); GPIOSET(MOTOA); DelayNS1(dly); GPIOCLR(MOTOC); // GPIOCLR(MOTOA); } GPIOCLR(MOTOA); } (6) 步进电机反转 void stepmotor_anti_clockwise(unsigned char dly) { // int i; // for(i=0; i<40; i++) { // DA 20 GPIOSET(MOTOD); GPIOSET(MOTOA); DelayNS(dly); GPIOCLR(MOTOA); // GPIOCLR(MOTOA); // CD GPIOSET(MOTOC); GPIOSET(MOTOD); DelayNS(dly); GPIOCLR(MOTOD); // GPIOCLR(MOTOD); // BC GPIOSET(MOTOB); GPIOSET(MOTOC); DelayNS(dly); GPIOCLR(MOTOC); // GPIOCLR(MOTOC); // AB GPIOSET(MOTOA); GPIOSET(MOTOB); DelayNS(dly); GPIOCLR(MOTOB); // GPIOCLR(MOTOB); } GPIOCLR(MOTOA); } 2.52.52.5 2.5 GPS/GPRSGPS/GPRSGPS/GPRS GPS/GPRS 实验 21 (1) GPS数据包 nmea数据如下: $GPGGA,121252.000,3937.3032,N,11611.6046,E,1,05,2.0,45.9,M,-5.7,M,,0000*77 $GPRMC,121252.000,A,3958.3032,N,11629.6046,E,15.15,359.95,070306,,,A*54 $GPVTG,359.95,T,,M,15.15,N,28.0,K,A*04 $GPGGA,121253.000,3937.3090,N,11611.6057,E,1,06,1.2,44.6,M,-5.7,M,,0000*72 $GPGSA,A,3,14,15,05,22,18,26,,,,,,,2.1,1.2,1.7*3D $GPGSV,3,1,10,18,84,067,23,09,67,067,27,22,49,312,28,15,47,231,30*70 $GPGSV,3,2,10,21,32,199,23,14,25,272,24,05,21,140,32,26,14,070,20*7E $GPGSV,3,3,10,29,07,074,,30,07,163,28*7D 说明:NMEA0183格式以“$”开始,主要语句有GPGGA,GPVTG,GPRMC等 1、 GPS DOP and Active Satellites(GSA)当前卫星信息 22 $GPGSA,<1>,<2>,<3>,<3>,,,,,<3>,<3>,<3>,<4>,<5>,<6>,<7> <1>模式 :M = 手动, A = 自动。 <2>定位型式 1 = 未定位, 2 = 二维定位, 3 = 三维定位。 <3>PRN 数字:01 至 32 表天空使用中的卫星编号,最多可接收12颗卫星信息。 <4> PDOP位置精度因子(0.5~99.9) <5> HDOP水平精度因子(0.5~99.9) <6> VDOP垂直精度因子(0.5~99.9) <7> Checksum.(检查位). 2、 GPS Satellites in View(GSV)可见卫星信息 $GPGSV, <1>,<2>,<3>,<4>,<5>,<6>,<7>,?<4>,<5>,<6>,<7>,<8> <1> GSV语句的总数 <2> 本句GSV的编号 <3> 可见卫星的总数,00 至 12。 <4> 卫星编号, 01 至 32。 <5>卫星仰角, 00 至 90 度。 <6>卫星方位角, 000 至 359 度。实际值。 <7>讯号噪声比(C/No), 00 至 99 dB;无表未接收到讯号。 <8>Checksum.(检查位). 第<4>,<5>,<6>,<7>项个别卫星会重复出现,每行最多有四颗卫星。其余卫星信息会于次一行出 现,若未使用,这些字段会空白。 3、Global Positioning System Fix Data(GGA)GPS定位信息 $GPGGA,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,M,<10>,M,<11>,<12>*hh <1> UTC时间,hhmmss(时分秒)格式 <2> 纬度ddmm.mmmm(度分)格式(前面的0也将被传输) <3> 纬度半球N(北半球)或S(南半球) <4> 经度dddmm.mmmm(度分)格式(前面的0也将被传输) <5> 经度半球E(东经)或W(西经) <6> GPS状态:0=未定位,1=非差分定位,2=差分定位,6=正在估算 <7> 正在使用解算位置的卫星数量(00~12)(前面的0也将被传输) <8> HDOP水平精度因子(0.5~99.9) <9> 海拔高度(-9999.9~99999.9) <10> 地球椭球面相对大地水准面的高度 <11> 差分时间(从最近一次接收到差分信号开始的秒数,如果不是差分定位将为空) <12> 差分站ID号0000~1023(前面的0也将被传输,如果不是差分定位将为空) 4、Recommended Minimum Specific GPS/TRANSIT Data(RMC)推荐定位信息 $GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,<12>*hh <1> UTC时间,hhmmss(时分秒)格式 <2> 定位状态,A=有效定位,V=无效定位 <3> 纬度ddmm.mmmm(度分)格式(前面的0也将被传输) <4> 纬度半球N(北半球)或S(南半球) <5> 经度dddmm.mmmm(度分)格式(前面的0也将被传输) <6> 经度半球E(东经)或W(西经) <7> 地面速率(000.0~999.9节,前面的0也将被传输) <8> 地面航向(000.0~359.9度,以真北为参考基准,前面的0也将被传输) 23 <9> UTC日期,ddmmyy(日月年)格式 <10> 磁偏角(000.0~180.0度,前面的0也将被传输) <11> 磁偏角方向,E(东)或W(西) <12> 模式指示(仅NMEA0183 3.00版本输出,A=自主定位,D=差分,E=估算,N=数据无效) 5、 Track Made Good and Ground Speed(VTG)地面速度信息 $GPVTG,<1>,T,<2>,M,<3>,N,<4>,K,<5>*hh <1> 以真北为参考基准的地面航向(000~359度,前面的0也将被传输) <2> 以磁北为参考基准的地面航向(000~359度,前面的0也将被传输) <3> 地面速率(000.0~999.9节,前面的0也将被传输) <4> 地面速率(0000.0~1851.8公里/小时,前面的0也将被传输) <5> 模式指示(仅NMEA0183 3.00版本输出,A=自主定位,D=差分,E=估算,N=数据无效) GPGGA GPS固定数据输出语句($GPGGA) 这是一帧GPS定位的主要数据,也是使用最广的数据。 $GPGGA 语句包括17个字段:语句标识头,世界时间,纬度,纬度半球,经度,经度半球,定位 质量指示,使用卫星数量,水平精确度,海拔高度,高度单位,大地水准面高度,高度单位,差 分GPS数据期限,差分参考基站标号,校验和结束标记(用回车符和换行符),分别用14 个逗号进行分隔。该数据帧的结构及各字段释义如下: $GPGGA,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,M,<10>,M,<11>,<12>*xx $GPGGA:起始引导符及语句格式说明(本句为GPS定位数据); <1> UTC时间,格式为hhmmss.sss; <2> 纬度,格式为ddmm.mmmm(第一位是零也将传送); <3> 纬度半球,N或S(北纬或南纬) <4> 经度,格式为dddmm.mmmm(第一位零也将传送); <5> 经度半球,E或W(东经或西经) <6> 定位质量指示,0=定位无效,1=定位有效; <7> 使用卫星数量,从00到12(第一个零也将传送) <8> 水平精确度,0.5到99.9 <9> 天线离海平面的高度,-9999.9到9999.9米 M 指单位米 <10> 大地水准面高度,-9999.9到9999.9米 M 指单位米 <11> 差分GPS数据期限(RTCM SC-104),最后设立RTCM传送的秒数量 <12> 差分参考基站标号,从0000到1023(首位0也将传送)。 * 语句结束标志符 xx 从$开始到*之间的所有ASCII码的异或校验和 回车 换行 (2) GPS实验对$GPGGA包进行解析,如 $GPGGA,121252.000,3937.3032,N,11611.6046,E,1,05,2.0,45.9,M,-5.7,M,,0000*77 (3) 输入电话号码如 02032461234,或者 15960241234 可拨打电话 发送短信时候,要加 106或者 86,如 10602032461234,或者 8615960241234 (4) 常用 AT命令 24 下面我们列举一些常用的 AT指令: (5) 发送中文短信实例 这是用串口调试助手成功发送的中文短信息完整过程,短信中心号码:13800513500 短信接收 方号码:13306285091 短信内容:晚上好 123 红色表示发送的内容,蓝色表示接收到的数据, 黑色表示备注。 AT(回车)通讯握手 OK A
本文档为【GEC2410B实验箱教学平台-uCOS教程】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_137875
暂无简介~
格式:pdf
大小:1MB
软件:PDF阅读器
页数:49
分类:互联网
上传时间:2011-10-16
浏览量:24