人人范文网 范文大全

uocsii和单片机结合的心得体会

发布时间:2020-03-02 03:06:51 来源:范文大全 收藏本文 下载本文 手机版

从寒假开始接触操作系统到今天初步完成一个基于STC89C52单片机,使用UC/OS-II微内核的时钟应用程序也有一段时间了.在这不长不短的一段时间里,可以说我每天都有新的发现.知识就是这样一点一点的积累起来的.我相信只要这样继续下去,我的水平一定能上一个层次.在没有看这本书之前,通过一些平时模糊的了解,就只能把进程这样的一些概念理解为许多个不同的应用程序在处理器上通过某种方法轮流地切换来实现处理器资源的使用率的最大化.还有更多的其他一些概念甚至是连听都没有听说过的.由于基础比较差,加上寒假在家里较封闭.少有信息获取渠道,所以在看这本书的时候比较吃力.可以说那一段时间看书真是一种煎熬.不过后来提前来了学校,情况就好多了.之前看书时有许多不懂的概念,在学校里可以通过上网查找资料了.最开始看到进程的时候,感觉进程就是跟之前理解的差不多嘛,但是当看到线程这里的时候一下子又蒙了.这个时候就把进程跟线程给弄混淆了,但是没办法,在家里条件艰苦,只好这样子带着混淆看下去啦.到了学校连了网立刻就在找到了一篇文章.它那里面举一个马车的例子来比喻进程与线程的关系.在后面的篇幅也很清晰的把进程和线程的各种关系说出来了.于是我就这样子理解:其实系统就是把一大堆资源分配给进程,由进程来管理它所获得的资源,它爱怎么用就怎么用.而线程又是进程里面的一小个环节.线程可以使用进程获得的资源来完成自己的事情.如果说进程要完成一个大的事情,那么它就必须把这样一个大的事情分成一个个小的事情.那么进程就是这些小的事情和必要的资源的集合,而线程就是完成这样一个个小的事情的实体.举个例子来说,比如一个人现在要做一道菜.如果我们把做一道菜看做是一个进程的话,那么我们先要找到这个会做菜的人.这个人就相当于我们的处理器.然后还必须要有煤气炉,锅.铲子.刀,一些调料之类等等一些工具,那这些就是我们必要的一些资源.我们的进程先要申请得到这些资源.首先我们要把做一道菜这个大任务分成一个个小的任务.这些任务包括有比如说切菜啦,煮水啦,炒菜啦,加调料啦,控制火候啦,还有等待啦.等等...而这些就可以看成是一个个线程了.那么当我们决定要做一道菜的时候可以看成是创建了一个进程了.接下来这个人开始做的时候就看做是进程开始运行了.首先这个人会开始切菜那这是第一个线程开始得到运行.就是在处理器上运行.切了一会的时候.他突然发现可以先煮一下水.那么他就会先放正在切着的菜转去煮水.这就是线程的切换啦.然后当把水放到锅里面去了就让它煮着吧,人不用去管它了.那这时处理器就可以空出来做其它的事情了.他可以返回去继续切菜,也可以转而去做其他事.我们假设他返回去继续切菜好了.当他切完之后就开始就开始炒菜了,而在炒菜的过程中他偶尔也可以做些其他事..如加调料啦.控制火候啦.等等.这样的一些工作可以是并发的.注意是并发不是同时.到最后必须要让这菜在锅里煮一下时.这时人也就是处理器就空闲下来了.他可以去做其他的事.那就相当于进程的切换了.只须要在菜煮熟的时候把它铲起来就行了.这样一个进程就算运行完毕了.当然我只是打了一个很粗略的比喻.并不能概括进程跟线程的全部关系.在后来当我看完了UC/OS-II的任务部分之后.虽然说UC/OS-II把进程和线程的概念模糊掉了,只有一个任务的概念.但是我还是不禁会把它跟进程跟线程联系起来.那这样的话我就认为UC/OS-II下只有一个应用程序.而把这个应用程序看作是一个进程.而把其中的每一个任务看做是一个个线程.不知道这样子理解对不对.好啦.进程跟线程好像纠结了好久的样子.其实在家里已经把这本书要看的章节都大概的看过一遍了虽然有看到进程的同步与通信那里有什么信号量啊,消息邮箱啊,还有消息队列之类,但是根本就不知道它们是什么东西.还有邵贝贝的UC/OS-II也看了一部分.只是由于第一次看看得相当纠心.只当是看天书了.所以到学校后.就拼命的找资料.看了一些操作系统比较基础的概念还有UC/OS-II的一些比较基础的东西之后.觉得操作系统那本书有必要再看一遍.但是后来第二遍还是没有看完,但是第二次看毕竟有不同看起来也比较没那么辛苦了.因为又发现了另一本更容易懂的讲UC/OS-II的书,就是任哲那本书.接下来的几天就一直看这本书了.他讲的还是比较浅显的.看完了他这本书之后呢又找时间看了一下UC/OS-II的源代码.感觉还是比较好懂的.这时候基本上对多任务的概念啊.任务之间的同步与通信啊及其具体的实现都有了初步的理解.接下来就讲一下我对UC/OS-II的理解吧.看过这样一篇文章说的是UC/OS-II的两个核心算法.该文章道出了UC/OS-II微内核的设计哲学:以空间换时间,因为UC/OS-II是一个嵌入式操作系统的内核.而大部分嵌入式讲究实时性.那要讲究实时性就必须知道任务切换的确定时间,而不应该因为任务数量而影响这个时间.因此UC/OS-II就是通过牺牲存储空间来保障其实时性的.两大核心算法其中一个是说基于优先级的任务调度的.Jean J.Labroe也就是UC/OS-II的作者使用一个数组OSRdyTbl[]来记录具有某一优先级的任务的就绪情况,称为就绪表.并用另一个变量OSRdyGrp以方便查询某一任务的就绪情况.另外再加两张表得出查询结果.这样查询某一任务的就绪情况的时间就变成了一个可以预测的值了.现在看起来, UC/OS-II本身内容并不多.也就是一个基于优先级的任务调度,一个任务切换,一个任务管理,一个时间管理,还有几个任务同步与通信的事件控制.如信号量.消息邮箱,消息队列.标志组,等等...先说基于优先级的任务调度吧,基于优先级就是近似保证在每一个时间段内都是优先级最高的任务处于运行状态.至于什么情况下才会需要任务调度呢.那就有很多种情况了,比如说正在运行的任务由于某种需要,自行挂起自身或者调用时间延时一段时间.在这种情况下就会产生任务调度.又比如说某任务释放一定的信号量或者其他的什么任务之间的同步与通信的事件,从而使具有更高优先级的任务处于就绪状态,这时也会产生任务调度.总之,一个任务有运行,就绪,等待,挂起,中断等等各状态,通过各种调度使得任务在这些状态之间来回变换.再说任务切换吧.任务切换其实就通过修改sp指针和任务堆栈来起来保存当前任务断点而转去运行另一个任务.这个在后面说到UC/OS-II的移植的时候再具体的讲吧.再来谈谈任务管理.任务管理需要一个叫做tcb的任务控制块.tcb里面保存有本任务所必要的一些基本信息.处理器根据这些信息来得到对应的任务.至于其他的一些比如任务的建立啊.任务的删除啊,任务的初始化啊等等的一些具体实现在这就不多说了.还有就是时间管理了,系统维护一个全局时钟,应用程序可以对这个全局时钟进行读写操作.同时任务控制块里有一个变量记录本任务需要等待延时的时间片数,通过时间中断逐一减少,等减到为零时,该任务重新返回到就绪状态..UC/OS-II的时间管理比较简单.至于任务之间的同步与通信,信号量,消息邮箱,消息队列都要使用到一个叫做ecb的事件控制块.里面主要有一个信号计数变量,一个消息指针.还有一个类似于就绪表的任务等待队列表.当一个任务申请得到一个信号或消息时,在有信号或消息的情况下,会立即给这个任务信号或消息,但是当没有信号或消息时,就会把任务送进任务等待队列,并挂起任务.直到有信号或消息或者等待超时.这里有衍生出来一个新的问题.就是如果在等待队列中有多个任务在等待.而信号只有一个,那么谁该得到信号并运行呢? UC/OS-II有两个解决方法,要么只给优先级最高的那个任务,要么通知所有等待的任务有信号了,至于该谁运行,那就要看谁的优先级最高了.好啦.UC/OS-II的基本部分都讲了,下面讲一下关于UC/OS-II在具体处理器上的移植吧.一般情况下的移植就是要把一些与处理器相关的内容做具体修改咯.那哪些是与处理器相关的内容呢?比如说C语言中的各种数据类型在本处理器上具体是多少个字节啊,一些硬件的接口啊.具体的任务切换啊,任务的堆栈分配啊.等等...所以我们就要根据具体的处理器做出相应的修改了.比较难的地方可能就是任务切换的设计吧.当然在开始任务切换之前我们必须先约定一下堆栈的协议.就是必须按照一定的出栈入栈的规则来操作堆栈,否则将不能正确的返回到断点继续执行.所以就要先写一个堆栈初始化的函数,先规定每一个断点信息在堆栈的位置.任务的切换前面提到了一点,就是通过修改sp指针和任务堆栈来起来保存当前任务断点而转去运行另一个任务.为了有更好的实时性,这些一般都是用汇编语言写的.我们可以想象,要进行任务切换,那首先你要先把当前的任务的断点信息给保存起来.否则将来要重新运行这个任务的时候怎样继续执行,难道要重新开始运行?当然不可能!所以要保存断点,那断点是保存在哪呢,当然就是刚才讲的任务堆栈啦.所以我们要做的事情就是先把断点保存在任务堆栈里,然后才能去取出另一个任务的断点,再从它的断点开始继续运行.说到断点,断点具体包括一些什么东西呢.比如说有pc指针啦.有cpu寄存器啦.psw啦.sp指针啦.这些都是断点的一部分.可是pc指针也就是程序断点地址我们是不能够直接操作的,即我们不能对它进行读写,那该怎么办呢.通常有两种方式可以引发pc指针自动入栈.那就是函数调用或者是中断出现.其中中断出现是随机的,不是我们能够控制的.但是函数调用我们是可以用的.所以我们一般是通过函数调用来模拟一次中断的出现.这样就可以做到pc指针自动入栈了.在硬件支持的情况下,我们可以直接把sp指针指到要运行的任务的任务堆栈的入口上去来导出断点.但是有些处理器可能硬件不支持.比如说51单片机,它的sp指针只有八位,而任务堆栈又一般是放在外部存储器上的,它的寻址需要两个字节.那sp指针就到不了任务堆栈而不能直接操作任务堆栈了.在这种情况下,我们只好在内部ram里开辟一个系统堆栈.对这个系统堆栈操作,然后通过复制的方法把它送到任务堆栈里.当然这又要花费一定的cpu时间了.所以从整一个切换的过程来看的话,那就是先使用入栈指令push按照先前规定好的入栈规则把断点信息保存在系统堆栈里.然后再把这个断点信息复制到任务堆栈里.接着从要运行的任务的任务堆栈里把断点信息复制到系统堆栈里去再使用出栈指令pop弹出到处理器的相应位置.说了那么多,还没有说明白到底怎样找到这个任务堆栈呢.原来在我们的任务控制块tcb里有一个指针变量专门用来指向它的任务堆栈的.那只要沿着tcb地址就能找到任务堆栈的地址了.对了,移植时还有一个地方可以用汇编语言写的.就是UC/OS-II的时间中断函数.UC/OS-II自身有一个时钟,这个时钟就是通过时间中断函数来确保的.中断的频率不同那时钟在每一秒钟内的节拍就不同.当我把UC/OS-II移植到51单片机的时候基本上就是按照上面的思路进行的.但是由于51单片机的特殊性,有些地方还是要注意的.比如说.UC/OS-II里面会用pdata,data等来做函数的形参.可是由于这些都是keil里面的关键字.如果不改的话就会报错.编译不通过.那么就必须把它们全部都改成其他的以防止编译器报错.还有一点就是由keil编译器编译通过的程序是不可重入的.但是我们要求UC/OS-II里的大部分函数具有可重入性.这样我们就必须在每个函数后面加一个reentrant关键字.还有我考虑到由于我们把任务堆栈放到了外部ram里了.那为了让可使用的任务数最大化,最好仅有的256个字节的外ram全部用于任务堆栈.那就必须把其他的东西搬到内部ram去了.其中任务控制块在外部ram占了很大一个空间.故后来我就在任务控制块的定义那里加了一个idata使其只能存放于内部ram,再修改了任务切换函数让它只在内部ram寻找任务控制块的地址.这样就能保证外部ram全部用于任务堆栈,从而可以容纳多一个任务吧.再有就是我又把UC/OS-II的空闲任务的任务堆栈减小到18个字节.因为空闲任务不需要那么多字节的堆栈空间.总之,我是想尽各种办法尽量节省存储空间了.经过这么一次实战的移植,我对UC/OS-II有了一个比较全面的理解,对程序的可移植性和模块化有了深刻的体会,对51单片机有了一个新的了解,对keil软件有了一个新的认识.首先我们现在接触的UC/OS-II它并不是一个完整的操作系统.它只是一个微内核,它缺少文件系统.缺少虚拟内存,可视化界面,它甚至还缺少一个现代操作系统所具有的时间片的概念,更不要说它没有进程和线程的清晰概念和独立的任务调度器.当然它有它的优点,至少它是一个专门为嵌入式设计的操作系统.由于它小,我们可以很容易地把它移植到各种资源不足的嵌入式系统中去.另外它的实时性能也很好.并且它提供了许多优良的功能,可以使我们更专注于应用功能的设计,而不用具体考虑如信号量这样的一些东西.至于UC/OS-II在51上跑吧,对于资源奇缺的51来说还是挺有鸭梨的.并且比裸跑速度要慢一些.对于程序的可移植性.如果在写程序的时候就考虑到可移植性的话并用配合模块化设计.那么当我们以后要再一次使用到同样的或者相似的功能时,就可以直接使用或者仅做一些小改动即可使用了.这样就方便许多了.而不必总是重复同一内容的编写.那样未免也太低级趣味了点...另外对51单片机也有了进一步的了解.以前竟然不知道原来STC内有内置256个字节的外部ram.真是惭愧啊.还有对堆栈指针和pc指针也有了新的认识.以前对sp指针还是有比较清晰的概念的.可是对pc指针就是全完摸不着头脑了.现在知道了pc指针不在我们的读写范围之内.我们要通过另外的方法间接对它操作.对中断的出现,对函数的调用等等也有了比较本质的认识了.对ret指令,reti指令也比较知道了.中断和函数调用都会引发pc指针自动入栈.所以两者在这一方面没有什么区别.比如说,使用函数调用进入任务切换再使用reti退出不会有什么不妥.但是如果用ret退出就不行了.因为reti指令在执行的时候会重新允许中断的产生.而ret不会做这样的动作.这就是两者的区别.还有对keil也有了一定的新的了解.keil中有些关键字还是很有用的.如data,idata,pdata,bdata,xdata,code.这些都是用来指明存储位置的.data指的是将变量存储在内部ram的低128个字节里,idata指可以将变量存储在内部ram的全部256个字节里.pdata是指外部ram的低256个字节.bdata指内部ram的位寻址区.xdata指外部ram 64kb的范围.最后一个code指的是程序存储区rom.还有一个关键字reentrant它可以告知编译器产生可重入代码.keil中可以设置变量的默认的存储位置,有三种.Small的模式,Compact的模式, Large的模式..Small模式是默认把变量存储在内部ram中, Compact模式是默认存储在外部ram低256个字节中,而Large模式则是整个64kb的外部ram中.移植完之后我就考虑开始写一个时钟程序了吧.虽然之前写过时钟程序,但是此次却是以一种完全不同的方式来写,这次是在有操作系统的情况下来.之前写的只有一个.C文件,没有头文件.写的完全浑然一体,毫无模块化可言.可是这次不同.是用一种自己之前不大熟悉的方式写程序.要考虑到任务的划分,优先级的安排,要考虑到模块化.还要让别人能够看懂.这每一件事都是不容易做的啊.现在写完了.也收获了许多.其中就包括头文件的使用.我觉得模块化最重要的就是要把本模块的一些具体实现封装起来,那么本模块的头文件就成了进出模块的唯一通道了.模块要引用的一些全局变量要在这里声明.模块本地函数要在这里声明.模块本地全局变量也要在这里声明.还有模块对外接口函数也是要在这里声明.这样那我们就可以通过#ifdef _模块名_C_..本地内容..#else..对外接口..#endif这样的形式来区分本地的声明与对外的声明.并且在本模块的.C文件里define _模块名_C_ 这样就可以包含模块所必须的信息了.而当其他模块要使用这个模块的时候,它也可以用include来包括这个头文件,不过这时它包括的就不是那个模块的本地内容了.而是它的对外接口.这样就不会出现重复包含的情况了.这是写多文件一个很好的方法.好啦好啦..该收手了.貌似写了好多.想我高考作文怎么挤也就挤出了那可怜的800多字.这次好像有敲有6300多字.真是吓到我了.本来还在担心能不能写够800字的.这是从昨晚开始写的.写到现在是第二天的下午五点多吧.原本我是不怎么喜欢写这样的一些东西的,但是现在写完之后感觉挻有用的.也重新梳理了一下自己的思路.写完了没有怎样修改.其中不少很荒谬的东西.看了不要拿砖头砸我哦...好了.终于把一些小小的心得,小小的体会敲完了.. 2011-3-10 17:23完

单片机心得体会

单片机实验心得体会

单片机课程设计心得体会

单片机学习心得体会

单片机课程设计心得体会

单片机实习心得体会

读单片机心得体会

自学单片机心得体会

单片机课程设计心得体会

单片机课程设计心得体会

uocsii和单片机结合的心得体会
《uocsii和单片机结合的心得体会.doc》
将本文的Word文档下载到电脑,方便编辑。
推荐度:
点击下载文档
点击下载本文文档