北京都哪有街霸5北京网通AE

在电子工程世界为您找到如下关于“STK单片机”的新闻
STK单片机资料下载
STK单片机选型表...
STK单片机相关帖子
本帖最后由 feiting94 于
18:32 编辑
还在玩emwin的小伙伴们,你们可以看看touchGFX啦,可以看看这个效果
什么是touchGFX?
它是一款UI设计软件,专为低功耗、低主频的cortex-m系列单片机打造
目前支持的芯片有
之前我在stm32论坛发了入门的知识,感觉太冷清了,还是来eeworld发帖子了
touchGFX...
& && &&&void& && && && && &&&Start(void (*task)(void),osPriority prio,void *stk,int stkSize);
& &nbsp...
Store2和数据表来保持更新你的信息,帮助你设计你的解决方案。具有很强的扩展的可能性和在线gallery3,无论它是可能的设计师和第三方提供的插件和定制的环境最好的利用和生产力。ATMEL工作室进行整合为AVR®和ARM GCC工具链,ATMEL AVR汇编程序和仿真软件框架。所有的新公司工具的支持,包括嵌入式调试器,AVR一!,jtagice MKII,jtagice3,实用,stk...
((OS_STK *)stk);复制代码新手提问:void *pdata 这个不太明白,在51单片机的KEIL中pdata是一个关键字,这样会不会冲突呢?
如果有一个任务是要一直执行的呢,比如我有一个任务是对串口数据不停的判断检测,那这样的话比这个任务优先级低的任务就一直得不到执行了。
楼主,下午一直在关注你的帖子,膜拜你。
我用的是STM32,移植是uC/OS官网上的。。你能不能把你移植的...
(),堆栈的初始化是要自己根据处处理器的特点编写的,51单片机在任务切换和中断来临时需要入栈的寄存器有12个:R0-R7,ACC,B,PSW,DPTR(DPH,DPL)共13个字节,在加上任务的地址(2字节),共15字节。
& &从上面看出OSTaskStkInit()函数接收4个参数:
task&&&&&&&nbsp...
俺搞单片机的,以前没接触过sim卡,现在要在一种叫CIU5180的51智能卡上做个stk菜单,无从下手。
在eeworld上看了1天资料,只了解各皮毛,这里请教给位大大了。
这样不可以不:首先做个初始化,接收,发送的程程序。卡上电后,初始化通信,设置波特率等,然后发送命令。
想做个stk菜单高人来帮帮忙 基本思路就是你这样的。
先可进行你的单片机的对应接口的初始化;
然后再给卡上电...
俺搞单片机的,以前没接触过sim卡,现在要在一种叫CIU5180的51智能卡上做个stk菜单,无从下手。
在eeworld上看了1天资料,只了解各皮毛,这里请教给位大大了。
这样不可以不:首先做个初始化,接收,发送的程程序。卡上电后,初始化通信,设置波特率等,然后发送命令。
想做个stk菜单高人来帮帮忙 基本思路就是你这样的。
先可进行你的单片机的对应接口的初始化;
然后再给卡上电...
资料的单张页面几乎是1.5mb,用打印机打印很慢 Re: [分享] stc单片机资料  如果你是一名单片机开发工程师,或者是一名即将从事单片机开发工作的朋友,在此向你推荐一款很不错的单片机--台湾STK单片机。
  STK单片机属于8051内核的单片机,和市面上的STC,SST,ATMEL,winbond,SyncMOS ,Myson等 51 单片机兼容。型号有:STK6031,STK6032...
我正在做SIM卡与STK相关的开发,看了了GSM11.11和GSM11.14,但是没有介绍与STK相关命令的编码值,比如FETCH(好像是0x12),ENVELOPE,TEMINAL RESPONSE,TERMINAL PROFILE。请问哪里可以找到相关内容?谢谢 请教:SIM卡中的STK命令是如何编码的 好像有本书叫什么 51单片机开发宝典的 好像是电子工业大学出版社的 上面好像有关于单片机...
经过近一个星期的战斗,现在的ucosii终于成功的移植到了avr单片机上,我发过帖子,觉得还是有很多朋友对这个比较感兴趣的,所以我把我记录的移植全过程及一些心得写出来与大家分享。
出于兴趣 ,本人也想再avr单片机上跑个操作系统玩玩,大家都知道,对于这样的单片机而言,ucosii当然是首选。
听说网上有现成的范例,偶用力搜搜搜,嘿嘿,结果搜到了两个例子,一个是8515的,另一个是103的...
STK单片机视频
STK单片机创意
你可能感兴趣的标签
热门资源推荐您访问的页面不存在
404页面内容正在努力加载中...
大家都在搜
公司主营:锯床备件,高速立式带锯床,金属切屑压块
公司简介:我司是锯床备件、压块机、吸屑装置、相关备件采购、技术转让等产品专业 公司主营:吹膜机系列,制袋机系列,印刷机系列,粉
公司简介:我司位于风景秀丽的东海之滨--瑞安市,是塑料包装机械专业生产企业。
公司主营:西门子PLC模块S7,300,ABplc,AB变频器,D
公司简介:我司是一家具有独立法人资格、集科、工、贸一体化的高科技企业,以生产 公司主营:炼油助剂,催化剂预硫化,抗磨剂,阻垢剂,
公司简介:我司是立足于炼油、乙烯、橡胶制造工业领域用化学品的生产销售及催化剂 公司主营:恒温摇床,超净工作台,生化培养箱,分光
公司简介:我司成立于2008年1月,注册资本伍佰零壹万元。是一家面向高等院校、科 公司主营:防静电炭黑,导电炭黑,半补强炭黑,环保
公司简介:我司专业生产导电炭黑、环保色素炭黑、炭黑N990,天然气炭黑,超细喷雾 公司主营:带锯机,带锯跑车,出榫机,铣边机,圆棒机
公司简介:佛山力威源木工机械厂地处“华南木工机械之乡”&&广东省佛山市顺德区 公司主营:氧化铁脱硫剂,氧化锌脱硫剂,锰铁脱硫剂
公司简介:四川省绵阳市江油创源科技净化有限公司是&家高新技术民营企业,专业从 公司主营:电动观光车,电动高尔夫球车,电动巡逻车
公司简介:我司座落于中国江南水乡苏州。是在国家倡导环保、低碳、节约型社会的东
您可能喜欢的产品最近几天工程师的朋友圈们都已经被STM32峰会相关消息刷……
一场Pokemon
Go,让全世界的小精灵师都暴露了。因此,在……
2016年初,一场人机大战点燃了人工智能芯片的争夺战,而……
伴随汽车高级辅助驾驶(ADAS)在过去几年的飞速发展,紧……
未来物联网世界到底是什么样子的?无线标准纷争最终究竟……
演讲人:张小平时间: 10:00:00
演讲人:Vincent Li时间: 10:00:00
演讲人:谢亦峰时间: 10:00:00
预算:小于¥5,000预算:大于¥100,000
详细介绍用51单片机解密任何红外遥控器
[导读] 在这里我仅把一些关键的带出来 关于硬件电路 那么抛开那么多文字介绍 最后意思就是说 你家里的遥控板 也就是发射部分 是把所有的封装好了的
比如键盘矩阵、编码调制、LED红外发送器 等等 那么接受部分 SM0038 3个脚
&在这里我仅把一些关键的带出来&关于硬件电路 那么抛开那么多文字介绍&最后意思就是说 你家里的遥控板 也就是发射部分 是把所有的封装好了的& 比如键盘矩阵、编码调制、LED红外发送器 等等&那么接受部分 SM0038 3个脚 一个脚地 一个脚电源 一个脚信号脚 接到 单片机随便个P口上(此处是P3。6) OK& 硬件部分就搞定了当然还有数码管显示&,这些肯定不用说你都能搞定吧,这些东东都有,所以就不用自己去搭电路那么麻烦了),那么 我们想 我们按一下遥控板 大家看到 有个灯闪了一下 然后OVER 那么 我们现在要做的就是在灯闪了那一下之后让 单片机来读它的键码 然后不同的键码来干不同的事&,本文 是向大家解释一种方法& 当然如果你知道遥控器的编码 那么 我想写解码程序应该是很简单的事 而我的意思是说我们现在从0开始& 拿到任何一种遥控板 那怕不知道它的型号 但是 大家想 即使它什么型号都没写 但是按一下不同的键 它的发射的脉冲 肯定不一样 无非就是引导码 然后 地址码 键码&验证码 因为不同的遥控板 它所定义的规则不一样 (这里说一点题外话 其实在读出波型后 大家就可以看出这个遥控板最开始设计时的人的意思 或者说考虑 它的这个设计方式是否是最好的 是否稳定 是否具有通用性 或者说 日本的和中国的设计师 在设计时他们所考虑的 名牌和 杂牌的 他们在设计时所考虑的 等等 这些其实也是件很有意思的事 就像偷窥到一个人的内心世界一样 扯远了 。。--)
& &下面我们来说说本文利用51单片机软件解密的方法,编码无非就是低电平高电平。但是我们知道一点 它肯定是有规律的&(这里申明一下 如果你能找到它的PDF 上面写好了它的波形 或者你在网上找到了前人把某型号的遥控器的波形已经分析出来了那么你完全可以把这篇帖子当水贴 跳过 我这里的目的是想通过一种方法 一种 完整的分析方法& 就像医生拿起手术刀 解开它的内部 看常人所不能看到的东西 最终能把一种很通用的东西 把它的内部原理能够完全的理解&一切从简单学起 做起 以后凡是涉及到 这种 类型的东西 相信你会更加自信 而不是只满足做一个课程设计 一个老师布置的作业&扯远了。。&&)
&&& 具体我们怎么记录这种规律 &很简单 我们用定时器把每个高低电平的时间记下来 然后显示在数码管上 设置2秒显示一个数据 然后用EXCLE记录下来
再用铅笔 或者 随便什么画图软件 把它的波形画出来 标上 低电平 高电平 再对比下不同的键的区别 一切就豁然开朗了
&现在举 实际的例子
万能遥控板大家应该都知道吧
此主题相关图片如下:图片 04.jpg
随便去那都能买到 几块钱 左右 安上电池 设置好型号(这里例子设置的是长虹 如果用家里的遥控板 那么不用设置了 )
&单片机上电 SM0038接好
& 关键程序如下 :(在这里我想鼓励下大家 不要一想到程序就是完整的 可以直接烧进去 看结果的 其实 我上个帖子也说过 你能看程序 看到关键的核心代码 那么说明你已经进步了 能找出其中的关键代码 其他比如SM0038的接口 数码管显示的接口 等等 自己加上去就行了 这段程序 的结果是最终把 脉冲波的个数 和每个高低电平的时间数 放在寄存器里 那么既然你要做的就是 用自己手边的单片机 把寄存器的值显示到 数码管上&把数据记录下来 然后分析&找出规律 得出你想要的结果 在这个过程中&我相信反是喜欢搞砖研的 都会享受这个过程&&&)&&&&&&&&&&&&&&&
&&&&&&&&& mov r5,#0&&&&&&&&&&& ;用于记录保存的时间值的个数
&&&&&&&&&& mov r1,#bmhcq&&& ;高低电平宽度值缓冲区
&&&&&&&&&& dec r1
&&&&&&&&&& jb&& p3.6,$&&&&&&&&& ;等待变低 , 即等待按键
next:&&&&& setb tr1&&&&&&&&&&&& ;启动定时器1
&&&&&&&&&& jnb p3.6,$&& ;& 等待变高,以测量低电平时间宽度
&&&&&&&&&& clr tr1&&&&& ;关闭定时器1&&&&&&&&&&&&&&&&&&&&&&&&&&&& ;1US
&&&&&&&&&& inc r5&&&&&& ;时间值个数加1&&&&&&&&&&&&&&&&&&&&&&&&&& ;1
&&&&&&&&&& inc r1&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ;1
&&&&&&&&&& mov @r1,th1& ;存低电平时间值 ,先存高8位,后存低8位&& ;2US
&&&&&&&&&& inc r1&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ;1
&&&&&&&&&& mov @r1,tl1&&&&&&&&&&&&&&&&&&&&&;2
&&&&&&&&&& mov th1,#0&& ;重赋初值&&&&&;2
&&&&&&&&&& mov tl1,#13& ;13为停止T1到重启T1经过的时间&&&& ;2
&&&&&&&&&& setb tr1&&&& ;重新启动定时器&&& ;1
&&&&&&&&&& jb p3.6,$&&& ;等待变低
&&&&&&&&&& clr tr1&&&&& ;关闭定时器1&&&&;1
&&&&&&&&&& inc r5&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ;1
&&&&&&&&&& inc r1&&&&&&&&&&&&&&&&&&&&&&&&&&&&&;1
&&&&&&&&&& mov @r1,th1& ;存高电平时间值&&&;2
&&&&&&&&&& inc r1&&&&&&&&&&&&&&&&&&&&&&& ;1
&&&&&&&&&& mov @r1,tl1&&&&&&&&&&&&&&;2
&&&&&&&&&& mov th1,#0&& ;重赋初值&&&&;2
&&&&&&&&&& mov tl1,#15& ;15为停止T1到重启T1经过的时间&&& ;2
&&&&&&&&&& ajmp next&&& ;循环检测,直到T1在遥控器无键按下时溢出时产生中断&& ;2
&&&&&&&&&& ajmp $
;-----------------------------------------
&;定时器1中断程序
&;在遥控器无键按下时产生中断,便依次将BMHCQ中的高低电平时间值转换为BCD码并显示出来
;-----------------------------------------
&&&&&&&&& setb tr0&&&&&& ;启动T0
&&&&&&&&& clr tr1&&&&&&& ;关闭T1
&&&&&&&&& setb et0&&&&&& ;T0开中断
&&&&&&&&& mov a,r5
&&&&&&&&& mov r2,a
&&&&&&&&& mov r3,#0
&&&&&&&&& lcall hextoxcq
&&&&&&&&& lcall display
&&&&&&&&& jb yszt,$&&&&&&&&&& ;延时一段时间,以便记录显示的时间值
&&&&&&&&& setb yszt
&&&&&&&&& mov r0,#bmhcq
dispnext: mov a,@r0&&&&&&&&&& ;从BMHCQ中依次取出时间值(16位)调BTOD子程序将其转换为5位BCD码并放入XCQ中再调显示子程序显示
&&&&&&&&& mov r3,a& ;取高8位
&&&&&&&&& inc r0
&&&&&&&&& mov a,@r0
&&&&&&&&& mov r2,a&& ;取低8位
&&&&&&&&& inc r0
&&&&&&&&& ;lcall BtoD&&&&& ;将高电平或低电平时间值转为BCD码放于XCQ中
&&&&&&&&& lcall HEXtoXCQ&& ;将高电平或低电平时间值转为十六进制的LED码放于XCQ中
&&&&&&&&& lcall display&& ;显示
&&&&&&&&& cpl p2.5&&&&&&& ;改变批示灯的状态,以此说明显示内容的改变
&&&&&&&&& jb&&& yszt,$&&& ;延时,以便抄录时间值
&&&&&&&&& setb& yszt
&&&&&&&&& djnz r5,获取的时间值没显示完则继续
&&&&&&&&& sjmp $&&&&&&&&&& ;显示完毕,在此踏步
&&&&&&&&& reti
&HEXtoXCQ:
&&&&&&&&& push 00h
&&&&&&&&& mov r0,#xcq
&&&&&&&&& mov a,r2
&&&&&&&&& anl a,#0fH
&&&&&&&&& mov dptr,#LED
&&&&&&&&& movc a,@a+dptr
&&&&&&&&& mov @r0,a
&&&&&&&&& inc r0
&&&&&&&&& mov a,r2
&&&&&&&&& swap a
&&&&&&&&& anl a,#0fH
&&&&&&&&& mov dptr,#LED
&&&&&&&&& movc a,@a+dptr
&&&&&&&&& mov @r0,a
&&&&&&&&& inc r0
&&&&&&&&& mov a,r3
&&&&&&&&& anl a,#0fH
&&&&&&&&& mov dptr,#LED
&&&&&&&&& movc a,@a+dptr
&&&&&&&&& mov @r0,a
&&&&&&&&& inc r0
&&&&&&&&& mov a,r3
&&&&&&&&& swap a
&&&&&&&&& anl a,#0fH
&&&&&&&&& mov dptr,#LED
&&&&&&&&& movc a,@a+dptr
&&&&&&&&& mov @r0,a
&&&&&&&&& inc r0
&&&&&&&&& mov @r0,#7eh
&&&&&&&&& inc r0
&&&&&&&&& mov @r0,#7eh
&&&&&&&&& pop 00H
&&&&&&&&& ret
&led:&&& db 7eh,30h,6dh,79h,33h,5bh,5fh,70h,7fh,7bh,77h,1fh,4eh,3dh,4fh,47h&&&&&&&&&&&&&&&&&&&&&&&&&
;---------------------------------------------
;将存于R3R2中高电平或低电平时间值转为BCD码放于XCQ中
;---------------------------------------------
&&&&&&&& push 00h
&&&&&&&& mov r0,#BCD
&&&&&&&& mov r4,#3
bd0:&&&& mov @r0,#0&&&&&& ;BCD缓冲区清0
&&&&&&&& inc r0
&&&&&&&& djnz r4,bd0
&&&&&&&& mov r6,#16
bd1:&&&& clr c&&&&&&&&&&& ;将R3R2中的16位二进制值转换为三字节BCD码存入BCD缓冲区中
&&&&&&&& mov a,r3
&&&&&&&& rlc a
&&&&&&&& mov r3,a
&&&&&&&& mov a,r2
&&&&&&&& rlc a
&&&&&&&& mov r2,a
&&&&&&&& mov r4,#3
&&&&&&&& mov r1,#bcd
BD3:&&&& mov a, @r1
&&&&&&&& addc a,@r1
&&&&&&&& da a
&&&&&&&& mov @r1,a
&&&&&&&& inc r1
&&&&&&&& djnz r4,bd3
&&&&&&&& djnz r6,bd1
&&&&&&&& mov r0,#xcq&&&&& ;将转换结果从BCD缓冲中存入XCQ中
&&&&&&&& mov r1,#bcd
&&&&&&&& mov r4,#3
bd4:&&&& mov a,@r1
&&&&&&&& xchd a,@r0
&&&&&&&& inc r0
&&&&&&&& swap a
&&&&&&&& xchd a,@r0
&&&&&&&& inc r0
&&&&&&&& inc r1
&&&&&&&& djnz r4,bd4
&&&&&&&& pop 00h
&&&&&&&& ret
通过上面的程序我们读出了按下一个键后的编码的本质的东西
& 那么动手把 图画下来 找规律 解码&
我把我例子长虹解码后的波形图 发出来
此主题相关图片如下:01.jpg 点击图片放大
&01。JPG 是脉冲开始时所有键前8个完全一样的高低脉冲
此主题相关图片如下:02.jpg
02。JPG 大家注意看按不同的键 中间只是有3个脉冲在变化 是EXCLE的 W列-AC列 而这3位数值就是我们解码的关键 01。JPG 中8位数 大家应该看出 所有键都是一样的 后面02。JPG中我们把键码整理出来就是&
按5键 。。。。。
后面就不写了
为了大家清晰可见 我把画出的最后的波形图03。JPG 贴出来 大家看下规律&
此主题相关图片如下:03.jpg 点击图片放大
然后我们 来分析应该怎么解码&我相信到了这一步应该很简单了吧 比如在这个例子中 我们发现 后面的键码改变的部分完全是重复&那么为什么完全可以不去读后面的码 只读前面的16位的脉冲 放在寄存器中 再用比较指令 跳转 下面是针对这个波形图的解码程序& 相信大家已经能用自己手中的利器 把它搞定了
写到这里 我觉得很疑惑 感觉自己没能把具体问题简单化& 很多东西还是要*大家自己去消化理解了
& 程序看不懂。?那么OK& 去翻指令 查书 一条一条看吧& 程序我敢保证都是 编译通过的
下面是解码程序的关键代码 :&
DYKJZ:&&&& JB&& P3.6,$
&&&&&&&&&& LCALL YKJM& ;核心解码代码子程序
&&&&&&&&&& cpl a
&&&&&&&&&& jz&&& no&&&& ;判断是否为错误代码(0FFH)
&&&&&&&&&& cpl a
&&&&&&&&&& AJMP JZPD
NO:&&&&& LJMP& DYKJZ
&&&&&&&&&&& RET&
JZPD:&&&&CJNE A,#09H,JZ1& ;键码为09H吗?
&&&&&&&&&&& AJMP KAIS&&&&&&&&&&& ;键码为09H 转开始程序()
JZ1:&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ;不为09H 转最开始 等待下一次遥控器按键到来
&&&&&&&&&&&&AJMP DYKJZ&&&&&&
&&&&&&&&&&& RET
KAIS:&;放你需要执行的代码&
&&&&&&&&&&&;比如 点亮一个灯&给单片机接上串口&& 用单片机控制电脑的打开 放音乐。等等&
&&&&&&&&&& ;这些不属于本问讨论的范围 有兴趣的可以自己扩展
&&&&&&& RET
;-----------------------
& ;核心解码代码子程序
;------------------------
&&&&&&&&&& PUSH&&&&&&&& PSW
&&&&&&&&&& PUSH&&&&&&&& 02H
&&&&&&&&&& PUSH&&&&&&&& 06H
&&&&&&&&&& PUSH&&&&&&&& 07H
&&&&&&&&&& PUSH&&&&&&&& B
&&&&&&&&&& MOV&&&&&&&&& B,#0FFH
&&&&&&&&&& JNB&&&&&&&&& TF1,JMCW&&&&&&&&&;通过T1从0开始定时到溢出来避开遥控器的重发码 ,也就是说在读了一个遥控按键后
&&&&&&&&&& CLR&&&&&&&&& TF1&&&&&&&&&&&&&&&&&&&;到少要等到T1从0开始定时到溢出才能读取第二个按键
;引导码正确时执行以下代码
&&&&&&& ;&& CLR&&&&&&&&& YKBZ&&&&&&&&&&&&&&;遥控标志清0
&&&&&&&&&& MOV&&&&&&&&& R2,#16&&&&&&&&&& ;每次循环读8位码
&&&&&&&&&& MOV&&&&&&&&& R6,#0&&&&&&&&&&&& ;存放16位码中的低8位
&&&&&&&&&& MOV&&&&&&&&& R7,#0&&&&&&&&&&&& ;存放16位码中的高8位
&&&&&&&&&& JNB&&&&&&&&& P3.6,$&&&&&&&&&&&&&;等待低电平结束,不管其宽度,因为是通过高电平的宽度来区分0(约为0.5ms)和1(约为1.6ms)
&&&&&&&&&& MOV&&&&&&&&& TH1,#0
&&&&&&&&&& MOV&&&&&&&&& TL1,#0
&&&&&&&&&& SETB&&&&&&&& TR1&&&&&&&&&&&&&&&;启动T1,统计高电平的宽度
&&&&&&&&&& JB&&&&&&&&&& P3.6,$
&&&&&&&&&& CLR&&&&&&&&& TR1
&&& MOV &&A,TH1
&&&&&&&&&& CJNE&&&&&&&& A,#2,JM4&&&&&&;若高电平宽度值大于2,则说明此高电平为宽脉冲(1),否则为窄脉冲(0)
JM4:&&&&&& CPL&&&&&&&&& C&&&&&&&&&&&&&&&& ;当TH1的值大于2时,C=0,小于2时,C=1
&&&&&&&&&& MOV&&&&&&&&& A,R7
&&&&&&&&&& RRC&&&&&&&&& A
&&&&&&&&&& MOV&&&&&&&&& R7,A
&&&&&&&&&& MOV&&&&&&&&& A,R6
&&&&&&&&&& RRC&&&&&&&&& A
&&&&&&&&&& MOV&&&&&&&&& R6,A
&&&&&&&&&& DJNZ&&&&&&&& R2,JM3&&&&&&&&& ;连读16位,先读的为低位,后读的为高位,高8位(数据码)存于R7中,低8位(地址码)存于R6中
&&&&&&&&&& MOV&&&&&&&&& A,R6
&&&&&&&&&& CJNE&&&&&&&& A,#47H,JMCW&&&& ;判断地址码是否为47H,不是转出错返回
&&&&&&&&&& MOV&&&&&&&&& A,R7&&&&&&&&&&& ;若地址码正确,则R7中便为数据码
&&&&&&&&&& mov&&&&&&&&& r1,#jzh
&&&&&&&&&& mov&&&&&&&&& @r1,A
&&&&&&&&&& LJMP&&&&&&&& JMFH
JMCW:&&&&& MOV&&&&&&&&& A,B
JMFH:&&&&& CLR&&&&&&&&& TF1&&&&&&&&&&& ;T1的溢出标志清0
&&&&&&&&&& MOV&&&&&&&&& TH1,#0&&&&&&&&& ;为T1设定初值并启动它
&&&&&&&&&& MOV&&&&&&&&& TL1,#0&&&&&&&&& ;以此来避免对同一按键读两次(避开遥控器的重发代码)
&&&&&&&&&& SETB&&&&&&&& TR2
&&&&&&&&&& POP&&&&&&&&& B
&&&&&&&&&& POP&&&&&&&&& 07H
&&&&&&&&&& POP&&&&&&&&& 06H
&&&&&&&&&& POP&&&&&&&&& 02H
&&&&&&&&&& POP&&&&&&&&& PSW
&&&&&&&&&& RET&&&&&&&&&&&&&&&&&&&&&&&&& ;此时,若引导码、地址码、键值码和键值反码中有一个有问题,A中便为错误代码,否则,A中便为所按键之键值码
&文章写完了。希望能对大家有少许的帮助。
美国政府的监听手段不绝如缕,除了此前曝光的多种方式,今晨维基解密又曝光了一个美国监听的手段,也和HT有关。7月20日消息,据国外媒体报道,美国波音的子公司Insitu正希望能够通过无人机传播监控软件,用以攻击用户的电脑。这是继可空中劫持其他......关键字:
在1号店快速发展的同时,还有一个不能忽略的大环境就是中国电子商务市场的快速发展。据艾瑞咨询的调查报告的数据显示,中国电子商务的教育规模一直从2008年的2.9万亿元增长至2011年的7万亿元。一位电子商务业内人士曾......关键字:
上个月维基解密网站曝光美国国家安全局NSA监听三任法国总统的震惊还未消散,近日法国媒体报道,法国情报机构同样在利用海底电缆监听世界,美国同样被监视。刚刚还一副受害人面目的法国转身就成为与美国一样的恶霸,真是上演了一番现实版的无间道。报道称,......关键字:
FZ-MCU51单片机开发板集实验开发、编程、仿真和下载于一体,支持AT89S51、AT89S52、AT89S53的和STC系列单片机如STC89C53RC等全系列单片机的编程和实验,使用配套的仿真模......关键字:
6月20日,在《阿甘正传》里有一句台词将亘古流传:&人生就像一颗巧克力,你永远不知道下一颗是什么。&对于科技圈来说,令人瞠目结舌的技术总在下一秒诞生。日前,特斯拉CEO马斯克表示,&当遇到积水......关键字:
随着2016年年报数据落定,三大运营商高管薪酬情况也浮出水面。......关键字:
我 要 评 论
热门关键词查看: 4131|回复: 21
51单片机的分时任务管理系统设计_coos
& &最近开始为51写一个分时任务管理,取名coos,终于也差不多把功能完善了,趁这几天还有点冲动发布上来吧。Coos最大的特色:完全用C语言实现。让我不禁原创一句:敲一敲键盘,不留下一句汇编。呵呵~~~接下来吐槽一下先。
吐槽 在51上实现任务管理?省省吧,有时间不如去搞arm,Linux?那才是高深技术!如果你是这样想的,那这篇文章你没必要再看下去了…….如果你觉得不把51玩个透彻,使尽脑汁就是要把它发挥到极致,就像PC上很多高手,听说有不少人拿CPU来超频,玩得可以闻到烧焦味,偶尔主板冒起烟来,甚至时不时地喷出火花(那种感觉是帅啊~~)。就算不是发烧友,但至少温度稍高一点点吧。如果是这样的话,那么,兄弟………………..知音呐!呜呜呜,海内难道真的存知己?
还是转入正题吧。貌似已经有不少高手为51写系统了,ucos也算是可以移植到51上(我没测试过),嵌入式实时内核,但是毕竟占用资源太多,而且让我感觉学术性大于使用性,好像很少人用?(至少我没用过)。俺的分时任务管理,算不上系统,估计也经不起什么考验,不过俺还是写了出来,毕竟自己写的东西自己用着才舒服嘛。老是用别人提供的玩久了也无聊。慢慢完善俺的coos吧,下次在把它移植到stm32上,嘿嘿~~
为什么写这个分时任务管理?嗯,这个问题问得好!(口气来自9527…)。这学期上了一门课,微型计算机原理与接口技术,加上看了ucos一点点任务管理代码,心里那个是不淡定啊。感觉任务管理也不难,何不尝试自己写一个任务管理?再加上本人实在无聊,就决定写出这个无聊的任务管理了。
Coos的命名 先说一下命名,本人网名coolweedman,操作系统简写为OS,coolweedman+OS让我只能想到coos,所以就命名coos了,译音“裤子”,在51上跑coos,我就想到了给51穿一条裤子呵呵,习惯裸跑,偶尔加条裤子感觉还行。
Coos的任务管理原理说一下任务管理的原理。学过微机的同学就知道,无非是直接或间接去修改PC指针。没错。我这里是间接修改PC指针的。怎么个间接法?利用出栈来修改!如果入栈的时候PC指针入栈,那么出栈的时候就是对PC指针的修改了。只要控制出栈时PC指针的值,就可以实现任务调度了。具体做法是:1.& && &定时器产生中断(分时的依据)2.& && &中断引起入栈,(PC指针入栈,其他寄存器也有)3.& && &定时器响应函数判断需要执行哪个任务4.& && &修改SP指针为相应任务的SP,(注意不是PC指针)5.& && &定时器按照相应的SP出栈,实现间接修改PC指针(任务调度)大概思路就是这样,算是伪代码吧。然后把相应的伪代码用C语言实现,就完成了(当然其中还有很多细节部分,编写代码时才会发现)。
Coos的任务管理机制 再说一下任务管理机制吧。分时任务管理,一个周期20个时间片(多少个可配置,时间片具体时间也可配置),在这20个时间片上,运行任务。coos最多管理8个任务(多少个可配置),每个任务时间片在创建时候指定。比如有5个任务,时间片分别为2,3,10,11,6。那么coos执行任务是这样的。
任务1执行1个时间片
任务2执行1个时间片
任务3执行1个时间片
任务4执行1个时间片
任务5执行1个时间片
(已占用5个时间片)
任务1执行1个时间片
任务2执行1个时间片
任务3执行1个时间片
任务4执行1个时间片
任务5执行1个时间片
(已占用10个时间片)
第三次:(任务1的2个时间片执行完,不执行任务1)
任务2执行1个时间片
任务3执行1个时间片
任务4执行1个时间片
任务5执行1个时间片
(已占用14个时间片)
第四次:(任务2的3个时间片执行完,不执行任务2)
任务3执行1个时间片
任务4执行1个时间片
任务5执行1个时间片
(已占用17个时间片)
任务3执行1个时间片
任务4执行1个时间片
任务5执行1个时间片
(已占用20个时间片)
一次系统周期结束(一次任务循环),coos重新刷新时间片。也就是5个任务,时间片分别为2,3,10,11,6。然后按照任务时间片去执行。
这样就实现了所谓的分时任务管理了。因为是分时,所以如果有多个任务,没有一个任务可以占用全部CPU,各个任务都是平等的,呵呵。
这样的效果是,如果有多个任务,那么,每个任务占用CPU必然减小,就像平时Windows开了太多任务,就会觉得有点卡。哈哈~~~
Coos的使用最后说一次怎么使用吧。coos包含文件:(6个)Coos_typedef.h& && &类型定义
Coos_conf.h& && &&&coos配置,相当于裁剪
Coos.c& && && && & coos实现的源文件
Coos.h& && && && & coos实现的头文件
Coos_hook.h& && &&&coos钩子函数头文件
Coos_hook.c& && &&&coos钩子函数源文件
包含这些文件之后,主函数只要调用几个coos函数就可以实现分时任务管理了。举个例子:
void main(void)
OS_Init();&&//coos初始化
OS_TaskCreate(Task_One, Stk_TaskOne, 5,0);
OS_TaskCreate(Task_Two Stk_TaskTwo, 2, 1);
OS_TaskCreate(Task_Thr, Stk_TaskThr, 7, 2);
OS_Start();&&//coos开始运行, 任务交给coos管理
结束语简介到此结束,再慢慢为coos写一份说明书吧,呵呵,源码开发下载,上传在我的百度网盘上。欢迎同学们下载,当然coos会有bug,但是我还没有发现,还请同学们多多支持多多反馈啊!!
第一章前言第二章coos简介第三章任务管理详解第四章任务管理的幕后操作第五章任务管理的幕后操作第六章coos条件编译第七章coos的配置 裁剪 类型定义
前言(以下所说的51特指STC89C52RC,晶振12M)
&&经过了七七四十九天的闭关修炼,终于把51的分时任务管理实现了?
有点夸张。从产生为51写任务管理的念头,到开始着手写代码,应该有3,4天的时间。然后接下来就一直写个不停了。本来是从开始写到第二天,功能就实现了,剩下的就是慢慢完善。但是,事情总是没那么顺利,发现了一个又一个的bug,修改完一个又有另一个,再修改一个。这样持续了好几天。有时候一整天没解决一个bug …
修改bug就是每天晚上睡不好,老是想着coos的bug,失眠是必须的。到最后发现了一个致命的bug,发现不得不用汇编来解决,然后就尝试着C语言嵌入汇编,但却偏偏一个C语言函数汇编出来的代码执行有错…让我只能怀疑编译器的问题的,因为本来没嵌入汇编那个函数是正常的,嵌入汇编后,函数的返回值传递出错了(编译器把返回值放到R3还是哪个忘记了,然后却从R4取返回值?问题我至今仍未能理解),我只能崩溃了。最后终于还是上火了,感冒发烧头痛…到校医院看病额。
&&把coos搁一边一两个星期了,心里那个还真是不爽。把代码全部重写,并用回了最初的设计思想,任务调度完全在中断里面实现,让中断负责任务切换所有工作,参考着自己上次写的代码,老样子,功能是一两天就实现了,幸运的是这次调试没发现什么bug。然后,这样一搁又是好多天。
在电脑上安装win8来玩玩,挺新鲜的,界面也挺好看。期间曾一度因为在win8上运行不了RVMDK而让我再度崩溃多次。最终放弃win8,用回win7。
&&重新在win7上把coos完善。也就是多写了一些函数。像延时,任务删除,条件编译等等,也是搞了好多天,每个函数都需要调试看看正不正确啊…
&&当然最终功能也差不多,而且发现暂时已经不想再写下去了,就发布一下新浪博客。虽然我知道没人看,但是因为以前在网上看到一句话,原话我忘记了。意思就差不多是:经历了一段时间的学习,最好最后把学到的东西记录下来,走的弯路也记下来,不然留不下什么东西,最终忘记了也就像一无所获。学到的东西最好是发到网上分享。这些话我是接受了,因为我也是经常在网上下载别人的资料学习,所以这次我就发了出来…虽然没用。就当留作纪念吧呵呵。
第二章& & coos简介
&&coos是一个专门为51写的分时任务管理,完全由C语言实现,传统的任务管理总会涉及到汇编,因为有些操作是C语言实现不了的,例如出栈入栈,现场保护等。设计coos是我就试着尽量减少汇编代码,到最后居然真的实现了零汇编,是最理想的结果。不过我得先说明的是,任务管理的话,我也觉得从汇编的角度去理解效果会好一点。
coos是利用51的定时器0中断作为分时依据,进入中断后判断需要运行哪个任务,中断退出便切换到相应的任务去执行,实现了任务调度。这种管理机制类似于我们熟悉Windows,例如我们平时在Windows上运行多个任务时,有时会觉得卡。coos也一样,如果任务多了,每个任务占用的CPU必然就减少,给我们的感觉也是有点卡。
&&分时笼统的讲就是把一秒钟(比较容易理解的单位)划分周期,我这里是划分成10个周期,每个周期100ms,然后每个周期划分成20个时间片,每个时间片为5ms,也即是每个任务运行时间的最小单位是5ms(一个时间片)。一个周期有20个时间片,当有多个任务时,每个任务轮流运行一个时间片。还需要说明的是一个周期有20个时间片,每个任务一个周期运行多少个时间片需要设置。例如有2个任务,其中一个任务设置运行时间片为4,另一个设置运行时间片为50,那么在coos管理的一个周期中,任务一运行4个时间片,任务二运行16个时间片。如果没创建新任务或者删除任务的话,下个周期也是这样执行。
&&当然为了让coos更灵活,我也用了不少的条件编译。实现可配置,可裁剪。例如一个时间片的时间是5ms还是其他,用户可自行配置。一个周期有多少个时间片也可配置。当然还提供了不少函数,例如任务删除,任务主动放弃CPU,系统延时等。因为有些实在不需要用到,所以用条件编译实现可裁剪。尝试了裁剪掉除任务管理以外的功能,coos占用RAM :44Byte + 1bit,code:692
&&还需要说的是coos的包含的文件。coos.c& && && && & 任务管理实现源文件coos.h& && && && & 任务管理实现头文件coos_hook.c& && &&&钩子函数源文件coos_hook.h& && &&&钩子函数头文件coos_conf.h& && &&&任务管理配置头文件coos_typedef.h& && &类型定义头文件
coos的实现由coos.c完成,是coos最核心的文件。coos_typedef.h是为了coos的移植性需要加入的,定义coos使用的变量类型,如uint8_tcoos_conf.h是coos的配置文件,实现的可裁剪功能都在这个文件设置,也就是条件编译的开关。coos_hook.c钩子函数源文件是由用户实现的,类似于ucos的钩子函数,例如选择启用任务调度的钩子函数,用户将自己的钩子函数写好后每次任务调度都会调用任务调度的钩子函数。
第三章 任务管理原理
&&在这里最重要的是要知道PC指针是什么?翻译成中文是程序计数器,它保存的是CPU下一个指令的地址。下一个指令是什么?PC指针不知道,但是它知道下一条指令放在哪里,就是PC指针指向的那个地址的内容。修改了PC指针,就修改了下一条指令的位置,PC指针指向哪里,CPU就运行哪个指令。任务调度就是通过修改PC指针实现的,我这里是间接修改PC指针,当然修改前要将它保存,也就是入栈操作。修改它就是通过出栈操作完成的。还有51的PC指针是16位的。入栈占用了两个字节。下面再详细介绍:先看任务管理函数的截图。
功能看截图就大概可以理解了。我再说明一下大概思路:606行之前:51产生定时中断,C语言看不到的入栈操作:包含R0~R7,ACC,B,DP0L,DP0H,PSW,还有最重要的PC指针,也就是现场保护。606行:一个赋值语句,保存的是当前的SP(栈指针),保存在当前任务的任务控制块里面607行:也是赋值语句,修改当前的SP,将当前栈指针修改为定时器函数专用的栈609~627行:先别管629行:赋值语句,修改SP指针为下一个任务的SP指针,中断退出将按下一个任务的任务栈出栈,出栈时修改了PC指针,实现了现场还原和任务调度
至于为什么要这么做我也说明一下。任务调度最重要的就是现场保护和现场还原了。现场保护利用的是51产生中断时的入栈操作,这是C语言不用管也管不了的。现场还原是利用51退出中断的出栈操作,也是C语言所管不了的。虽然说不用管,但是大部分时候现场保护并不完全。我们需要将每个任务用到的寄存器都入栈。经调试发现,51入栈机制是,在中断服务程序有用到的寄存器就一定会入栈,PSW和PC是一定会入栈的。
为了现场保护完全,我在中断服务函数里面,用C语言把每个通用寄存器都访问了一遍(因为有一些通用寄存器没入栈保护),所以每个通用寄存器都入栈。其他像ACC,B寄存器等也入栈了。这些操作在606行之前完成的。要看汇编出来的代码才知道,所以说任务管理还是从汇编的角度去理解好一点。然后现场还原就好办了。只要在中断服务函数退出前修改SP指针(629行),SP指针在中断服务函数就保存在相应任务的任务控制块了(606行),629行一个赋值语句的作用就是,中断会按照相应的任务栈出栈(在606行保存的SP的值),之后会还原寄存器和PC指针,实现了任务调度。只要修改了PC指针,程序就跳转到相应的位置执行,而PC指针在中断服务函数里面已将入栈保存起来了,出栈后就切换到上次该任务执行的断点位置,实现任务的继续。
&&能理解这些操作就好办了,简单的说就是定时器产生中断会引起入栈,退出中断会出栈,每个任务的任务栈不同,入栈由51中断的现场保护完成,出栈由51中断的现场还原完成。任务切换需要做的就仅仅是在退出中断前修改出栈的SP指针(栈指针),629行就完成这个功能。剩下的就是51的现场还原了。还原后就回去上次被中断的任务的断点处所,继续执行上次被中断的任务。
&&详细的任务管理将在下一章继续介绍。
第四章 任务管理详解
&&有了上一章的任务管理原理的基础,来理解整个中断响应函数的功能就容易多了。继续上一章的截图。(大概浏览一下代码,不到20行)
609~612行,624~627行。这两个实现相同的功能,为定时器赋初值,条件编译的条件为是否使能精确延时,条件编译结果是选择其中的一个。在coos_conf.h文件里有:#define& & OS_ACRT_TIM_EN& &&&0也就是默认没有使能精确延时,如果需要使能精确延时的话只要将0改为1就行了。说明一下65535 - OS_TICK_CNT + OS_ETR_TICK_TIMOS_TICK_CNT& && & 是定时器计数个数,可配置(coos_conf.h),默认5000,分时时间片OS_ETR_TICK_TIM& &是定时器响应周期,也就是入栈所用时间,默认0x2A
使能精确延时的结果是,coos提供的时钟对外是比较精确的,例如做一个定时器时钟,可以比较精确的运行一段时间。但是每个任务执行的时间却减少了,因为中断响应函数的执行也是需要时间的,这对于分时任务管理来说是不公平的,因为任务调度的时间是不一定相同的,导致任务执行的时间也不一定相同。没有使能精确延时,那么coos提供的延时默认是5ms + 任务调度的时间。分时任务管理的话,每个任务是公平的,执行的时间相同。但是coos提供的延时对外是不精确的。
&&接下来看一下619~621行。条件编译,条件是如果使能定时器钩子函数,在配置文件里是否使能(coos_conf.h)。函数OS_Hook_Tick()在coos_hook.c文件,默认函数体为空,该函数由用户实现。
&&最后就剩下614~617行,三个函数了,一个一个来,都是比较好理解的。先看最简单的617行,OS_ResSav();该函数访问通用寄存器,引起定时器中断函数执行前,通用寄存器入栈(中断服务函数访问到哪些通用寄存器,那些通用寄存器就会入栈),具体代码是:540行:让res_ptr指向0x00,也就是51的工作寄存器组0的R0,这个还是从汇编的角度去看会好理解一点。51的256Byte的RAM,前8Byte * 4是四个工作寄存器组。542~549行:访问通用寄存器,用下标的形式访问,自己给自己赋值,分别访问R0,R1…R7,实际寄存器值没改变,目的是要在定时器函数执行前将通用寄存器入栈。完善现场保护工作。
接下来看614行,OS_TickTimDeal();代码也是相当简单的,看截图该函数处理coos的时间,由于是分时任务管理,当然要知道当前运行到哪个时间片,并且每个任务一旦运行了一个时间片,也要将时间片减一。499行:当前任务时间片减一,也就是当前任务运行了一个时间片501行:系统时间片加一,分时管理任务,当然要有一个变量(OS_Tick)记录当前时间片
502行:OS_TICK_PERIOD系统时间片周期,默认为20,判断是否满一个周期504行:满一个时间片周期,时间片清零505行:满一个时间片周期,置位系统周期标志位
508行:判断是否满一个系统周期,标志位是在505行置位的510行:满一个系统周期,标志位清零512行~518行:条件编译,如果使能系统提供参考时间,也就是延时时间才编译这几行&&513行:系统时间加一&&514行:如果时间满一个时间周期&&516行:时间清零520行:调用任务时间片初始化函数,重新刷新任务时间片,具体代码如下截图477行:一个for循环,循环次数为任务个数,其中OS_TASK_NUM可配置,最大为8479行:for循环的循环体,OS_TaskTimGrp数组记录任务时间片,这里是按照任务创建时的时间片去刷新481~483行:条件编译,如果使能系统空闲任务。系统空闲任务是指在一个系统周期内(例如20个时间片内),如果没有可运行任务(只需要执行不到20个时间片的任务),也就是创建的各个任务时间片已经执行完,但是一个周期还没到,就执行空闲任务。coos默认提供的空闲任务是让51进入低功耗模式,省电。当然可配置,用户可以自行创建空闲任务。482行:刷新空闲任务时间片
任务调度还剩下最后一个函数,继续任务调度那张截图:看615行最后一个函数:目的是获取下一个需要执行的任务,为切换任务做准备具体函数代码如下截图:
该函数的思路是:在任务状态表上查找下一个任务。任务状态表是579行的OS_TaskStatGrp,是一个8bit的变量,每一位为0或者为1代表是否创建了任务,1表示创建了任务,当然最多支持8个任务。查找到有创建的任务,然后判断该任务时间片是否为0,如果不为0,那么下一个任务就是被查找到的任务,如果为0,那么继续查找下一个任务。如果所有被创建的任务时间片都为0,那么返回OS_TASK_NUM,代表着下一个任务执行的是空闲任务。567行:为id赋初值,为当前执行任务的id568行:i初值为0,循环控制用570行:进入循环,循环次数为coos管理任务的个数,由OS_TASK_NUM决定,可配置&&572行:进入了循环,循环次数加一&&573行:id加一,表示下一个任务&&574行:判断id是否溢出,超出coos管理任务的个数&&676行:id溢出则清零579行:重点!!判断该id的任务是否需要执行,判断的条件有两个,分别是:1、在该id上创建了任务2、该任务时间片不为0
前半部分:(OS_TaskStatGrp & SET_BIT(id))OS_TaskStatGrp是coos任务状态表,8bit,每一位代表一个任务,为1表示创建了任务SET_BIT()是一个宏操作,代码是#define SET_BIT(i) (1 && i)表示置位某个位,这里SET_BIT(id)是置位id那一位操作(OS_TaskStatGrp & SET_BIT(id)表示判断在任务状态表上判断id那一位是否创建了任务后半部分:OS_TaskTimGrp[id] & 0判断任务时间片数组上该任务时间片是否为0如果满足前半部分和后半部分都为真,那么就需要切换到的任务就是临时变量id了。所以就有:return id;
当然如果不能同时满足两个条件,就return&&OS_TASK_NUM;表示下一个任务是空闲任务。
至此,任务调度讲解是完了,不过还是再总结一下:1、 进入任务调度函数前(定时器中断服务函数),有C语言看不见的入栈操作,保存了寄存器和PC指针等2、 入栈后就进入任务调度函数,第一步保存当前任务的SP在相应任务的任务控制块里面3、 将SP修改为任务调度专用的SP,任务调度函数专用的栈4、 系统时间处理,分时管理需要处理时间5、 获取下一个需要执行的任务6、 访问通用寄存器,为了第一步入栈操作所有通用寄存器都入栈7、 任务调度的钩子函数(如果使能)8、 定时器计时赋初值9、 修改SP为下一个任务的SP,在相应的任务控制块里面读取(第2步保存)10、退出任务调度函数,按照下一个任务的SP出栈,还原寄存器,PC指针等,实现了任务调度
到这里其实还遗留一个问题:切换到的任务如果还没被执行过的话(定时器中断入栈是入栈被中断的任务,说明该任务已经执行了),那么相应的PC指针,寄存器值是什么?下一章继续介绍。
第五章 任务管理的幕后操作
来到这里,可以看到,要实现任务管理功能,还需要很多幕后操作的。这次我们实际来看任务管理从头到尾怎么做的,要开始来弄清楚来龙去脉了。这一章,需要分几个小节了。5、1 coos的文件结构和使用
看看coos的C语言工程吧。截图:
先看左边的文件,两个文件夹coos和user。coos里面两个源文件coos.c和coos_hook.c。这两个文件是任务管理文件,只要包含了这两个文件和相应的头文件,再调用几个函数就可以实现分时任务管理功能了。user里面两个源文件是用户自己编写的。main.c和task.c分别是主函数文件和被管理任务的文件。任务到底是什么,等一下再看。这里先介绍主函数应该怎么样写,也就是前面啰嗦了那么多,那到底coos怎么用?
要先添加了coos的几个文件到自己的工程,然后大概浏览一下那10来行代码。可以看到主函数的操作分成三部分:1、初始化coos2、创建任务3、开始运行coos
具体再看代码:
12~14行:定义三个数组,用来做任务栈。可以看到该主函数创建了三个任务,因为每个任务要有一个任务栈,所以定义了三个数组来当作任务栈。16行:主函数开始入口。18行:coos初始化。调用coos的函数,一些coos运行必要的操作,等一下再说。20~22行:创建任务。也是调用coos的函数,创建任务后准备交给coos管理。24行:coos开始运行。同样是coos的函数,coos开始分时管理被创建的三个任务。
可以看到,要使用来管理任务是非常简单的,主要在主函数里面调用几个coos提供的函数就行了。没错,但是这次我们要看coos是怎样运行的,了解到具体的每一步。只要理解coos几个重要的函数,就能很深入地理解coos了。
5、2 coos重要函数说明
1、void OS_Tick_Init();coos定时器初始化函数,跟普通的51定时器初始化函数没什么不同,但也看一下具体代码。功能是配置定时器0,让51能够产生中断,相当好理解。其中457行的TR0 = 1;被我注释掉是因为我们并不是要在这个时候让coos开始运行,等到创建好任务在让它开始运行。
2、void&&OS_TaskCreate(void Task(void), uint8_t *TaskStk, uint8_t TaskTim, uint8_t TaskID)coos创建任务的函数,非常重要!!
可以说coos得以运行都是这个函数和定时器中断函数在幕后的操作了,这个函数有这跟定时器中断函数同样级别的重要性!!并且coos的很多概念都在这个函数里面使用到。
先介绍一下一些基本概念,再来说明任务创建函数。
①在C语言中,函数名代表函数的地址。什么意思?举个例子说明一下:比如有一个函数:void&&Func();Func是函数名,Func()是这个函数。要知道它们是有区别的。首先我们可以把Func当成一个常量,这个常量是一个地址,也就是Func()在ROM存放的地址,ROM在51上我们称为code。这些属于C语言的知识,大家有兴趣在继续深入了解。我们这里要用到的只是要知道Func就是一个常量,这个常量是一个地址,这个地址是函数Func()在ROM上的地址。就行了。
但是它有什么用?如果跟PC指针联系起来的话就知道了解这个是有作用了。PC指针存放的是下一条指令的地址,如果把Func赋值给PC,那么CPU下一个执行的指令就是Func()函数的指令了,类似于C语言的函数调用,调用的函数是Func()。其实调用函数的时候就是将PC指针修改成对应函数的地址,CPU就跳转去执行相应的函数了。但是调用函数的话还涉及到函数参数的传递和函数的返回值,与只修改PC指针也是有区别的。
②任务控制块先看代码截图:要管理任务,当然要有任务的信息。任务控制块就是用来保存任务信息的。因为51的RAM只有256Byte,所以任务控制块我也尽量减小,只有任务栈和任务时间片是必要的。
任务栈地址:每个任务要有自己的栈,任务栈的地址用来记录任务进入中断的SP的值(栈指针),方便中断退出按该任务栈出栈实现现场还原。在第二章讲任务管理原理时,进入中断的第一件事就是保存任务的SP到任务控制块的栈地址,也就是606行的赋值语句。任务时间片:每个任务还要有时间片。也就是任务在一个周期内最多执行多少个时间片。因为是分时任务管理,所以不能让某个任务占用所有CPU,要按照时间片去执行。
接下来看任务创建函数,截图:
函数带四个参数,每个参数都相当重要。第一个参数:void&&Task(void)&&---&&这个参数是一个函数,可能有点难以理解。但是函数的参数可以是一个函数,这个参数函数不带参数,不带返回值。这个参数函数就是我们用C语言写的任务函数。也就是任务创建函数创建的任务就放在这个参数。第二个参数:uint8_t&&*TaskStk&&---&&这个参数是任务栈首地址。如果我们定义一个数组,那么数组名就是数组的首地址,一般这个参数传递的是数组名(数组的首地址),然后数组就作为该任务的任务栈。(当然动态分配内存也行)第三个参数:uint8_t&&TaskTim&&--- 这个参数是任务的时间片。比较容易理解了,一个任务在一个周期内最多运行多少个时间片就是看创建任务时传递进来的这个参数。第四个参数:uint8_t&&TaskID&&---&&任务的id。coos管理任务是根据任务的id管理的,只有任务挂在coos任务状态表(OS_TaskStatGrp)上coos才管理这个任务,不然任务是不会被运行的,哪怕有再多的时间片。并且coos的任务状态表是一个8bit的变量,每一位代表一个任务id。任务的id分别是从低位的0到高位的7。
开始看具体的函数代码,现在应该很好理解了。099行:目的是判断该id上是否已经创建了任务。判断条件是任务状态表该为是否为1。其中操作SET_BIT()是一个宏操作。在coos.h里面有:#define&&SET_BIT(i)& & (1 && i)目的是置位某个位,操作(SET_BIT(TaskID))是置位id那一位,然后跟OS_TaskStatGrp(任务状态表)与一下是否为真。如果为真,该id上已经创建了任务;如果不为真,该id上未创建任务。
如果任务id已被占用存在,那么运行101~104行。101~103行:条件编译,条件是是否使能系统错误统计,如果使能系统错误统计则运行OS_ErrCnt(); ,这个函数是当coos出错时候统计错误次数的,这里不是重点。104行:return,函数返回。因为不能创建任务(任务id被占用了)
如果任务id未被占用,则运行108~118行:108行:因为要在该id上创建任务,所以置位任务状态表在该id上的那一位
109行:记录任务的任务栈,也就是任务的SP。记录在对应任务的任务控制块里面。任务控制块是一个结构,任务控制块在上面已经说明了。我这里是定义一个结构数组,结构就是任务控制块结构,每个任务的任务控制块就是在该结构数组上的一个元素(结构数组的元素是一个结构)。
右边(uint8_t)TaskStk&&+&&OS_TASK_STK_SIZE_MIN有两部分。第一部分(uint8_t)TaskStk 是任务创建函数的第二个参数,任务栈首地址,本来是一个指针,强制转换成uint8_t,无符号八位的变量第二部分 OS_TASK_STK_SIZE_MIN 是任务栈的大小,是一个常量,默认值为13,这个有点难理解。因为与定时器中断服务函数相关,并且是从汇编的角度去看才能知道这个常量的大小。详细说明一下:中断服务函数执行前有入栈操作,但是具体入栈寄存器多少事先难以预知,最好的办法是查看编译后的汇编代码。我就是查看汇编代码的,默认总共入栈的寄存器有13个,占用14个字节(PC指针占用两个字节,其他寄存器占用一个字节)。除了PC指针还有额外的12个字节,分别是R0~R7,ACC,DP0H,DP0L,PSW。还需要了解的是51入栈机制,栈是向高地址增长的,而且是先增长再入栈(貌似专业一点讲是一个是满栈,UB,U是up,B是before,要入栈前先增长栈地址)。了解了这些之后就可以推断出 OS_TASK_STK_SIZE_MIN 这个常量是13了,当然我也顺便说一下。总共入栈14个字节,数组名是首地址,数组名加上13就是栈顶了,总共是14个字节,这样就模仿得跟中断入栈后的栈顶的值是一样的。
左边OS_TaskTcbGrp[TaskID].TaskStk 是该任务的任务栈,接受右边的栈顶地址。
110行:右边是任务创建函数的第三个参数,任务时间片,在任务控制块上记录任务时间片。112~113行也是重点和难点!!赋值语句,模拟入栈。要先知道PC指针是16bit的,入栈占用两个字节。但是究竟是高字节先入栈还是低字节先入栈?有办法!进入调试模式,然后观察内存。我是用这个办法知道51入栈PC指针是低地址先入栈,然后高地址的。大家有兴趣可以自行尝试。知道了先入栈低地址,下一步是模拟出入栈的是任务刚要运行时的PC指针。上面已经讲到函数名就是函数的地址,与PC指针有联系。112行: TaskStk[0] = FUNC_ADDR_LOW(Task);右边是一个宏操作,在coos.h里面有:#define& &FUNC_ADDR_LOW(func)& &(uint8_t)(((uint32_t)func) && 0)目的是获取函数的低地址,宏操作的参数是func,具体应用时候是一个函数名,也就是一个常量(函数的地址),操作先将函数的地址func强制转换成一个32bit的变量,右移0是为了配合获取函数高地址操作写的,实际没用,然后再强制转换成8bit的变量。左边是任务栈,用下标形式访问栈底,将函数的低地址赋值给栈底,模拟了PC指针入栈时的低八位地址入栈。113行:TaskStk[1] = FUNC_ADDR_HIGH(Task)理解了112行,这一行就好办了。模拟入栈PC指针的高八位。右边一样是一个宏操作,在coos.h里面有:#define&&FUNC_ADDR_HIGH(func)& &(uint8_t)(((uint32_t)func) && 8)目的是获取函数func的高八位地址。左边任务栈,因为刚才入栈函数的低八位地址,所以栈要向上增长,用下标访问的形式就是TaskStk[1]了,这一行模拟出PC指针入栈是的高八位地址入栈。
115~118行:模拟其它寄存器入栈,默认都是0x00,其他寄存器包含有R0~R7,ACC,DP0H,DP0L,PSW具体要看汇编代码才知道是这些寄存器的。
至此任务创建函数就完了。这里在总结一下,在coos里要创建一个任务就是要将任务挂在任务状态表上,供coos管理,而且要填好任务的信息,包括任务栈顶,任务时间片。最后模拟任务被中断服务函数中断了的入栈操作。具体再分几步说明:1、判断任务id是否被占用2、如果任务id被占用就不创建任务,根据条件编译是否运行系统错误统计函数
3、任务id没有被占用,置位coos任务状态表对应id那一位,说明要在该id创建任务&&4、为任务栈的栈顶初始值&&5、任务时间片初始化&&6、模拟入栈PC指针和其他寄存器。
3、void&&OS_TaskTim_Init(void)因为coos管理任务是按时间片管理的,任务一旦运行一个时间片,时间片就被减一。所以每个周期要刷新一次任务时间片。这个函数就是每个周期调用一次的任务时间片初始化,重新刷新任务时间片共coos管理。477行:for循环,循环次数是coos管理的任务个数479行:for的循环体,功能是根据任务时间片初始化任务时间片数组,就是记录各个任务创建时的时间片,创建一个副本。任务运行后的时间片减一操作在这个副本进行的。481~483行:条件编译,条件是如果使能系统提供空闲任务。如果使能了系统提供空闲任务,那么就会刷新空闲任务的时间片。其中常量OS_IDLE_TASK_TIM的值与coos一个周期的时间片个数相等。在coos_conf.h里面有:#define&&OS_IDLE_TASK_TIM&&OS_TICK_PERIOD其中后半部分OS_TICK_PERIOD是coos一个周期时间片的个数。
理解了这三个函数后就可以来看看coos具体的运行过程了。现在开始要具体从main函数开始看coos的任务管理了。
5、3 从main函数的执行理解coos的运行
再来main函数的截图吧:从现在开始一步一步分析main函数。
1、OS_Init();
进入这个函数继续分析。看该函数截图:062行:OS_Tick_Init();代码上节已经分析过,重温一下,看截图:064行:变量OS_CurTaskID记录当前是执行那个任务,初始化将它初始化为空闲任务。065行:变量OS_TaskStatGrp是coos任务状态表,初始化为0表示没有创建任务。067行:for循环,循环次数是coos管理任务的个数,也就是常量OS_TASK_NUM,可配置069~070行:for循环的循环体,将coos管理的任务的任务控制块任务栈初始化为0x00,时间片初始化为0073~075行:条件编译,两个条件。分别是1、如果使能coos空闲任务,可以不使能2、如果使能coos提供的空闲任务,当然可以自行创建其他任务作为coos空闲任务coos默认提供的空闲任务是让51进入低功耗模式,省电。此时51等待中断唤醒。具体可以查找51数据手册继续深入理解,代码看截图:到了这里,主函数的第一个函数就完了,接下来继续看主函数的其他操作。
2、OS_TaskCreate(Task_One,&&Stk_TaskOne,&&5,&&0);
重温一下任务创建函数,截图:
这个函数在上一节也已经说明过,再罗嗦一下。该函数的操作是创建一个名字为“Task_One”的任务,其中Task_One是一个函数名,也就是有一个Task_One()的函数,具体任务做什么等一下再说。任务 Task_One的任务栈是Stk_TaskOne,也就是主函数文件中012行定义的那个数组,将数组的首地址传递进来,这个数组的空间给Task_One做任务栈。任务Task_One的时间片为5,也就是Task_One一个周期最多执行5个时间片任务Task_One的id为0,也就是Task_One在任务状态表OS_TaskStatGrp占用了第0位
Task_One的具体代码再看一下,相当简单的一个任务。截图:说明一下任务必须在一个死循环里面,即时任务只需执行一次,也必须让任务在死循环里面执行,不能让任务函数返回。因为返回的话,有发生不可预知的结果,一般就是程序跑飞了。因为返回时谁也不知PC指针会指向哪里。如果有只需执行一次的任务的话,coos当然考虑了这个情况。那就是在任务运行完后调用coos的任务删除函数void&&OS_TaskDel(uint8_t&&TaskID);将该任务删除掉,coos就再也不会执行该任务了。参数TaskID是待删除任务的id。比如要删除刚才创建的任务的话就调用:OS_TaskDel(0);就将任务删除了。3、OS_TaskCreate(Task_Two, Stk_TaskTwo, 2, 1);和OS_TaskCreate(Task_Thr, Stk_TaskThr, 7, 3);再创建两个任务,类似与创建任务1。任务代码也很简单,截图:功能类似与任务一。任务二中被注释的内容是我在写coos时测试函数功能是否正常用的。创建了任务之后,我们要让coos开始运行了。继续看mian函数中的最后一个函数。
3、OS_Start();代码在截图:
135行:coos任务时间片初始化,该函数上面已经上一节也已经说过,重温一下代码:因为创建任务的时候在任务控制块里面填写了任务的时间片。然后我们想让coos管理这些任务,我就创建了一个数组,作为任务时间片的副本。因为任务运行后我们要记录已经运行了,直接在任务控制块里面操作会造成任务信息丢失,所以创建一个副本。在coos.c里面有:static&&uint8_t&&idata&&OS_TaskTimGrp[OS_TASK_NUM + 1];用这个数组来记录任务时间片,也就是运行了任务就来一次任务时间片减一操作,满一个周期后再重新刷新。任务时间片为0任务就不会被执行。
138行:因为coos运行前默认coos是在运行空闲任务,第一次进入中断服务函数(任务调度函数),会将相应任务的时间片减一(第一次进入中断空闲任务时间片会被减一),所以先加一,解决第一次进行任务调度出现的bug138行:因为第一次进入中断,OS_Tick会加一(coos时间片记录函数),表示中断了一个任务,coos运行了一个时间片,但实际第一次进入中断并没有运行一个时间片的任务,所以OS_Tick减一,解决第一次进行任务调度的bug
140行:表示定时器开始计时。141行:表示定时器产生溢出,实际没溢出,只是为了立刻进入中断。此时CPU的不会继续执行141行下面的代码了,它会进入定时器0中断服务函数,但是下面的代码还是有可能被执行的。143~147行:条件编译,如果使能空闲任务和coos提供的空闲任务空闲任务放在这里,是因为当没有可运行任务的时候,coos任务调度返回,141行下面的代码。为什么,可以自行思考一下。原因是141行是第一次被中断的断点,然后进行任务调度。任务调度函数会记录断点,入栈保护,并且coos初始化是默认的任务是空闲任务,所以入栈保护入的栈是空闲任务的栈。如果将空闲任务放在141行下面,那么就模仿的非常的像是第一次中断断点就是空闲任务了。
至此,coos任务调度讲解完毕。当然要看代码,要调试,要看一下汇编代码,要看51的说明书,要懂一点微机原理,要有C语言基础,才能更深刻的了解coos。简单总结:1、初始化定时器,coos使用的变量。为coos分时管理任务做准备2、创建任务,准备让coos管理(创建任务是记录任务信息,并模拟任务被中断函数打断)3、开始运行coos,启用定时器中断根据任务信息调度任务
当然为了让coos更强大,并且作为嵌入式的东西,可裁剪是必不可少的。所以很多条件编译默认都是不编译的,下一章主要说一下条件编译函数。
以下已经不是重点了,可有可无。coos的主要目的是任务管理。并且发现分时任务管理比较简单实现,所以就是分时任务管理的coos了。
第六章 coos条件编译
数了一下是11个条件编译函数,都是相当简单或者说理所当然会有这些函数,没有多少技术含量了这些。下面一一说明:
1、void OS_TaskDel(uint8_t TaskID)任务删除函数,看截图:169行:传递进来的参数是任务的id171行:判断任务是否创建了,因为创建任务函数默认已经置位了任务状态表(OS_TaskStatGrp)对应的id那一位,所以如果对应的为1则说明确实创建了任务,准备删除任务。173行:目的是将任务状态表(OS_TaskStatGrp)对应任务id那一位清零。其中RESET_BIT()是一个宏操作,在coos.h文件里面有:#define&&RESET_BIT(i)&&(~(1 && i))目的是清零对应i的那一位,最重要是这一步就把任务删除了,任务就再也不会运行了,下面的步骤只能说是善后吧。174~175行:任务栈置为0x00,时间片置零176行:任务时间片数组(OS_TaskTimGrp)对应任务id那个元素的时间片清零
如果任务状态表(OS_TaskStatGrp)对应任务id那一位为零,也就是对应id上没有创建任务,根据条件编译是否运行系统错误统计函数,这里不是重点。
2、void OS_IdleTask(void)coos提供的空闲任务,老样子,截图:跟普通任务一样是进入一个while死循环,因为一旦函数返回,会有意想不到的结果反生,难以预测发生什么事,程序跑飞了那是不可避免的。204行:根据51数据手册,置位PCON的第0位让51进入低功耗,具体可参考数据手册
3、uint8_t OS_GetCurTaskID(void)获取当前运行任务id的函数,截图:直接将OS_CurTaskID返回,该变量记录当前被运行的任务来到这里相信同学们也觉得条件编译函数是相当的…继续
4、uint8_t OS_GetCurTickTim(void)获取coos提供的参考时间,截图:类似与上一个函数,不说了。
5、void OS_SetCurTickTim(uint8_t TickTim)设置coos当前参考时间,截图:对OS_Tim赋值,就是设置coos的参考时间了
6、void OS_TaskExit(void)例如当前正在运行某个任务,我们已经不想再让任务运行下去了,就可以调用这个函数,进入任务调度函数,让任务调度函数判断下一个任务是什么而去执行下一个任务,当前任务就没有被执行了。这个时候任务这个函数的价值就体现出来了。因为我们的任务都必须设置成在一个死循环里面执行,如果没有这个函数,那么coos必须也让该任务运行一个时间片,如果在这个时间片内引脚的状态都为0,那么可想而知,该任务是在浪费CPU。如果我们改进一下:如果状态为0,则一样运行一段代码,如果引脚状态为1,调用该函数,让任务放弃CPU。那么CPU的利用率就大大提高了,下面看代码。截图:282行:判断任务是否存在284行:任务确实存在,置位TF0,定时器0溢出标志,则进入定时器中断函数进行任务调度。289行:任务并不存在,根据条件编译是否运行coos错误统计函数(这里不是重点)
7、void OS_TaskTimEdit(uint8_t TaskID, uint8_t TaskTim)任务时间片修改函数:截图因为创建任务的时候我们指定了任务的时间片,coos管理任务后任务的CPU使用率是一定的,如果要增加或减少任务的CPU使用率可以试着用这个函数。传递进来的参数:1、uint8_t&&TaskID& &任务的id2、uint8_t&&TaskTim&&任务的新时间片当然311行先判断任务是否存在任务存在则修改任务控制块数组中该任务的任务控制块的时间片为新设置的时间片任务不存在根据条件是否编译运行coos错误统计函数
8、void OS_ErrCntClr(void)coos错误次数清零函数。截图:条件编译有两个条件:1、使能coos的错误统计2、使能错误统计清零340行:简单的将OS_Err_Cnt赋值为0就清零了
9、uint8_t OS_GetTick(void)获取coos当前时间片,截图:360行:直接将OS_Tick返回。
10、void OS_TimDly(uint8_t Tim)coos提供延时函数,截图:稍微有一点点复杂,不过说一下基本思路应该就很清晰了。延时的话是根据coos提供的参考时间作为延时依据的,所以要根据延时的时间和coos提供的参考时间,计算出延时的终点(延时的结束条件),在延时的条件内就等待。384行:临时保存coos参考时间变量OS_Tim385行:Tim是传递进来的参数,加上OS_Tim是延时的终点,但要判断是否溢出387行:判断延时终点是否溢出,溢出条件是Tim 〉 OS_TIM_PERIOD(coos参考时间的周期,可配置)&&389行:延时终点溢出了,用coos的参考时间周期取余Tim,得到新的延时终点。& && && & 其实由这里也可以看出,coos提供的延时范围实在一个coos参考时间周期内的,因为越界部分取余后已经没了。&&390行:进入while等待延时结束。因为延时终点越界了,可知等待的终点coos提供的OS_Tim是小于当前临时保存的coos参考时间tim_tmp,所以等待条件第一个为:OS_Tim &= tim_tmp因为延时终点溢出也可知延时终点coos的参考时间OS_Tim大于计算出的延时终点Tim(Tim是计算出的延时终点,第二个条件是只要coos参考时间大于该值则等待结束) ,所以有OS_Tim & Tim
&&394行:延时终点为溢出,那么延时就好理解了,只要coos提供的参考时间大于计算出的延时终点,那么延时就结束了,有:& && && & while(OS_Tim &= Tim);
如果对延时函数不理解的话拿起笔和纸写一下就懂了,我是用笔和纸计算出来的…(——#!)
11、void OS_ErrCnt(void)最后一个条件编译函数,coos错误统计。虽然是个很简单的函数,不过因为没有更复杂的函数了,所以也只能拿它来压压轴,看截图:415行:判断错误次数是否溢出,未溢出进入417~420行&&417行:错误次数未溢出,错误次数加一&&418~420行:条件编译,条件是是否使能coos错误统计钩子函数。什么是钩子函数,了解过ucos的同学们就知道,为了增强ucos的功能,ucos作者为ucos引入10个钩子函数,是在当ucos发生某些情况时候运行的函数,由用户实现的。我这里也是模仿ucos的,引入钩子函数OS_Hook_Errr(),在coos_hook.c文件里面,默认函数体为空,该函数又用户实现,目的是为了增强coos的功能,多一些自定义功能,其实也没什么大不了的。
422~428行:条件编译,条件是是否使能错误次数溢出钩子函数,进行错误次数溢出处理。&&425行:错误次数清零&&426行:错误次数溢出钩子函数,同样在coos_hook.c文件里面,默认函数体为空,由用户实现,目的是增强coos功能。
条件编译函数就完了,最后还剩下的就是coos的配置,裁剪了,下一章介绍。
第七章 coos的配置、裁剪、类型定义
当然作为嵌入式的东西很将就可裁剪性的,配置和裁剪在coos_conf.h文件里面。先看看配置部分,截图:一个一个说:19行:coos定时器计数值,也就是coos一个时间片的长度。该值越大,coos任务调度的频率就越小,CPU的使用率就越高。但是太大的话任务被打算时间太长,所以要折衷配置。默认5000,晶振12M的时候一个任务时间片是5ms
20行:coos时间片周期,也就是多少个时间片为一个coos周期。一个周期后coos会重新刷新任务时间片。同样该值越大,CPU利用率越高,但这个值的影响是不明显的。
21行:coos参考时间的周期,也是coos提供延时的最大值。对CPU利用率几乎没影响。
22行:coos管理任务的个数。该值越小,CPU利用率越高,RAM占用越少。因为任务调度的时候遍历了每个任务,需要时间。并且每个任务都要有任务控制块(2Byte)和任务时间片副本(1Byte),占用RAM。综合说名一下就是,我们需要创建多少个任务,就定义该值为多少,不用预留余量之类的。
23行:定时器专用栈的栈大小,默认为8其实已经够用了,如果使能的定时器钩子函数,并且钩子函数过于复杂(运行起来占用栈较大),那么该值需要适当加大,因为栈溢出了程序运行是肯定会有问题的。
24行:coos空闲任务默认的时间片,该值与coos时间片周期大小一样。目的是为了在一个时间片周期内,如果没有一个可以运行的任务,那么所有时间片周期运行空闲任务(不会因为空闲任务时间片不够而发生意想不到的结果)
接下来是裁剪,老样子,截图:裁剪也就是上一章的条件编译函数的使能,后面记录裁剪掉多少RAM和code需要使用到上一章的条件编译函数就使能,1是使能可以看到coos默认使用很少条件编译函数,因为都是比较简单的(就是上一章的内容),所以不说了。
钩子函数的配置,截图:相信大家一看就懂了的,1使能。coos钩子函数要用户自己实现(自定义的功能了),在coos_hook.c文件里面,将自己的代码写进去就行了,当然要使能了才有用。看一下coos_hook.c这几个函数吧。截图:
还有类型定义,看截图:uint8_t 是stm32的风格,因为我已经习惯了这种风格了,不该了,当然也在coos用了这种风格。
附录coos的说明书也应该结束了吧。顺便提一下就是,实现coos任务管理功能也就那不到200行代码(除去条件编译这些可有可无的东西),但是也写了我一个月左右的时间了。因为确实也走了一下弯路。例如我想让任务调度独立成为一个函数,定时器中断只是负责篡改返回地址,但是却有寄存器没入栈保存完善的bug。这个bug曾让我一度想放弃,因为发现到不得不用汇编,我是大大的不想用汇编的。机器语言已经跟机器密切相关了,移植性大大减少了,同时新鲜性也没了。因为用汇编的话实现任务管理难度是不大的。期间也上火,头痛,牙痛,在校医院看了两次,差点要放弃。装上win8,安装了RVMDK,运行不了,用什么win7兼容啊,XP SP3兼容啊什么的,都不行。百度也找不到win8兼容的RVMDK,我崩溃了好几次。因为装一次和卸载一次都是比较花时间的…(RVMDK是什么?接近keil增强版吧,我就是用RVMDK写coos的,keil是RVMDK的前身,RVMDK是stm32,arm之类用的,当然51也行,支持很多微处理器)
参考文献:挺多的,可以说看了不少书吧。能想到的就写出来吧1、C和指针(C语言的书)2、51单片机汇编实例(网上随便下载看看的)3、c51中文书名keil c51(网上随便下载的)4、微型计算机原理与接口技术(上课的课本…)5、《嵌入式实时操作系统uCOS-II》(第二版)6、其它的对coos贡献不大,有C语言的,数据结构的,算法的,stm32的
03:47 上传
点击文件名下载附件
下载积分: 黑币 -5
6.13 MB, 下载次数: 131, 下载积分: 黑币 -5
03:47 上传
点击文件名下载附件
下载积分: 黑币 -5
2.56 MB, 下载次数: 39, 下载积分: 黑币 -5
 楼主你收了我吧,如此牛,汇编厉害,C语言也厉害。我一直想学51任务管理来着,谢谢!
 牛的不行了
金币不够 发个贴子顶楼主
51黑有你更精彩
要好好学习了,高深实用
好文章!!!这就是可抢占式时间片轮转任务机制!!!可以算是一种线程。
本菜只能写一些相当简单的程序。看到楼主的帖子,感觉真的很高大上啊。。
好!!!!!!!!!!
无效楼层,该帖已经被删除
首先要给楼主赞一个,有趣果然是货真价实的春药!
粗看了一遍有几点疑问,请教一二:
1、假如系统周期是20个时间片,有5个任务,分别都是1个时间片,那么一个系统周期里面还有15个时间片是浪费了吗?
2、关于延时函数,如果目标时间刚刚好是 FF或FFFF,那么是不是会永远在延时里面出不来。
3、任务之间的通信和互斥是怎么考虑的?
不错,看了有疑问请教
本帖最后由 utzuzu 于
22:33 编辑
1、如果系统周期是20个时间片,有5个任务每个1个时间片,那么一个系统周期内剩下的15个时间片是什么状态,浪费了吗2、在延时函数内,如果目标时间刚好是FF或者FFFF,会不会永远在延时里出不来了。
3、有没有提供任务之间的通信和互斥的机制。
高深实用,很给力!
哈哈&&又被多扣一次 要再多积一点 在下其他
无效楼层,该帖已经被删除
要好好学习了,高深实用
楼主思路太好了
学习学习楼主的思路和代码风格
感谢分享!
这个和rxt riny有区别吗
真的是很受用吗
Powered by

我要回帖

更多关于 街霸 的文章

 

随机推荐