第一章-叫你如何使用硬件延时【51篇】
本帖最后由 电子Inc 于 2014-12-15 14:30 编辑本论坛有我们鸿哥给大家分享他积累的知识,给大家带进能够充分发挥你想象力的世界,那么,喜欢嵌入式的童鞋,也可以跟我一起学习,我们怎么去把51的基本外设用得精,所以这里我给大家介绍第一篇,
我初步看了一下群里以及各位平常的习惯,为了让一个LED灯闪烁,开定时器中断,还有的是用软件延时,这里我先给
大家举一个粟子,我们怎么用定时器不中断的方法来实现延时呢?
PS:c此贴只为让大家知道51外设的使用,不是求怎么用的好,用得秒。但是,这里会让你看见,原来外设还可以这样用,
我们首先来看看我们平常是怎么延时的:
void DelayMs( unsigned int Tms )
{
while(Tms--);
}在这里,相信大家已经注意到很多问题了,第一就是,阻塞,第二,不精确,那么我们首先排除不精确这个问题,所以,我
们使用硬件延时,硬件延时,其实说白了就是利用MCU内部的计数工具来作为延时计数吗,等待计数工具溢出后来达到延时
的效果,那么下面请看代码
void DelayMs(const unsigned int Tms )
{
unsigned int ms;
TMOD &= 0xF0;
TMOD |= 0x0F;
ET0 = 0;
for( ms = 0; ms < Tms; ms ++ )
{
TH0 = PRELOAD01H;
TL0 = PRELOAD01L;
TF0 = 0;
TR0 = 1;
while( !TF0 );
TR0 = 0;
}
}因为一旦定时器溢出,TF0会置一,如果不用中断,我们设置ET0 = 0;然后直接等待TF0中断溢出标志位置1,然后停止计数,以达到延时的效果,这样,我们就能确保
精准延时了。然后是阻塞问题的解决方法,大家一定说,肯定就是定时器中断啦,是的,但是大家一般是怎么编排你的中断服务函数的?i++?这样方法是可行,但是一
个单片机就那么一到两个硬件定时器,这里当然不收高级的了,而且太多中断只会让系统变得不稳定,我们这里怎么产生多个延时函数而只用1个定时器呢,大家请看:
void SCH_Update(void) interrupt INTERRUPT_Timer_0_Overflow
{
unsigned intIndex;
SCH_Manual_Timer0_Reload();//重装初值
for (Index = 0; Index < SCH_MAX_TASKS; Index++)//遍历定义好的定时器
{
if (SCH_tasks_G.pTask)//判断是否存在任务
{
if (SCH_tasks_G.Delay == 0)
{
SCH_tasks_G.RunMe += 1;// 延时时间到,执行任务
if (SCH_tasks_G.Period) //重新装载
{
SCH_tasks_G.Delay = SCH_tasks_G.Period;
}
}
else
{
SCH_tasks_G.Delay -= 1; //延时计数
}
}
}
}
这样,每增加一个任务,用SCH_Add_Task函数增加,定时器也叫调度器,当轮询到任务需要运行时,置位运行标志,函数切换即可。
必须顶一下!!!:lol 必须加精。又漂亮又简洁又实用。 黑夜之狼 发表于 2014-12-15 14:39
必须顶一下!!!
谢谢帮顶,在哪里都看到你的身影,多多交流 jianhong_wu 发表于 2014-12-15 16:42
必须加精。又漂亮又简洁又实用。
谢谢 顶一个,学习一下 (SCH_tasks_G.pTask)这是什么语法呢,结构体么?怎么判断是否有任务呢 楼主,你要继续,我们都期待你的后续作品呢 楼主,给出一个完整的实例吧,毕竟代码不是很完整,让大家都能学习{:soso_e113:} 看花开花落 发表于 2014-12-15 19:15
(SCH_tasks_G.pTask)这是什么语法呢,结构体么?怎么判断是否有任务呢
其实,我们看这个就能看的出来,从字面意思上看,pTask是一个指针,如果这个指针非空,那么说明有任务,如果空的,那么就没有任务。结构体么?对,这个字面意思很容易判断出来,这是读代码的基本功啊。 waphaoyun 发表于 2014-12-15 22:51
楼主,给出一个完整的实例吧,毕竟代码不是很完整,让大家都能学习
放心,我正在整理,会跟大家分享我学到的东西的 电子Inc 发表于 2014-12-15 17:36
谢谢帮顶,在哪里都看到你的身影,多多交流
因为我是无处不在;P 楼主好人! 等待中,系统的看一下 :D,谢谢分享,受教了
页:
[1]