请教各位大神,51怎么进行无堵塞的延时

[复制链接]
1986|6
 楼主| xingyu1156 发表于 2013-5-18 23:06 | 显示全部楼层 |阅读模式
本帖最后由 xingyu1156 于 2013-5-18 23:08 编辑

这两天一直在纠结,找到个51多任务系统的代码,想问问能不能用这个多任务系统的程序转换模块进行无堵塞的延时。(就是将一些扫描按键之类的放在一个程序中,然后在需要延时的时候转换到这个程序,到指定时间跳回原来的位置),可行么??
  1. //在网上搜索51单片机多任务支持代码,都太复杂,要么就是伪系统;
  2. //本代码使用T1定时切换,在此基础上,如果再进行完善可以完成不同时间片轮转以及消息挂起等功能
  3. //本代码编译通过,需要23个data单元,8051也轻松运行。
  4. //用keil 编译测试通过,代码完整。感觉有用的请评价。
  5. #include "reg51.h"
  6. #include "absacc.h"
  7. #define DEEP 6                 //堆栈深度,自身压栈2字节地址,中断压栈2字节数据,ACC PSW,DEEP必须>=4
  8. #define PROC 3                 //自由任务数量,不包含主函数main()
  9. #define DS 15556        //定时常数,用于0.1秒定时 =65536-(OSC/12*0.1)-20
  10. //use interrupt function build a real multi task system        用中断实现真正的多任务系统
  11. //主要能够实现编程的可读性易读性,模块化
  12. //in multi task system, 参数声明最好声明成全局变量,避免出现覆盖现象

  13. //中断系统进行多任务需要设置堆栈当调用一个任务时需要保存相应的堆栈,可以设置私有堆栈深度为DEEP=6
  14. //如果任务1的当前值是16,栈顶就是16+ DEEP,系统应该监控该数值
  15. //任务2的栈栈底就是        16+ DEEP
  16. //版本1.0  2012-09-03
  17. //liwg//@//weichai.com//wenguang.li//@//163.com//
  18. unsigned int a;
  19. unsigned char sta[PROC]=0;        //设置堆栈指针寄存器
  20. unsigned char activeproc=0;        //活动进程指针
  21. void init()        //中断初始化函数
  22. {
  23. unsigned char c;
  24. for(c=0;c<PROC;c++)sta[c]=0;        //清除堆栈数据

  25. EA=0;           //disable interrupts
  26. TR1=0;
  27. ES=0;
  28. ET1=0;

  29. TMOD=0x90;        //set timer1 mode to 16 bit timer
  30. TH1=DS/256;
  31. TL1=DS%256;
  32. ET1=1;
  33. EX1=0;
  34. ET0=0;
  35. EX0=0;
  36. EX0=1;         //允许外部中断0,用于操作切换任务
  37. TR1=1;         //定时器1 启动
  38. }

  39. void sysrun()
  40. {
  41. EA=1;  //允许中断,系统执行
  42. }
  43. void Exint0() interrupt 0 using 1           //外部中断0函数,用于切换任务
  44. {
  45. EA=0;
  46. activeproc++;                                                  //关闭所有中断
  47. if (activeproc>PROC )activeproc=0;          //切换到下一个任务,轮转
  48. EA=1;                                                                  //开启中断
  49. SP=sta[activeproc];                                          //转移堆栈指针到新任务

  50. }  
  51. void Timer1_Overflow() interrupt 3 using 0                 //定时器1 溢出中断        用于切换进程
  52. {
  53. TR1=0;
  54. TH1=DS/256;
  55. TL1=DS%256;
  56. TR1=1;
  57. //进程切换内容                                   
  58. EA=0;                                                        //关闭所有中断
  59. while(sta[++activeproc]==0)                 //栈指针==0的进程不装入
  60. {                                                  
  61. if (activeproc>PROC )activeproc=0;          //切换到下一个任务,轮转
  62. }
  63. if (activeproc>PROC )activeproc=0;
  64. EA=1;                                                                  //开启中断
  65. SP=sta[activeproc];                                          //转移堆栈指针到新任务
  66. //切换完毕
  67. }

  68. void loadtask(unsigned int funcname, unsigned char slot)
  69. {
  70. char lowadd,hiadd,tmpsp;
  71. lowadd=funcname%256        ;           //任务入口地址低8位
  72. hiadd=funcname/256;                   //任务入口地址高8
  73. tmpsp=SP+DEEP*slot;                   //设置堆栈指针
  74. DBYTE[tmpsp]=lowadd;           //存入堆栈数据低八位地址
  75. DBYTE[++tmpsp]=hiadd;           //存入堆栈数据高八位地址
  76. sta[slot]= tmpsp+2 ;          //2是因为系统中断的时候要有保护ACC,PSW的堆栈操作,任务切换是用系统中断完成的,具体情况根据汇编代码确认。
  77. if(sta[0]==0)sta[0]=SP+2;        //main()是函数0        
  78. }
  79. //任务1 每个任务都必须是死循环
  80. void task1 ()
  81. {
  82. while(1){
  83.                 P0++;//add your code here.


  84.                 }
  85. }
  86. //任务2 每个任务都必须是死循环
  87. void task2 ()  
  88. {
  89. while(1){
  90.                 P1++;//add your code here.
  91.                 }
  92. }
  93. //任务3 每个任务都必须是死循环
  94. void task3()  
  95. {

  96. while(1){
  97.                 P2++;//add your code here.
  98.                 }
  99. }

  100. main()
  101. {
  102. init();
  103. loadtask(task1,1); //载入任务1
  104. //loadtask(task2,2); //载入任务2
  105. loadtask(task3,3); //载入任务3
  106. sysrun();                //打开中断开关,任务轮转启动
  107. while(1)          //主程序死循环任务0
  108.                 {

  109.         //add your code here.

  110.                  }
  111. }
 楼主| xingyu1156 发表于 2013-5-18 23:10 | 显示全部楼层
另外  我对void loadtask(unsigned int funcname, unsigned char slot)函数进行的操作也不太清楚,能给详细讲讲么,有资料也可以。
wangch_sh 发表于 2013-5-19 18:54 | 显示全部楼层
看看书,有一本邵贝贝翻译的实时多任务ucosii不错!
youku 发表于 2013-5-20 01:14 | 显示全部楼层
不知你的代码哪里来的干啥的,,
请研究主流的比较完整的RTOS,会调用就可以了,别太深入。。。
你的需求就是OS能完成的一个基本功能,实际延时的时候也是调用一个delay延时函数,但这个函数跟
普通的死循环的蛮干不一样,它会导致任务切换,切换到另一个待运行的任务,这就等效于你延时了,
然后延时时间到了,OS会自动帮你切换回来!

你几乎不用关心太多,只要调用OS提供给你的特别的delay函数即可,跟平时几乎没区别!
(注意,我说的都是几乎,实际要用时会碰到新的比较郁闷的问题,那是后话了,先别管,先用!,比较满大街的uCOS...可以先拿过来玩下。。)
dirtwillfly 发表于 2013-5-20 08:56 | 显示全部楼层
楼主若是真要在51上玩操作系统,建议找个资料全的。
推荐《嵌入式实时操作系统small RTOS51原理及应用》这本书,网上有代码,很容易找到
 楼主| xingyu1156 发表于 2013-5-21 17:20 | 显示全部楼层
重点在无堵塞的延时程序设计~~就像4#说的OS系统的延时
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

6

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部