独闷闷网

标题: 第一章-叫你如何使用硬件延时【51篇】 [打印本页]

作者: 电子Inc    时间: 2014-12-15 13:06
标题: 第一章-叫你如何使用硬件延时【51篇】
本帖最后由 电子Inc 于 2014-12-15 14:30 编辑

       本论坛有我们鸿哥给大家分享他积累的知识,给大家带进能够充分发挥你想象力的世界,那么,喜欢嵌入式的童鞋,也可以跟我一起学习,我们怎么去把51的基本外设用得精,所以这里我给大家介绍第一篇,
      我初步看了一下群里以及各位平常的习惯,为了让一个LED灯闪烁,开定时器中断,还有的是用软件延时,这里我先给
大家举一个粟子,我们怎么用定时器不中断的方法来实现延时呢?
      PS:c此贴只为让大家知道51外设的使用,不是求怎么用的好,用得秒。但是,这里会让你看见,原来外设还可以这样用,
我们首先来看看我们平常是怎么延时的:
  1. void DelayMs( unsigned int Tms )
  2. {
  3.     while(Tms--);
  4. }
复制代码
在这里,相信大家已经注意到很多问题了,第一就是,阻塞,第二,不精确,那么我们首先排除不精确这个问题,所以,我
们使用硬件延时,硬件延时,其实说白了就是利用MCU内部的计数工具来作为延时计数吗,等待计数工具溢出后来达到延时
的效果,那么下面请看代码
  1. void DelayMs(const unsigned int Tms )
  2. {
  3.       unsigned int ms;
  4.       TMOD &= 0xF0;
  5.       TMOD |= 0x0F;
  6.       ET0 = 0;
  7.       for( ms = 0; ms < Tms; ms ++ )
  8.      {
  9.          TH0 = PRELOAD01H;  
  10.          TL0 = PRELOAD01L;
  11.          TF0 = 0;
  12.         TR0 = 1;
  13.         while( !TF0 );
  14.         TR0 = 0;
  15.       }

  16. }
复制代码
因为一旦定时器溢出,TF0会置一,如果不用中断,我们设置ET0 = 0;然后直接等待TF0中断溢出标志位置1,然后停止计数,以达到延时的效果,这样,我们就能确保
精准延时了。然后是阻塞问题的解决方法,大家一定说,肯定就是定时器中断啦,是的,但是大家一般是怎么编排你的中断服务函数的?i++?这样方法是可行,但是一
个单片机就那么一到两个硬件定时器,这里当然不收高级的了,而且太多中断只会让系统变得不稳定,我们这里怎么产生多个延时函数而只用1个定时器呢,大家请看:
  1. void SCH_Update(void) interrupt INTERRUPT_Timer_0_Overflow
  2.    {
  3.       unsigned int  Index;

  4.       SCH_Manual_Timer0_Reload();//重装初值
  5.       for (Index = 0; Index < SCH_MAX_TASKS; Index++)//遍历定义好的定时器
  6.      {
  7.           if (SCH_tasks_G[Index].pTask)//判断是否存在任务
  8.           {
  9.                 if (SCH_tasks_G[Index].Delay == 0)  
  10.                {
  11.                     SCH_tasks_G[Index].RunMe += 1;  // 延时时间到,执行任务

  12.                   if (SCH_tasks_G[Index].Period) //重新装载
  13.                    {
  14.                           SCH_tasks_G[Index].Delay = SCH_tasks_G[Index].Period;
  15.                   }
  16.                }
  17.                else
  18.                {            
  19.                 SCH_tasks_G[Index].Delay -= 1; //延时计数
  20.                }
  21.          }         
  22.      }
  23.    }
复制代码
这样,每增加一个任务,用SCH_Add_Task函数增加,定时器也叫调度器,当轮询到任务需要运行时,置位运行标志
,函数切换即可。











作者: 黑夜之狼    时间: 2014-12-15 14:39
必须顶一下!!!
作者: jianhong_wu    时间: 2014-12-15 16:42
必须加精。又漂亮又简洁又实用。
作者: 电子Inc    时间: 2014-12-15 17:36
黑夜之狼 发表于 2014-12-15 14:39
必须顶一下!!!

谢谢帮顶,在哪里都看到你的身影,多多交流
作者: 电子Inc    时间: 2014-12-15 17:36
jianhong_wu 发表于 2014-12-15 16:42
必须加精。又漂亮又简洁又实用。

谢谢                  
作者: 看花开花落    时间: 2014-12-15 19:07
顶一个,学习一下
作者: 看花开花落    时间: 2014-12-15 19:15
(SCH_tasks_G[Index].pTask)这是什么语法呢,结构体么?怎么判断是否有任务呢
作者: waphaoyun    时间: 2014-12-15 22:29
楼主,你要继续,我们都期待你的后续作品呢
作者: waphaoyun    时间: 2014-12-15 22:51
楼主,给出一个完整的实例吧,毕竟代码不是很完整,让大家都能学习{:soso_e113:}
作者: 电子Inc    时间: 2014-12-16 00:42
看花开花落 发表于 2014-12-15 19:15
(SCH_tasks_G.pTask)这是什么语法呢,结构体么?怎么判断是否有任务呢

其实,我们看这个就能看的出来,从字面意思上看,pTask是一个指针,如果这个指针非空,那么说明有任务,如果空的,那么就没有任务。结构体么?对,这个字面意思很容易判断出来,这是读代码的基本功啊。
作者: 电子Inc    时间: 2014-12-16 00:42
waphaoyun 发表于 2014-12-15 22:51
楼主,给出一个完整的实例吧,毕竟代码不是很完整,让大家都能学习

放心,我正在整理,会跟大家分享我学到的东西的
作者: 黑夜之狼    时间: 2014-12-16 09:00
电子Inc 发表于 2014-12-15 17:36
谢谢帮顶,在哪里都看到你的身影,多多交流

因为我是无处不在
作者: 重庆-风雪    时间: 2014-12-16 19:37
楼主好人!
作者: hope    时间: 2015-1-19 19:30
等待中,系统的看一下
作者: jianghong891011    时间: 2015-1-24 17:17
,谢谢分享,受教了




欢迎光临 独闷闷网 (http://dumenmen.com/) Powered by Discuz! X3.2