基于uCOS-II的时钟设计
转:一步一步教你使用uCOS-II
转:⼀步⼀步教你使⽤uCOS-II第⼀篇 UCOS介绍第⼀篇 UCOS介绍这个⼤家都知道。
呵呵。
考虑到咱们学习的完整性还是在这⾥唠叨⼀下。
让⼤家再熟悉⼀下。
⾼⼿们忍耐⼀下吧! uC/OS II(Micro Control Operation System Two)是⼀个可以基于ROM运⾏的、可裁减的、抢占式、实时多任务内核,具有⾼度可移植性,特别适合于微处理器和控制器,是和很多商业操作系统性能相当的实时操作系统(RTOS)。
为了提供最好的移植性能,uC/OS II最⼤程度上使⽤ANSI C语⾔进⾏开发,并且已经移植到近40多种处理器体系上,涵盖了从8位到64位各种CPU(包括DSP)。
uC/OS II可以简单的视为⼀个多任务调度器,在这个任务调度器之上完善并添加了和多任务操作系统相关的系统服务,如信号量、邮箱等。
其主要特点有公开源代码,代码结构清晰、明了,注释详尽,组织有条理,可移植性好,可裁剪,可固化。
内核属于抢占式,最多可以管理60个任务。
µC/OS-II 的前⾝是µC/OS,最早出⾃于1992 年美国嵌⼊式系统专家Jean brosse 在《嵌⼊式系统编程》杂志的5 ⽉和6 ⽉刊上刊登的⽂章连载,并把µC/OS 的源码发布在该杂志的B B S 上。
µC/OS 和µC/OS-II 是专门为计算机的嵌⼊式应⽤设计的,绝⼤部分代码是⽤C语⾔编写的。
CPU 硬件相关部分是⽤汇编语⾔编写的、总量约200⾏的汇编语⾔部分被压缩到最低限度,为的是便于移植到任何⼀种其它的CPU 上。
⽤户只要有标准的ANSI 的C交叉编译器,有汇编器、连接器等软件⼯具,就可以将µC/OS-II嵌⼈到开发的产品中。
µC/OS-II 具有执⾏效率⾼、占⽤空间⼩、实时性能优良和可扩展性强等特点,最⼩内核可编译⾄ 2KB 。
µC/OS-II 已经移植到了⼏乎所有知名的CPU 上。
ucosii中文书邵贝贝
u c o s i i中文书邵贝贝集团标准化工作小组 [Q8QX9QT-X8QQB8Q8-NQ8QJ8-M8QMN]第5章时间管理在节时钟节拍中曾提到,μC/OS-Ⅱ(其它内核也一样)要求用户提供定时中断来实现延时与超时控制等功能。
这个定时中断叫做时钟节拍,它应该每秒发生10至100次。
时钟节拍的实际频率是由用户的应用程序决定的。
时钟节拍的频率越高,系统的负荷就越重。
节讨论了时钟的中断服务子程序和节时钟节函数OSTimeTick——该函数用于通知μC/OS-Ⅱ发生了时钟节拍中断。
本章主要讲述五个与时钟节拍有关的系统服务:OSTimeDly()OSTimeDlyHMSM()OSTimeDlyResume()OSTimeGet()OSTimeSet()本章所提到的函数可以在文件中找到。
5.0任务延时函数,OSTimeDly()μC/OS-Ⅱ提供了这样一个系统服务:申请该服务的任务可以延时一段时间,这段时间的长短是用时钟节拍的数目来确定的。
实现这个系统服务的函数叫做OSTimeDly()。
调用该函数会使μC/OS-Ⅱ进行一次任务调度,并且执行下一个优先级最高的就绪态任务。
任务调用OSTimeDly()后,一旦规定的时间期满或者有其它的任务通过调用OSTimeDlyResume()取消了延时,它就会马上进入就绪状态。
注意,只有当该任务在所有就绪任务中具有最高的优先级时,它才会立即运行。
程序清单所示的是任务延时函数OSTimeDly()的代码。
用户的应用程序是通过提供延时的时钟节拍数——一个1 到65535之间的数,来调用该函数的。
如果用户指定0值[(1)],则表明用户不想延时任务,函数会立即返回到调用者。
非0值会使得任务延时函数OSTimeDly()将当前任务从就绪表中移除[(2)]。
接着,这个延时节拍数会被保存在当前任务的OS_TCB中[(3)],并且通过OSTimeTick()每隔一个时钟节拍就减少一个延时节拍数。
第3章 μCOS-II的中断和时钟
cpu_sr = get_processor_psw();
disable_interrupts(); /* 处理临界代码*/ set_processor_psw(cpu_sr);
}
3.2 uC/OS-II的时钟
• 任何操作系统都要提供一个周期性的信号源,以供系统处理诸如 延时、超时等与时间有关的事件,这个周期性的信号源叫做时钟。 • 与大多数计算机系统一样,用硬件定时器产生一个周期为毫秒级 的周期性中断来实现系统时钟。最小的时钟单位就是两次中断之 间间隔的时间,这个最小时钟单位叫做时钟节拍。 • 硬件定时器以时钟节拍为周期定时的产生中断,该中断的中断服 务程序叫做OSTickISR(),中断服务程序通过调用函数 OSTimeTick()来完成系统在每个时钟节拍时需要做的工作。
为记录中断嵌套的层数 , μ C/OS-II内核定义 了一个全局变量 OSIntNesting。
NO
}
OSIntNesting++; } }
NO
任务是被中断的任务?
返回中断服务程序
if(OSIntNesting > 0){
NO 获得任务TCB的指针
OSIntNesting--;
执行中断级任务切换
这个函数在中断嵌套层数 计数器为0、调度器未被锁 定且从任务就绪表中查找 到的最高级就绪任务又不 是被中断的任务的条件下 将要进行任务切换,否则 就返回被中断的任务程序
C/OS节拍率最好选在10→100次/秒。 必须在多任务系统启动OSStart()以后,再开启时钟节拍器。
13
3.2.1 时钟节拍中断服务子程序
程序清单 : 时钟节拍中断服务子程序的示意代码
void OSTickISR(void) { 保存CPU寄存器; 调用OSIntEnter(); if(OSIntNesting == 1) { OSTCBCur -> OSTCBStkPtr = SP; } 调用OSTimeTick(); 清除中断; 开中断; 调用OSIntExit(); 恢复CPU寄存器; 执行中断返回指令; } // 记录中断嵌套层数
毕业设计(论文)-基于单片机多功能电子时钟的设计与仿真(含程序仿真)[管理资料]
程序仿真等全套设计,联系153893706第1章绪论二十一世纪的今天,最具代表性的计时产品就是电子万年历,它是近代世界钟表业界的第三次革命。
第一次是摆和摆轮游丝的发明,相对稳定的机械振荡频率源使钟表的走时差从分级缩小到秒级,代表性的产品就是带有摆或摆轮游丝的机械钟或表。
第二次革命是石英晶体振荡器的应用,发明了走时精度更高的石英电子钟表,使钟表的走时月差从分级缩小到秒级。
第三次革命就是单片机数码计时技术的应用(电子万年历),使计时产品的走时日差从分级缩小到1/600万秒,从原有传统指针计时的方式发展为人们日常更为熟悉的夜光数字显示方式,直观明了,并增加了全自动日期、星期、温度以及其他日常附属信息的显示功能,它更符合消费者的生活需求!因此,电子万年历的出现带来了钟表计时业界跨跃性的进步……我国生产的电子万年历有很多种,总体上来说以研究多功能电子万年历为主,使万年历除了原有的显示时间,日期等基本功能外,还具有闹铃,报警等功能。
商家生产的电子万年历更从质量,价格,实用上考虑,不断的改进电子万年历的设计,使其更加的具有市场。
本设计为软件,硬件相结合的一组设计。
在软件设计过程中,应对硬件部分有相关了解,这样有助于对设计题目的更深了解,有助于软件设计。
基本的要了解一些主要器件的基本功能和作用。
除了采用集成化的时钟芯片外,还有采用MCU的方案,利用AT89系列单片微机制成万年历电路,采用软件和硬件结合的方法,控制LED数码管输出,分别用来显示年、月、日、时、分、秒,其最大特点是:硬件电路简单,安装方便易于实现,软件设计独特,可靠。
AT89C52是由ATMEL公司推出的一种小型单片机。
95年出现在中国市场。
其主要特点为采用Flash存贮器技术,降低了制造成本,其软件、硬件与MCS-51完全兼容,可以很快被中国广大用户接受。
本文介绍了基于AT89C52单片机设计的电子万年历。
选题背景及研究的目的与意义设计的目的电子钟已成为人们日常生活中必不可少的物品,广泛用于个人家庭以及车站码头、剧院、办公室等公共场所,给人们的生活、学习、工作、娱乐带来了极大的方便。
北航ARM9实验报告:实验3uCOS-II实验
北航ARM9实验报告:实验3uCOS-II实验北航 ARM9 实验报告:实验 3uCOSII 实验一、实验目的本次实验的主要目的是深入了解和掌握 uCOSII 实时操作系统在ARM9 平台上的移植和应用。
通过实际操作,熟悉 uCOSII 的任务管理、内存管理、中断处理等核心机制,提高对实时操作系统的理解和应用能力,为后续的嵌入式系统开发打下坚实的基础。
二、实验环境1、硬件环境:ARM9 开发板、PC 机。
2、软件环境:Keil MDK 集成开发环境、uCOSII 源代码。
三、实验原理uCOSII 是一个可裁剪、可剥夺型的多任务实时内核,具有执行效率高、占用空间小、实时性能优良和可扩展性强等特点。
其基本原理包括任务管理、任务调度、时间管理、内存管理和中断管理等。
任务管理:uCOSII 中的任务是一个独立的执行流,每个任务都有自己的堆栈空间和任务控制块(TCB)。
任务可以处于就绪、运行、等待、挂起等状态。
任务调度:采用基于优先级的抢占式调度算法,始终让优先级最高的就绪任务运行。
时间管理:通过系统时钟节拍来实现任务的延时和定时功能。
内存管理:提供了简单的内存分区管理和内存块管理机制。
中断管理:支持中断嵌套,在中断服务程序中可以进行任务切换。
四、实验步骤1、建立工程在 Keil MDK 中创建一个新的工程,选择对应的 ARM9 芯片型号,并配置相关的编译选项。
2、导入 uCOSII 源代码将 uCOSII 的源代码导入到工程中,并对相关的文件进行配置,如设置任务堆栈大小、系统时钟节拍频率等。
3、编写任务函数根据实验要求,编写多个任务函数,每个任务实现不同的功能。
4、创建任务在主函数中使用 uCOSII 提供的 API 函数创建任务,并设置任务的优先级。
5、启动操作系统调用 uCOSII 的启动函数,使操作系统开始运行,进行任务调度。
6、调试与测试通过单步调试、查看变量值和输出信息等方式,对系统的运行情况进行调试和测试,确保任务的执行符合预期。
基于uCOS_II的以太网移植实例
基于μC/OS_II的以太网移植实例目录第一章以太网移植准备工作 (2)1.1 硬件平台 (2)1.2 软件平台 (2)第二章以太网移植步骤 (4)2.1 文件结构以及文件说明 (4)2.2以太网文件移植 (5)2.3MDK中文件的导入 (5)2.4 程序中需要编辑的代码 (8)第三章以太网任务创建以及初始化流程 (11)3.1 以太网任务创建 (11)3.2 以太网初始化流程 (12)3.3 以太网数据收发流程 (12)第四章测试以太网连接以及任务间通信 (14)4.1Ping命令测试 (14)4.2 网络调试助手测试 (14)第一章以太网移植准备工作以移动基站的电表管理系统为背景,探讨基于μC/OS嵌入式系统的以太网移植方法。
移动基站电表管理系统终端的基本功能就是上位机通过以太网发送命令或数据给终端,终端收到后,再通过485通信对电表执行相应的动作,最后,终端把得到的信息处理后再次通过以太网上传回来。
这里重点是把以太网协议栈移植到程序中来,以创建一个以太网通信任务。
1.1 硬件平台硬件平台是主芯片为STM32F107VC的金牛开发板,开发板上已集成有以太网功能模块和RS485功能模块。
只是在开发板上RS-485与RS-232接口共用了微处理器的接收串口,需要设置JP4,且配置为1-2,如表1.1所示。
金牛开发板支持两种以太网接口模式,一种是MII接口模式,另一种是RMII接口模式。
这里选用MII接口模式,根据表1.2对跳线JP2、JP6、JP7、JP8、JP12进行相应的配置。
1.2 软件平台软件平台为RVMDK软件。
RVMDK是由ARM编译器RVCT与Keil的工程管理、调试仿真工具集成,RVMDK是业界最好的Cortex-M3开发工具之一,它拥有流畅的用户界面与强大的仿真功能,是一款非常强大的ARM微控制器开发工具。
移植前需要熟悉RVMDK软件的使用。
移植过程中需要用到如图1.1和图1.2所示文件,一个是基于μC/OS_II的移动基站电表管理系统终端程序,另一个是基于μC/OS_II系统以太网移植文件。
ucosii中的systick和OSTimeDly
ucosii中的systick和OSTimeDlyOSTimeDly(x)函数和SYSTick系统时钟,这两个为整个系统的关键点,同时也是我开始学习uC/OS-ii到现在碰到的最难理解的问题,可能是一直都处于裸机奔跑状态,对OS还是感觉到很陌生,一时间很难去接收这样一个非常伟大的东西。
首先是systick的介绍,systick为系统时钟,作为uC/OS-ii的嘀嗒时钟,也许有人会问什么是嘀嗒时钟?就是这个时钟不会停止,一直在运行,它好像是uC/OS-ii的心脏一样,保证它不会死掉,可能又有人问,一般的单片机不是有时钟嘛,代码一样在运行,为什么要要这么个玩意---嘀嗒时钟!我开始学习uC/OS-ii的时候也是这种感觉,当时没有人去讲解,自己不停的在那里想,看书啥的,后来通过写一个2个任务的代码就明白了这个嘀嗒时钟的重要性,如果系统中移植了OS,那么就得把OS和用户应用程序代码(也就是任务)作为2个部分看待,所以我们可以看作系统需要两个时钟,我是这么理解的,具体是怎么样的,在以后的博文中会细细说来!假如我们将systick设置为10ms(根据处理器的clock而定),也就是每10ms的时候会进入systick中断,systick这个功能可由一般的定时器取代,在这个中断服务程序中会执行OSTimeTick和OSIntExit两个函数(可能结合源代码看)。
在介绍这两个函数之前需要先对OSTimeDly(x)进行相应的说明,OSTimeDly(x)为系统延时,假如在某个任务中对其进行调用,表示这个任务已经由运行状态转换到等待状态了(任务比较常规的状态为等待、就绪和运行这3个,另外2个:休眠和中断相对那3个状态而言显得就不是这么突出了),并且会做一次任务调度(什么是调度?不用纠结很多,就是把处于就绪态的任务通过某一算法转移到运行态),使就绪态中(所有的任务通过OSTaskCreate()函数使其处于就绪状态)最高优先级的任务处于运行状态,同时会将该任务TCB中的OSTCBDly参数设置为x(注意是全局变量),系统任务的状态转移如下图1所示,这个转移图非常重要,如果还没有意识到它的重要性,那么表示看书看的还不够,还得继续:图1:uC/OS-ii状态转移图前面提到了systick中断服务程序中的两个函数OSTimeTick和OSIntExit,每次进入systick中断都会在函数OSTimeTick中对OSTCBDly(OSTCBDly为任务调用OSTimeDly(x)函数中的x)进行减1操作,当这个值减到0的时候,uC/OS-ii会将该任务由等待状态PUSH到就绪状态(注意这里不是任务切换),OSIntExit函数会获得就绪表中优先级较高的任务的prio值,并且判断具有这个prio值的任务是不是当初那个被中断了的任务,如果不是则需要获得这个新任务的TCB指针并且执行中断级的任务切换使其处于运行状态,如果是当初那个给中断了的任务,则需要继续执行这个任务,不会进行任务切换。
根据QuartusII软件的数字时钟设计
根据QuartusII软件的数字时钟设计实验名称:数字时钟设计姓名:杨龙成班级:电子与通信工程学号: 3120302012 成绩:一、实验目的1.掌握各类计数器及它们相连的设计方法;2.掌握多个数码管显示的原理与方法;3.掌握模块化设计方式;4.掌握用VHDL语言的设计思想以及整个数字系统的设计。
二、实验内容1. 设计要求1)具有时、分、秒计数显示功能,在数码管显示00:00:00~23:59:59,以24小时循环计时。
2)完成可以计时的数字时钟时钟计数显示时有LED灯的花样显示。
3)具有调节小时、分钟及清零的功能。
4)具有整点报时功能。
2. 性能指标及功能设计1)时钟计数:完成时、分、秒的正确计时并且显示所计的数字;对秒、分60进制计数,时钟—24进制计数,并且在数码管上显示数值。
2)时间设置:手动调节分钟、小时,可以对所设计的时钟任意调时间。
可以通过实验板上的键7和键4进行任意的调整,因为时钟信号均是1HZ的,所以LED灯每变化一次就来一个脉冲,即计数一次。
3)清零功能:reset为复位键,低电平时实现清零功能,高电平时正常计数。
4)蜂鸣器在整点时有报时信号产生,产生“滴答.滴答”的报警声音。
5)根据进位情况,LED灯在时钟显示时有花样显示信号产生。
3. 系统方框图三、设计原理和过程3.1 硬件设计本设计使用VHDL硬件开发板,可编程逻辑器件EMP1270T144C5系列。
设计过程中用到的外围电路的设计有电源部分,可编程器件EMP1270T144C5,CPLD –JTAG接口,晶振和蜂鸣器,LED数码管显示,DIP开关与按键输入(具体电路见附录)3.2 软件设计3.2..1 程序包my_pkg的设计说明为了简化程序设计增加可读性,系统采用模块化的设计方法,重复使用的组件以元件(component)的形式存在,以便相关块的调用。
下面列出my_pkg组件包的代码。
library ieee;use ieee.std_logic_1164.all;package my_pkg iscomponent div40M------------------------------------------------------------------元器件1 Port( clk: in std_logic;f1hz : out std_logic);end component;component count60-----------------------------------------------------------------元器件2 Port(clr,clk:in std_logic;one :buffer std_logic_vector(3 downto 0);ten :buffer std_logic_vector(3 downto 0);full:out std_logic;dout:buffer std_logic_vector(7 downto 0));end component;component count24-----------------------------------------------------------------元器件3 Port(clr,clk:in std_logic;one :buffer std_logic_vector(3 downto 0);ten :buffer std_logic_vector(3 downto 0);full:out std_logic);end component;component scan6----------------------------------------------------------------元器件4 port (clr,clk : in STD_LOGIC;h_ten,h_one,m_ten,m_one,s_ten,s_one: in STD_LOGIC_vector(3 downto 0);cs: out STD_LOGIC_vector(5 downto 0);mux_out: out STD_LOGIC_vector(3 downto 0));end component;component bin2led---------------------------------------------------------------元器件5 port (bin : in std_logic_vector (3 downto 0);led : out std_logic_vector (7 downto 0) );end component;component sh1k ----------------------------------------------------------------------元器件6 Port( clk: in std_logic;--from system clock(40MHz)f1hz : out std_logic);-- 1Hz output signalend component;component alarm_set------------------------------------------------------------------元器件7 Port(rst,hz1: in std_logic;--system clock 1Hzalarm,ok: in std_logic;--keep pushing to declare alarm setsec_tune: in std_logic;sec_one,sec_ten:out std_logic_vector(3 downto 0));end component;end my_pkg;3.2.2 count60组件由此提供分(秒)计数值,当分计数器计数到59再来一个脉冲信号秒计数器清零从新开始计数,而进位则作为小时计数器的计数脉冲,使小时计数器计数加1,同时分计数器在分设置时钟信号的响应下设置分计数器的数值。
北航ARM9嵌入式系统实验实验三uCOS-II实验
北航ARM9嵌⼊式系统实验实验三uCOS-II实验实验三 uCOS-II实验⼀、实验⽬的在内核移植了uCOS-II 的处理器上创建任务。
⼆、实验内容1)运⾏实验⼗,在超级终端上观察四个任务的切换。
2)任务1~3,每个控制“红”、“绿”、“蓝”⼀种颜⾊的显⽰,适当增加OSTimeDly()的时间,且优先级⾼的任务延时时间加长,以便看清三种颜⾊。
3)引⼊⼀个全局变量BOOLEAN ac_key,解决完整刷屏问题。
4)任务4管理键盘和超级终端,当键盘有输⼊时在超级终端上显⽰相应的字符。
三、预备知识1)掌握在EWARM 集成开发环境中编写和调试程序的基本过程。
2)了解ARM920T 处理器的结构。
3)了解uCOS-II 系统结构。
四、实验设备及⼯具1)2410s教学实验箱2)ARM ADS1.2集成开发环境3)⽤于ARM920T的JTAG仿真器4)串⼝连接线五、实验原理及说明所谓移植,指的是⼀个操作系统可以在某个微处理器或者微控制器上运⾏。
虽然uCOS-II的⼤部分源代码是⽤C语⾔写成的,仍需要⽤C语⾔和汇编语⾔完成⼀些与处理器相关的代码。
⽐如:uCOS-II在读写处理器、寄存器时只能通过汇编语⾔来实现。
因为uCOS-II 在设计的时候就已经充分考虑了可移植性,所以,uCOS-II的移植还是⽐较容易的。
要使uCOS-II可以正常⼯作,处理器必须满⾜以下要求:(1)处理器的C编译器能产⽣可重⼊代码可重⼊的代码指的是⼀段代码(如⼀个函数)可以被多个任务同时调⽤,⽽不必担⼼会破坏数据。
也就是说,可重⼊型函数在任何时候都可以被中断执⾏,过⼀段时间以后⼜可以继续运⾏,⽽不会因为在函数中断的时候被其他的任务重新调⽤,影响函数中的数据。
(2)在程序中可以打开或者关闭中断在uCOS-II中,可以通过OS_ENTER_CRITICAL()或者OS_EXIT_CRITICAL()宏来控制系统关闭或者打开中断。
这需要处理器的⽀持,在ARM920T的处理器上,可以设置相应的寄存器来关闭或者打开系统的所有中断。
ucosII实验报告
实验1《任务的创建、删除、挂起、恢复》实验学时: 2 实验地点:二综x203 实验日期:2013/12/13一、实验目的1.实验环境的建立2.任务的接口函数的应用二、实验内容1.设计一个只有一个任务Task1,当程序运行后任务的工作就是每秒在显示器上显示一个字符“M”。
2.在任务Task1中在创建一个任务Task2 。
当程序运行后,任务Task1的工作在显示器上显示一个字符“M”;Task2 则是在显示器上显示字符“Y”。
3. 要求任务Task2运行20次后,挂起任务Task1;任务Task2运行40次后,恢复任务Task1。
4. 当任务Task1运行5次时,用函数OSSchedLock()对调度器进行加锁;而当任务Task1运行到第10次时,再用函数OSSchedUnlock()对调度器进行解锁,并运行该程序。
5. 使任务Task1能删除任务Task2。
三、实验方法包括实验方法、原理、技术、方案等。
四、实验步骤1.将BC45文件夹拷贝到C分区根目录下。
2.将software文件夹拷贝到任意分区根目录下。
3. 分别完成实验1、2、3、4、5五、实验结果1. DOS窗口每秒显示一个字符“M”。
每行显示10个“M”字符,行与行的间隔是一行。
按ESC键程序退出2. DOS窗口交替显示字符"M"和“Y”,每隔一秒显示一次。
每行显示10个字符,行与行之间的间隔是一行。
按ESC键程序退出3.DOS窗口开始交替显示字符"M"和“Y”,显示20次以后,Task1挂起,只显示“Y”,当Task2运行40次以后,Task1恢复,然后开始Task1,Task2交替运行。
4.DOS窗口开始交题显示字符"M"和“Y”,显示5次以后,Task1将任务调度器上锁,此时只有“M”打印,当Task1运行10次后,Task1,Task2开始交替运行。
5.DOS窗口开始交替显示字符“M”和“Y”,显示10次后,只显示“Y”六、实验结论对实验数据和结果进行分析描述,给出实验取得的成果和结论。
1-uCOS-II 工作流程图
uC/OS 的实时性就是靠定时中断来完成。 每个时钟节拍到来,就会产生一次定时中断,中断后进行任务调度,运行 就绪表中优先级最高的任务(非抢先型内核中断后继续运行被中断任 务)。即过一段时间就检测是否有重要任务需要运行,是的就转而运行更 重要的任务,从而确保实时性(裸机程序就无法这样做了)。
至少创建一个任务。 一般创建一个最高优 先级别 TaskStart 任 务(建议),任务调 度后,在这个任务中 再创建其他任务,初 始化硬件,并开中 断。
进入多任务管理阶 段,将就绪表ቤተ መጻሕፍቲ ባይዱ最高 优先级任务的栈指针 加载到 SP 中,并强 制中断返回。
uC/OS 的任务调度工作: ①查找就绪表中最高优先级任务。 ②实现任务切换。 分为:
⑥ ①
初始化变量 OSIint
中断
②
创建任务 OSTaskCreate
③
进入多任务管理阶段 OSStart
④
任务调度 OSSched/OSIntExt
⑤
用户任务 MyTask
初始化所有全局变量、数 据结构、创建最低优先级 空闲任务 OSTaskIde, (如果使用了统计任务, 也在此创建),创建 6 个 空数据链表: ①空任务控制块链表 ②空事件控制块链表 ③空队列控制块链表 ④空标志组链表 ⑤空内存控制块链表 ⑥空闲定时器控制块链表
主动让出 CPU:延时、 请求临界资源而挂起、
如果按照刚才的建议 去做,首次调度时, 肯定运行 TaskStart ,在这任 务中再创建其他任
任务调度,是内核的主要服务,是 区分裸机跟多任务系统的最大特 点。好的调度策略,能更好地发挥 系统的效率
嵌入式实时操作系统ucosii
医疗电子
ucosii在医疗电子领域 中应用于医疗设备、监
护仪、分析仪等。
物联网
ucosii在物联网领域中 应用于传感器节点、网
关、路由器等设备。
02
ucosii的体系结构与内核
任务管理
任务创建
ucosii提供了创建新任务的函数,如 OSTaskCreate(),用于创建新任务。
任务删除
ucosii提供了删除任务的函数,如 OSTaskDelete(),用于删除不再需要的任 务。
时间管理
01
02
03
时间节拍
ucosii通过定时器产生固 定时间间隔的节拍信号, 用于任务调度和时间管理 。
超时处理
ucosii支持超时机制,当 某个任务等待时间超过预 定阈值时触发相应的处理 函数。
时间函数
ucosii提供了一系列时间 函数,如OSTimeDly()、 OSTimeTick()等,用于时 间相关的操作和控制。
智能家居
ucosii适用于智能家居领域,可应用于 智能家电控制、家庭安全监控等场景。
02
03
医疗电子
ucosii适用于医疗电子领域,如医疗设 备控制、病人监控等,其可靠性和实 时性为医疗系统提供了有力保障。
THANKS。
应用软件的开发
任务管理
在UCOSII中,任务是用来实现应用程序功能的。在进行应用软件的开发时,需要创建和管理任务。这包括任务的创 建、删除、挂起和恢复等操作。
任务间通信
为了实现任务间的协同工作,需要进行任务间通信。UCOSII提供了信号量、消息队列、互斥量等机制来实现任务间 通信。在进行应用软件的开发时,需要利用这些机制来实现任务间的同步和数据交换。
嵌入式系统应用课程设计
课程论文首页院、系(部) 电子信息工程 专业 电子信息工程班级 092学号 910706201 姓名 XXX 任课教师 XXX 课程名称 嵌入式系统应用论文题目 时钟显示实验 成绩评语签字:年 月 日复 核 人 意 见签字:年 月 日时钟显示实验XXX中文摘要: 利用实验室提供的软硬件资源,结合ADS1.2和EasyARM2200开发板设计时钟实时显示功能。
设计已完成的时钟系统的基本功能包括正常走时,显示年、月、日、星期、时、分、秒,并能通过按键检测来重新设置RTC 的时间。
关键词: EasyARM2200开发板 ADS1.2 uC/OS-II 嵌入式1 设计目标设计在EasyARM2200开发板上移植uC/OS-II 操作系统,利用RTC 不断读取时间值,经UART0输出到上位机EasyARM 软件上来显示时间。
该时钟系统功能包括显示年月日、星期和时分秒。
星期和时分秒。
并能通过按键检测并能通过按键检测并能通过按键检测((P0.14口的输入),若有按键则重新设置RTC 的时间(将年增加1,时增加1)。
并尽量达到美观、实用。
2 设计环境1、ADS1.2集成开发环境2、EasyARM2200开发板和EasyARM 软件3、PC 机和uC/OS-II 操作系统3 设计原理3.1 实时时钟(RTC )实时时钟特性:带日历和时钟功能;超低功耗设计,支持电池供电系统;提供秒、分、小时、日、月、年和星期;可编程基准时钟分频器允许调节RTC 以适应不同的晶振频率。
实时时钟(RTC )提供一套计数器,在系统工作时对时间进行测量。
RTC 消耗的功率非常低,这使其适合于由电池供电的,CPU 不连续工作的系统。
实时时钟的时钟源是由PCLK 通过基准时钟分频器(PREINT 、PREFRAC ),调整出32768Hz 的频率,然后供给CTC 计数器;CTC 是一个15位的计数器,位的计数器,它位于秒计数器之前,它位于秒计数器之前,CTC 每秒计数32768个时钟;当有CTC 秒进位时,秒进位时,完整时间完整时间CTME0~CTME2、RTC 时间寄存器将会更新;RTC中断有两种,一种是增量中断,由CIIR进行控制,另一种为报警中断,由AMR寄存器和各报警时间寄存器控制。
嵌入式实时操作系统ucosII
嵌入式实时操作系统ucosIIucosII是一款源代码公开、可免费使用的嵌入式实时操作系统。
它是由德国嵌入式系统专家brosse于1992年编写完成的,主要适用于嵌入式系统的开发。
ucosII具有源代码短小精悍、可移植性好、稳定性高等优点,被广泛应用于各种嵌入式系统中。
源代码短小精悍:ucosII的源代码只有几百KB,相对于其他RTOS来说,其代码量较小,易于理解和修改。
可移植性好:ucosII采用了可移植性的设计方法,可以在不同的处理器和编译器上进行移植和优化。
稳定性高:ucosII在各种嵌入式系统中得到了广泛应用,其稳定性和可靠性得到了充分的验证。
支持多任务:ucosII支持多任务处理,可以同时运行多个任务,提高系统的效率和响应速度。
实时性:ucosII具有较高的实时性,可以满足各种实时性要求高的应用场景。
可扩展性:ucosII具有较好的可扩展性,可以根据需要进行功能扩展和优化。
系统内核:包括任务调度、任务管理、时间管理、内存管理等核心功能。
中断处理程序:处理各种中断请求,包括硬件中断、软件中断等。
系统API:提供了一套完善的API函数,方便应用程序的开发和调试。
调试和测试工具:包括各种调试和测试工具,如内存检查工具、性能分析工具等。
ucosII被广泛应用于各种嵌入式系统中,如工业控制、智能家居、智能交通、航空航天等。
其应用场景涵盖了消费类电子产品、医疗设备、通信设备、汽车电子等领域。
ucosII作为一款源代码公开、可免费使用的嵌入式实时操作系统,具有短小精悍、可移植性好、稳定性高等优点。
它广泛应用于各种嵌入式系统中,为应用程序的开发提供了便利和支持。
其可扩展性和实时性也使得它在各种领域中具有广泛的应用前景。
随着嵌入式系统的广泛应用,对嵌入式操作系统的需求也日益增长。
uCOSII是一种流行的实时嵌入式操作系统,具有轻量级、实时性、可扩展性等优点。
本文将介绍如何在AT91平台上实现uCOSII的移植。
uCOS-II简介
4.1OC/OS-II简介UC/OS-II 是一种基于优先级的可抢先的硬实时内核。
自从92 年发布以来,在世界各地都获得了广泛的应用,它是一种专门为嵌入式设备设计的内核,目前已经被移植到40 多种不同结构的CPU 上,运行在从8 位到64 位的各种系统之上。
尤其值得一提的是,该系统自从2.51版本之后,就通过了美国FAA 认证,可以运行在诸如航天器等对安全要求极为苛刻的系统之上。
鉴于UC/OS-II 可以免费获得代码,对于嵌入式RTOS 而言,选择UC/OS 无疑是最经济的选择。
需要说明的是,UC/OS-II 作为一个实时操作系统只提供了多任务调度等基本功能,这在实际应用中显然是不够的。
除了移植好的操作系统内核部分,还必须有文件系统,全部硬件的驱动程序,图形API,控件函数,综合提高的消息函数以及几个系统必须的基本任务,象键盘,触摸屏,LCD 刷新等。
有了这些,UC/OS-II 才能实现复杂的功能。
特殊需求的地方还需要像USB通信协议,TCP/IP 协议等更复杂的软件模块。
博创提供的UC/OS-II 库文件中包含了上述大部分功能,基于库的开发变的非常简单,在基本的程序框架下应用我们提供的丰富API 函数即可。
实际开发中,用户的工程中无需包括UC/OS-II 的源代码,只需要包括库文件即可。
当然,用户也可以了解库中部分代码的源文件,可以根据自己的需求就行重新编译,也可以对自己的一系列源文件生成一个专门的库,方便自己后续工作。
UC/OS-II 的开发中,应用程序和操作系统是绑在一起编译的,所生成的system.bin 文件是唯一的可执行文件,其中包括了所需要的UC/OS-II 代码和被用到的驱动程序等函数代码,以及应用程序的代码。
system.bin 文件是存放在平台的16M FLASH 中的,在系统启动时由BIOS依靠文件系统从FLASH 中读入到SDRAM 中,然后把控制转移到该代码上,完成所谓的引导。
UCOS-II操作系统详解
VμC/OS 和μC/OS-II是专门为计算机的嵌入式应用设计的,绝大部分代码是用C语言编写的。
CPU 硬件相关部分是用汇编语言编写的、总量约200行的汇编语言部分被压缩到最低限度,为的是便于移植到任何一种其它的CPU 上。
工作原理编辑uC/OS-II是一种基于优先级的可抢先的硬实时内核。
要实现多任务机制,那么目标CPU必须具备一种在运行期更改PC的途径,否则无法做到切换。
不幸的是,直接设置PC指针,还没有哪个CPU支持这样的指令。
但是一般CPU都允许通过类似JMP,CALL这样的指令来间接的修改PC。
我们的多任务机制的实现也正是基于这个出发点。
事实上,我们使用CALL指令或者软中断指令来修改PC,主要是软中断。
但在一些CPU上,并不存在软中断这样的概念,所以,我们在那些CPU上,使用几条PUSH指令加上一条CALL指令来模拟一次软中断的发生。
在uC/OS-II里,每个任务都有一个任务控制块(Task Control Block),这是一个比较复杂的数据结构。
在任务控制块的偏移为0的地方,存储着一个指针,它记录了所属任务的专用堆栈地址。
事实上,在uC/OS-II内,每个任务都有自己的专用堆栈,彼此之间不能侵犯。
这点要求程序员在他们的程序中保证。
一般的做法是把他们申明成静态数组。
而且要申明成OS_STK类型。
当任务有了自己的堆栈,那么就可以将每一个任务堆栈在那里记录到前面谈到的任务控制快偏移为0的地方。
以后每当发生任务切换,系统必然会先进入一个中断,这一般是通过软中断或者时钟中断实现。
然后系统会先把当前任务的堆栈地址保存起来,仅接着恢复要切换的任务的堆栈地址。
由于哪个任务的堆栈里一定也存的是地址(还记得我们前面说过的,每当发生任务切换,系统必然会先进入一个中断,而一旦中断CPU就会把地址压入堆栈),这样,就达到了修改PC为下一个任务的地址的目的。
任务管理编辑uC/OS-II 中最多可以支持64 个任务,分别对应优先级0~63,其中0 为最高优先级。
实验九 基于uCOS的多任务程序设计实验
实验九基于uCOS的多任务程序设计实验
[实验目的]
1.了解uCOS在ARM7上的移植思想。
2.掌握uCOS-II的多任务程序的编写。
[实验仪器]
1.Proteus仿真的LPC2000系列的ARM处理器
2.软件:PC机操作系统Win98、Win2000或WinXP,Keil for ARM(MDK)集成开发环境
[实验原理]
uCOS-II是一个多任务实时操作系统内核,可以在ARM7等微处理器上运行。
[实验内容]
使用uCOS-II设计两个任务,一个任务用于向串行口0发送“hello uCOS-II”,1秒钟运行一次。
另一个任务点亮LED,每500ms闪烁一次。
[预备知识]
参照教材上uCOS-II的移植一节。
[实验步骤]
硬件设计仍采用串行口实验的硬件。
用到的器件有:。
虚拟串口终端按下图查找
虚拟终端的设置如下:
打开已经移植好的ucosii项目。
修改主程序代码:
分析代码中各个语句的含义。
了解此类设计的编程思想。
[思考题与数据分析]
1.修改代码,使串口能够格式化输出数值到虚拟终端。
2.将led的开关控制设置为字符串控制,当输入字符串“ON”时候led点亮;输入字符串
“OFF”led熄灭。
3.修改代码,使实现在串口终端中输入的字符能够显示。
4.设置串口中断输入方式点亮led。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
《嵌入式系统》综合实验报告实验内容基于uC/OS-II的时钟设计系专业班级学号学生姓名指导教师2011年05月25日基于uC/OS-II的时钟设计一.实验要求1. 按正常逻辑显示“年-月-日”,“时:分:秒”,其中分与秒间“:”每0.5秒闪烁1次。
2. 可利用键盘的上,下,左,右键进行日期,时间设置;按“ESC”退出程序;3. 可利用键盘的上,下键进行走时快慢调整,以便检验走时逻辑[可选功能];4. 功能的实现过程中,必须体现所学的uC/OS-II相关知识,信号量、互斥量、消息邮箱、消息队列必须用到;5. 独立完成,正常演示结果,且正确回答老师抽查问题。
二.实验设计思想1、划分了6个任务,分别为year、month、day、hour、min、sec,建立了2个信号量semsec、semhalfsec。
2、dis1Num(char x, char y, char num)表示在界面(x,y)坐标上显示一位数,dis2Num(char x, char y, char num)表示两位数组成一个时间块。
3、用方向键定义了4个key,left、right可以进行年月日时分秒的切换,up、down可以对每一项的数值的加减。
4、每过一个信号量semsec,时间加1秒,OSSemPend(semHalfSec, 0, &err)调用semhalfsec实现两个点亮半秒、暗半秒的闪烁功能。
OSMboxPost(mboxPosNumMode, &dateTime)调用semhalfsec实现被选中的任务时间块的闪烁。
5、通过key实现任务之间的调度,left和right方向键对时间块的选择用到了互斥量。
6、OSMboxPost(mboxPosNumMode, &dateTime)把dateTime的地址发送给mboxPosNumMode。
7、。
“消息队列”是在消息的传输过程中保存消息的容器。
三.具体程序实现实验结果代码/*********************************************************************************************** * uC/OS-II* The Real-Time Kernel** description : 移植uC/OS-II(2.51 Kernal)在Visual C++ Complier运行。
* date : 2006.10.19* change by : HCF********************************************************************************************** * 版本历史* 10_19 : 1.0版本------------------------------------------------------------------------------------------------ * 目前发现的问题:* 任务堆栈只能设置成2048(OS_STK)大小------------------------------------------------------------------------------------------------ */#include "includes.h"#include "stdlib.h"/*********************************************************************************************** * CONSTANTS********************************************************************************************** */#define TASK_STK_SIZE 2048 //任务堆栈长度,只能设置为2048!!!!!/*********************************************************************************************** * 必须定义以下任务堆栈空间使用,作为创建优先级别为0的TaskStart()任务的任务堆栈********************************************************************************************** */OS_STK TASKSTARTSTK[10*TASK_STK_SIZE]; //TaskStart的任务堆栈空间OS_STK taskTimeTickStk[TASK_STK_SIZE];OS_STK taskTimeRefreshStk[TASK_STK_SIZE];OS_STK taskShow2DotStk[TASK_STK_SIZE];OS_STK taskDispDateTimeStk[TASK_STK_SIZE];OS_STK taskdispDateTimeOptStk[TASK_STK_SIZE];OS_STK taskKeyDealStk[TASK_STK_SIZE];INT8U x=0,y=0; //字符显示位置char dateTime[7]={11,5,18,10,30,12,0};HANDLE mainhandle; // 主线程句柄CONTEXT Context; // 主线程切换上下文BOOLEAN FlagEn = 1; // 增加一个全局变量,做为是否时钟调度的标志OS_EVENT *semSec;OS_EVENT *semHalfSec;OS_EVENT *mutexDis;OS_EVENT *mboxDateTime;OS_EVENT *mboxPosNumMode;OS_EVENT *qKey;void *keyQTbl[110];/*********************************************************************************************** * FUNCTION PROTOTYPES********************************************************************************************** */void VCInit(void); // 初始化相关变量,一定需要void TaskStart( void * pParam );void taskShow2Dot(void *pdata);void taskTimeTick(void *pdata);void taskTimeRefresh(void *pdata);void taskDispDateTime(void *pdata);void taskdispDateTimeOpt(void *pdata);void taskKeyDeal(void *pdata);/*********************************************************************************************** * 函数名: main(int argc, char **argv)* 函数功能:* 入口参数:* 返回参数:********************************************************************************************** */void main(int argc, char **argv){VCInit(); //初始化一些变量,编译器相关OSInit(); //初始化uCOS_II//必须创建以下这个任务,作为设置uCOS_II时钟频率使用,与MyTask()中的这两行代码等效OSTaskCreate(TaskStart,0, &TASKSTARTSTK[10*TASK_STK_SIZE - 1], 0 ); // 必须使用OSStart(); //启动uCOS_II的多任务管理}/*********************************************************************************************** * 函数名: VCInit()* 函数功能: 编译器初始化,VC环境下一定需要* 入口参数: 无* 返回参数: 无********************************************************************************************** */void VCInit(void){HANDLE cp,ct;Context.ContextFlags = CONTEXT_CONTROL;cp = GetCurrentProcess(); //得到当前进程句柄ct = GetCurrentThread(); //得到当前线程伪句柄DuplicateHandle(cp, ct, cp, &mainhandle, 0, TRUE, 2); //伪句柄转换,得到线程真句柄}/*********************************************************************************************** * 函数名: Task_start( )* 函数功能: 启动统计任务(只创建,不做参与任务调度),该任务创建,作为设置uCOS_II时钟频率使用, * 与MyTask()中的这两行代码等效:* PC_VectSet(0x08, OSTickISR); //安装uCOS_II时钟中断向量* PC_SetTickRate(OS_TICKS_PER_SEC); //设置uCOS_II时钟频率* 入口参数:* 返回参数: 无********************************************************************************************** */void TaskStart( void * pParam ){INT16S key; //用于退出uCOS_II的键char key8;timeSetEvent(1000/OS_TICKS_PER_SEC, 0, OSTickISR, 0, TIME_PERIODIC); //开启一个定时器线程,感觉10 ticks/s比较好OSStatInit();semSec = OSSemCreate(0);semHalfSec = OSSemCreate(0);mboxDateTime = OSMboxCreate(0);mboxPosNumMode = OSMboxCreate(0);qKey = OSQCreate(keyQTbl, 100);OSTaskCreate(taskTimeTick, 0, &taskTimeTickStk[TASK_STK_SIZE - 1], 20); //使任务MyTask的优先级别为1OSTaskCreate(taskKeyDeal, 0, &taskKeyDealStk[TASK_STK_SIZE - 1], 21);OSTaskCreate(taskdispDateTimeOpt, 0, &taskdispDateTimeOptStk[TASK_STK_SIZE - 1], 22);OSTaskCreate(taskShow2Dot, 0, &taskShow2DotStk[TASK_STK_SIZE - 1], 30);//使任务MyTask的优先级别为1OSTaskCreate(taskTimeRefresh, 0, &taskTimeRefreshStk[TASK_STK_SIZE - 1], 40);//使任务MyTask的优先级别为0OSTaskCreate(taskDispDateTime, 0, &taskDispDateTimeStk[TASK_STK_SIZE - 1], 50);//使任务MyTask的优先级别为0//使任务MyTask的优先级别为0while(1){//sleep ,wait for sem1,run other taskOSTimeDlyHMSM(0,0,0,500);if (PC_GetKey(&key) == TRUE){if (key == 0x1B) //如果按下Esc键则退出uCOS_II{exit(0);}else{key8 = (char)key;OSQPost(qKey, (void*)&key8);}key = 0;}}}/**********************************************************************************************/void dis1Num(char x, char y, char num){char hor,ver;//OS_ENTER_CRITICAL();switch(num){case 0:hor = y; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+1; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+2; ver = x; PC_DispStr(ver, hor, "MM MM", DISP_FGND_WHITE); hor = y+3; ver = x; PC_DispStr(ver, hor, "MM MM", DISP_FGND_WHITE); hor = y+4; ver = x; PC_DispStr(ver, hor, "MM MM", DISP_FGND_WHITE); hor = y+5; ver = x; PC_DispStr(ver, hor, "MM MM", DISP_FGND_WHITE); hor = y+6; ver = x; PC_DispStr(ver, hor, "MM MM", DISP_FGND_WHITE); hor = y+7; ver = x; PC_DispStr(ver, hor, "MM MM", DISP_FGND_WHITE); hor = y+8; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+9; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); break;case 1:hor = y; ver = x; PC_DispStr(ver, hor, " MM", DISP_FGND_WHITE); hor = y+1; ver = x; PC_DispStr(ver, hor, " MM", DISP_FGND_WHITE); hor = y+2; ver = x; PC_DispStr(ver, hor, " MM", DISP_FGND_WHITE); hor = y+3; ver = x; PC_DispStr(ver, hor, " MM", DISP_FGND_WHITE); hor = y+4; ver = x; PC_DispStr(ver, hor, " MM", DISP_FGND_WHITE); hor = y+5; ver = x; PC_DispStr(ver, hor, " MM", DISP_FGND_WHITE); hor = y+6; ver = x; PC_DispStr(ver, hor, " MM", DISP_FGND_WHITE); hor = y+7; ver = x; PC_DispStr(ver, hor, " MM", DISP_FGND_WHITE); hor = y+8; ver = x; PC_DispStr(ver, hor, " MM", DISP_FGND_WHITE); hor = y+9; ver = x; PC_DispStr(ver, hor, " MM", DISP_FGND_WHITE); break;case 2:hor = y; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+1; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+2; ver = x; PC_DispStr(ver, hor, " MM", DISP_FGND_WHITE); hor = y+3; ver = x; PC_DispStr(ver, hor, " MM", DISP_FGND_WHITE); hor = y+4; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+5; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+6; ver = x; PC_DispStr(ver, hor, "MM ", DISP_FGND_WHITE); hor = y+7; ver = x; PC_DispStr(ver, hor, "MM ", DISP_FGND_WHITE); hor = y+8; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+9; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); break;case 3:hor = y; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+1; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+2; ver = x; PC_DispStr(ver, hor, " MM", DISP_FGND_WHITE); hor = y+3; ver = x; PC_DispStr(ver, hor, " MM", DISP_FGND_WHITE); hor = y+4; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+5; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+6; ver = x; PC_DispStr(ver, hor, " MM", DISP_FGND_WHITE); hor = y+7; ver = x; PC_DispStr(ver, hor, " MM", DISP_FGND_WHITE); hor = y+8; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+9; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); break;case 4:hor = y; ver = x; PC_DispStr(ver, hor, "MM MM", DISP_FGND_WHITE); hor = y+1; ver = x; PC_DispStr(ver, hor, "MM MM", DISP_FGND_WHITE); hor = y+2; ver = x; PC_DispStr(ver, hor, "MM MM", DISP_FGND_WHITE); hor = y+3; ver = x; PC_DispStr(ver, hor, "MM MM", DISP_FGND_WHITE); hor = y+4; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+5; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+6; ver = x; PC_DispStr(ver, hor, " MM", DISP_FGND_WHITE); hor = y+7; ver = x; PC_DispStr(ver, hor, " MM", DISP_FGND_WHITE); hor = y+8; ver = x; PC_DispStr(ver, hor, " MM", DISP_FGND_WHITE); hor = y+9; ver = x; PC_DispStr(ver, hor, " MM", DISP_FGND_WHITE); break;case 5:hor = y; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+1; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+2; ver = x; PC_DispStr(ver, hor, "MM ", DISP_FGND_WHITE); hor = y+3; ver = x; PC_DispStr(ver, hor, "MM ", DISP_FGND_WHITE); hor = y+4; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+5; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+6; ver = x; PC_DispStr(ver, hor, " MM", DISP_FGND_WHITE); hor = y+7; ver = x; PC_DispStr(ver, hor, " MM", DISP_FGND_WHITE); hor = y+8; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+9; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); break;case 6:hor = y; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+1; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+2; ver = x; PC_DispStr(ver, hor, "MM ", DISP_FGND_WHITE); hor = y+3; ver = x; PC_DispStr(ver, hor, "MM ", DISP_FGND_WHITE); hor = y+4; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+5; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+6; ver = x; PC_DispStr(ver, hor, "MM MM", DISP_FGND_WHITE);hor = y+8; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+9; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); break;case 7:hor = y; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+1; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+2; ver = x; PC_DispStr(ver, hor, " MM", DISP_FGND_WHITE); hor = y+3; ver = x; PC_DispStr(ver, hor, " MM", DISP_FGND_WHITE); hor = y+4; ver = x; PC_DispStr(ver, hor, " MM", DISP_FGND_WHITE); hor = y+5; ver = x; PC_DispStr(ver, hor, " MM", DISP_FGND_WHITE); hor = y+6; ver = x; PC_DispStr(ver, hor, " MM", DISP_FGND_WHITE); hor = y+7; ver = x; PC_DispStr(ver, hor, " MM", DISP_FGND_WHITE); hor = y+8; ver = x; PC_DispStr(ver, hor, " MM", DISP_FGND_WHITE); hor = y+9; ver = x; PC_DispStr(ver, hor, " MM", DISP_FGND_WHITE); break;case 8:hor = y; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+1; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+2; ver = x; PC_DispStr(ver, hor, "MM MM", DISP_FGND_WHITE); hor = y+3; ver = x; PC_DispStr(ver, hor, "MM MM", DISP_FGND_WHITE); hor = y+4; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+5; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+6; ver = x; PC_DispStr(ver, hor, "MM MM", DISP_FGND_WHITE); hor = y+7; ver = x; PC_DispStr(ver, hor, "MM MM", DISP_FGND_WHITE); hor = y+8; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+9; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); break;case 9:hor = y; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+1; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+2; ver = x; PC_DispStr(ver, hor, "MM MM", DISP_FGND_WHITE); hor = y+3; ver = x; PC_DispStr(ver, hor, "MM MM", DISP_FGND_WHITE); hor = y+4; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+5; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+6; ver = x; PC_DispStr(ver, hor, " MM", DISP_FGND_WHITE); hor = y+7; ver = x; PC_DispStr(ver, hor, " MM", DISP_FGND_WHITE); hor = y+8; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); hor = y+9; ver = x; PC_DispStr(ver, hor, "MMMMMMMM", DISP_FGND_WHITE); break;default:hor = y; ver = x; PC_DispStr(ver, hor, " ", DISP_FGND_WHITE); hor = y+1; ver = x; PC_DispStr(ver, hor, " ", DISP_FGND_WHITE); hor = y+2; ver = x; PC_DispStr(ver, hor, " ", DISP_FGND_WHITE);hor = y+4; ver = x; PC_DispStr(ver, hor, " ", DISP_FGND_WHITE); hor = y+5; ver = x; PC_DispStr(ver, hor, " ", DISP_FGND_WHITE); hor = y+6; ver = x; PC_DispStr(ver, hor, " ", DISP_FGND_WHITE); hor = y+7; ver = x; PC_DispStr(ver, hor, " ", DISP_FGND_WHITE); hor = y+8; ver = x; PC_DispStr(ver, hor, " ", DISP_FGND_WHITE); hor = y+9; ver = x; PC_DispStr(ver, hor, " ", DISP_FGND_WHITE); break;}//OS_EXIT_CRITICAL();}void dis2Num(char x, char y, char num){char hor,ver;/*if(num == ' '){hor = y; ver = x; dis1Num(ver, hor, 11);hor = y; ver = x+14; dis1Num(ver, hor, 11);}else*/{hor = y; ver = x; dis1Num(ver, hor, (char)((num/10)%10));hor = y; ver = x+14; dis1Num(ver, hor, (char)(num%10));}}void taskdispDateTimeOpt(void *pdata){INT8U err;char hor = 10;char ver = 10;char pos,num,mode;void *msg;pdata = pdata;msg = OSMboxPend(mboxPosNumMode, 0, &err);for(;;){// msg = OSMboxPend(mboxPosNumMode, 0, &err);pos = *(6+(char*)msg);num=dateTime[pos];// num = *(2+(char*)msg);// mode = *(3+(char*)msg);switch(pos){case 0:hor = 0; ver = 0;break;case 1:hor = 0; ver = 0+28; dis2Num(ver, hor, num); break;case 2:hor = 0; ver = 0+56; dis2Num(ver, hor, num); break;case 3:hor = 11; ver = 0; dis2Num(ver, hor, num); break;case 4:hor = 11; ver = 0+28; dis2Num(ver, hor, num); break;case 5:hor = 11; ver = 0+56; dis2Num(ver, hor, num); break;// OSMboxPost(mboxDateTime, &dateTime);}// OSTaskSuspend(20);OSTimeDlyHMSM(0, 0, 0, 500);num=' ';dis1Num(ver, hor, num);dis1Num(ver+14, hor, num);OSTimeDlyHMSM(0, 0, 0, 500);OSMboxPost(mboxDateTime, &dateTime);// OSTaskResume(20);}// OSTaskResume(20);}void taskDispDateTime(void *pdata){INT8U err;char hor = 10;char ver = 10;char num;char lDateTime[6];char i;void *msg;pdata = pdata;for(;;){msg = OSMboxPend(mboxDateTime, 0, &err);for(i=0; i<6; i++){lDateTime[i] = dateTime[i];}num = lDateTime[0];hor = 0; ver = 0; dis2Num(ver, hor, num);num = lDateTime[1];hor = 0; ver = 0+28; dis2Num(ver, hor, num);num = lDateTime[2];hor = 0; ver = 0+56; dis2Num(ver, hor, num);num = lDateTime[3];hor = 11; ver = 0; dis2Num(ver, hor, num);num = lDateTime[4];hor = 11; ver = 0+28; dis2Num(ver, hor, num);num = lDateTime[5];hor = 11; ver = 0+56; dis2Num(ver, hor, num);}}void taskShow2Dot(void *pdata){INT8U err;char ver, hor;char dat[6];pdata = pdata;for(;;){OSSemPend(semHalfSec, 0, &err);OS_ENTER_CRITICAL();hor = 11+2; ver = 52; PC_DispStr(ver, hor, "MM", DISP_FGND_WHITE); hor = 11+3; ver = 52; PC_DispStr(ver, hor, "MM", DISP_FGND_WHITE);hor = 11+7; ver = 52; PC_DispStr(ver, hor, "MM", DISP_FGND_WHITE); hor = 11+8; ver = 52; PC_DispStr(ver, hor, "MM", DISP_FGND_WHITE);hor = 0+2; ver = 52; PC_DispStr(ver, hor, "MM", DISP_FGND_WHITE);hor = 0+3; ver = 52; PC_DispStr(ver, hor, "MM", DISP_FGND_WHITE);hor = 0+7; ver = 52; PC_DispStr(ver, hor, "MM", DISP_FGND_WHITE);hor = 0+8; ver = 52; PC_DispStr(ver, hor, "MM", DISP_FGND_WHITE);hor = 11+2; ver = 24; PC_DispStr(ver, hor, "MM", DISP_FGND_WHITE); hor = 11+3; ver = 24; PC_DispStr(ver, hor, "MM", DISP_FGND_WHITE); hor = 11+7; ver = 24; PC_DispStr(ver, hor, "MM", DISP_FGND_WHITE); hor = 11+8; ver = 24; PC_DispStr(ver, hor, "MM", DISP_FGND_WHITE);hor = 0+2; ver = 24; PC_DispStr(ver, hor, "MM", DISP_FGND_WHITE);hor = 0+3; ver = 24; PC_DispStr(ver, hor, "MM", DISP_FGND_WHITE);hor = 0+7; ver = 24; PC_DispStr(ver, hor, "MM", DISP_FGND_WHITE);hor = 0+8; ver = 24; PC_DispStr(ver, hor, "MM", DISP_FGND_WHITE);OS_EXIT_CRITICAL();OSSemPend(semHalfSec, 0, &err);OS_ENTER_CRITICAL();hor = 11+2; ver = 52; PC_DispStr(ver, hor, " ", DISP_FGND_WHITE); hor = 11+3; ver = 52; PC_DispStr(ver, hor, " ", DISP_FGND_WHITE); hor = 11+7; ver = 52; PC_DispStr(ver, hor, " ", DISP_FGND_WHITE); hor = 11+8; ver = 52; PC_DispStr(ver, hor, " ", DISP_FGND_WHITE);hor = 0+2; ver = 52; PC_DispStr(ver, hor, " ", DISP_FGND_WHITE);hor = 0+3; ver = 52; PC_DispStr(ver, hor, " ", DISP_FGND_WHITE);hor = 0+7; ver = 52; PC_DispStr(ver, hor, " ", DISP_FGND_WHITE);hor = 0+8; ver = 52; PC_DispStr(ver, hor, " ", DISP_FGND_WHITE);hor = 11+2; ver = 24; PC_DispStr(ver, hor, " ", DISP_FGND_WHITE); hor = 11+3; ver = 24; PC_DispStr(ver, hor, " ", DISP_FGND_WHITE); hor = 11+7; ver = 24; PC_DispStr(ver, hor, " ", DISP_FGND_WHITE); hor = 11+8; ver = 24; PC_DispStr(ver, hor, " ", DISP_FGND_WHITE);hor = 0+2; ver = 24; PC_DispStr(ver, hor, " ", DISP_FGND_WHITE);hor = 0+3; ver = 24; PC_DispStr(ver, hor, " ", DISP_FGND_WHITE);hor = 0+7; ver = 24; PC_DispStr(ver, hor, " ", DISP_FGND_WHITE);hor = 0+8; ver = 24; PC_DispStr(ver, hor, " ", DISP_FGND_WHITE);OS_EXIT_CRITICAL();// dat[0] = dateTime[6];// dat[1] = ' ';// dat[2] = 0;// OSMboxPost(mboxPosNumMode, dat);}}void taskTimeRefresh(void *pdata){INT8U err;char tmp=0;int year = 2011;char month = 5;char day = 18;char hour = 10;char min = 10;char sec = 12;char dayInMonthTbl[]={31,28,31,30,31,30,31,31,30,31,30,31,}; char dayInMonth;pdata = pdata;for(;;){#if 1OSSemPend(semSec, 0, &err);#elseOSTimeDly(2);cnt = OSSemAccept(semSec);if(cnt == 0)continue;#endifyear = dateTime[0]+2000;month = dateTime[1];day = dateTime[2];hour = dateTime[3];min = dateTime[4];sec = dateTime[5];if(month != 2){dayInMonth = dayInMonthTbl[month];}else{if((year%400==0)||(year%4==0&&year%100!=0)) {dayInMonth = 29;}else{dayInMonth = 28;}}sec++;if(sec >= 60){sec = 0;min++;if(min >= 60){min=0;hour++;if(hour>=24 ){hour=0;day++;if(day > dayInMonth){day = 1;month++;if(month > 12){month = 1;year++;}}}}}dateTime[0] = year-2000;dateTime[1] = month;dateTime[2] = day;dateTime[4] = min;dateTime[5] = sec;OSMboxPost(mboxDateTime, &dateTime);}}void taskTimeTick(void *pdata){pdata = pdata;for(;;){OSTimeDly(OS_TICKS_PER_SEC/2);OSSemPost(semHalfSec);OSTimeDlyHMSM(0, 0, 0, 500);OSSemPost(semHalfSec);OSSemPost(semSec);}}void taskKeyDeal(void *pdata){INT8U err;char key;pdata = pdata;for(;;){//OSTimeDlyHMSM(0,0,0,400);key = *(char*)OSQPend(qKey, 0, &err);OS_ENTER_CRITICAL();PC_DispChar(4, 23, (char)('0'+((key/100))), DISP_FGND_WHITE); PC_DispChar(5, 23, (char)('0'+((key/10)%10)), DISP_FGND_WHITE); PC_DispChar(6, 23, (char)('0'+(key%10)), DISP_FGND_WHITE); OS_EXIT_CRITICAL();OSTaskSuspend(20);OSTaskResume(22);if(key == 'q'){OSTaskSuspend(22);OSTaskResume(20);}// exit(0);//OS_ENTER_CRITICAL();if(key == 72) //UP{{dateTime[dateTime[6]]++;if(dateTime[dateTime[6]]>=24) {dateTime[dateTime[6]]=0;}}else if(dateTime[6]==2){dateTime[dateTime[6]]++;if(dateTime[dateTime[6]]>=31) {dateTime[dateTime[6]]=0;}}else if(dateTime[6]==1){dateTime[dateTime[6]]++;if(dateTime[dateTime[6]]>=13) {dateTime[dateTime[6]]=0;}}else if(dateTime[6]==0){dateTime[dateTime[6]]++;if(dateTime[dateTime[6]]>=99) {dateTime[dateTime[6]]=0;}}else{dateTime[dateTime[6]]++;if(dateTime[dateTime[6]]>59) {dateTime[dateTime[6]]=0;}}}else if(key == 75) //LEFTif(dateTime[6] == 0) dateTime[6] = 5;elsedateTime[6]--;}else if(key == 77) //RIGHT {dateTime[6]++;if(dateTime[6] > 5) dateTime[6] = 0;}else if(key == 80) //DOWN {if(dateTime[6]==3){dateTime[dateTime[6]]--;if(dateTime[dateTime[6]]<=0) {dateTime[dateTime[6]]=23;}}else if(dateTime[6]==2){dateTime[dateTime[6]]--;if(dateTime[dateTime[6]]<=0) {dateTime[dateTime[6]]=30;}}else if(dateTime[6]==1){dateTime[dateTime[6]]--;if(dateTime[dateTime[6]]<=0) {dateTime[dateTime[6]]=12;}}else if(dateTime[6]==0){dateTime[dateTime[6]]--;if(dateTime[dateTime[6]]<=0) {dateTime[dateTime[6]]=99;}else if(dateTime[6]==4||dateTime[6]==5){dateTime[dateTime[6]]--;if(dateTime[dateTime[6]]<0){dateTime[dateTime[6]]=59;}}}elsecontinue;//OS_EXIT_CRITICAL();// OSMboxPost(mboxDateTime, &dateTime);OSMboxPost(mboxPosNumMode, &dateTime);}}/************************End*************************************************/ 四.问题及解决在实验过程中,碰到了一些问题:时间调整上时间会一直加上去。