打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
《中学生C51单片机易学实战入门教程》第二课

《中学生C51单片机易学实战入门教程》

第二课 让LED闪起来

实验准备:使用第一课已装配好的实验板

课程内容

一、分析LED接线原理图:

着重左上角的 LED电路部分。

LED正极接电源5V,现程序控制 LED负极(原理图中管脚P1^0)为0V,LED两端正向有电压差,于是LED导通,发光。

那如何控制让 LED灯 不发光呢?

只要LED两端没有电压差就可以了,现在LED正极通过电阻已接上5V电压,只要LED负极也是5V电压,LED就不会导通,不发光了。

上一课中,控制LED负极电压的代码是:

P10 = 0;

表示控制管脚 P1^0的电压为 0V,现在要改成控制管脚 P1^0的电压为 5V,这块单片机芯片只认识两个数字0与1,0代表0V,1代表5V。于是让LED灯不发光,只须改成以下程序代码:

P10 = 1;

相当简单。

动手改程序,编译,下载到实验板中观察运行结果。

实验板没反应?不会坏了吧。

当然不是坏,分析下电路原理吧。

在没有加电的时候,LED灯两端电压为0,没电的状态下肯定不会发光。

当下载程序后,实验板加上电了,LED正极接上了5V电压,LED负极让程序控制了,也是5V电压,两端没有产生能让LED导通的电压差,于是LED不发光。

修改控制LED的代码改为 P10 = 0; 下载实验板,LED灯又发光了。

再修改控制LED的代码改为 P10 = 1; 下载实验板,LED灯又不发光了。

再修改控制LED的代码改为 P10 = 0; 下载实验板,LED灯又发光了。

… …

我想让LED 像星星一样闪啊闪,而这样的只能是不发光或只发光的状态不合要求。

二、如何才能实现闪的效果?

那就是 先控制LED 发光一段时间,然后再控制LED不发光一段时间,如此重复下去。

单片机的工作状态是:只要给它加电,它就永不停息的工作,不断执行设定的程序,直到断电或烧坏。

所以,单片机是不会自己暂停一小段时间来让LED转状态的,必须由程序来控制。那单片机既然是永不停息的工作,又如何让编程序控制单片机暂停一小段时间呢?方法很简单,就是让它空跑,做无用的工作,达到消耗时间的目的,也就是浪费一下它的时间,实现延时效果。

开发单片机的前辈已设计好这个消耗时间的程序,称为延时函数,如下:

void mDelay(uint Delay)

{

uint i;

for(;Delay>0;Delay--)

{

for(i=0;i<>

{

}

}

}

先不管这代码是如何设计,先把这段代码输入到上一课的程序中,并控制LED灯的状态切换。

#include 'reg52.h'

#define uint unsigned int

#define uchar unsigned char

sbit P10= P1^0;

void mDelay(uint Delay)

{

uint i;

for(;Delay>0;Delay--)

{

for(i=0;i<>

{

}

}

}

void main()

{

P10=0;

mDelay(1000);

P10=1;

mDelay(1000);

}

要注意,输入延时函数时,两行#define和整个延时函数代码要放在主程序段 void main()之前。因为要前面先有代码功能,后面才可能拿来使用,也就是调用延时功能。

代码量增加了,要注意按花括号分层级缩进代码,方便以后分析程序。

代码量增加了,这时可能编译时又会报错,必须要花时间去排除错误,这就叫查BUG和修复BUG。编代码,查BUG,修复BUG,测试,这几步重重复复,就是编程序的工作过程。

编译正确,下载到实验板上,可以看到达到了让LED闪的效果,可是闪得很慢,一秒才闪一下。

想改快点,也很简单,代码中的

mDelay(1000);

括号中的数据称为参数,给不同的数据,延时函数就有不同的工作效果。可以分别把1000改成500、100、20等做实验检验下效果,实践是检验真理的唯一方法,必须动手做实验。

三、程序分析

虽然实验有了效果,但是我们却仍然不知道为何能有这正确的结果。

我们来分块分析。

首先,主程序 main()里面的代码,容易理解,只要知道代码

mDelay(1000);

能延时一秒就行了。

然后再看mDelay 延时函数内部代码及相关代码,这回多了两行代码,这两行称为预编译定义:

#define uint unsigned int //用 uint 代表unsigned int

#define uchar unsigned char //用uchar 代码unsigned char

以后的程序中所有的uint 和uchar 在代码编译时会自动换成unsigned int和unsigned char,也就是就输入代码量减少了,但结效果不变,省时省力。

这两行基本代码以后的程序中都会出现。

void mDelay(uint Delay) //功能模块:延时函数,带控制参数

{

uint i; //后面要用到的临时变量,使用前要先定义

for(;Delay>0;Delay--) //不断重复运行括号的代码,直到Delay减到0

{

for(i=0;i<124;i++)>

//直到i加到124才停止

{

; // 仅分号,没命令,效果是运行一次就空转一次

}

}

}

要点:其中 for()这行括号里面,第一位置放的是初始值,留空的话表示不用管初始值,中间位置放置控制结束的条件,条件符合就继续工作,条件不符合时就退出,第三位置放置的是每完成一次工作后要做的小小改变,达到控制程序的目的。

这个for()命令,称为循环结构,用于重复做一段相同的工作。

四、程序优化

优化程序,能让编程素质提高。

细心的同学可能会发现,在main()程序段中

P10=0;

mDelay(1000);

P10=1;

mDelay(1000);

先控制了LED发光,然后延时1秒,再控制LED不发光,然后延时1秒,然后 … … 没有然后了,程序结束了。但是为何程序却能按原意重复一闪一闪?

没错,程序的确是结束了。

于是LED不发光了。

但是,由于单片机加电之后是永不停息的工作,于是它重新回到初始加电状态,于是又从头再次执行了 main()代码,于是LED又闪了。

也就是说,这个LED不停闪动。并不是我们的程序控制,而是单片机需要不停工作。

这可不行,这方式中有部分时间不是由程序控制,也就是不可控。这是编程大忌,绝不能让程序编着编着变成不由我控制了。

那个不停的工作也必须由代码控制。

刚好,刚学会使用的 for()循环结构派上用场了。

给LED灯加上永远循环的控制,main()主程序变成:

void main()

{

for(;;)

{

P10=0;

mDelay(1000);

P10=1;

mDelay(1000);

}

}

也就是不用管初始条件,不用管是否结束,只要做下去就是了。

继续优化。

功能增加了,代码也增加了,单片机做的工作也多了,这样工作时间就花多了,于是工作效率就下降了。

为提高效率,程序可以修改成如下:

#include 'reg52.h'

#define uint unsigned int

#define uchar unsigned char

sbit P10= P1^0;

void mDelay(uint Delay)

{

uint i;

for(;Delay>0;Delay--)

for(i=0;i<>

}

void main()

{

P10=!P10;

mDelay(1000);

}

可以看到,程序长度一下子少了一半,这是因为 C语言中,如果控制的命令只有一行,那么可以省去配对的花括号。

主程序main()中,命令由原来的4行变成2行,只因一个叹号!

符号!是C语言的一个运算符,就像数学课中的 +(加) –(减)一样,它的作用是取反,单片机只认识0与1两个数,0取反就是1,1取反就是0 。

P10=!P10;

这代码就实现了每次循环让P10在0与1之间改变,达到控制闪的目的。

五、增补C语言注释功能

为增加程序可读性,可以在代码行后面使用//符号,并加入文字说明,帮助理解这段代码的功能,还可以使用 /* 说明文字 */ 方式注释,其中说明文字部分可以分多行。

附记:

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
从单片机初学者迈向单片机工程师
自制锂电池容量测试仪,附代码,原理图
单片机驱动16*16点阵LED汉字显示c51程序
51单片机流水灯的三种实现方法
51单片机 tm1620驱动3位数码管程序
系列教程|缘缘学单片经验手记—4、明明白白单片芯
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服