单片机实验.docx
《单片机实验.docx》由会员分享,可在线阅读,更多相关《单片机实验.docx(32页珍藏版)》请在冰点文库上搜索。
单片机实验
单片机实验
第一个试验:
点亮一个发光管
一、单片机的外部结构
拿到一块芯片,想要使用它,首先必须要知道怎样连线,我们用的一块称之为89C51的芯片,下面我们就看一下如何给它连线。
1、电源:
这当然是必不可少的了。
单片机使用的是5V电源,其中正极接40引脚,负极(地)接20引脚。
2、振蒎电路:
单片机是一种时序电路,必须提供脉冲信号才能正常工作,在单片机内部已集成了振荡器,使用晶体振荡器,接18、19脚。
只要买来晶振,电容,连上就可以了,按图1接上即可。
3、复位引脚:
按图1中画法连好,至于复位是何含义及为何需要复要复位,在单片机功能中介绍。
4、EA引脚:
EA引脚接到正电源端。
至此,一个单片机就接好,通上电,单片机就开始工作了。
当然:
您并不一定完全需要一片89c51,实际上我们用8051系列的任何一种芯片都是可以的。
例如89s51,89c52等等。
图1
二、任务分析
我们的第一个任务是要用单片机点亮一只发光二极管LED,显然,这个LED必须要和单片机的某个引脚相连,否则单片机就没法控制它了,那么和哪个引脚相连呢?
单片机上除了刚才用掉的5个引脚,还有35个,我们将这个LED和1脚相连。
(见图1,其中R1是限流电阻)
按照这个图的接法,当1脚是高电平时,LED不亮,只有1脚是低电平时,LED才发亮。
因此要1脚我们要能够控制,也就是说,我们要能够让1引脚按要求变为高或低电平。
即然我们要控制1脚,就得给它起个名字,总不能就叫它一脚吧?
叫它什么名字呢?
设计51芯片的INTEL公司已经起好了,就叫它P1.0,这是规定,不可以由我们来更改。
名字有了,我们又怎样让它变'高'或变'低'呢?
叫人做事,说一声就可以,这叫发布命令,要计算机做事,也得要向计算机发命令,计算机能听得懂的命令称之为计算机的指令。
让一个引脚输出高电平的指令是SETB,让一个引脚输出低电平的指令是CLR。
因此,我们要P1.0输出高电平,只要写SETBP1.0,要P1.0输出低电平,只要写CLRP1.0就可以了。
现在我们已经有办法让计算机去将P1.0输出高或低电平了,但是我们怎样才能计算机执行这条指令呢?
总不能也对计算机也说一声了事吧。
要解决这个问题,还得有几步要走。
第一,计算机看不懂SETBCLR之类的指令,我们得把指令翻译成计算机能懂的方式,再让计算机去读。
计算机能懂什么呢?
它只懂一样东西——数字。
因此我们得把SETBP1.0变为(D2H,90H),把CLRP1.0变为(C2H,90H),至于为什么是这两个数字,这也是由51芯片的设计者--INTEL规定的,我们不去研究。
第二步,在得到这两个数字后,怎样让这两个数字进入单片机的内部呢?
这要借助于一个硬件工具"编程器"。
当然,如果您使用我们的倚天版开发套件或者xp开发套件,那么编程器和试验板都有了,只需要编程序就可以了。
打开我们前面介绍的uvw51e中文版;参照它的使用方法;写入程序,
我们把它的名字设为:
001led.最后把生成的001led.hex烧入我们的倚天版套件配的89s51里面,然后把芯片换到试验卡座里,这时候我们可以看到p1.0这个灯亮了。
三、单片机内部结构分析
我们来思考一个问题,当我们在编程器中把一条指令写进单片要内部,然后取下单片机,单片机就可以执行这条指令,那么这条指令一定保存在单片机的某个地方,并且这个地方在单片机掉电后依然可以保持这条指令不会丢失,这是个什么地方呢?
这个地方就是单片机内部的只读存储器即ROM(READONLYMEMORY)。
为什么称它为只读存储器呢?
刚才我们不是明明把两个数字写进去了吗?
原来在89C51中的ROM是一种电可擦除的ROM,称为FLASHROM,刚才我们是用的编程器,在特殊的条件下由外部设备对ROM进行写的操作,在单片机正常工作条件下,只能从那面读,不能把数据写进去,所以我们还是把它称为ROM。
第二个试验:
点亮一个闪烁的发光管
一次我们的程序实在是没什么用,要灯亮还要重写一下片子,下面我们要让灯不断地闪烁,这就有一定的实用价值了,比如可以把它当成汽车上的一个信号灯用了。
怎样才能让灯不断地闪烁呢?
实际上就是要灯亮一段时间,再灭一段时间,也就是说要P10不断地输出高和低电平。
怎样实现这个要求呢?
请考虑用下面的指令是否可行:
SETBP1.0
CLRP1.0
……
这是不行的,有两个问题,第一,计算机执行指令的时间很快,执行完SETBP10后,灯是灭了,但在极短时间(微秒级)后,计算机又执行了CLRP10指令,灯又亮了,所以根本分辨不出灯曾灭过。
第二,在执行完CLRP10后,不会再去执行SETBP10指令,所以以后再也没有机会让灭了。
为了解决这两个问题,我们可以做如下设想,第一,在执行完SETBP10后,延时一段时间(几秒或零点几秒)再执行第二条指令,就可以分辨出灯曾灭过了。
第二在执行完第二条指令后,让计算机再去执行第一条指令,不断地在原地兜圈,我们称之为"循环",这样就可以完成任务了。
以下先给出程序(后面括号中的数字是为了便于讲解而写的,实际不用输入):
;主程序:
LOOP:
SETBP1.0 ;(1)
LCALLDELAY ;(2)
CLRP1.0 ;(3)
LCALLDELAY ;(4)
AJMPLOOP ;(5)
;以下子程序
DELAY:
MOVR7,#250 ;(6)
D1:
MOVR6,#250 ;(7)
D2:
DJNZR6,D2 ;(8)
DJNZR7,D1 ;(9)
RET ;(10)
END ;(11)
按上面的设想分析一下前面的五条指令。
第一条是让灯灭,第二条应当是延时,第三条是让灯亮,第四条和第二条一模一样,也是延时,第五条应当是转去执行第一条指令。
第二和第四条实现的原理稍后谈,先看第五条,LJMP是一条指令,意思是转移,往什么地方转移呢?
后面跟的是LOOP,看一下,什么地方还有LOOP,对了,在第一条指令的前面有一个LOOP,所以很直观地,我们可以认识到,它要转到第一条指令处。
这个第一条指令前面的LOOP被称之为标号,它的用途就是给这一行起一个名字,便于使用。
是否一定要给它起名叫LOOP呢?
当然不是,起什么名字,完全由编程序的人决定,可以称它为A,X等等,当然,这时,第五条指令LJMP后面的名字也得跟着改了。
第二条和第四条指令的用途是延时,它是怎样实现的呢?
指令的形式是LCALL,这条指令称为调用子程序指令,看一下指令后面跟的是什么,DELAY,找一下DELAY,在第六条指令的前面,显然,这也是一个标号。
这条指令的作用是这样的:
当执行LCALL指令时,程序就转到LCALL后面的标号所标定的程序处执行,如果在执行指令的过程中遇到RET指令,则程序就返回到LCALL指令的下面的一条指令继续执行,从第六行开始的指令中,可以看到确实有RET指令。
在执行第二条指令后,将转去执行第6条指令,而在执行完6,7,8,9条指令后将遇到第10条令:
RET,执行该条指令后,程序将回来执行第三条指令,即将P10清零,使灯亮,然后又是第四条指令,执行第四条指令就是转去执行第6,7,8,9,10条指令,然后回来执行第5条指令,第5条指令就是让程序回到第1条开始执行,如此周而复始,灯就在不断地亮、灭了。
在标号DELAY标志的这一行到RET这一行中的所有程序,这是一段延时程序,大概延时零点几秒,至于具体的时间,以后我们再学习如何计算。
程序的最后一行是END,这不是一条指令,它只是告诉我们程序到此结束,它被称为"伪指令"。
二、单片机内部结构分析:
为了知道延时程序是如何工作的,我们必需首先了解延时程序中出现的一些符号,就从R1开始,R1被称之为工作寄存器。
什么是工作寄存器呢?
让我们从现实生活中来找找答案。
如果出一道数学题:
123+567,让你回答结果是多少,你会马上答出是690,再看下面一道题:
123+567+562,要让你要上回答,就不这么容易了吧?
我们会怎样做呢?
如果有张纸,就容易了,我们先算出123+567=690,把690写在纸上,然后再算690+562得到结果是1552。
这其中1552是我们想要的结果,而690并非我们所要的结果,但是为了得到最终结果,我们又不得不先算出690,并记下来,这其实是一个中间结果,计算机中做运算和这个类似,为了要得到最终结果,往往要做很多步的中间结果,这些中间结果要有个地方放才行,把它们放哪呢?
放在前面提到过的ROM中可以吗?
显然不行,因为计算机要将结果写进去,而ROM是不可以写的,所以在单片机中另有一个区域称为RAM区(RAM是随机存取存储器的英文缩写),它可以将数据写进去。
特别地,在MCS-51单片机中,将RAM中分出一块区域,称为工作寄存器区。
以下是它的a51文件:
我们把它的名字叫作002.A51
LOOP:
SETBP1.0
LCALLDELAY
CLRP1.0
LCALLDELAY
AJMPLOOP
DELAY:
MOVR7,#250
D1:
MOVR6,#250
D2:
DJNZR6,D2
DJNZR7,D1
RET
END
以下是我们用编译器C51EVAL编译过的HEX文件,它就可以烧写啦。
:
10000000D29012000CC29012000C01007FFA7EFA0E
:
05001000DEFEDFFA2214
:
00000001F
第三个试验:
认识声音
什么是声音?
上过初中的朋友都知道声音是由震动所产生的。
一定频率的震动就产生了一定频率的声音。
在我们的倚天版开发套件和XP开发套件中,实验版的P3.3口(13脚)接了一个小喇叭,如果我们往它那里送一个高电平,送一个低电平,他就会发出滴嗒的声音。
我们把上面的闪烁发光管试验的P1.0改为P3.3就好了。
上图就是我们倚天版开发套件的小喇叭
LOOP:
SETBP3.3
LCALLDELAY
CLRP3.3
LCALLDELAY
AJMPLOOP
DELAY:
MOVR7,#250
D1:
MOVR6,#250
D2:
DJNZR6,D2
DJNZR7,D1
RET
END
这时候我们就可以听到小喇叭的响声啦。
可是有的朋友会问,声音又那么多种,怎么办呢?
很简单,我们把它的延时时间给改一下,声音就会有所变化了。
LOOP:
SETBP3.3
LCALLDELAY
CLRP3.3
LCALLDELAY
AJMPLOOP
DELAY:
MOVR7,#25
D1:
MOVR6,#25
D2:
DJNZR6,D2
DJNZR7,D1
RET
END
这时候我们就可以听到小喇叭发出嘀“的尖叫声。
适当的调整他的延时时间,我们就可以让他发出DO,RUI,MI,FASO,LA,XI,DO.的声音。
这就使单片机发声的基本原理。
第四个试验:
小喇叭发出救护车的声音
这个实验演示了我们的倚天版开发套件小喇叭发出救护车声音的实例,您直接汇编这个文件,
烧写进我们配送的89s51里面,然后再插入试验卡座。
打开电源,就可以听到喇叭里发出
滴答一长一短的报警声音。
这个就有一点点使用价值啦/送出的端口是p3.3输出1khz,2khz
变频信号报警。
每一秒交换一次。
dlv:
movr2,#08h;1kz持续时间
dlv1:
movr3,#0fah
dlv2:
cplp3.3;输出1khz方波
lcalld5ms;调用延时程序1
djnzr3,dlv2;持续1秒
djnzr2,dlv1
movr2,#10h;2khz持续时间
dlv3:
movr3,#0fah
dlv4:
cplp3.3;输出2khz方波
lcalld25ms;调用延时程序2
djnzr3,dlv4
djnzr2,dlv3
sjmpdlv;反复循环
d5ms:
movr7,#0ffh;延时子程序1
loop:
nop
nop
djnzr7,loop
ret
d25ms:
movr6,#0ffh;延时子程序2
lin:
djnzr6,lin
ret
end
以下是汇编以后的源代码hex。
:
100000007A087BFAB2B312001CDBF9DAF57A107BBE
:
10001000FAB2B3120023DBF9DAF580E47FFF0000C7
:
08002000DFFC227EFFDEFE2260
:
00000001FF
第六个试验:
认识数码管
玩单片机一定要玩转数码管了;上图是我们xp套件的两位数码管的截图照片;这个数码管怎样来显示1,2,3,4呢?
别着急,听我慢慢道来。
数码管实际上是由7个发光管组成8字形构成的,加上小数点就是8个。
我们的xp套件和倚天套件用的都是两位8的共阳极扫描型数码管。
什么是共阳极呢;就是他们的公共端接正极。
扫描型的意思是,几位的数码管的段选都是并联的
由他们的位选位来控制哪一位的数码管来亮。
看看上面的照片,由两个黑糊糊的三极管,来控制两边的数码管
哪一边亮。
动态扫描显示接口是单片机中应用最为广泛的一种显示方式之一。
其接口电路是把所有显示器的8个笔划段a-h同名端连在一起,而每一个显示器的公共极COM是各自独立地受I/O线控制。
CPU向字段输出口送出字形码时,所有显示器接收到相同的字形码,但究竟是那个显示器亮,则取决于COM端,而这一端是由I/O控制的,所以我们就可以自行决定何时显示哪一位了。
而所谓动态扫描就是指我们采用分时的方法,轮流控制各个显示器的COM端,使各个显示器轮流点亮。
在轮流点亮扫描过程中,每位显示器的点亮时间是极为短暂的(约1ms),但由于人的视觉暂留现象及发光二极管的余辉效应,尽管实际上各位显示器并非同时点亮,但只要扫描的速度足够快,给人的印象就是一组稳定的显示数据,不会有闪烁感。
现在大家应当明白了我们应当怎样做,如果显示一个2字,那么呢应当是A亮B亮G亮E亮D亮F不亮C不亮。
现在在看看我们的倚天套件的硬件原理。
可以看到他的COM端由两个A1015的三极管控制,控制端分别接在P2.6,P2.7,字段则分别接在P0.0--0.7口。
假如我们要让左边的数码管显示一个2字
可以编以下的程序。
CLRP2.6;选中左边的数码管
SETBP2.7;不选右边的数码管
SETBP0.7;B段不亮
SETBP0.5;小数点不亮
SETBP0.1;C段不亮
CLRP0.2;其余的都亮
CLRP0.3
CLRP0.4
CLRP0.6
CLRP0.0
END
运行程序可以看到他们显示的数字为2。
在这样一种情况下,我们会发现这个程序非常麻烦。
呵呵,现在回到上面一课,跟我来作加减法;就会发现
一排数字其实就是二进制的数字。
我们把他转换为16进制。
直接送到P0口就行啦。
注意0为点亮1为灭
显示数字
p0.7
p0.6
p0.5
p0.4
p0.3
p0.2
p0.1
p0.0
16进制代码
0
0
0
1
0
1
0
0
0
28H
1
0
1
1
1
1
1
1
0
7EH
2
1
0
1
0
0
0
1
0
A2H
3
0
1
1
0
0
0
1
0
62H
4
0
1
1
1
0
1
0
0
74H
5
0
1
1
0
0
0
0
1
61H
6
0
0
1
0
0
0
0
1
21H
7
0
1
1
1
1
0
1
0
7AH
8
0
0
1
0
0
0
0
0
20H
9
0
1
1
0
0
0
0
0
60H
我们把他从高往低排列为二进制,例如2,就是10100010,用计算器转换为16进制就是A2.我们在单片机里为了把16进制和10进制有所区别,就把16进制后面跟一个H,同时如果首位为字母的为了区别于指令,同时前面跟一个0,就成了0A2H了。
大家可能有一点疑问,为啥P0.5始终为1呢。
因为它接在小数点上。
我们没有用它而已。
根据上面的方法。
如果我们把数码管的接线给打乱,同样的可以分析出他的数字代码。
现在程序就简单啦:
还是显示一个2字:
CLRP2.6;选中右边的数码管
SETBP2.7;不选左边的数码管
MOVP0,#0A2H;将10100010送P0口
END
可以看到显示的结果是一样的。
把所有的代码分析出来后以后编程序就可以直接调用啦。
我们的倚天版套件注意一共用了4个数码管
他们的位选为P2.3P2.4P2.6P2.7这样他一共可以显示四位数字。
甚至我们可以直接用它来做一个
显示仪表,或者闹钟了。
他的0,1,2,3,4,5,6,7,8,9的代码分别为28h,7eh,0a2h,62h,74h,61h,21h,7ah,20h,60h
以下为我们的倚天版开发套件运行现实8051的程序
loop:
movp0,#0ffh;关显示
movp2,#0ffh;关显示
clrp2.4 ;选中第一个数码管
movp0,#20h;数码管显示8
lcalldelay;调用延时
movp0,#0ffh
movp2,#0ffh
clrp2.5;选中第二个数码管
movp0,#28h;数码管显示0
lcalldelay
movp2,#0ffh
movp0,#0ffh
clrp2.6;选中第三个数码管
movp0,#61h;数码管显示5
lcalldelay
movp0,#0ffh
movp2,#0ffh
clrp2.7;选中第四个数码管
movp0,#7eh;数码管显示1
lcalldelay
ajmploop;程序条转到第一步,反复执行
delay:
;延时子程序
movr6,#250
d1:
djnzr6,d1
ret
end
流水灯数字显示综合练习
该程序运行结果为个位数码管轮流现实0,1,2,3,4,5,6,7,8
然后十位数码管轮流现实0,1,2,3,4,5,6,7,8反复循环
P1.0,P1.1,P1.2,P1.3,P1.4,P1.5,P1.6,P1.7,依次点亮然后轮流点亮
小喇叭不停发出滴答声:
注意该程序配套为我站的倚天版开发套件:
如果是标准版:
因他的数码管接法不同。
显示的数字不对。
该程序在本站XP开发套件上调试通过,以下是程序运行在XP版时的照片.(sorry,照片很模糊)
数码管显示数字
注意0为点亮1为灭
显示数字
p0.7
p0.6
p0.5
p0.4
p0.3
p0.2
p0.1
p0.0
16进制代码
0
0
0
1
0
1
0
0
0
28H
1
0
1
1
1
1
1
1
0
7EH
2
1
0
1
0
0
0
1
0
A2H
3
0
1
1
0
0
0
1
0
62H
4
0
1
1
1
0
1
0
0
74H
5
0
1
1
0
0
0
0
1
61H
6
0
0
1
0
0
0
0
1
21H
7
0
1
1
1
1
0
1
0
7AH
8
0
0
1
0
0
0
0
0
20H
9
0
1
1
0
0
0
0
0
60H
代码表的意思和方法参照前面的教程;注意0为点亮1为灭然后我们可以把代码送到P0口,就可以是数码管显示需要的数字;当然,必须有位选,因为我们的实验板是动态扫描数码管,两个8的位选分别是P2.6P2.7.
LOOP:
;标号
CLRP2.6;选中p2.6数码管左边的8字使能
SETBP2.7;p2.7不使能。
右边的数码管消隐
MOVP0,#28H;把28h送p0口;数码管显示0
LCALLDELAY;延时
MOVP0,#0FFH;0ffh送p0口,数码管清除
CLRP1.0;点亮p1.0发光管
MOVP0,#7EH;把7eh送p0口;数码管显示1
LCALLDELAY
MOVP0,#0FFH
CLRP1.1;点亮p1.0发光管
CLRP1.0;点亮p1.0发光管
MOVP0,#0A2H;数码管显示2
LCALLDELAY
MOVP0,#0FFH
CLRP1.2
CLRP1.1
CLRP1.0
MOVP0,#62H;数码管显示3
LCALLDELAY
MOVP0,#0FFH
CLRP1.3
CLRP1.2
CLRP1.1
CLRP1.0
MOVP0,#74H;;数码管显示4
LCALLDELAY
MOVP0,#0FFH
CLRP1.4
CLRP1.3
CLRP1.2
CLRP1.1
CLRP1.0
MOVP0,#61H;数码管显示5;
LCALLDELAY
MOVP0,#0FFH
CLRP1.5
CLRP1.4
CLRP1.3
CLRP1.2
CLRP1.1
CLRP1.0
MOVP0,#21H;数码管显示6
LCALLDELAY
MOVP0,#0FFH
CLRP1.6
CLRP1.5
CLRP1.4
CLRP1.3
CLRP1.2
CLRP1.1
CLRP1.0
MOVP0,#7AH;数码管显示7
LCALLDELAY
MOVP0,#0FFH
CLRP1.7
CLRP1.6
CLRP1.5
CLRP1.4
CLRP1.3
CLRP1.2
CLRP1.1
CLRP1.0
MOVP0,#20H;数码管显示8
LCALLDELAY
MOVP0,#0FFH
LCALLDELAY
MOVP0,#0FFH
MOVP1,#0FFH
;程序到此结果为左边的数码管显示0,1,2,3,4,5,6,7,8
;p1.0------------p1.7指示灯依次点亮
SETBP2.6;左边的8消隐
CLRP2.7;选中p2.7数码管右边的8字使能,;
MOVP0,#28H
LCALLDELAY
MOVP0,#0FFH
MOVP1,#0FFH
CLRP1.0
MOVP0,#7EH
LCALLDELAY
MOVP0,#0FFH
MOVP1,#0FFH
CLRP1.1
MOVP0,#0A2H
LCALLDELAY
MOVP0,#0FFH
MOVP1,#0FFH
CLRP1.2
MOVP0,#62H
LCALLDELAY
MOVP0,#0FFH
MOVP1,#0FFH
CLRP1.3