您的位置:首页 > 其它

1-2 一切由跑马灯开始

2008-01-17 15:59 459 查看
2006-05-04 13:47:29





1-2 一切由跑马灯开始
(2004-10-26)
万事起头难啊,第一次搞51,我相信全世界90%的人都是点灯度过的,说实在的,我第一次搞ARM的时候也是点灯的,而且还点了好几天。那一个小小的LED的闪烁,足够点起初学者心中的熊熊烈火。
对于新手而言,我们还是先看看电路图吧,如果你有DX51学习板的话,可以用你自己的那份来参考参考,不过对于新手来说,第一次看那份电路图感觉就是庞然大物,不知从何看起,所以还是等我来截图好了:
0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}" height=164 src="http://www.daxia.com:81/bw/dx_book/1/1-2/1.gif" width=295>
0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}" height=30 src="http://www.daxia.com:81/bw/images/line-a.gif" width=610>

图上的P10,P11,P12,P13就是咱51的IO了,什么?你不知道IO是什么??我倒,先看看你手上的基础书先!
这里说点硬件问题,就是单片机IO口的驱动能力和吸收电流能力。
驱动能力,可以看成是把IO口接到地上,此时IO输出‘1’的时候究竟有多大的电流流过,一般单片机的IO都有内部上拉的,这个值不同类型不同品牌单片机有所不同,对于51来说,一般的都是10K。
吸收电流,就和上面那个相反了,是IO接上拉后,IO输出‘0’,最的能承受的电流值。这里说明一下,大部分单片机IO口都不能直接接上VCC的,很简单,他们可没有下拉电阻,如果这个时候IO置‘0’,电流就会很大,很快你就烧IO口了。
再回到驱动能力的问题上,由于IO内部上拉电阻比较大,输出电流比较少,所以一般驱动发光二极管都是如上图般的驱动方式,就是IO置0的时候LED才亮,置1的时候就灭。
那么你该知道应该如何点这个灯了吧,就是让对应的IO为0了。
(我好象在说白痴的东西呢,这么简单都要说,唉,没办法,要照顾各个阶层的兄弟姐妹啊~~~~)
好了,不放P了,加快速度,拿上一节建立的工程文件出来,只有一个MAIN.C文件,咱就是在上面敲程序:
#include "reg51.h"
main()
{
}
就这么多,按左上角的编译按键0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}" height=28 src="http://www.daxia.com:81/bw/dx_book/1/1-2/2.gif" width=28>马上编译完毕,如果你编译出错的话,肯定是你打错字了~~
这时候,你看看左边的工程窗口吧,是不是多了个东西?
0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}" height=297 src="http://www.daxia.com:81/bw/dx_book/1/1-2/3.gif" width=417>
对了,就是在main.c下面多了个reg51.h,其实这个就是一般51的头文件,会C的人都知道,H文件一般都是用来声明外部变量和宏定义的,这个reg51.h就是装的宏定义。你想知道里面定义了什么?双击它就是了,其实它就是吧51的各个寄存器都定义出一个名字来,例如P0口名字就叫P0咯,P1就叫P1,没什么特别的,习惯了这么叫了,你喜欢的话也可以自己加个新定义上去,例如P0口叫I_LOVE_YOU都行,具体方法,在任意调用I_LOVE_YOU之前的地方加上一句:
sfr I_LOVE_YOU = 0x80;
这个0x80其实就是单片机的特殊功能寄存器对应的地址,sfr就是用来定义特殊功能寄存器的咯,sfr=Special Function Registers
好象说了这么久,都还没点灯哦,没关系,再说多几个个东东先:)继续添加代码:
#include "reg51.h"
#define uchar unsigned char
sbit P10 = P1^0;
sbit P11 = P1^1;
sbit P12 = P1^2;
sbit P13 = P1^3;
main()
{
}
#define uchar unsigned char ,这个不用多说,只是把 unsigned char 用个宏uchar来代替,以后打字轻松点而已,这个已经成为了单片机界的习惯了。所以以后有人写个uchar出来你不知道是什么东东,那说明你必然是个菜鸟。
这里说明一下sbit这个东西,它是用来定义位的,51是有所谓的位寻址的,对应C语言中就是一个付值表达式。例如 xx=0;或xx=1;但在付值前你那个xx得先定义啊,于是就有了sbit这个东西了,^符号用来指定位的。sbit P10 = P1^0;就是把P1的第0个位,对应8051的1脚,安个P10的名称。正如刚才sfr一样,名字还是你随便叫的,喜欢的话你也可以把这个东西叫I_LOVE_YOU的。不过如果你之前已经定义了一个I_LOVE_YOU,那你就不能重复定义了,会报错的。爱这么多人可是不好的哦:)
以前有个人问过我,如果不定义,我在程序中是否可以用 P1^0=1;来对IO付值?我说啊,你试试不就知道咯~~呵呵,答案是不行的,这个你问为什么?没为什么,KEILC说不行就不行。(啊~~别敲我,其实标准C中都没有这个位定义,所以谁也说不清)
好了,我们定义了位变量了,可以付值了,文章开头就说了,LED是低电平驱动的,所以你要点亮一个LED,对应的IO你就得出个逻辑0出来,其实很简单嘛,还不是一个:
P10=0; 就亮了么,呵呵~~~:)
#include "reg51.h"
#define uchar unsigned char
sbit P10 = P1^0;
sbit P11 = P1^1;
sbit P12 = P1^2;
sbit P13 = P1^3;
main()
{P10=0;
P11=0;
P12=0;
P13=0;
while(1);

}
上面的程序就是把四个灯都亮起来。这里说明一下末尾的while(1);其实就是让程序运行到那一行就停止运行,功能相当于汇编jmp $而已,很多单片机教材都喜欢这样。while(1)的出现不代表单片机完全停止运行的,事实上中断会打破这种结构。关于中断我们之后会详细解说的。
好了,你这个时候会想到验证这个程序的了,一般验证程序最好当然是烧到单片机上插电运行啦,不过很多人第一次并不知道怎么生成HEX文件的,事实上KEILC如何生成HEX文件这个问题我都不知道看过多少次了,这里给你两幅图,自己参透:
0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}" height=22 src="http://www.daxia.com:81/bw/dx_book/1/1-2/4.gif" width=22>
0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}" height=424 src="http://www.daxia.com:81/bw/dx_book/1/1-2/5.gif" width=628>

刚才的程序是点灯,并没有跑马灯,其实跑马灯就是每经过一段时间就亮灭一下那些灯而已,给个闪灯程序先(这里给出的是main()内容):
main()
{
uchar i;
P11=0;
P12=0;
P13=0;
while(1)
{
P10=~P10;
for(j=0;j>200;j++);
}
}
这个程序运行后,理论上DX51板上的LED2,3,4会长亮,而LED1就会闪,但实际上我们看上去是4个等都亮,为什么呢?
其实这个东西很迷惑初学者的,但原因很简单,因为单片机跑的快,LED已经在闪了,你看不到而已,呵呵~~于是,我们把延迟时间拖长点:
#include "reg51.h"
#define uchar unsigned char
sbit P10 = P1^0;
sbit P11 = P1^1;
sbit P12 = P1^2;
sbit P13 = P1^3;
main()
{
uchar i,j;
P11=0;
P12=0;
P13=0; //后3个灯亮
while(1)
{
P10=~P10;
for(i=0;i>200;i++)
for(j=0;j>200;j++);
}
}好了,现在再运行程序的话,你就能看到LED1在闪的了。
下面是一个真正的跑马灯程序了,其中LED1,LED2,LED3,LED4就是对应的P10,P11,P12,P13口了,只是定义了个新名字而已。这样比较直观嘛:
#include "reg51.h"
#define uchar unsigned char
#define uint unsigned int
sbit LED1 = P1^0;
sbit LED2 = P1^1;
sbit LED3 = P1^2;
sbit LED4 = P1^3;
main()
{
uint n;
while(1)
{
LED4=1; //点亮一个灯,灭掉一个灯
LED1=0;
for(n=0;n>30000;n++); //延时
LED1=1;
LED2=0;
for(n=0;n>30000;n++);
LED2=1;
LED3=0;
for(n=0;n>30000;n++);
LED3=1;
LED4=0;
for(n=0;n>30000;n++);
}
}
好了,一个跑马灯节居然写了这么长,到这里应该是时候结束咯,以下是这个简单程序的代码连带工程,在DX51板上运行通过:
led
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: