您的位置 首页 资料

第四节:累计守时中止次数使LED灯闪耀

开场白:上一节提到在累计主循环次数来实现计时,随着主函数里任务量的增加,为了保证延时时间的准确性,要不断修正设定上限阀值const_time

开场白:

上一节说到在累计主循环次数来完成计时,跟着主函数里使命量的添加,为了确保延时时刻的准确性,要不断批改设定上限阀值const_time_level 。咱们该怎样处理这个问题呢?本节教咱们使用累计守时中止次数的办法来处理这个问题。这一节要教会咱们四个知识点:

榜首点:使用累计守时中止次数的办法完成时刻延时

第二点:展现鸿哥最完好的实战程序结构。在主函数循环里用switch句子完成状况机的切换,在守时中止里累计中止次数,这两个的结合便是我写代码最实质的结构思维。

第三点:提示咱们C语言中的int ,long变量是由几个字节构成的数据,但凡在main函数和中止函数里有或许一起改动的变量,这个变量应该在主函数中被更改之前,先封闭相应的中止,更改完了此变量,再翻开中止,不然会留下不宜发觉的缝隙。当然在大部分的项目中能够不必这么操作,可是在一些要求十分高的项目中,有一些中心变量有必要这么做。

第四点:守时中止的初始值该怎样设置。不必严厉按公式来核算时刻,一般取个经历值是最大初始值减去1000就能够了。

具体内容,请看源代码解说。

(1)硬件渠道:根据朱兆祺51单片机学习板

(2)完成功用:让一个LED闪耀。

(3)源代码解说如下:

#include “REG52.H”

#define const_time_level 200

void initial_myself();

void initial_peripheral();

void delay_long(unsigned int uiDelaylong);

void led_flicker();

void T0_time(); //守时中止函数

sbit led_dr=P3^5;

unsigned char ucLedStep=0; //过程变量

unsigned int uiTimeCnt=0; //计算守时中止次数的延时计数器

void main()

{

initial_myself();

delay_long(100);

initial_peripheral();

while(1)

{

led_flicker();

}

}

void led_flicker() ////第三区 LED闪耀应用程序

{

switch(ucLedStep)

{

case 0:

/* 注释一:

* uiTimeCnt累加守时中止的次数,每一次守时中止它都会在中止函数里自加一。

* 只要当它的次数大于或等于设定上限const_time_level时,

* 才会去改动LED灯的状况,不然CPU退出led_flicker()使命,持续快速扫描其他的使命,

* 这样的程序结构就能够到达多使命并行处理的意图。这便是鸿哥在所有开发项目中的中心结构。

*/

if(uiTimeCnt>=const_time_level) //时刻到

{

/* 注释二:

* ET0=0;uiTimeCnt=0;ET0=1;—-在清零uiTimeCnt之前,为什么要先制止守时中止?

* 因为uiTimeCnt是unsigned int类型,实质上是由两个字节组成。

* 在C语言中uiTimeCnt=0看似一条指令,实际上通过编译之后它不只一条汇编指令

* 因为守时中止函数里也对这个变量进行累加操作,假如不制止守时中止,

* 那么uiTimeCnt这个变量在main()函数中还没被彻底清零的时分,假如这个时分

* 忽然来一个守时中止,并且在中止里又更改了此变量,这种状况在某些要求高的

* 项目上会是一个不容易发觉的缝隙,为项目带来危险。当然,大部分的一般项目,

* 都能够不必那么严厉,能够不必制止守时中止。在这儿仅仅提示各位初学者有这种状况。

*/

ET0=0; //制止守时中止

uiTimeCnt=0; //时刻计数器清零

ET0=1; //敞开守时中止

led_dr=1; //让LED亮

ucLedStep=1; //切换到下一个过程

}

break;

case 1:

if(uiTimeCnt>=const_time_level) //时刻到

{

ET0=0; //制止守时中止

uiTimeCnt=0; //时刻计数器清零

ET0=1; //敞开守时中止

led_dr=0; //让LED灭

ucLedStep=0; //回来到上一个过程

}

break;

}

}

/* 注释三:

* C51的中止函数格局如下:

* void 函数名() interrupt 中止号

* {

* 中止程序内容

* }

* 函数名能够随意取,只需不是编译器现已征用的要害字。

* 这儿最要害的是中止号,不同的中止号代表不同类型的中止。

* 守时中止的中止号是 1.至于其它中止的中止号,咱们能够查找

* 相关书本和材料。咱们进入中止时,有必要先铲除中止标志,并且

* 封闭中止,然后再写代码,最终出来时,记住重装初始值,并且

* 翻开中止。

*/

void T0_time() interrupt 1

{

TF0=0; //铲除中止标志

TR0=0; //关中止

if(uiTimeCnt<0xffff) //设定这个条件,避免uiTimeCnt超范围。

{

uiTimeCnt++; //累加守时中止的次数,

}

TH0=0xf8; //重装初始值(65535-2000)=63535=0xf82f

TL0=0x2f;

TR0=1; //开中止

}

void delay_long(unsigned int uiDelayLong)

{

unsigned int i;

unsigned int j;

for(i=0;i

{

for(j=0;j<500;j++) //内嵌循环的空指令数量

{

; //一个分号相当于履行一条空句子

}

}

}

void initial_myself() //榜首区 初始化单片机

{

/* 注释四:

* 单片机有几个守时器,每个守时器又有几种工作方式,

* 那么多种改变,咱们记不了那么多,怎样办?

* 咱们记住鸿哥的话,不管一个单片机有多少内置资源,

* 咱们做体系结构的,只需求一个守时器,一种工作方式。

* 开守时器越多这个体系越欠好。需求哪种守时工作方式呢?

* 就需求呼应守时中止后重装一下初始值持续跑那种。

* 在51单片机中便是工作方式1。其它的工作方式很少项目能用到。

*/

TMOD=0x01; //设置守时器0为工作方式1

/* 注释五:

* 装守时器的初始值,就像一个水桶里装的水。假如这个桶是空桶,那么想

* 把这个桶灌满水的时刻就很长,假如是里边现已装了多半的水,那么想

* 把这个桶灌满水的时刻就相对比较短。也便是守时器初始值越小,发生一次

* 守时中止的时刻就越长。假如初始值太小了,每次发生守时中止

* 的时刻分辨率太粗,假如初始值太大了,尽管每次发生守时中止的时刻分辨率很细,

* 可是太频频的发生中止,不但会影响主函数main()的履行功率,并且累记中止次数

* 的时刻误差也会很大。凭鸿哥多年的江湖经历,

* 我觉得最大初始值减去2000是比较好的经历值。当然,大一点小一点不要紧。不要走

* 两个极点就行。

*/

TH0=0xf8; //重装初始值(65535-2000)=63535=0xf82f

TL0=0x2f;

led_dr=0; //LED灭

}

void initial_peripheral() //第二区 初始化外围

{

EA=1; //开总中止

ET0=1; //答应守时中止

TR0=1; //发动守时中止

}

总结陈词:

本节程序麻雀虽小五脏俱全。在本节中现已展现了我最完好的实战程序结构。

本节程序只要一个LED灯闪耀的单使命,假如要多添加一个使命来并行处理,该怎样办?

欲知概况,请听下回分解—–蜂鸣器的驱动程序。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/ziliao/262129.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部