课程设计(论文)-基于实时操作系统的单片机多任务应用程序设计.doc_第1页
课程设计(论文)-基于实时操作系统的单片机多任务应用程序设计.doc_第2页
课程设计(论文)-基于实时操作系统的单片机多任务应用程序设计.doc_第3页
课程设计(论文)-基于实时操作系统的单片机多任务应用程序设计.doc_第4页
课程设计(论文)-基于实时操作系统的单片机多任务应用程序设计.doc_第5页
免费预览已结束,剩余23页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

重庆科技学院重庆科技学院 课程设计报告课程设计报告 院(系):_电气与信息工程学院_ 专业班级: 计科普 2008-02 学生姓名: 学 号: 设计地点(单位)_ _ i515_ _ _ 设计题目:_ 基于实时操作系统的单片机多任务应用程序设计_ 完成日期: 2011 年 7 月 4 日 指导教师评语: _ _ _ _ _ _ _ _ 成绩(五级记分制):_ _ _ 指导教师(签字):_ _ _ 重庆科技学院重庆科技学院 课程设计任务书课程设计任务书 设计题目:基于实时操作系统的单片机多任务应用程序设计 学生姓名 课程名称 实时操作系统 (ucos-ii) 专业班级计科普 2008 地 点 i313 起止时间2011 年 6 月 27 日-2011 年 7 月 8 日 设 计 内 容 及 要 求 1、 充分消化 ucos-ii 内核,理解其内核架构。体会相关数据结构的设计。 2、 在第 1 步的基础上,消化 small rtos51 内核。弄清其为了实现在 128 个字节的 单片机环境下在内核的数据结构做了如何优化设计。 3、 将 small rtos51 移植到 mcs-51 单片机的最小系统板上,使在上面进行正常运 行。 4、 基于 small rtos51 平台的 mcs-51 单片机上,编写: (1)led 显示驱动程序。 (2)键盘扫描驱动程序。 (3)串口通信接收和发送驱动程序 5、 在前面的基础上完成一个基于 small rtos51 的多任务应用程序,并在 mcs-51 最小系统板上调试通过。 设 计 参 数 1、 写出 ucos-ii 内核的架构 2、 比较 small rtos 与 ucos-ii 实时操作系统的异同,及各自优缺点。 3、 实现 small rtos 在 mcs-51 最小系统板上的移植,写清移植原理和步骤。 4、 至少实现设计要求中的三个驱动程序中的二个及以上。 5、 结合自已在课程中、平时或竞赛中涉及的题目,改用基于 small rtos 进行 实现(系统必须实现的多任务应用程序在 mcs-51 上应能稳定的运行) 。 进 度 要 求 6 月 27 完成 ucos-ii 内核架构剖析,6 月 27 日-29 日完成 small rtos51 内核的分 析。6 月 30 日完成 small rtos51 向 mcs-51 单片机最小系统板的移植。7 月 1 日-7 月 2 日完成相关驱动程序的编写和调试。7 月 3 日-7 月 6 日完成相应在多任务应用 程序的编写,并集成到 mcs-51 最小系统板上,使其稳定运行。7 月 7 日设计志成果 汇报和答辩。7 月 8 日完成设计报告。 参 考 资 料 其 它 说 明 .本表应在每次实施前一周由负责教师填写二份,院系审批后交院系办备案,一 份由负责教师留用。.若填写内容较多可另纸附后。 3.一题多名学生共用的,在设计内容、参数、要求等方面应有所区别。 教研室主任: 指导教师: 年 月 日 i 摘要 嵌入式系统是软件和硬件的综合体,嵌入式系统是与应用紧密结合的,具 有很强专用性,必须结合实际系统需求进行合理的裁减利用。 本设计任务是基于实时操作系统的单片机多任务应用程序设计。通过深入 剖析 c/os-内核架构,之后理解和读懂 small rtos 微型嵌入式操作系统的 内核。实现多任务的驱动程序,实现 led 驱动、串口驱动和键盘驱动。 关键词:嵌入式系统 实时 多任务 驱动 ii 目目 录录 1 系统需求分析1 1.1 设计内容与目的 .1 1.2 设计的实现方案.1 2.总体设计2 2.1 设计模块图.2 2.2 ucos-ii 内核架构 .2 2.3 small rtos 与uc/os-ii 的异同5 2.4 small rtos 移植到单片机5 2.4 small rtos 驱动程序9 3 详细设计10 3.1led 驱动程序 .10 3.2 键盘驱动程序 .14 3.3 串口收发驱动程序 .17 3.4 功能实现 20 4. 设计总结21 5 致谢22 6 参考文献23 1 1 1 系统需求分析系统需求分析 1.1 设计内容与目的 本课程完成的主要内容有:本课程完成的主要内容有: (1)写出 c/os-内核的架构。 (2)比较 small rtos 与 c/os-实时操作系统的异同,及各自优缺点。 (3)实现 small rtos 在 mcs-51 最小系统板上的移植,写清移植原理和步骤。 (4)至少实现设计要求中的三个驱动程序中的二个及以上。 本课程设计的目的是:本课程设计的目的是: 通过该课程设计学习,深入理解嵌入式操作系统的作用,c/os-内核 的架构。深入理解 small rtos 内核架构,学会移植 small rtos 到单片机上, 并在单片机上运行应用程序。 1.2 设计的实现方案 本设计在 51 单片机上移植小系统,并且在小系统上编写多任务驱动程序。 驱动程序包括:led 驱动、串口驱动和键盘驱动。 驱动的设计可以用多任务实现,这样可以让系统更加稳定,减少开发时间。 2 2.2.总体设计总体设计 2.1 设计模块图 该设计的功能模块如下图所示: 微型操作系统 small rtos 移植 small rtos 到 51 单片机上 编写 led 驱动 程序 编 写 键盘 驱动 程序 编 写 串 口 收 发 程 序 图 2.1 功能模块图 2.2 ucos-ii 内核架构 作为一个轻量级的操作系统,c/os-提供的功能包括:任务管理、中断 管理、时间管理、信号量、邮箱、消息队列、互斥信号量等,可基本满足较小 系统的需要。c/os-内核支持优先级调度算法,每个任务可根据重要程度的 不同被赋予一定的优先级,cpu 总是让处于就绪态的、优先级最高的任务先运 行。 c/os-的实时内核都是可剥夺型内核。最高优先级的任务一旦就绪,总 能得到 cpu 的控制权。当一个运行着的任务使一个比它优先级高的任务进入了 就绪态,当前任务的 cpu 使用权就被剥夺了,或者说被挂起了,那个高优先级 3 的任务立刻得到了 cpu 的控制权。如果是中断服务子程序使一个高优先级的任 务进入就绪态,中断完成时,中断了的任务被挂起,优先级高的那个任务开始 运行。 1.c/os-1.c/os-的特点的特点 可移植性可移植性 c/os-绝大部分的源码是用移植性很强的 ansi c 写的。和微处理器硬件相 关的那部分是用汇编语言写的。汇编语言写的部分已经压到最低限度,使得 c/os-便于移植到其他微处理器上。 可裁剪可裁剪 可以只使用 c/os-中应用程序需要的那些系统服务。这样可以减少产品 中的 c/os-所需的存储空间(ram 和 rom),这种可裁剪性是靠条件编译实 现的。 占先式占先式 c/os-完全是占先式的实时内核。这意味着 c/os-总是运行就绪条 件下任务级最高的任务。 多任务多任务 c/os-最多只能管理 64 个任务,包括空闲任务和统计任务。同时赋予 每个任务的优先级必须是不同的,c/os-不支持时间片轮转法。 任务栈任务栈 每个任务有自己单独的栈,c/os-允许每个任务有不同的栈空间。以便 压低应用程序对 ram 的需求。 系统服务系统服务 c/os-提供一些系统服务,例如消息队列、信号量、互斥信号量、时间 相关函数等。 中断管理中断管理 中断可以使正在执行的任务暂时挂起。如果优先级更高的任务被该中断唤 醒,则高优先级的任务在中断嵌套全部退出后立即执行,中断嵌套层数可达 255 层。 4 实时性实时性 c/os-对实时任务有很强的支持能力,能完成多任务并且有较短的中断 响应时间,从而使内部的代码和实时内核心的执行时间减少到最低限度。 2.uc/os-ii2.uc/os-ii 组成部分组成部分 uc/os-ii 大致可以分成系统核心(包含任务调度)、任务管理、时间管理、 多任务同步与通信、内存管理、cpu 移植等部分。 (1) 核心部分(oscore.c) :uc/os-ii 处理核心,包括初始化、启动、中断 管理、时钟中断、任务调度及事件处理等用于系统基本维持的函数。 (2) 任务管理(ostask.c) :包含与任务操作密切相关的函数,包括任务建 立、删除、挂起及恢复等,uc/os ii 以任务为基本单位进行调度。 (3) 时钟部分(ostime.c) :uc/os-ii 中最小时钟单位是 timetick(时钟节 拍),其中包含时间延迟、时钟设置及时钟恢复等与时钟相关的函数。 (4) 多任务同步与通信(osmbox.c, osq.c, ossem.c, osmutex.c, osflag.c): 包含事件管理函数,涉及 mbox、msgq、sem、mutex、flag 等。 (5) 内存管理部分(osmem.c):主要用于构建私有的内存分区管理机制,其 中包含创建 mempart、申请/释放 mempart、获取分区信息等函数。 (6) cpu 接口部分:uc/os-ii 针对特定 cpu 的移植部分,由于牵涉到 sp 等系统指针,通常用汇编语言编写,包括任务切换、中断处理等内容。 3.uc/os-ii 任务调度任务调度 uc/os-ii 采用基于优先级的调度算法,总是选择当前处于就绪状态的优先 级最高的任务进行调度。uc/os-ii 是可抢占性的强实时性 os,在完成中断后允 许进行新的任务调度。 uc/os-ii 有两种调度方式:任务级任务调度、中断级任务调度。有两种调度方式:任务级任务调度、中断级任务调度。 (1)任务级任务调度 指在非中断返回时进行任务调度,一般发生在当前任务因时间延迟或等待 某事件而阻塞或被挂起,或有更高优先级的任务处于就绪状态。 任务的基本信息: cpu 的 pc 寄存器:任务当前执行的位置; cpu 的通用寄存器:任务当前执行涉及的临时数据; 5 cpu 的状态寄存器:存储当前 cpu 的状态。 任务级任务切换:从一个任务直接切换至另一个任务,不涉及 cpu 状态的 切换,os_task_sw()既保存当前任务上下文,又恢复新任务上下文。 过程:os_sched()- os_task_sw() (2)中断级任务调度 在中断处理完成后,通过 osintexit()判断是否有更高优先级就绪任务。如果 有,调用 osintctxsw()恢复新任务上下文。在中断处理中,已经保存了被中断 任务的上下文,所以这里仅仅恢复。 过程:osintext() osintenter() - isr osintexit() - osintctxsw() 2.3 small rtos 与uc/os-ii的异同 1.small rtos 和 uc/os-ii 的相同点有: (1)都是抢占式微型操作系统。 (2)调度算法都是基于优先级的调度算法。 (3)两种调度方式:任务级别任务调度和中断级别任务调度。 (4)任务间可以进行消息通信。 (5)可以实现调度器上锁和解锁。 (6)具有空闲任务,并且空闲任务优先级最低。 2. small rtos 和 uc/os-ii 的不同点有: (1) uc/os-ii 最多可以管理 64 个任务,而 small rtos 最多只能管理 16 个任务。 (2) uc/os-ii 可以删除任务,而 small rtos 不能删除任务。 (3) uc/os-ii 每个任务拥有独立的堆栈,而 small rtos 共享堆栈。 (4) uc/os-ii 有邮箱通信方式,而 small rtos 没有。 2.4 small rtos 移植到单片机 small rtos的移植步骤和方法如下: 6 (1) 在os_cpu.h中定义几个宏(以keil c51为例): #define os_int_enter() osintnesting+ /* 中断嵌套管理 */ #define os_enter_critical() ea = 0,os_enter_sum+ /* 关中断*/ #define os_exit_critical() if (-os_enter_sum=0) ea = 1 #define high_byte 0 /* uint16的高位字节 */ #define low_byte 1 /* uint16的低位字节 */ #define os_task_sw() osctxsw() /* 任务切换函数 */ os_enter_critical()、os_exit_critical()分别定义为关中断和开 中断在特定的c编译器的表示方法。 high_byte、low_byte定义uint16型变量在特定的c编译器的存储方法, 如果高位字节的地址小于低位字节的地址(如keil c51) ,则 high_byte为0,low_byte为1。否则(如8086系列) ,high_byte为1, low_byte为0。 os_int_enter则将变量osintnesting加1。它仅在中断服务程序中使用。 注意:如果中断嵌套层数可能超过255,os_int_enter要防止 osintnesting溢出。 os_task_sw()定义非中断中任务切换时执行的指令,可以是一条软中断指 令(例如在8086系列cpu上) ,或仅仅是函数调用(如keil c51) 。 (2)定义与编译器无关的变量类型(以keil c51为例): typedef unsigned char uint8; /* 定义可移植的无符号8位整数关键字 */ typedef signed char int8; /* 定义可移植的有符号8位整数关键字 */ typedef unsigned int uint16; /* 定义可移植的无符号16位整数关键字 */ typedef signed int int16; /* 定义可移植的有符号16位整数关键字 */ typedef unsigned long uint32; /* 定义可移植的无符号32位整数关键字 */ 7 typedef signed long int32; /* 定义可移植的有符号32位整数关键字 */ (3)在os_cpu_c.c和os_cpu_a.asm中定义几个函数: osstart、osintctxsw、ostickisr、osidle和os_task_sw()最终调用的 函数或中断。 osstart:初始化任务并让id为0的任务执行。同时允许中断。 定义如下: void osstart(void) 初始化除id为0以外所有任务堆栈; ostaskid = 0; 使堆栈指针指向id为0的任务堆栈空间; os_exit_critical(); 使程序指针指向id为0的任务的程序首地址; osintctxsw:中断中任务切换函数 定义如下: void osintctxsw(void) 堆栈指针调整为中断程序调用osintexit前的状态; 堆栈空间变换; 堆栈指针指向新的堆栈; ostaskid = osnexttaskid; 恢复任务环境; 中断返回指令; osintctxsw由osintexit直接调用,堆栈指针调整为中断程序调用 osintexit前的状态即为执行若干出栈指令。 堆栈空间变换可以参照keilc51目录下os_cpu_c.c文件中被注释的 8 c_osctxsw函数,c_osctxsw还包括 堆栈指针指向新的堆栈. ostickisr为系统节拍中断服务程序 定义如下: void ostickisr(void) #if tick_timer_sharing 1 static unsigned char ticksum=0; #endif 禁止中断; 保存任务环境; #if tick_timer_sharing 1 ticksum = (ticksum + 1) % tick_timer_sharing; if (ticksum != 0) 允许中断; 恢复任务环境; return; #endif #if en_os_int_enter 0 os_int_enter(); /* 中断开始处理 #endif 允许中断; #if user_tick_timer_en = 1 userticktimer(); /* 用户函数 #endif #if en_timer_sharing 0 9 ostimetick(); /* 调用系统时钟处理函数 #else osintsendsignal(time_isr_task_id); #endif osintexit(); /* 中断结束处理 其中有一些cpu的禁止中断和保存任务环境由cpu自动处理或是自动处 理一部分。 osidle()优先级最低的任务 定义如下: void osidle(void) while(1) /* 使cpu处于省电状态 */ os_task_sw()最终调用的函数或中断:非中断中任务切换函数 定义如下: void os_task_sw(void) 保存任务环境; 堆栈空间变换; 堆栈指针指向新的堆栈; ostaskid = osnexttaskid; 恢复任务环境; 恢复程序指针; 2.5 small rtos 驱动程序 small rtos 的驱动包括:led 驱动、键盘驱动、串口收发驱动。用系统的 10 多任务实现。 11 3 3 详细设计详细设计 3.1led 驱动程序 程序具有两个用户任务:一个显示任务(show) ;另一个是计时任务 (timesum) 。由于显示器需要 cpu 周期为其服务,所以必须使用任务来编写程 序。 void show(void) uint8 i,keytemp; /* 初始化显示缓冲区 */ showcase0 = showtable10; showcase1 = showtable10; showcase2 = showtable10; showcase3 = showtable10; while (1) for (i = 0; i = 10) timeadd3 = 0; timeadd2+; if (timeadd2 = 6) timeadd2 = 0; timeadd1+; if (timeadd1 = 10) timeadd1 = 0; timeadd0+; if(timeadd0 = 10) timeadd0 = 0; showcase0 = showtabletimeadd0; showcase1 = showtabletimeadd1; showcase2 = showtabletimeadd2; showcase3 = showtabletimeadd3; 15 计时寄存器 timeadd0为分的十位,范围为 0-9;计时寄存器 timeadd1 为分的个数,范围为 0-9;计时寄存器 timeadd2为秒得十位,范围为 0-5; 计时寄存器 timeadd3为秒的个数,范围为 0-9。 开始 点亮两个发光二 极管 延时 0.5 秒 熄灭所有发光二 极管 延时 0.5 秒 计时寄存器加一 显示当前计时值 图 3.1.2:计时任务流程图 3.2 键盘驱动程序 void keyinput(void) uint8 i; uint8 temp; osqcreate(commanddata,16); /* 创建主任务使用的消息队列 while (1) oswait(k_tmo,(os_ticks_per_sec / 50) + 1); /* 延时 20ms */ temp = keyscan(); /* 获取闭合按键位图 */ 16 if (temp = no_key) continue; oswait(k_tmo,os_ticks_per_sec / 50); /* 去抖(延时 20ms)*/ if (temp != keyscan() continue; key(temp,key_down); /* 处理按键闭合事件 */ /* 第一次连击延时 */ i = key_start / (os_ticks_per_sec / 50); do oswait(k_tmo,os_ticks_per_sec / 50); if (temp != keyscan() goto keyend; /* 按键松开 */ while (-i != 0); * 后续连击延时 */ while (1) key(temp,key_always); :/* 处理按键连击事件 */ i = key_delay / (os_ticks_per_sec / 50); do oswait(k_tmo,os_ticks_per_sec / 50); if (temp != keyscan() goto keyend; /* 按键松开 */ while (-i != 0); keyend: key(temp,key_up); /* 处理按键松开事件 */ 17 开始 初始化键盘消息的 消息队列 延时 20ms 有键按下 延时 20ms 与上次按键相同 发送 key_down 消息 等待 key_start 个时钟节 拍 与上次按键相同 发送 key_up 消息 等待 key_delay 个时 钟节拍 发送 key_up 消 息 y n ny yn 图 3.2.1 键盘任务程序流程图 uint8 keyscan(void) return keyborddata; keyscan()只需返回键盘瞬间状态,只要按照硬件的要求扫描键盘,把信息存 入返回值即可。 18 消息处理任务:消息处理任务: void command(void) uint8 data temp; while (1) osqpend( /* 等待键盘的消息 */ /* 显示得到的消息 */ showcase0 = showtable10; showcase1 = showtable10; showcase2 = showtable10; showcase3 = showtabletemp % 10; if (temp = 10) showcase2 = showtable(temp / 10) % 10; if (temp = 100) showcase1 = showtabletemp / 100; 程序分析如下: 任务挂起等待按键消息的到来,如果有按键消息到了,该任务运行,并且将键 值显示在 led 上。 3.3 串口收发驱动程序 1.串口发送部分: (1)发送一个字节:putchar void putchar(uint8 data) os_enter_critical(); if (serialcansend = 1) serialcansend = 0; sbuf = data; else osqintpost(serialoutdata,data); os_exit_critical(); 19 程序分析: 函数中使用一个全局变量 serialcansend,用来指示当前串口的发送部分是否空 闲。如果串口的发送部分不空闲,就直接将数据加入消息队列。用 osqintpos()发送消息是因为这个消息队列的唯一接受者是中断,发送消息不 会产生任务调度,osqintpost()不会产生不必要的任务调度。 (2)串口发送中断 #if en_os_int_enter 0 #pragma disable #endif void comm(void) interrupt 4 uint8 data temp; if (ri = 1) #if en_os_int_enter 0 os_int_enter(); #endif ri = 0; osqintpost(serialindata,sbuf); osintexit(); return; if (ti = 1) ti = 0; if (osqaccept( else serialcansend = 1; 程序分析: 首先判断是否为发送中断;若是,则首先清除发送中断标志,然后判断消 息队列是否有消息。如果消息队列中有消息,则将数据发送出去;如果消息队 列中没有消息,则将全局变量 serialcansend 置 1,以表示串口空闲。程序需 20 要判断当前是否处于发送状态,若是则这样处理;否则退出,不管消息队列中 是否有消息。同时,在串口由接收状态转为发送状态时,需要将 ti 置 1,以产 生串口发送中断。 2 2 串口接收部分:串口接收部分: 串口接收处理任务: void recuve(void) uint8 data temp,temp1; uint8 sum; /* 建立所需要的消息队列 */ osqcreate(commanddata,16); osqcre

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论