求一个数的模%256模是80这个数是多少

导读:就爱阅读网友为您分享以下“单片机的40个经典的基础实验_图文”的资讯,希望对您有所帮助,感谢您对92to.com的支持!
(1. 我们用单片机实定时/计数器 T0 来产生 700HZ 和 500HZ 的频率,根据定时
/计数器 T0,我们取定时 250us,因此,700HZ 的频率要经过 3 次 250us
的定时,而 500HZ 的频率要经过 4 次 250us 的定时。
(2. 在设计过程,只有当按下 SP1 之后,才启动 T0 开始工作,当T0 工作完毕 ,
回到最初状态。
(3. “叮”和“咚”声音各占用 0.5 秒,因此定时/计数器 T0 要完成 0.5 秒的
定时,对于以 250us 为基准定时 2000 次才可以。
5. 程序框图 主程序框图 T0 中断服务程序框图
6. 汇编源程序
T5HZ EQU 30H
T7HZ EQU 31H
T05SA EQU 32H
T05SB EQU 33H
FLAG BIT 00H
STOP BIT 01H
SP1 BIT P3.7
LJMP START
LJMP INT_T0
START: MOV TMOD,#02H
MOV TH0,#06H
MOV TL0,#06H
NSP: JB SP1,NSP
LCALL DELY10MS
JB SP1,NSP
MOV T5HZ,#00H
MOV T7HZ,#00H
MOV T05SA,#00H
MOV T05SB,#00H
JNB STOP,$
DELY10MS: MOV R6,#20
D1: MOV R7,#248
DJNZ R6,D1
INT_T0: INC T05SA
MOV A,T05SA
CJNE A,#100,NEXT
MOV T05SA,#00H
MOV A,T05SB
CJNE A,#20,NEXT
MOV T05SB,#00H
JB FLAG,STP
STP: SETB STOP
NEXT: JB FLAG,S5HZ
MOV A,T7HZ
CJNE A,#03H,DONE
MOV T7HZ,#00H
S5HZ: INC T5HZ
MOV A,T5HZ
CJNE A,#04H,DONE
MOV T5HZ,#00H
DONE: RETI
7. C 语言源程序
#include &AT89X51.H&
unsigned char t5
unsigned char t7
void main(void)
unsigned char i,j;
TMOD=0x02;
if(P3_7==0)
for(i=10;i&0;i--)
for(j=248;j&0;j--);
if(P3_7==0)
while(stop==0);
void t0(void) interrupt 1 using 0 {
1. 闪烁灯
如图 4.1.1 所示:在 P1.0 端口上接一个发光二极管 L1,使 L1 在不停地一亮一 灭,一亮一灭的时间间隔为 0.2 秒。
把“单片机系统”区域中的 P1.0 端口用导线连接到“八路发光二极管指示模
块”区域中的 L1 端口上。
(1). 延时程序的设计方法
作为单片机的指令的执行的时间是很短,数量大微秒级,因此,我们要
求的闪烁时间间隔为 0.2 秒,相对于微秒来说,相差太大,所以我们在
执行某一指令时,插入延时程序,来达到我们的要求,但这样的延时程
序是如何设计呢?下面具体介绍其原理:
如图 4.1.1 所示的石英晶体为 12MHz,因此,1 个机器周期为 1 微秒
机器周期 微秒
MOV R6,#20 2 个机器周期 D1: MOV R7,#248 2 个机器周期 DJNZ R7,$ 2 个机器周期
DJNZ R6,D1 2 个机器周期
因此,上面的延时程序时间为 10.002ms。
由以上可知,当 R6=10、R7=248 时,延时 5ms,R6=20、R7=248 时 ,
延时 10ms,以此为基本的计时单位。如本实验要求 0.2 秒=200ms,
10ms×R5=200ms,则 R5=20,延时子程序如下:
DELAY: MOV R5,#20
D1: MOV R6,#20
D2: MOV R7,#248
DJNZ R6,D2
DJNZ R5,D1
(2). 输出控制
如图 1 所示,当P1.0 端口输出高电平,即P1.0=1 时,根据发光二极管
的单向导电性可知,这时发光二极管 L1 熄灭;当P1.0 端口输出低电平,
即 P1.0=0 时,发光二极管 L1 亮;我们可以使用 SETB P1.0 指令使 P1.0
端口输出高电平,使用 CLR P1.0 指令使 P1.0 端口输出低电平。
5. 程序框图
如图4.1.2所
6. 汇编源程序
START: CLR P1.0
LCALL DELAY
LCALL DELAY
LJMP START
DELAY: MOV R5,#20 ;延时子程序,延时 0.2 秒
D1: MOV R6,#20
D2: MOV R7,#248
DJNZ R6,D2
DJNZ R5,D1
7. C 语言源程序
#include &AT89X51.H&
sbit L1=P1^0;
void delay02s(void) //延时 0.2 秒子程序
unsigned char i,j,k;
for(i=20;i&0;i--)
for(j=20;j&0;j--)
for(k=248;k&0;k--);
void main(void)
delay02s();
delay02s();
2. 模拟开关灯
1. 实验任务
如图 4.2.1 所示,监视开关 K1(接在 P3.0 端口上),用发光二极管 L1(接
在单片机 P1.0 端口上)显示开关状态,如果开关合上,L1 亮,开关打开,
2. 电路原理图
3. 系统板上硬件连线
(1). 把“单片机系统”区域中的 P1.0 端口用导线连接到“八路发光二极管指示模块”
区域中的 L1 端口上;
(2). 把“单片机系统”区域中的 P3.0 端口用导线连接到“四路拨动开关”区域中的
K1 端口上;
4. 程序设计内容 4
(1). 开关状态的检测过程
单片机对开关状态的检测相对于单片机来说,是从单片机的 P3.0 端口输入信号, 而输入的信号只有高电平和低电平两种,当拨开开关 K1 拨上去,即输入高电平, 相当开关断开,当拨动开关 K1 拨下去,即输入低电平,相当开关闭合。单片机 可以采用 JB BIT,REL 或者是 JNB BIT,REL 指令来完成对开关状态的检测即 可。
(2). 输出控制
如图 3 所示,当 P1.0 端口输出高电平,即 P1.0=1 时,根据发光二极管的单向 导电性可知,这时发光二极管 L1 熄灭;当 P1.0 端口输出低电平,即 P1.0=0 时,发光二极管 L1 亮;我们可以使用 SETB P1.0 指令使 P1.0 端口输出高电平, 使用 CLR P1.0 指令使 P1.0 端口输出低电平。
5. 程序框图
6. 汇编源程序 ORG 00H
START: JB P3.0,LIG
SJMP START
LIG: SETB P1.0
SJMP START
7. C 语言源程序
#include &AT89X51.H&
sbit K1=P3^0;
sbit L1=P1^0;
void main(void)
L1=0; //灯亮
L1=1; //灯灭
3. 多路开关状态指示
1. 实验任务
如图 4.3.1 所示,AT89S51 单片机的 P1.0-P1.3 接四个发光二极管 L1-L4, P1.4-P1.7 接了四个开关 K1-K4,编程将开关的状态反映到发光二极管上。 (开关闭合,对应的灯亮,开关断开,对应的灯灭)。
62. 电路原理图
3. 系统板上硬件连线
(1. 把“单片机系统”区域中的 P1.0-P1.3 用导线连接到“八路发光二
极管指示模块”区域中的 L1-L4 端口上;
(2. 把“单片机系统”区域中的 P1.4-P1.7 用导线连接到“四路拨动开
关”区域中的 K1-K4 端口上;
4. 程序设计内容
(1. 开关状态检测
对于开关状态检测,相对单片机来说,是输入关系,我们可轮流检测每个开关状 态,根据每个开关的状态让相应的发光二极管指示,可以采用 JB P1.X,REL 或 JNB
示,可以采用 MOV A,P1 指令一次把 P1 端口的状态全部读入,然后取高 4 位的 状态来指示。
(2. 输出控制
根据开关的状态,由发光二极管 L1-L4 来指示,我们可以用 SETB P1.X 和 CLR P1.X 指令来完成,也可以采用 MOV P1,#1111XXXXB 方法一次指示。
读 P1 口数据到 ACC 中
ACC 内容右移 4 次
ACC 内容与 F0H 相或
ACC 内容送入 P1 口
&![endif]--& 5. 程序框图
6. 方法一(汇编源程序)
START: MOV A,P1
ANL A,#0F0H
ORl A,#0F0H
SJMP START
7. 方法一(C 语言源程序) #include &AT89X51.H& void main(void) {
while(1) {
temp=P1&&4;
temp=temp | 0xf0; P1= } }
8. 方法二(汇编源程序) ORG 00H
START: JB P1.4,NEXT1 CLR P1.0 SJMP NEX1
NEXT1: SETB P1.0 NEX1: JB P1.5,NEXT2 CLR P1.1 SJMP NEX2
NEXT2: SETB P1.1 NEX2: JB P1.6,NEXT3 CLR P1.2 SJMP NEX3
NEXT3: SETB P1.2 NEX3: JB P1.7,NEXT4 CLR P1.3 SJMP NEX4
NEXT4: SETB P1.3 NEX4: SJMP START END
9. 方法二(C 语言源程序) #include &AT89X51.H&
void main(void) {
while(1) {
if(P1_4==0) {
if(P1_5==0) {
P1_1=0; } else {
if(P1_6==0) {
P1_2=0; } else {
if(P1_7==0) {
P1_3=0; } else {
P1_3=1; } } }
4. 广告灯的左移右移
1. 实验任务
做单一灯的左移右移,硬件电路如图 4.4.1 所示,八个发光二极管 L1-L8 分别接在单片机的 P1.0-P1.7 接口上,输出“0”时,发光二极管亮,开始 时 P1.0→P1.1→P1.2→P1.3→┅→P1.7→P1.6→┅→P1.0 亮,重复循环。
2. 电路原理图
3. 系统板上硬件连线
把“单片机系统”区域中的 P1.0-P1.7 用 8 芯排线连接到“八路发光二极管指
示模块”区域中的 L1-L8 端口上,要求:P1.0 对应着 L1,P1.1 对应着 L2,??, P1.7 对应着 L8。
4. 程序设计内容
我们可以运用输出端口指令 MOV P1,A 或 MOV P1,#DATA,只要给累加器 值或常数值,然后执行上述的指令,即可达到输出控制的动作。
每次送出的数据是不同,具体的数据如下表 1 所示 :
5. 程序框图
6. 汇编源程序 ORG 0
START: MOV R2,#8 MOV A,#0FEH SETB C
LOOP: MOV P1,A LCALL DELAY RLC A
DJNZ R2,LOOP MOV R2,#8
LOOP1: MOV P1,A LCALL DELAY RRC A
DJNZ R2,LOOP1 LJMP START
DELAY: MOV R5,#20 ; D1: MOV R6,#20 D2: MOV R7,#248 DJNZ R7,$ DJNZ R6,D2 DJNZ R5,D1
7. C 语言源程序
#include &AT89X51.H&
unsigned char a,b;
void delay(void)
unsigned char m,n,s;
for(m=20;m&0;m--)
for(n=20;n&0;n--)
for(s=248;s&0;s--);
void main(void)
for(i=1;i&8;i++)
a=temp&&i;
b=temp&&(8-i);
for(i=1;i&8;i++)
a=temp&&i;
b=temp&&(8-i);
1. 实验任务 5. 广告灯(利用取表方式)
利用取表的方法,使端口 P1 做单一灯的变化:左移 2 次,右移 2 次,闪烁 2 次
(延时的时间 0.2 秒)。
2. 电路原理图
3. 系统板上硬件连线
把“单片机系统”区域中的 P1.0-P1.7 用 8 芯排线连接到“八路发光二极 管指示模块”区域中的 L1-L8 端口上,要求:P1.0 对应着 L1,P1.1 对应 着 L2,??,P1.7 对应着 L8。
4. 程序设计内容
在用表格进行程序设计的时候,要用以下的指令来完成
(1). 利用 MOV
(2). 利用 MOVC A,@A+DPTR 的指令,根据累加器的值再加上 DPTR 的
值,就可以使程序计数器 PC 指到表格内所要取出的数据。
因此,只要把控制码建成一个表,而利用 MOVC A,@A+DPTR 做取码的操作,
就可方便地处理一些复杂的控制动作,取表过程如下图所示:
5. 程序框图
6. 汇编源程序
START: MOV DPTR,#TABLE
LOOP: CLR A
MOVC A,@A+DPTR
CJNE A,#01H,LOOP1
LOOP1: MOV P1,A
MOV R3,#20
LCALL DELAY
DELAY: MOV R4,#20
D1: MOV R5,#248
DJNZ R4,D1
DJNZ R3,DELAY
TABLE: DB 0FEH,0FDH,0FBH,0F7H
DB 0EFH,0DFH,0BFH,07FH
DB 0FEH,0FDH,0FBH,0F7H
DB 0EFH,0DFH,0BFH,07FH
DB 07FH,0BFH,0DFH,0EFH
DB 0F7H,0FBH,0FDH,0FEH
DB 07FH,0BFH,0DFH,0EFH
DB 0F7H,0FBH,0FDH,0FEH
DB 00H, 0FFH,00H, 0FFH
7. C 语言源程序
#include &AT89X51.H&
unsigned char code table[]={0xfe,0xfd,0xfb,0xf7, 0xef,0xdf,0xbf,0x7f,
0xfe,0xfd,0xfb,0xf7,
0xef,0xdf,0xbf,0x7f,
0x7f,0xbf,0xdf,0xef,
0xf7,0xfb,0xfd,0xfe,
0x7f,0xbf,0xdf,0xef,
0xf7,0xfb,0xfd,0xfe,
0x00,0xff,0x00,0xff,
void delay(void)
unsigned char m,n,s;
for(m=20;m&0;m--)
for(n=20;n&0;n--)
for(s=248;s&0;s--);
void main(void)
if(table[i]!=0x01)
P1=table[i];
6. 报警产生器
1. 实验任务
用 P1.0 输出 1KHz 和 500Hz 的音频信号驱动扬声器,作报警信号,要求 1KHz 信号响 100ms,500Hz 信号响 200ms,交替进行,P1.7 接一开关进行控制,当 开关合上响报警信号,当开关断开告警信号停止,编出程序。
172. 电路原理图
图 4.6.1 3. 系统板上硬件连线
(1. 把“单片机系统”区域中的 P1.0 端口用导线连接到“音频放大模块”
区域中的 SPK IN 端口上;
(2. 在“音频放大模块”区域中的 SPK OUT 端口上接上一个 8 欧的或者是
16 欧的喇叭;
(3. 把“单片机系统”区域中的 P1.7/RD 端口用导线连接到“四路拨动开
关”区域中的 K1 端口上;
4. 程序设计内容
(1. 信号产生的方法
500Hz 信号周期为 2ms,信号电平为每 1ms 变反 1 次,1KHz 的信号周
期为 1ms,信号电平每 500us 变反 1 次;
5. 程序框图
图 4.6.2 18
6. 汇编源程序
FLAG BIT 00H
START: JB P1.7,START
JNB FLAG,NEXT
MOV R2,#200
DV: CPL P1.0
LCALL DELY500
LCALL DELY500
DJNZ R2,DV
NEXT: MOV R2,#200
DV1: CPL P1.0
LCALL DELY500
DJNZ R2,DV1
SJMP START
DELY500: MOV R7,#250
DJNZ R7,LOOP
7. C 语言源程序
#include &AT89X51.H&
#include &INTRINS.H&
void dely500(void)
for(i=250;i&0;i--)
void main(void)
if(P1_7==0)
for(count=200;count&0;count--)
P1_0=~P1_0;
dely500();
for(count=200;count&0;count--)
P1_0=~P1_0;
dely500();
dely500();
7. I/O 并行口直接驱动 LED 显示
1. 实验任务
如图 13 所示,利用 AT89S51 单片机的 P0 端口的 P0.0-P0.7 连接到一个共阴数 码管的 a-h 的笔段上,数码管的公共端接地。在数码管上循环显示 0-9 数 字 , 时间间隔 0.2 秒。
2. 电路原理图 20
3. 系统板上硬件连线
把“单片机系统”区域中的 P0.0/AD0-P0.7/AD7 端口用 8 芯排线连接到“四路 静态数码显示模块”区域中的任一个数码管的 a-h 端口上;要求:P0.0/AD0 与 a 相连,P0.1/AD1 与 b 相连,P0.2/AD2 与 c 相连,??,P0.7/AD7 与 h 相连。
4. 程序设计内容
(1. LED 数码显示原理
七段 LED 显示器内部由七个条形发光二极管和一个小圆点发光二极管组成,根 据各管的极管的接线形式,可分成共阴极型和共阳极型。
LED 数码管的 g~a 七个发光二极管因加正电压而发亮,因加零电压而不以发亮, 不同亮暗的组合就能形成不同的字形,这种组合称之为字形码,下面给出共阴极 的字形码见表 2
(2. 由于显示的数字 0-9 的字形码没有规律可循,只能采用查表的方式来完 成我们所需的要求了。这样我们按着数字 0-9 的顺序,把每个数字的笔段代码
按顺序排好!建立的表格如下所示:TABLE DB 3FH,06H,5BH,4FH,66H,6DH,7DH, 07H,7FH,6FH 5.程序框图
6. 汇编源程序 ORG 0
START: MOV R1,#00H NEXT: MOV A,R1 MOV DPTR,#TABLE MOVC A,@A+DPTR MOV P0,A LCALL DELAY INC R1
CJNE R1,#10,NEXT LJMP START
DELAY: MOV R5,#20 D2: MOV R6,#20 D1: MOV R7,#248
DJNZ R7,$ DJNZ R6,D1 DJNZ R5,D2 RET
TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH END
7. C 语言源程序 #include &AT89X51.H&
unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66, 0x6d,0x7d,0x07,0x7f,0x6f}; uns void delay02s(void) {
unsigned char i,j,k; for(i=20;i&0;i--) for(j=20;j&0;j--) for(k=248;k&0;k--); }
void main(void) {
while(1) {
for(dispcount=0;dispcount&10;dispcount++) {
P0=table[dispcount]; delay02s(); } } }
8. 按键识别方法之一
1. 实验任务
每按下一次开关 SP1,计数值加 1,通过 AT89S51 单片机的 P1 端口的 P1.0 到 P1.3 显示出其的二进制计数值。
2. 电路原理图
3. 系统板上硬件连线
(1. 把“单片机系统”区域中的 P3.7/RD 端口连接到“独立式键盘”区域中的
SP1 端口上;
(2. 把“单片机系统”区域中的 P1.0-P1.4 端口用 8 芯排线连接到“八路发
光二极管指示模块”区域中的“L1-L8”端口上;要求,P1.0 连接到 L1, P1.1 连接到 L2,P1.2 连接到 L3,P1.3 连接到 L4 上。
4. 程序设计方法
(1. 其实,作为一个按键从没有按下到按下以及释放是一个完整的过程,
也就是说,当我们按下一个按键时,总希望某个命令只执行一次,而 在按键按下的 过程中,不要有干扰进来,因为,在按下的过程中, 一旦有干扰过来,可能造成误触发过程,这并不是我们所想要的。因 此在按键按下的时候,
要把我们手上的干扰信号以及按键的机械接触等干扰信号给滤除掉,一般情况 下,我们可以采用电容来滤除掉这些干扰信号,但实际上,会增加硬件成本及硬 件电路的体积,这是我们不希望,总得有个办法解决这个问题,因此我们可以采 用软件滤波的方法去除这些干扰
信号,一般情况下,一个按键按下的时候,总是在按下的时刻存在着一定的干扰 信号,按下之后就基本上进入了稳定的状态。具体的一个按键从按下到释放的全 过程的信号图如上图所示:
从图中可以看出,我们在程序设计时,从按键被识别按下之后,延时 5ms 以 上 , 从而避开了干扰信号区域,我们再来检测一次,看按键是否真得已经按下,若真 得已经按下,这时肯定输出为低电平,若这时检测到的是高电平,证明刚才是由 于干扰信号引起的误触发,CPU 就认为是误触发信号而舍弃这次的按键识别过 程。从而提高了系统的可靠性。
由于要求每按下一次,命令被执行一次,直到下一次再按下的时候,再执行一次 命令,因此从按键被识别出来之后,我们就可以执行这次的命令,所以要有一个 等待按键释放的过程,显然释放的过程,就是使其恢复成高电平状态。
(1. 对于按键识别的指令,我们依然选择如下指令 JB BIT,REL 指令是用
来检测 BIT 是否为高电平,若 BIT=1,则程序转向 REL 处执行程序,
否则就继续向下执行程序。或者是 JNB BIT,REL 指令是用来检测
BIT 是否为低电平,若 BIT=0,则程序转向 REL 处执行程序,否则就
继续向下执行程序。
(2. 但对程序设计过程中按键识别过程的框图如右图所示:
图 4.8.3 5. 程序框图
6. 汇编源程序
START: MOV R1,#00H ;初始化 R1 为 0,表示从 0 开始计数
MOV A,R1 ;
CPL A ;取反指令
MOV P1,A ;送出 P1 端口由发光二极管显示
REL: JNB P3.7,REL ;判断 SP1 是否按下
LCALL DELAY10MS ;若按下,则延时 10ms 左右
JNB P3.7,REL ;再判断 SP1 是否真得按下
INC R1 ;若真得按下,则进行按键处理,使
MOV A,R1 ;计数内容加 1,并送出 P1 端口由
CPL A ;发光二极管显示
MOV P1,A ;
JNB P3.7,$ ;等待 SP1 释放
SJMP REL ;继续对 K1 按键扫描
DELAY10MS: MOV R6,#20 ;延时 10ms 子程序
L1: MOV R7,#248
DJNZ R6,L1
7. C 语言源程序
#include &AT89X51.H&
void delay10ms(void)
unsigned char i,j;
for(i=20;i&0;i--)
for(j=248;j&0;j--);
void main(void)
if(P3_7==0)
delay10ms();
if(P3_7==0)
if(count==16)
while(P3_7==0);
9. 一键多功能按键识别技术
1.实验任务
如图 4.9.1 所示,开关 SP1 接在 P3.7/RD 管脚上,在 AT89S51 单片机的 P1 端口 接有四个发光二极管,上电的时候,L1 接在 P1.0 管脚上的发光二极管在闪烁, 当每一次按下开关 SP1 的时候,L2 接在 P1.1 管脚上的发光二极管在闪烁,再按 下开关 SP1 的时候,L3 接在 P1.2 管脚上的发光二极管在闪烁,再按下开关 SP1 的时候,L4 接在 P1.3 管脚上的发光二极管在闪烁,再按下开关 SP1 的时候,又 轮到 L1 在闪烁了,如此轮流下去。
2.电路原理图
图 4.9.1 28
3.系统板上硬件连线
(1. 把“单片机系统”区域中的 P3.7/RD 端口连接到“独立式键盘”
区域中的 SP1 端口上;
(2. 把“单片机系统”区域中的 P1.0-P1.4 端口用 8 芯排线连接到“八
路发光二极管指示模块”区域中的“L1-L8”端 口上;要求,P1.0
连接到 L1,P1.1 连接到 L2,P1.2 连接到 L3,P1.3 连接到 L4 上。
4.程序设计方法
(1. 设计思想由来
在我们生活中,我们很容易通过这个叫张三,那个叫李四,另外一个是王五;那 是因为每个人有不同的名子,我们就很快认出,同样,对于要通过一个按键来识 别每种不同的功能,我们给每个不同的功能模块用不同的 ID 号标识,这样,每 按下一次按键,ID 的值是不相同的,所以单片机就很容易识别不同功能的身份 了。
(2. 设计方法
从上面的要求我们可以看出,L1 到 L4 发光二极管在每个时刻的闪烁的时间是受 开关 SP1 来控制,我们给 L1 到 L4 闪烁的时段定义出不同的 ID 号,当L1 在闪烁 时,ID=0;当 L2 在闪烁时,ID=1;当 L3 在闪烁时,ID=2;当 L4 在闪烁时, ID=3;很显然,只要每次按下开关 K1 时,分别给出不同的 ID 号我们就能够完 成上面的任务了。下面给出有关程序设计的框图。
5.程序框图 29
6. 汇编源程序
ID EQU 30H
SP1 BIT P3.7
L1 BIT P1.0
L2 BIT P1.1
L3 BIT P1.2
L4 BIT P1.3
MOV ID,#00H
START: JB K1,REL
LCALL DELAY10MS
CJNE A,#04,REL
MOV ID,#00H
REL: JNB K1,$
CJNE A,#00H,IS0
LCALL DELAY
SJMP START
IS0: CJNE A,#01H,IS1
LCALL DELAY
SJMP START
IS1: CJNE A,#02H,IS2
LCALL DELAY
SJMP START
IS2: CJNE A,#03H,IS3
LCALL DELAY
SJMP START
IS3: LJMP START
DELAY10MS: MOV R6,#20
LOOP1: MOV R7,#248
DJNZ R6,LOOP1
DELAY: MOV R5,#20
LOOP2: LCALL DELAY10MS
DJNZ R5,LOOP2
7. C 语言源程序
#include &AT89X51.H&
unsigned char ID;
void delay10ms(void)
unsigned char i,j;
for(i=20;i&0;i--)
for(j=248;j&0;j--);
void delay02s(void)
for(i=20;i&0;i--)
{delay10ms();
void main(void)
{ while(1)
{ if(P3_7==0)
{delay10ms();
if(P3_7==0)
while(P3_7==0);
switch(ID)
P1_0=~P1_0;
delay02s();
P1_1=~P1_1;
delay02s();
P1_2=~P1_2;
delay02s();
P1_3=~P1_3;
delay02s();
10. 00-99 计数器
1. 实验任务
利用 AT89S51 单片机来制作一个手动计数器,在 AT89S51 单片机的 P3.7 管脚接 一个轻触开关,作为手动计数的按钮,用单片机的 P2.0-P2.7 接一个共阴数码
管,作为 00-99 计数的个位数显示,用单片机的 P0.0-P0.7 接一个共阴数码管 , 作为 00-99 计数的十位数显示;硬件电路图如图 19 所示。
2. 电路原理图
3. 系统板上硬件连线
(1. 把“单片机系统”区域中的 P0.0/AD0-P0.7/AD7 端口用 8 芯排线连接到
“四路静态数码显示模块”区域中的任一个 a-h 端口上;要求:P0.0/AD0 对应着 a,P0.1/AD1 对应着 b,??,P0.7/AD7 对应着 h。
(2. 把“单片机系统”区域中的P2.0/A8-P2.7/A15 端口用8 芯排线连接到“四
路静态数码显示模块”区域中的任一个数码管的 a-h 端口上;
(3. 把“单片机系统”区域中的 P3.7/RD 端口用导线连接到“独立式键盘”区
域中的 SP1 端口上;
4. 程序设计内容
(1. 单片机对按键的识别的过程处理
33(2. 单片机对正确识别的按键进行计数,计数满时,又从零开始计数;
(3. 单片机对计的数值要进行数码显示,计得的数是十进数,含有十位和个位 ,
我们要把十位和个位拆开分别送出这样的十位和个位数值到对应的数码
管上显示。如何拆开十位和个位我们可以把所计得的数值对 10 求余,即
可得个位数字,对 10 整除,即可得到十位数字了。
(4. 通过查表方式,分别显示出个位和十位数字。
5. 程序框图
6. 汇编源程序
Count EQU 30H
SP1 BIT P3.7
START: MOV Count,#00H
NEXT: MOV A,Count
MOV DPTR,#TABLE
MOVC A,@A+DPTR
MOVC A,@A+DPTR
WT: JNB SP1,WT
WAIT: JB SP1,WAIT
LCALL DELY10MS
JB SP1,WAIT
MOV A,Count
CJNE A,#100,NEXT
LJMP START
DELY10MS: MOV R6,#20
D1: MOV R7,#248
DJNZ R6,D1
TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH
7. C 语言源程序
#include &AT89X51.H&
unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66,
0x6d,0x7d,0x07,0x7f,0x6f};
unsigned char C
void delay10ms(void)
unsigned char i,j;
for(i=20;i&0;i--)
for(j=248;j&0;j--);
void main(void)
P0=table[Count/10];
P2=table[Count%10];
if(P3_7==0)
delay10ms();
if(P3_7==0)
if(Count==100)
P0=table[Count/10];
P2=table[Count%10];
while(P3_7==0);
11. 00-59 秒计时器(利用软件延时)
1. 实验任务
如下图所示,在 AT89S51 单片机的 P0 和 P2 端口分别接有两个共阴数码管, P0 口驱动显示秒时间的十位,而 P2 口驱动显示秒时间的个位。
2. 电路原理图
3. 系统板上硬件连线
(1. 把“单片机系统”区域中的 P0.0/AD0-P0.7/AD7 端口用 8 芯排线连接到
“四路静态数码显示模块”区域中的任一个 a-h 端口上;要求:P0.0/AD0 对应着 a,P0.1/AD1 对应着 b,??,P0.7/AD7 对应着 h。
(2. 把“单片机系统”区域中的P2.0/A8-P2.7/A15 端口用8 芯排线连接到“四
路静态数码显示模块”区域中的任一个 a-h 端口上;要求:P2.0/A8 对 应着 a,P2.1/A9 对应着 b,??,P2.7/A15 对应着 h。
4. 程序设计内容 36
(1. 在设计过程中我们用一个存储单元作为秒计数单元,当一秒钟到来时,就
让秒计数单元加 1,当秒计数达到 60 时,就自动返回到 0,重新 秒计数。
(2. 对于秒计数单元中的数据要把它十位数和个数分开,方法仍采用对 10 整
除和对 10 求余。
(3. 在数码上显示,仍通过查表的方式完成。
(4. 一秒时间的产生在这里我们采用软件精确延时的方法来完成,经过精确计
算得到 1 秒时间为 1.002 秒。
DELY1S: MOV R5,#100
D2: MOV R6,#20
D1: MOV R7,#248
DJNZ R6,D1
DJNZ R5,D2
5. 程序框图 图 4.11.2
6. 汇编源程序
Second EQU 30H
START: MOV Second,#00H
NEXT: MOV A,Second
MOV DPTR,#TABLE
MOVC A,@A+DPTR
MOVC A,@A+DPTR
LCALL DELY1S
INC Second
MOV A,Second
CJNE A,#60,NEXT
LJMP START
DELY1S: MOV R5,#100
D2: MOV R6,#20
D1: MOV R7,#248
DJNZ R6,D1
DJNZ R5,D2
TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH
7. C 语言源程序
#include &AT89X51.H&
unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66,
0x6d,0x7d,0x07,0x7f,0x6f};
unsigned char S
void delay1s(void)
unsigned char i,j,k;
for(k=100;k&0;k--)
for(i=20;i&0;i--)
for(j=248;j&0;j--);
void main(void)
P0=table[Second/10];
P2=table[Second%10];
delay1s();
if(Second==60)
P0=table[Second/10];
P2=table[Second%10];
12. 可预置可逆 4 位计数器
1. 实验任务
利用 AT89S51 单片机的 P1.0-P1.3 接四个发光二极管 L1-L4,用来指示当前计 数的数据;用 P1.4-P1.7 作为预置数据的输入端,接四个拨动开关 K1-K4,用 P3.6/WR 和 P3.7/RD 端口接两个轻触开关,用来作加计数和减计数开关。具体的 电路原理图如下图所示
2. 电路原理图
3. 系统板上硬件连线
(1. 把“单片机系统”区域中的 P1.0-P1.3 端口用 8 芯排线连接到“八路发
光二极管指示模块”区域中的 L1-L4 上;要求:P1.0 对应着 L1,P1.1 对应着 L2,P1.2 对应着 L3,P1.3 对应着 L4;
(2. 把“单片机系统”区域中的 P3.0/RXD,P3.1/TXD,P3.2/INT0,P3.3/INT1
用导线连接到“四路拨动开关”区域中的 K1-K4 上;
(3. 把“单片机系统”区域中的 P3.6/WR,P3.7/RD 用导线连接到“独立式键
盘”区域中的 SP1 和 SP2 上;
4. 程序设计内容
(1. 两个独立式按键识别的处理过程;
(2. 预置初值读取的问题
(3. LED 输出指示
5. 程序框图
6. 汇编源程序
COUNT EQU 30H
START: MOV A,P3
ANL A,#0FH
MOV COUNT,A
SK2: JB P3.6,SK1
LCALL DELY10MS
JB P3.6,SK1
MOV A,COUNT
CJNE A,#16,NEXT
ANL A,#0FH
MOV COUNT,A
NEXT: MOV P1,A
WAIT: JNB P3.6,WAIT
SK1: JB P3.7,SK2
LCALL DELY10MS
JB P3.7,SK2
MOV A,COUNT
CJNE A,#0FFH,NEX
ANL A,#0FH
MOV COUNT,A
NEX: MOV P1,A
WAIT2: JNB P3.7,WAIT2
DELY10MS: MOV R6,#20
MOV R7,#248
D1: DJNZ R7,$
DJNZ R6,D1
7. C 语言源程序
#include &AT89X51.H&
void delay10ms(void)
unsigned char i,j;
for(i=20;i&0;i--)
for(j=248;j&0;j--);
void main(void)
curcount=P3 & 0x0f;
if(P3_6==0)
delay10ms();
if(P3_6==0)
if(curcount&=15)
curcount=15;
curcount++;
while(P3_6==0);
if(P3_7==0)
delay10ms();
if(P3_7==0)
if(curcount&=0)
curcount=0;
curcount--;
while(P3_7==0);
13. 动态数码显示技术
1. 实验任务
如图 4.13.1 所示,P0 端口接动态数码管的字形码笔段,P2 端口接动态数码 管的数位选择端,P1.7 接一个开关,当开关接高电平时,显示“12345”字 样;当开关接低电平时,显示“HELLO”字样。
2. 电路原理图
3. 系统板上硬件连线
(1. 把“单片机系统”区域中的 P0.0/AD0-P0.7/AD7 用 8 芯排线连接到“动
态数码显示”区域中的 a-h 端口上;
(2. 把“单片机系统”区域中的 P2.0/A8-P2.7/A15 用 8 芯排线连接到“动态
数码显示”区域中的 S1-S8 端口上;
(3. 把“单片机系统”区域中的 P1.7 端口用导线连接到“独立式键盘”区域
中的 SP1 端口上;
4. 程序设计内容
(1. 动态扫描方法
动态接口采用各数码管循环轮流显示的方法,当循环显示频率较高时,利用人眼
的暂留特性,看不出闪烁显示现象,这种显示需要一个接口完成字形码的输出(字 形选择),另一接口完成各数码管的轮流点亮(数位选择)。
(2. 在进行数码显示的时候,要对显示单元开辟 8 个显示缓冲区,每个显示缓
冲区装有显示的不同数据即可。
(3. 对于显示的字形码数据我们采用查表方法来完成。
5. 程序框图
6. 汇编源程序
START: JB P1.7,DIR1
MOV DPTR,#TABLE1
DIR1: MOV DPTR,#TABLE2
DIR: MOV R0,#00H
MOV R1,#01H
NEXT: MOV A,R0
MOVC A,@A+DPTR
CJNE R1,#0DFH,NEXT
SJMP START
DAY: MOV R6,#4
D1: MOV R7,#248
DJNZ R6,D1
TABLE1: DB 06H,5BH,4FH,66H,6DH
TABLE2: DB 78H,79H,38H,38H,3FH
7. C 语言源程序
#include &AT89X51.H&
void main(void)
for(i=0;i&5;i++)
if(P1_7==1)
P0=table1[i];
P0=table2[i];
a=temp&&(i+1);
b=temp&&(7-i);
for(a=4;a&0;a--)
for(b=248;b&0;b--);
14. 4×4 矩阵式键盘识别技术
1. 实验任务
如图 4.14.2 所示,用AT89S51 的并行口 P1 接 4×4 矩阵键盘,以P1.0-P1.3 作输入线,以P1.4-P1.7 作输出线;在数码管上显示每个按键的“0-F”序 号。对应的按键的序号排列如图 4.14.1 所示
47 图 4.14.1 2. 硬件电路原理图
3. 系统板上硬件连线
(1. 把“单片机系统“区域中的 P3.0-P3.7 端口用 8 芯排线连接到“4X4 行
列式键盘”区域中的 C1-C4 R1-R4 端口上;
(2. 把“单片机系统”区域中的 P0.0/AD0-P0.7/AD7 端口用 8 芯排线连接到
“四路静态数码显示模块”区域中的任一个 a-h 端口上;要求:P0.0/AD0 对应着 a,P0.1/AD1 对应着 b,??,P0.7/AD7 对应着 h。
4. 程序设计内容
(1. 4×4 矩阵键盘识别处理
(2. 每个按键有它的行值和列值 ,行值和列值的组合就是识别这个按键
的编码。矩阵的行线和列线分别通过两并行接口和 CPU 通信。每个按
键的状态同样需变成数字量“0”和“1”,开关的一端(列线)通过
电阻接 VCC,而接地是通过程序输出数字“0”实现的。键盘处理程序
的任务是:确定有无键按下,判断哪一个键按下,键的功能是什么;
还要消除按键在闭合或断开时的抖动。两个并行口中,一个输出扫描
码,使按键逐行动态接地,另一个并行口输入按键状态,由行扫描值
和回馈信号共同形成键编码而识别按键,通过软件查表,查出该键的
5. 程序框图
6. 汇编源程序 KEYBUF EQU 30H ORG 00H
START: MOV KEYBUF,#2 WAIT:
MOV P3,#0FFH
ANL A,#0FH
XRL A,#0FH
LCALL DELY10MS
ANL A,#0FH
XRL A,#0FH
ANL A,#0FH
CJNE A,#0EH,NK1 MOV KEYBUF,#0 LJMP DK1
NK1: CJNE A,#0DH,NK2 MOV KEYBUF,#1 LJMP DK1
NK2: CJNE A,#0BH,NK3 MOV KEYBUF,#2 LJMP DK1
NK3: CJNE A,#07H,NK4 MOV KEYBUF,#3 LJMP DK1
MOV A,KEYBUF
MOV DPTR,#TABLE MOVC A,@A+DPTR MOV P0,A
DK1A: MOV A,P3 ANL A,#0FH
XRL A,#0FH
MOV P3,#0FFH
ANL A,#0FH
XRL A,#0FH
LCALL DELY10MS MOV A,P3
ANL A,#0FH
XRL A,#0FH
ANL A,#0FH
CJNE A,#0EH,NK5
MOV KEYBUF,#4 LJMP DK2
NK5: CJNE A,#0DH,NK6 MOV KEYBUF,#5 LJMP DK2
NK6: CJNE A,#0BH,NK7 MOV KEYBUF,#6 LJMP DK2
NK7: CJNE A,#07H,NK8 MOV KEYBUF,#7 LJMP DK2
MOV A,KEYBUF
MOV DPTR,#TABLE MOVC A,@A+DPTR MOV P0,A
DK2A: MOV A,P3 ANL A,#0FH
XRL A,#0FH
MOV P3,#0FFH
ANL A,#0FH
XRL A,#0FH
LCALL DELY10MS MOV A,P3
ANL A,#0FH
XRL A,#0FH
ANL A,#0FH
CJNE A,#0EH,NK9 MOV KEYBUF,#8 LJMP DK3
NK9: CJNE A,#0DH,NK10 MOV KEYBUF,#9 LJMP DK3
NK10: CJNE A,#0BH,NK11 MOV KEYBUF,#10
NK11: CJNE A,#07H,NK12
MOV KEYBUF,#11
MOV A,KEYBUF
MOV DPTR,#TABLE
MOVC A,@A+DPTR
DK3A: MOV A,P3
ANL A,#0FH
XRL A,#0FH
MOV P3,#0FFH
ANL A,#0FH
XRL A,#0FH
LCALL DELY10MS
ANL A,#0FH
XRL A,#0FH
ANL A,#0FH
CJNE A,#0EH,NK13
MOV KEYBUF,#12
NK13: CJNE A,#0DH,NK14
MOV KEYBUF,#13
NK14: CJNE A,#0BH,NK15
MOV KEYBUF,#14
NK15: CJNE A,#07H,NK16
MOV KEYBUF,#15
MOV A,KEYBUF
MOV DPTR,#TABLE
MOVC A,@A+DPTR
DK4A: MOV A,P3
ANL A,#0FH
XRL A,#0FH
MOV R6,#10
D1: MOV R7,#248
DJNZ R6,D1
TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H DB 7FH,6FH,77H,7CH,39H,5EH,79H,71H
7. C 语言源程序
#include &AT89X51.H&
unsigned char code table[]={0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
unsigned char i,j;
void main(void)
temp=temp & 0x0f;
if (temp!=0x0f)
for(i=50;i&0;i--)
for(j=200;j&0;j--);
temp=temp & 0x0f;
temp=temp & 0x0f; switch(temp) {
case 0x0e: key=7;
case 0x0d: key=8;
case 0x0b: key=9;
case 0x07: key=10;
P1_0=~P1_0; P0=table[key]; temp=temp & 0x0f; while(temp!=0x0f) {
temp=temp & 0x0f; }
temp=temp & 0x0f; if (temp!=0x0f) {
for(i=50;i&0;i--) for(j=200;j&0;j--); temp=P3;
temp=temp & 0x0f; if (temp!=0x0f) {
switch(temp) {
case 0x0e: key=4;
case 0x0d: key=5;
case 0x0b: key=6;
case 0x07: key=11;
P1_0=~P1_0; P0=table[key]; temp=temp & 0x0f; while(temp!=0x0f) {
temp=temp & 0x0f; }
temp=temp & 0x0f; if (temp!=0x0f) {
for(i=50;i&0;i--) for(j=200;j&0;j--); temp=P3;
temp=temp & 0x0f; if (temp!=0x0f) {
temp=temp & 0x0f; switch(temp) {
case 0x0e:
case 0x0d:
case 0x0b:
case 0x07:
P1_0=~P1_0;
P0=table[key];
temp=temp & 0x0f;
while(temp!=0x0f)
temp=temp & 0x0f;
temp=temp & 0x0f;
if (temp!=0x0f)
for(i=50;i&0;i--)
for(j=200;j&0;j--);
temp=temp & 0x0f;
if (temp!=0x0f)
temp=temp & 0x0f;
switch(temp)
case 0x0e:
case 0x0d:
case 0x0b:
case 0x07:
P1_0=~P1_0;
P0=table[key];
temp=temp & 0x0f;
while(temp!=0x0f)
temp=temp & 0x0f;
15. 定时计数器 T0 作定时应用技术(一)
1. 实验任务
用 AT89S51 单片机的定时/计数器 T0 产生一秒的定时时间,作为秒计数时间,当 一秒产生时,秒计数加 1,秒计数到 60 时,自动从 0 开始。硬件电路如下图所 示
2. 电路原理图 57
3. 系统板上硬件连线
(1. 把“单片机系统”区域中的 P0.0/AD0-P0.7/AD7 端口用 8 芯排线连接到
“四路静态数码显示模块”区域中的任一个 a-h 端口上;要求:P0.0/AD0 对应着 a,P0.1/AD1 对应着 b,??,P0.7/AD7 对应着 h。
(2. 把“单片机系统”区域中的P2.0/A8-P2.7/A15 端口用8 芯排线连接到“四
路静态数码显示模块”区域中的任一个 a-h 端口上;要求:P2.0/A8 对
应着 a,P2.1/A9 对应着 b,??,P2.7/A15 对应着 h。
4. 程序设计内容
AT89S51 单片机的内部 16 位定时/计数器是一个可编程定时/计数器,它既 可以工作在 13 位定时方式,也可以工作在 16 位定时方式和 8 位定时方式。只要 通过设置特殊功能寄存器 TMOD,即可完成。定时/计数器何时工作也是通过软件 来设定 TCON 特殊功能寄存器来完成的。
现在我们选择 16 位定时工作方式,对于 T0 来说,最大定时也只有 65536us, 即 65.536ms,无法达到我们所需要的 1 秒的定时,因此,我们必须通过软件来 处理这个问题,假设我们取 T0 的最大定时为 50ms,即要定时 1 秒需要经过 20 次的 50ms 的定时。对于这 20 次我们就可以采用软件的方法来统计了。
因此,我们设定 TMOD=B,即 TMOD=01H
下面我们要给 T0 定时/计数器的 TH0,TL0 装入预置初值,通过下面的公式 可以计算出
TH0=(216-50000)
TL0=(216-50000)
当 T0 在工作的时候,我们如何得知 50ms 的定时时间已到,这回我们通过检 测 TCON 特殊功能寄存器中的 TF0 标志位,如果 TF0=1 表示定时时间已到。
5. 程序框图
6. 汇编源程序(查询法)
SECOND EQU 30H
TCOUNT EQU 31H
START: MOV SECOND,#00H
MOV TCOUNT,#00H
MOV TMOD,#01H
MOV TH0,#() / 256
MOV TL0,#() MOD 256
DISP: MOV A,SECOND
MOV DPTR,#TABLE
MOVC A,@A+DPTR
MOVC A,@A+DPTR
WAIT: JNB TF0,WAIT
MOV TH0,#() / 256
MOV TL0,#() MOD 256
INC TCOUNT
MOV A,TCOUNT
CJNE A,#20,NEXT
MOV TCOUNT,#00H
INC SECOND
MOV A,SECOND
CJNE A,#60,NEX
MOV SECOND,#00H
NEX: LJMP DISP
NEXT: LJMP WAIT
TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH
7. C 语言源程序(查询法)
#include &AT89X51.H&
unsigned char code dispcode[]={0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,0x00};
void main(void)
TMOD=0x01;
TH0=()/256;
TL0=()%256;
P0=dispcode[second/10];
P2=dispcode[second%10];
if(TF0==1)
if(tcount==20)
if(second==60)
P0=dispcode[second/10];
P2=dispcode[second%10];
TH0=()/256;
TL0=()%256;
1. 汇编源程序(中断法)
SECOND EQU 30H
TCOUNT EQU 31H
LJMP START
LJMP INT0X
START: MOV SECOND,#00H
MOV A,SECOND
MOV DPTR,#TABLE
MOVC A,@A+DPTR
MOVC A,@A+DPTR
MOV TCOUNT,#00H
MOV TMOD,#01H
MOV TH0,#()
MOV TL0,#()
MOV TH0,#()
MOV TL0,#()
INC TCOUNT
MOV A,TCOUNT
CJNE A,#20,NEXT
MOV TCOUNT,#00H
INC SECOND
MOV A,SECOND
CJNE A,#60,NEX
MOV SECOND,#00H
NEX: MOV A,SECOND
MOV DPTR,#TABLE
MOVC A,@A+DPTR
MOVC A,@A+DPTR
NEXT: RETI
TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH
2. C 语言源程序(中断法)
#include &AT89X51.H&
unsigned char code dispcode[]={0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,0x00};
void main(void)
TMOD=0x01;
TH0=()/256;
TL0=()%256;
P0=dispcode[second/10];
P2=dispcode[second%10];
void t0(void) interrupt 1 using 0
if(tcount==20)
if(second==60)
P0=dispcode[second/10];
P2=dispcode[second%10];
TH0=()/256;
TL0=()%256;
16. 定时计数器 T0 作定时应用技术(二)
1. 实验任务
用 AT89S51 的定时/计数器 T0 产生 2 秒钟的定时,每当 2 秒定时到来时,更换指 示灯闪烁,每个指示闪烁的频率为 0.2 秒,也就是说,开始 L1 指示灯以 0.2 秒 的速率闪烁,当 2 秒定时到来之后,L2 开始以 0.2 秒的速率闪烁,如此循环下 去。0.2 秒的闪烁速率也由定时/计数器 T0 来完成。
2. 电路原理图 63
3. 系统板硬件连线
(1. 把“单片机系统”区域中的 P1.0-P1.3 用导线连接到“八路发光二极管
指示模块”区域中的 L1-L4 上
4. 程序设计内容
(1. 由于采用中断方式来完成,因此,对于中断源必须它的中断入口地址 ,
对于定时/计数器 T0 来说,中断入口地址为 000BH,因此在中断入口
地方加入长跳转指令来执行中断服务程序。书写汇编源程序格式如下
LJMP START
ORG 0BH ;定时/计数器 T0 中断入口地址
LJMP INT_T0
START: NOP ;主程序开始
INT_T0: PUSH ACC ;定时/计数器 T0 中断服务程序
RETI ;中断服务程序返回
(2. 定时 2 秒,采用 16 位定时 50ms,共定时 40 次才可达到 2 秒,每50ms
产生一中断,定时的 40 次数在中断服务程序中完成,同样 0.2 秒的
定时,需要 4 次才可达到 0.2 秒。对于中断程序,在主程序中要对中
断开中断。
(3. 由于每次 2 秒定时到时,L1-L4 要交替闪烁。采用 ID 来号来识别。
当 ID=0 时,L1 在闪烁,当 ID=1 时,L2 在闪烁;当 ID=2 时,L3 在闪烁;当 ID=3 时,L4 在闪烁
5. 程序框图 T0 中断服务程序框图
主程序框图 65
6. 汇编源程序
6. 汇编源程序
TCOUNT2S EQU 30H
TCNT02S EQU 31H
ID EQU 32H
LJMP START
LJMP INT_T0
START: MOV TCOUNT2S,#00H
MOV TCNT02S,#00H
MOV ID,#00H
MOV TMOD,#01H
MOV TH0,#() / 256 MOV TL0,#() MOD 256 SETB TR0
INT_T0: MOV TH0,#() / 256 MOV TL0,#() MOD 256 INC TCOUNT2S
MOV A,TCOUNT2S
CJNE A,#40,NEXT
MOV TCOUNT2S,#00H
CJNE A,#04H,NEXT
MOV ID,#00H
NEXT: INC TCNT02S
MOV A,TCNT02S
CJNE A,#4,DONE
MOV TCNT02S,#00H
CJNE A,#00H,SID1
SID1: CJNE A,#01H,SID2
SID2: CJNE A,#02H,SID3
SID3: CJNE A,#03H,SID4
SID4: SJMP DONE
DONE: RETI
7. C 语言源程序
#include &AT89X51.H&
unsigned char tcount2s;
unsigned char tcount02s;
unsigned char ID;
void main(void)
TMOD=0x01;
TH0=()/256;
TL0=()%256;
void t0(void) interrupt 1 using 0
tcount2s++;
if(tcount2s==40)
tcount2s=0;
tcount02s++;
if(tcount02s==4)
tcount02s=0;
switch(ID)
P1_0=~P1_0;
P1_1=~P1_1;
P1_2=~P1_2;
P1_3=~P1_3;
17. 99 秒马表设计
1. 实验任务
(1. 开始时,显示“00”,第 1 次按下 SP1 后就开始计时。
(2. 第 2 次按 SP1 后,计时停止。
(3. 第 3 次按 SP1 后,计时归零。
2. 电路原理图
3. 系统板上硬件连线
(1. 把“单片机系统”区域中的 P0.0/AD0-P0.7/AD7 端口用 8 芯排线连接到
“四路静态数码显示模块”区域中的任一个 a-h 端口上;要求:P0.0/AD0 对应着 a,P0.1/AD1 对应着 b,??,P0.7/AD7 对应着 h。
(2. 把“单片机系统”区域中的P2.0/A8-P2.7/A15 端口用8 芯排线连接到“四
路静态数码显示模块”区域中的任一个 a-h 端口上;要求:P2.0/A8 对 应着 a,P2.1/A9 对应着 b,??,P2.7/A15 对应着 h。
(3. 把“单片机系统“区域中的 P3.5/T1 用导线连接到”独立式键盘“区域中
的 SP1 端口上;
4. 程序框图
主程序框图
T0 中断服务程序框图
5. 汇编源程序 TCNTA EQU 30H TCNTB EQU 31H SEC EQU 32H
KEYCNT EQU 33H SP1 BIT P3.5
LJMP START
LJMP INT_T0
START: MOV KEYCNT,#00H MOV SEC,#00H
MOV DPTR,#TABLE MOVC A,@A+DPTR MOV P0,A
MOV DPTR,#TABLE
MOVC A,@A+DPTR
MOV TMOD,#02H
WT: JB SP1,WT
LCALL DELY10MS
INC KEYCNT
MOV A,KEYCNT
CJNE A,#01H,KN1
MOV TH0,#06H
MOV TL0,#06H
MOV TCNTA,#00H
MOV TCNTB,#00H
KN1: CJNE A,#02H,KN2
KN2: CJNE A,#03H,DKN
MOV SEC,#00H
MOV DPTR,#TABLE
MOVC A,@A+DPTR
MOV DPTR,#TABLE
MOVC A,@A+DPTR
MOV KEYCNT,#00H
DKN: JNB SP1,$
MOV R6,#20
D1: MOV R7,#248
DJNZ R6,D1
MOV A,TCNTA
CJNE A,#100,NEXT
MOV TCNTA,#00H
MOV A,TCNTB
CJNE A,#4,NEXT
MOV TCNTB,#00H
CJNE A,#100,DONE
MOV SEC,#00H
DONE: MOV A,SEC
MOV DPTR,#TABLE
MOVC A,@A+DPTR
MOV DPTR,#TABLE
MOVC A,@A+DPTR
NEXT: RETI
TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH
6. C 语言源程序
#include &AT89X51.H&
unsigned char code dispcode[]={0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,0x00};
void main(void)
unsigned char i,j;
TMOD=0x02;
P0=dispcode[second/10];
P2=dispcode[second%10];
if(P3_5==0)
for(i=20;i&0;i--)
for(j=248;j&0;j--);
if(P3_5==0)
switch(keycnt)
P0=dispcode[second/10];
P2=dispcode[second%10];
while(P3_5==0);
void t0(void) interrupt 1 using 0
if(tcnt==400)
if(second==100)
P0=dispcode[second/10];
P2=dispcode[second%10];
18. “嘀、嘀、??”报警声
1. 实验任务
用 AT89S51 单片机产生“嘀 、嘀 、?”报警声从 P1.0 端口输出,产生频率为 1KHz, 根据上面图可知:1KHZ 方波从 P1.0 输出 0.2 秒,接着 0.2 秒从 P1.0 输出电平 信号,如此循环下去,就形成我们所需的报警声了。
2. 电路原理图
3. 系统板硬件连线
(1. 把“单片机系统”区域中的 P1.0 端口用导线连接到“音频放大模块”区
域中的 SPK IN 端口上,
(2. 在“音频放大模块”区域中的 SPK OUT 端口上接上一个 8 欧或者是 16 欧
4. 程序设计方法
(1.生活中我们常常到各种各样的报警声,例如“嘀、嘀、?”就是常见 的一种声音报警声,但对于这种报警声,嘀 0.2 秒钟,然后断 0.2 秒钟,如此循 环下去,假设嘀声的频率为 1KHz,则报警声时序图如下图所示:
上述波形信号如何用单片机来产生呢?
(2. 由于要产生上面的信号,我们把上面的信号分成两部分,一部分为 1KHZ
方波,占用时间为 0.2 秒;另一部分为电平,也是占用 0.2 秒;因此,我 们利用单片机的定时/计数器 T0 作为定时,可以定时 0.2 秒;同时,也要 用单片机产生 1KHZ 的方波,对于 1KHZ 的方波信号周期为 1ms,高电平占
用 0.5ms,低电平占用 0.5ms,因此也采用定时器 T0 来完成 0.5ms 的定时 ; 最后,可以选定定时/计数器 T0 的定时时间为 0.5ms,而要定时 0.2 秒则 是 0.5ms 的 400 倍,也就是说以 0.5ms 定时 400 次就达到 0.2 秒的定时时 间了。
5. 程序框图 主程序框图 中断服务程序框图
6. 汇编源程序
T02SA EQU 30H
T02SB EQU 31H
FLAG BIT 00H
LJMP START
LJMP INT_T0
START: MOV T02SA,#00H
MOV T02SB,#00H
MOV TMOD,#01H
MOV TH0,#() / 256
MOV TL0,#() MOD 256
MOV TH0,#() / 256
MOV TL0,#() MOD 256
MOV A,T02SA
CJNE A,#100,NEXT
MOV A,T02SB
CJNE A,#04H,NEXT
MOV T02SA,#00H
MOV T02SB,#00H
NEXT: JB FLAG,DONE
DONE: RETI
7. C 语言源程序
#include &AT89X51.H&
unsigned int t02s;
unsigned char t05
void main(void)
TMOD=0x01;
TH0=()/256;
TL0=()%256;
void t0(void) interrupt 1 using 0
TH0=()/256;
TL0=()%256;
if(t02s==400)
if(flag==0)
P1_0=~P1_0;
19. “叮咚”门铃
1. 实验任务
当按下开关 SP1,AT89S51 单片机产生“叮咚”声从 P1.0 端口输出到 LM386,经 过放大之后送入喇叭。
2. 电路原理图
3. 系统板上硬件连线
(1. 把“单片机系统”区域中的 P1.0 端口用导线连接到“音频放大模块”区
域中的 SPK IN 端口上;
(2. 在“音频放大模块”区域中的 SPK OUT 端口上接上一个 8 欧或者是 16 欧
(3. 把“单片机系统”区域中的 P3.7/RD 端口用导线连接到“独立式键盘”区
域中的 SP1 端口上;
4. 程序设计方法 79
if(tcnt==2000)
if(flag==0)
if(flag==0)
if(t7hz==3)
P1_0=~P1_0;
if(t5hz==4)
P1_0=~P1_0;
20. 数字钟﹝★﹞
1. 实验任务
(1. 开机时,显示 12:00:00 的时间开始计时;
(2. P0.0/AD0 控制“秒”的调整,每按一次加 1 秒;
(3. P0.1/AD1 控制“分”的调整,每按一次加 1 分;
(4. P0.2/AD2 控制“时”的调整,每按一次加 1 个小时;
2. 电路原理图
3. 系统板上硬件连线
(1. 把“单片机系统”区域中的 P1.0-P1.7 端口用 8 芯排线连接到“动态数
码显示”区域中的 A-H 端口上;
(2. 把“单片机系统:区域中的 P3.0-P3.7 端口用 8 芯排线连接到“动态数
码显示”区域中的 S1-S8 端口上;
(3. 把“单片机系统”区域中的 P0.0/AD0、P0.1/AD1、P0.2/AD2 端口分别用
导线连接到“独立式键盘”区域中的 SP3、SP2、SP1 端口上;
4. 相关基本知识
(1. 动态数码显示的方法
(2. 独立式按键识别过程
(3. “时”,“分”,“秒”数据送出显示处理方法
5. 程序框图
6. 汇编源程序
SECOND EQU 30H
MINITE EQU 31H
HOUR EQU 32H
HOURK BIT P0.0
MINITEK BIT P0.1
SECONDK BIT P0.2
DISPBUF EQU 40H
DISPBIT EQU 48H
T2SCNTA EQU 49H
T2SCNTB EQU 4AH
TEMP EQU 4BH
LJMP START
LJMP INT_T0
START: MOV SECOND,#00H
MOV MINITE,#00H
MOV HOUR,#12
MOV DISPBIT,#00H
MOV T2SCNTA,#00H
MOV T2SCNTB,#00H
MOV TEMP,#0FEH
LCALL DISP
MOV TMOD,#01H
MOV TH0,#() / 256
MOV TL0,#() MOD 256
WT: JB SECONDK,NK1
LCALL DELY10MS
JB SECONDK,NK1
INC SECOND
MOV A,SECOND
CJNE A,#60,NS60
MOV SECOND,#00H
NS60: LCALL DISP
JNB SECONDK,$
NK1: JB MINITEK,NK2
LCALL DELY10MS
JB MINITEK,NK2
INC MINITE
MOV A,MINITE
CJNE A,#60,NM60
MOV MINITE,#00H
NM60: LCALL DISP
JNB MINITEK,$
NK2: JB HOURK,NK3
LCALL DELY10MS
JB HOURK,NK3
MOV A,HOUR
CJNE A,#24,NH24
MOV HOUR,#00H
NH24: LCALL DISP
JNB HOURK,$
NK3: LJMP WT
MOV R6,#10
D1: MOV R7,#248
DJNZ R6,D1
MOV A,#DISPBUF
MOV A,HOUR
MOV A,MINITE
MOV A,SECOND
MOV TH0,#() / 256
MOV TL0,#() MOD 256
MOV A,#DISPBUF
ADD A,DISPBIT
MOV DPTR,#TABLE
MOVC A,@A+DPTR
MOV A,DISPBIT
MOV DPTR,#TAB
MOVC A,@A+DPTR
INC DISPBIT
MOV A,DISPBIT
CJNE A,#08H,KNA
MOV DISPBIT,#00H
KNA: INC T2SCNTA
MOV A,T2SCNTA
CJNE A,#100,DONE
MOV T2SCNTA,#00H
INC T2SCNTB
MOV A,T2SCNTB
CJNE A,#05H,DONE
MOV T2SCNTB,#00H
INC SECOND
MOV A,SECOND
CJNE A,#60,NEXT
MOV SECOND,#00H
INC MINITE
MOV A,MINITE
CJNE A,#60,NEXT
MOV MINITE,#00H
MOV A,HOUR
CJNE A,#24,NEXT
MOV HOUR,#00H
NEXT: LCALL DISP
DONE: RETI
TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,40H TAB: DB 0FEH,0FDH,0FBH,0F7H,0EFH,0DFH,0BFH,07FH END
7. C 语言源程序
#include &AT89X51.H&
unsigned char code dispcode[]={0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,0x00};
unsigned char dispbitcode[]={0xfe,0xfd,0xfb,0xf7, 0xef,0xdf,0xbf,0x7f};
unsigned char dispbuf[8]={0,0,16,0,0,16,0,0}; unsi
unsigned char i,j;
void main(void)
TMOD=0x02;
if(P0_0==0)
for(i=5;i&0;i--)
for(j=248;j&0;j--);
if(P0_0==0)
if(second==60)
dispbuf[0]=second%10;
dispbuf[1]=second/10;
while(P0_0==0);
if(P0_1==0)
for(i=5;i&0;i--)
for(j=248;j&0;j--);
if(P0_1==0)
if(minite==60)
dispbuf[3]=minite%10;
dispbuf[4]=minite/10;
while(P0_1==0);
if(P0_2==0)
for(i=5;i&0;i--)
for(j=248;j&0;j--);
if(P0_2==0)
if(hour==24)
dispbuf[6]=hour%10;
dispbuf[7]=hour/10;
while(P0_2==0);
void t0(void) interrupt 1 using 0
if(mstcnt==8)
P1=dispcode[dispbuf[dispbitcnt]];
P3=dispbitcode[dispbitcnt];
dispbitcnt++;
if(dispbitcnt==8)
dispbitcnt=0;
if(tcnt==4000)
if(second==60)
if(minite==60)
if(hour==24)
dispbuf[0]=second%10;
dispbuf[1]=second/10;
dispbuf[3]=minite%10;
dispbuf[4]=minite/10;
dispbuf[6]=hour%10;
dispbuf[7]=hour/10;
21. 拉幕式数码显示技术
1. 实验任务
用 AT89S51 单片机的 P0.0/AD0-P0.7/AD7 端口接数码管的 a-h 端,8 位数码管 的 S1-S8 通过 74LS138 译码器的 Y0-Y7 来控制选通每个数码管的位选端。
AT89S51 单片机的 P1.0-P1.2 控制 74LS138 的 A,B,C 端子。在 8 位数码管上 从右向左循环显示“”。能够比较平滑地看到拉幕的效果。
2. 电路原理图
图 4.21.1 3. 系统板上硬件连线
(1. 把“单片机系统”区域中的 P0.0/AD0-P0.7/AD7 用 8 芯排线连接到“动
态数码显示”区域中的 a-h 端口上;
(2. 把“三八译码模块”区域中的 Y0-Y7 用 8 芯排线连接到“动态数码显示”
区域中的 S1-S8 端口上;
(3. 把“单片机系统”区域中的 P1.0-P1.2 端口用 3 根导线连接到“三八译
码模块”区域中的 A、B、C“端口上;
4. 程序设计方法
(1. 动态数码显示技术;如何进行动态扫描,由于一次只能让一个数码管
显示,因此,要显示 8 位的数据,必须经过让数码管一个一个轮流显
示才可以,同时每个数码管显示的时间大约在 1ms 到 4ms 之间,所以
为了保证正确显示,我必须每隔 1ms,就得刷新一个数码管。而这刷
新时间我们采用单片机的定时/计数器 T0 来控制,每定时 1ms 对数码
管刷新一次,T0 采用方式 2。
(2. 在进行数码显示的时候,要对显示单元开辟 8 个显示缓冲区,每个显
示缓冲区装有显示的不同数据即可。
5. 程序框图
主程序框图
中断服务程序框图
6. 汇编源程序
DISPBUF EQU 30H
DISPCNT EQU 38H
DISPBIT EQU 39H
T1CNTA EQU 3AH
T1CNTB EQU 3BH
CNT EQU 3CH
LJMP START
LJMP INT_T0
START: MOV DISPCNT,#8
MOV R1,#DISPBUF
LP: MOV @R1,A
DJNZ DISPCNT,LP
MOV DISPBIT,#00H
MOV T1CNTA,#00H
MOV T1CNTB,#00H
MOV CNT,#00H
MOV TMOD,#01H
MOV TH0,#() / 256
MOV TL0,#() MOD 256
MOV TH0,#() / 256
MOV TL0,#() MOD 256
MOV A,DISPBIT
ADD A,#DISPBUF
MOV DPTR,#TABLE
MOVC A,@A+DPTR
ANL A,#0F8H
ADD A,DISPBIT
INC DISPBIT
MOV A,DISPBIT
CJNE A,#08H,NEXT
MOV DISPBIT,#00H
NEXT: INC T1CNTA
MOV A,T1CNTA
CJNE A,#50,LL1
MOV T1CNTA,#00H
INC T1CNTB
MOV A,T1CNTB
CJNE A,#8,LL1
MOV T1CNTB,#00H
CJNE A,#9,LLX
MOV CNT,#00H
LLX: CJNE A,#01H,NEX1
MOV 30H,#8
LL1: LJMP DONE
NEX1: CJNE A,#02H,NEX2
MOV 31H,#8
MOV 30H,#8
NEX2: CJNE A,#03H,NEX3
MOV 32H,#8
MOV 31H,#8
MOV 30H,#8
NEX3: CJNE A,#04H,NEX4
MOV 33H,#8
MOV 32H,#8
MOV 31H,#8
MOV 30H,#8
NEX4: CJNE A,#05H,NEX5
MOV 34H,#8
MOV 33H,#8
MOV 32H,#8
MOV 31H,#8
MOV 30H,#8
NEX5: CJNE A,#06H,NEX6
MOV 35H,#8
MOV 34H,#8
MOV 33H,#8
MOV 32H,#8
MOV 31H,#8
MOV 30H,#8
NEX6: CJNE A,#07H,NEX7
MOV 36H,#8
MOV 35H,#8
MOV 34H,#8
MOV 33H,#8
MOV 32H,#8
MOV 31H,#8
MOV 30H,#8
NEX7: CJNE A,#08H,NEX8
MOV 37H,#8
MOV 36H,#8
MOV 35H,#8
MOV 34H,#8
MOV 33H,#8
MOV 32H,#8
MOV 31H,#8
MOV 30H,#8
NEX8: CJNE A,#00H,DONE
MOV 37H,#10
MOV 36H,#10
MOV 35H,#10
MOV 34H,#10
MOV 33H,#10
MOV 32H,#10
MOV 31H,#10
MOV 30H,#10
LL: LJMP DONE
DONE: RETI
TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,00H END
7. C 语言源程序
#include &AT89X51.H&
unsigned char code dispcode[]={0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,0x00};
unsigned char dispbitcode[]={0xf8,0xf9,0xfa,0xfb, 0xfc,0xfd,0xfe,0xff};
unsigned char dispbuf[8]={16,16,16,16,16,16,16,16}; unsi
unsigned int t02
unsigned char t5
void main(void)
TMOD=0x02;
void t0(void) interrupt 1 using 0
t5mscnt++;
if(t5mscnt==4)
t5mscnt=0;
P0=dispcode[dispbuf[dispbitcnt]];
P1=dispbitcode[dispbitcnt];
dispbitcnt++;
if(dispbitcnt==8)
dispbitcnt=0;
t02scnt++;
if(t02scnt==1600)
t02scnt=0;
for(i=0;i&8;i++)
dispbuf[i]=16;
for(i=0;i&u;i++)
dispbuf[i]=8;
22. 电子琴 100
1. 实验任务
(1. 由 4X4 组成 16 个按钮矩阵,设计成 16 个音。
(2. 可随意弹奏想要表达的音乐。
2. 电路原理图
3. 系统板硬件连线
(1. 把“单片机系统”区域中的 P1.0 端口用导线连接到“音频放大模块”区
域中的 SPK IN 端口上;
(2. 把“单片机系统“区域中的 P3.0-P3.7 端口用 8 芯排线连接到“4X4 行
列式键盘”区域中的 C1-C4 R1-R4 端口上;
4. 相关程序内容
(1. 4X4 行列式键盘识别;
(2. 音乐产生的方法;
一首音乐是许多不同的音阶组成的,而每个音阶对应着不同的频率,这样我 们就可以利用不同的频率的组合,即可构成我们所想要的音乐了,当然对于单片 机来产生不同的频率非常方便,我们可以利用单片机的定时/计数器 T0 来产生这 样方波频率信号,因此,我们只要把一首歌曲的音阶对应频率关系弄正确即可。 现在以单片机 12MHZ 晶振为例,例出高中低音符与单片机计数 T0 相关的计数值 如下表所示
下面我们要为这个音符建立一个表格,有助于单片机通过查表的方式来获得相应 的数据
低音 0-19 之间,中音在 20-39 之间,高音在 40-59 之间
TABLE: DW 0,,,,
DW 0,,0,,,0 102
DW 0,,0,,,0
DW 0,,0,,,0
2、音乐的音拍,一个节拍为单位(C 调)
对于不同的曲调我们也可以用单片机的另外一个定时/计数器来完成。
下面就用 AT89S51 单片机产生一首“生日快乐”歌曲来说明单片机如何产生的。
在这个程序中用到了两个定时/计数器来完成的。其中 T0 用来产生音符频率,T1 用来产生音拍。
5. 程序框图
6. 汇编源程序
KEYBUF EQU 30H
STH0 EQU 31H
STL0 EQU 32H
TEMP EQU 33H
103ORG 00H
LJMP START
LJMP INT_T0
START: MOV TMOD,#01H SETB ET0
MOV P3,#0FFH
ANL A,#0FH
XRL A,#0FH
LCALL DELY10MS MOV A,P3
ANL A,#0FH
XRL A,#0FH
ANL A,#0FH
CJNE A,#0EH,NK1 MOV KEYBUF,#0 LJMP DK1
NK1: CJNE A,#0DH,NK2 MOV KEYBUF,#1 LJMP DK1
NK2: CJNE A,#0BH,NK3 MOV KEYBUF,#2 LJMP DK1
NK3: CJNE A,#07H,NK4 MOV KEYBUF,#3 LJMP DK1
MOV A,KEYBUF
MOV DPTR,#TABLE MOVC A,@A+DPTR MOV P0,A
MOV A,KEYBUF
MOV TEMP,A
MOV DPTR,#TABLE1
MOV STH0,A
MOV A,TEMP
MOVC A,@A+DPTR MOV STL0,A
DK1A: MOV A,P3 ANL A,#0FH
XRL A,#0FH
MOV P3,#0FFH
ANL A,#0FH
XRL A,#0FH
LCALL DELY10MS MOV A,P3
ANL A,#0FH
XRL A,#0FH
ANL A,#0FH
CJNE A,#0EH,NK5 MOV KEYBUF,#4 LJMP DK2
NK5: CJNE A,#0DH,NK6 MOV KEYBUF,#5 LJMP DK2
NK6: CJNE A,#0BH,NK7 MOV KEYBUF,#6 LJMP DK2
NK7: CJNE A,#07H,NK8 MOV KEYBUF,#7 LJMP DK2
MOV A,KEYBUF
MOVC A,@A+DPTR MOV P0,A
MOV A,KEYBUF
MOV TEMP,A
MOV DPTR,#TABLE1 MOVC A,@A+DPTR MOV STH0,A
MOV A,TEMP
MOVC A,@A+DPTR MOV STL0,A
DK2A: MOV A,P3 ANL A,#0FH
XRL A,#0FH
MOV P3,#0FFH
ANL A,#0FH
XRL A,#0FH
LCALL DELY10MS MOV A,P3
ANL A,#0FH
XRL A,#0FH
ANL A,#0FH
CJNE A,#0EH,NK9 MOV KEYBUF,#8 LJMP DK3
NK9: CJNE A,#0DH,NK10 MOV KEYBUF,#9 LJMP DK3
NK10: CJNE A,#0BH,NK11 MOV KEYBUF,#10 LJMP DK3
NK11: CJNE A,#07H,NK12 MOV KEYBUF,#11 LJMP DK3
MOV A,KEYBUF
MOV DPTR,#TABLE MOVC A,@A+DPTR MOV P0,A
MOV A,KEYBUF
MOV TEMP,A
MOV DPTR,#TABLE1 MOVC A,@A+DPTR MOV STH0,A
MOV A,TEMP
MOVC A,@A+DPTR MOV STL0,A
DK3A: MOV A,P3 ANL A,#0FH
XRL A,#0FH
MOV P3,#0FFH
ANL A,#0FH
XRL A,#0FH
LCALL DELY10MS MOV A,P3
ANL A,#0FH
XRL A,#0FH
107MOV A,P3
ANL A,#0FH
CJNE A,#0EH,NK13
MOV KEYBUF,#12
NK13: CJNE A,#0DH,NK14
MOV KEYBUF,#13
NK14: CJNE A,#0BH,NK15
MOV KEYBUF,#14
NK15: CJNE A,#07H,NK16
MOV KEYBUF,#15
MOV A,KEYBUF
MOV DPTR,#TABLE
MOVC A,@A+DPTR
MOV A,KEYBUF
MOV TEMP,A
MOV DPTR,#TABLE1
MOVC A,@A+DPTR
MOV STH0,A
MOV A,TEMP
MOVC A,@A+DPTR
MOV STL0,A
DK4A: MOV A,P3
ANL A,#0FH
XRL A,#0FH
MOV R6,#10
D1: MOV R7,#248
DJNZ R6,D1
MOV TH0,STH0
MOV TL0,STL0
TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H DB 7FH,6FH,77H,7CH,39H,5EH,79H,71H
TABLE1: DW ,
7. C 语言源程序
#include &AT89X51.H&
unsigned char code table[]={0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
unsigned char i,j;
unsigned char STH0;
unsigned char STL0;
unsigned int code tab[]={,, ,,
void main(void)
TMOD=0x01;
temp=temp & 0x0f; if (temp!=0x0f) {
for(i=50;i&0;i--) for(j=200;j&0;j--); temp=P3;
temp=temp & 0x0f; if (temp!=0x0f) {
temp=temp & 0x0f; switch(temp) {
case 0x0e: key=0;
case 0x0d: key=1;
case 0x0b: key=2;
case 0x07: key=3;
P1_0=~P1_0; P0=table[key]; STH0=tab[key]/256; STL0=tab[key]%256; TR0=1;
temp=temp & 0x0f; while(temp!=0x0f) {
temp=temp & 0x0f; }
temp=temp & 0x0f; if (temp!=0x0f) {
for(i=50;i&0;i--) for(j=200;j&0;j--); temp=P3;
temp=temp & 0x0f; if (temp!=0x0f) {
temp=temp & 0x0f; switch(temp) {
case 0x0e: key=4;
case 0x0d: key=5;
case 0x0b: key=6;
case 0x07: key=7;
P1_0=~P1_0; P0=table[key]; STH0=tab[key]/256; STL0=tab[key]%256; TR0=1;
temp=temp & 0x0f; while(temp!=0x0f) {
temp=temp & 0x0f; }
111temp=P3;
temp=temp & 0x0f;
if (temp!=0x0f)
for(i=50;i&0;i--)
for(j=200;j&0;j--);
temp=temp & 0x0f;
if (temp!=0x0f)
temp=temp & 0x0f;
switch(temp)
case 0x0e:
case 0x0d:
case 0x0b:
case 0x07:
P1_0=~P1_0;
P0=table[key];
STH0=tab[key]/256;
STL0=tab[key]%256;
temp=temp & 0x0f;
while(temp!=0x0f)
temp=temp & 0x0f;
temp=temp & 0x0f;
if (temp!=0x0f)
for(i=50;i&0;i--)
for(j=200;j&0;j--);
temp=temp & 0x0f;
if (temp!=0x0f)
temp=temp & 0x0f;
switch(temp)
case 0x0e:
case 0x0d:
case 0x0b:
case 0x07:
P1_0=~P1_0;
P0=table[key];
STH0=tab[key]/256;
STL0=tab[key]%256;
temp=temp & 0x0f;
while(temp!=0x0f)
temp=temp & 0x0f;
void t0(void) interrupt 1 using 0
P1_0=~P1_0;
23. 模拟计算器数字输入及显示
1. 实验任务
(1. 开机时,显示“0”
(2. 第一次按下时,显示“D1”;第二次按下时,显示“D1D2”;第三按下时 ,
显示“D1D2D3”,8 个全显示完毕,再按下按键下时,给出“嘀”提示音 。
2. 电路原理图
3. 系统板上硬件连线
(1. 把“单片机系统”区域中的 P1.0 端口用导线连接到“音频放大模块”区
域中的 SPK IN 端口上;
(2. 把“单片机系统“区域中的 P3.0-P3.7 端口用 8 芯排线连接到“4X4 行
列式键盘”区域中的 C1-C4 R1-R4 端口上;
(3. 把“单片机系统”区域中的 P0.0-P0.7 端口用 8 芯排线连接到“动态数
码显示”区域中的 A-H 端口上;
(4. 把“单片机系统:区域中的 P2.0-P2.7 端口用 8 芯排线连接到“动态数
码显示”区域中的 S1-S8 端口上;
4. 相关程序设计内容
(1. 行列式键盘输入及按键功能设定;
(2. 动态数码显示;
(3. 数码显示方式处理;
5. 汇编源程序
6. C 语言源程序
#include &AT89X51.H&
unsigned char code
dispcode[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
unsigned char code
dispbitcode[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
unsigned char dispbuf[8]={0,16,16,16,16,16,16,16};
unsigned char i,j;
void change(unsigned char *p,unsigned char count)
while(count&0)
*(p+count)=*(p+count-1); count--;
void main(void) {
TMOD=0x01;
TH0=() / 256; TL0=() % 256; TR0=1;
temp=temp & 0x0f; if (temp!=0x0f) {
for(i=50;i&0;i--) for(j=200;j&0;j--); temp=P3;
temp=temp & 0x0f; if (temp!=0x0f) {
temp=temp & 0x0f; switch(temp)
case 0x0e:
case 0x0d:
case 0x0b:
case 0x07:
if ((key&=0) && (key&10)) {
if(keypos&8)
change(dispbuf,keypos); dispbuf[0]= }
alarmflag=1;
P1_0=~P1_0;
temp=temp & 0x0f; while(temp!=0x0f) {
temp=temp & 0x0f; }
alarmflag=0;
temp=temp & 0x0f; if (temp!=0x0f) {
for(i=50;i&0;i--) for(j=200;j&0;j--); temp=P3;
temp=temp & 0x0f; if (temp!=0x0f) {
temp=temp & 0x0f; switch(temp)
case 0x0e:
case 0x0d:
case 0x0b:
case 0x07:
if ((key&=0) && (key&10)) {
if(keypos&8)
change(dispbuf,keypos); dispbuf[0]= }
alarmflag=1;
P1_0=~P1_0;
temp=temp & 0x0f; while(temp!=0x0f) {
temp=temp & 0x0f; }
alarmflag=0;
temp=temp & 0x0f; if (temp!=0x0f) {
for(i=50;i&0;i--) for(j=200;j&0;j--); temp=P3;
temp=temp & 0x0f; if (temp!=0x0f) {
temp=temp & 0x0f; switch(temp)
case 0x0e:
case 0x0d:
case 0x0b:
case 0x07:
if ((key&=0) && (key&10)) {
if(keypos&8)
change(dispbuf,keypos); dispbuf[0]= }
alarmflag=1;
P1_0=~P1_0;
temp=temp & 0x0f; while(temp!=0x0f) {
temp=temp & 0x0f;
alarmflag=0;
temp=temp & 0x0f;
if (temp!=0x0f)
for(i=50;i&0;i--)
for(j=200;j&0;j--);
temp=temp & 0x0f;
if (temp!=0x0f)
temp=temp & 0x0f;
switch(temp)
case 0x0e:
case 0x0d:
case 0x0b:
case 0x07:
if ((key&=0) && (key&10))
if(keypos&8)
change(dispbuf,keypos);
dispbuf[0]=
alarmflag=1;
P1_0=~P1_0;
temp=temp & 0x0f;
while(temp!=0x0f)
temp=temp & 0x0f;
alarmflag=0;
void t0(void) interrupt 1 using 0
TH0=() / 256;
TL0=() % 256;
P0=dispcode[dispbuf[dispbitcount]];
P2=dispbitcode[dispbitcount];
dispbitcount++;
if (dispbitcount==8)
dispbitcount=0;
if (alarmflag==1)
P1_1=~P1_1;
24. 8X8 LED 点阵显示技术
1. 实验任务
在 8X8 LED 点阵上显示柱形,让其先从左到右平滑移动三次,其次从右到左 平滑移动三次,再次从上到下平滑移动三次,最后从下到上平滑移动三次, 如此循环下去。
2. 电路原理图
3. 硬件电路连线
(1). 把“单片机系统”区域中的 P1 端口用 8 芯排芯连接到“点阵模块”
区域中的“DR1-DR8”端口上;
(2). 把“单片机系统”区域中的 P3 端口用 8 芯排芯连接到“点阵模块”
区域中的“DC1-DC8”端口上;
4. 程序设计内容
8X8 点阵 LED 结构如下图所示
从图 4.24.2 中可以看出,8X8 点阵共需要 64 个发光二极管组成,且每个发光二 极管是放置在行线和列线的交叉点上,当对应的某一列置 1 电平,某一行置 0 电平,则相应的二极管就亮;因此要实现一根柱形的亮法,如图 49 所示,对应 的一列为一根竖柱,或者对应的一行为一根横柱,因此实现柱的亮的方法如下所 述:
一根竖柱:对应的列置 1,而行则采用扫描的方法来实现。
一根横柱:对应的行置 0,而列则采用扫描的方法来实现。
5.汇编源程序
START: NOP
LOP2: MOV R4,#8
123MOV R2,#0
LOP1: MOV P1,#0FFH
MOV DPTR,#TABA
MOVC A,@A+DPTR
LCALL DELAY
DJNZ R4,LOP1
DJNZ R3,LOP2
LOP4: MOV R4,#8
LOP3: MOV P1,#0FFH
MOV DPTR,#TABA
MOVC A,@A+DPTR
LCALL DELAY
DJNZ R4,LOP3
DJNZ R3,LOP4
LOP6: MOV R4,#8
LOP5: MOV P3,#00H
MOV DPTR,#TABB
MOVC A,@A+DPTR
LCALL DELAY
DJNZ R4,LOP5
DJNZ R3,LOP6
LOP8: MOV R4,#8
LOP7: MOV P3,#00H
MOV DPTR,#TABB
MOVC A,@A+DPTR
LCALL DELAY
DJNZ R4,LOP7
DJNZ R3,LOP8
LJMP START
DELAY: MOV R5,#10
D2: MOV R6,#20
D1: MOV R7,#248
DJNZ R6,D1
DJNZ R5,D2
TABA: DB 0FEH,0FDH,0FBH,0F7H,0EFH,0DFH,0BFH,07FH
TABB: DB 01H,02H,04H,08H,10H,20H,40H,80H
6. C 语言源程序
#include &AT89X52.H&
unsigned char code taba[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; unsigned char code tabb[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
void delay(void)
unsigned char i,j;
for(i=10;i&0;i--)
for(j=248;j&0;j--);
void delay1(void)
unsigned char i,j,k;
for(k=10;k&0;k--)
for(i=20;i&0;i--)
for(j=248;j&0;j--);
void main(void)
unsigned char i,j;
for(j=0;j&3;j++)
for(i=0;i&8;i++)
P3=taba[i];
for(j=0;j&3;j++)
for(i=0;i&8;i++)
P3=taba[7-i];
for(j=0;j&3;j++)
for(i=0;i&8;i++)
P1=tabb[7-i];
for(j=0;j&3;j++)
for(i=0;i&8;i++)
P1=tabb[i];
25. 点阵式 LED“0-9”数字显示技术
1. 实验任务
利用 8X8 点阵显示数字 0 到 9 的数字。
2. 电路原理图
3. 硬件系统连线
(1). 把“单片机系统”区域中的 P1 端口用 8 芯排芯连接到“点阵模块”
区域中的“DR1-DR8”端口上;
(2). 把“单片机系统”区域中的 P3 端口用 8 芯排芯连接到“点阵模块”
区域中的“DC1-DC8”端口上;
4. 程序设计内容
(1). 数字 0-9 点阵显示代码的形成
如下图所示,假设显示数字“0”
,00H,3EH,41H,41H,3EH,00H,00H;只要把这 0”的数字显示。
送第一列线代码到 P3 端口,同时置第一行线为“0”,其它行线为“1”,延时 2ms 左右,送第二列线代码到 P3 端口,同时置第二行线为“0”,其它行线为 “1”,延时 2ms 左右,如此下去,直到送完最后一列代码,又从头开始送。
数字“1”代码建立如下图所示
1 2 3 4 5 6 7 8
数字“2”代码建立如下图所示 1
,45H,39H,00H
,49H,36H,00H
,7FH,04H,00H
数字“5”代码建立如下图所示 1
,51H,4EH,00H
,49H,26H,00H
,4FH,70H,00H
数字“8”代码建立如下图所示 1
,49H,36H,00H
,49H,3EH,00H
LJMP START
START: MOV TIM,#00H MOV CNTA,#00H
MOV CNTB,#00H
MOV TMOD,#01H
MOV TH0,#()/256
MOV TL0,#() MOD 256
MOV TH0,#()/256
MOV TL0,#() MOD 256
MOV DPTR,#TAB
MOV A,CNTA
MOVC A,@A+DPTR
MOV DPTR,#DIGIT
MOV A,CNTB
ADD A,CNTA
MOVC A,@A+DPTR
MOV A,CNTA
CJNE A,#8,NEXT
MOV CNTA,#00H
NEXT: INC TIM
CJNE A,#250,NEX
MOV TIM,#00H
MOV A,CNTB
CJNE A,#10,NEX
MOV CNTB,#00H
TAB: DB 0FEH,0FDH,0FBH,0F7H,0EFH,0DFH,0BFH,07FH
DIGIT: DB 00H,00H,3EH,41H,41H,41H,3EH,00H
DB 00H,00H,00H,00H,21H,7FH,01H,00H
DB 00H,00H,27H,45H,45H,45H,39H,00H
DB 00H,00H,22H,49H,49H,49H,36H,00H
DB 00H,00H,0CH,14H,24H,7FH,04H,00H
DB 00H,00H,72H,51H,51H,51H,4EH,00H
DB 00H,00H,3EH,49H,49H,49H,26H,00H
DB 00H,00H,40H,40H,40H,4FH,70H,00H
DB 00H,00H,36H,49H,49H,49H,36H,00H
DB 00H,00H,32H,49H,49H,49H,3EH,00H
6. C 语言源程序
#include &AT89X52.H&
unsigned char code tab[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; unsigned char code digittab[10][8]={
{0x00,0x00,0x3e,0x41,0x41,0x41,0x3e,0x00}, //0
{0x00,0x00,0x00,0x00,0x21,0x7f,0x01,0x00}, //1
{0x00,0x00,0x27,0x45,0x45,0x45,0x39,0x00}, //2
{0x00,0x00,0x22,0x49,0x49,0x49,0x36,0x00}, //3
{0x00,0x00,0x0c,0x14,0x24,0x7f,0x04,0x00}, //4
{0x00,0x00,0x72,0x51,0x51,0x51,0x4e,0x00}, //5
{0x00,0x00,0x3e,0x49,0x49,0x49,0x26,0x00}, //6
{0x00,0x00,0x40,0x40,0x40,0x4f,0x70,0x00}, //7
{0x00,0x00,0x36,0x49,0x49,0x49,0x36,0x00}, //8
{0x00,0x00,0x32,0x49,0x49,0x49,0x3e,0x00} //9
void main(void)
TMOD=0x01;
TH0=()/256;
TL0=()%256;
void t0(void) interrupt 1 using 0
TH0=()/256;
TL0=()%256;
P3=tab[cnta];
P1=digittab[cntb][cnta];
if(cnta==8)
timecount++;
if(timecount==333)
timecount=0;
if(cntb==10)
26. 点阵式 LED 简单图形显示技术
1. 实验任务
在 8X8 点阵式 LED 显示“★”、“●”和心形图,通过按键来选择要显示的 图形。
2. 电路原理图
3. 硬件系统连线
(1). 把“单片机系统”区域中的 P1 端口用 8 芯排芯连接到“点阵模块”
区域中的“DR1-DR8”端口上;
(2). 把“单片机系统”区域中的 P3 端口用 8 芯排芯连接到“点阵模块”
区域中的“DC1-DC8”端口上;
(3). 把“单片机系统”区域中的 P2.0/A8 端子用导线连接到“独立式键
盘”区域中的 SP1 端子上;
4. 程序设计内容
(1). “★”在 8X8LED 点阵上显示图如下图所示
6 7 8 12H,00H
6 7 8 44H,38H,00H 点阵上显示图如下图所示
30H,00H 136
5. 汇编源程序
CNTA EQU 30H
COUNT EQU 31H
LJMP START
START: MOV CNTA,#00H
MOV COUNT,#00H
MOV TMOD,#01H
MOV TH0,#() / 256
MOV TL0,#() MOD 256
WT: JB P2.0,WT
MOV R7,#248
D1: DJNZ R7,$
DJNZ R6,D1
JB P2.0,WT
MOV A,COUNT
CJNE A,#03H,NEXT
MOV COUNT,#00H
NEXT: JNB P2.0,$
MOV TH0,#() / 256
MOV TL0,#() MOD 256
MOV DPTR,#TAB
MOV A,CNTA
MOVC A,@A+DPTR
MOV DPTR,#GRAPH
MOV A,COUNT
ADD A,CNTA
MOVC A,@A+DPTR
MOV A,CNTA
CJNE A,#8,NEX
MOV CNTA,#00H
TAB: DB 0FEH,0FDH,0FBH,0F7H,0EFH,0DFH,0BFH,07FH
GRAPH: DB 12H,14H,3CH,48H,3CH,14H,12H,00H
DB 00H,00H,38H,44H,44H,44H,38H,00H
DB 30H,48H,44H,22H,44H,48H,30H,00H
6. C 语言源程序
#include &AT89X52.H&
unsigned char code tab[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; unsigned char code
graph[3][8]={{0x12,0x14,0x3c,0x48,0x3c,0x14,0x12,0x00},
{0x00,0x00,0x38,0x44,0x44,0x44,0x38,0x00},
{0x30,0x48,0x44,0x22,0x44,0x48,0x30,0x00}
void main(void)
unsigned char i,j;
TMOD=0x01;
TH0=()/256;
TL0=()%256;
if(P2_0==0)
for(i=5;i&0;i--)
for(j=248;j&0;j--);
if(P2_0==0)
if(count==3)
while(P2_0==0);
void t0(void) interrupt 1 using 0
TH0=()/256;
TL0=()%256;
P3=tab[cnta];
P1=graph[count][cnta];
if(cnta==8)
27. ADC0809A/D 转换器基本应用技术
1. 基本知识
ADC0809 是带有 8 位 A/D 转换器、8 路多路开关以及微处理机兼容的控制逻 辑的 CMOS 组件。它是逐次逼近式 A/D 转换器,可以和单片机直接接口。
139(1). ADC0809 的内部逻辑结构
由上图可知,ADC0809 由一个 8 路模拟开关、一个地址锁存与译码器、一个 A/D 转换器和一个三态输出锁存器组成。多路开关可选通 8 个模拟通道,允许 8 路模 拟量分时输入,共用 A/D 转换器进行转换。三态输出锁器用于锁存 A/D 转换完的 数字量,当 OE 端为高电平时,才可以从三态输出锁存器取走转换完的数据。
(2). 引脚结构
IN0-IN7:8 条模拟量输入通道
ADC0809 对输入模拟量要求:信号单极性,电压范围是 0-5V,若信号太小,必 须进行放大;输入的模拟量在转换过程中应该保持不变,如若模拟量变化太快, 则需在输入前增加采样保持电路。
地址输入和控制线:4 条
ALE 为地址锁存允许输入线,高电平有效。当 ALE 线为高电平时,地址锁存与译 码器将 A,B,C 三条地址线的地址信号进行锁存,经译码后被选中的通道的模拟 量进转换器进行转换。A,B 和 C 为地址输入线,用于选通 IN0-IN7 上的一路模 拟量输入。通道选择表如下表所示。
数字量输出及控制线:11 条
ST 为转换启动信号。当 ST 上跳沿时,所有内部寄存器清零;下跳沿时,开始进 行 A/D 转换;在转换期间,ST 应保持低电平。EOC 为转换结束信号。当 EOC 为高 电平时,表明转换结束;否则,表明正在进行 A/D 转换。OE 为输出允许信号, 用于控制三条输出锁存器向单片机输出转换得到的数据。OE=1,输出转换得到 的数据;OE=0,输出数据线呈高阻状态。D7-D0 为数字量输出线。
CLK 为时钟输入信号线。因 ADC0809 的内部没有时钟电路,所需时钟信号必须由 外界提供,通常使用频率为 500KHZ,
VREF(+),VREF(-)为参考电压输入。
2. ADC0809 应用说明
(1). ADC0809 内部带有输出锁存器,可以与 AT89S51 单片机直接相连。
(2). 初始化时,使 ST 和 OE 信号全为低电平。
(3). 送要转换的哪一通道的地址到 A,B,C 端口上。
(4). 在 ST 端给出一个至少有 100ns 宽的正脉冲信号。
(5). 是否转换完毕,我们根据 EOC 信号来判断。
(6). 当 EOC 变为高电平时,这时给 OE 为高电平,转换的数据就输出给单
3. 实验任务
如下图所示,从ADC0809 的通道 IN3 输入 0-5V 之间的模拟量,通过 ADC0809 转换成数字量在数码管上以十进制形成显示出来。ADC0809 的 VREF 接+5V 电压。
4. 电路原理图
5. 系统板上硬件连线
(1). 把“单片机系统板”区域中的 P1 端口的 P1.0-P1.7 用 8 芯排线连
接到“动态数码显示”区域中的 A B C D E F G H 端口上,作为数码 管的笔段驱动。
(2). 把“单片机系统板”区域中的 P2 端口的 P2.0-P2.7 用 8 芯排线连
接到“动态数码显示”区域中的 S1 S2 S3 S4 S5 S6 S7 S8 端口上 , 作为数码管的位段选择。
(3). 把“单片机系统板”区域中的 P0 端口的 P0.0-P0.7 用 8 芯排线连
接到“模数转换模块”区域中的 D0D1D2D3D4D5D6D7 端口上,A/D 转换 完毕的数据输入到单片机的 P0 端口
(4). 把“模数转换模块”区域中的 VREF 端子用导线连接到“电源模块”
区域中的 VCC 端子上;
(5). 把“模数转换模块”区域中的 A2A1A0 端子用导线连接到“单片机
系统”区域中的 P3.4 P3.5 P3.6 端子上;
(6). 把“模数转换模块”区域中的 ST 端子用导线连接到“单片机系统”
区域中的 P3.0 端子上;
(7). 把“模数转换模块”区域中的 OE 端子用导线连接到“单片机系统”
区域中的 P3.1 端子上; (8). 把“模数转换模块”区域中的 EOC 端子用导线连接到“单片机系统”
区域中的 P3.2 端子上;
(9). 把“模数转换模块”区域中的 CLK 端子用导线连接到“分频模块”
区域中的 /4 端子上;
(10). 把“分频模块”区域中的 CK IN 端子用导线连接到“单片机系统”
区域中的 ALE 端子上;
(11). 把“模数转换模块”区域中的 IN3 端子用导线连接到“三路可调
压模块”区域中的 VR1 端子上;
6. 程序设计内容
(1). 进行 A/D 转换时,采用查询 EOC 的标志信号来检测 A/D 转换是
否完毕,若完毕则把数据通过 P0 端口读入,经过数据处理之后在 数码管上显示。
(2). 进行 A/D 转换之前,要启动转换的方法:
ABC=110 选择第三通道
ST=0,ST=1,ST=0 产生启动转换的正脉冲信号
7. 汇编源程序
CH EQU 30H DPCNT EQU 31H DPBUF EQU 33H GDATA EQU 32H ST BIT P3.0 OE BIT P3.1 EOC BIT P3.2
ORG 00H LJMP START ORG 0BH LJMP T0X ORG 30H
START: MOV CH,#0BCH MOV DPCNT,#00H MOV R1,#DPCNT MOV R7,#5
MOV R0,#DPBUF
LOP: MOV @R0,A
DJNZ R7,LOP
MOV @R0,#00H
MOV @R0,#00H
MOV @R0,#00H
MOV TMOD,#01H
MOV TH0,#()/256
MOV TL0,#() MOD 256
WT: CLR ST
WAIT: JNB EOC,WAIT
MOV GDATA,P0
MOV A,GDATA
MOV B,#100
MOV TH0,#()/256
MOV TL0,#() MOD 256
MOV DPTR,#DPCD
MOV A,DPCNT
ADD A,#DPBUF
MOVC A,@A+DPTR
MOV DPTR,#DPBT
MOV A,DPCNT
MOVC A,@A+DPTR
MOV A,DPCNT
CJNE A,#8,NEXT
MOV DPCNT,#00H
NEXT: RETI
DPCD: DB 3FH,06H,5BH,4FH,66H
DB 6DH,7DH,07H,7FH,6FH,00H
DPBT: DB 0FEH,0FDH,0FBH,0F7H
DB 0EFH,0DFH,0BFH,07FH
8. C 语言源程序
#include &AT89X52.H&
unsigned char code dispbitcode[]={0xfe,0xfd,0xfb,0xf7,
0xef,0xdf,0xbf,0x7f};
unsigned char code dispcode[]={0x3f,0x06,0x5b,0x4f,0x66,
0x6d,0x7d,0x07,0x7f,0x6f,0x00};
unsigned char dispbuf[8]={10,10,10,10,10,0,0,0};
sbit ST=P3^0;
sbit OE=P3^1;
sbit EOC=P3^2;
unsigned char channel=0//IN3
void main(void)
TMOD=0x01;
TH0=()/256;
TL0=()%256;
while(EOC==0);
getdata=P0;
dispbuf[2]=getdata/100;
getdata=getdata%10;
dispbuf[1]=getdata/10;
dispbuf[0]=getdata%10;
void t0(void) interrupt 1 using 0
TH0=()/256;
TL0=()%256;
P1=dispcode[dispbuf[dispcount]];
P2=dispbitcode[dispcount];
dispcount++;
if(dispcount==8)
dispcount=0;
28. 数字电压表
1. 实验任务
利用单片机 AT89S51 与 ADC0809 设计一个数字电压表,能够测量 0-5V 之间 的直流电压值,四位数码显示,但要求使用的元器件数目最少。
2. 电路原理图 146
3. 系统板上硬件连线
a) 把“单片机系统”区域中的 P1.0-P1.7 与“动态数码显示”区域中的
ABCDEFGH 端口用 8 芯排线连接。
b) 把“单片机系统”区域中的 P2.0-P2.7 与“动态数码显示”区域中的
S1S2S3S4S5S6S7S8 端口用 8 芯排线连接。
c) 把“单片机系统”区域中的 P3.0 与“模数转换模块”区域中的 ST 端子
用导线相连接。
d) 把“单片机系统”区域中的 P3.1 与“模数转换模块”区域中的 OE 端子
用导线相连接。
e) 把“单片机系统”区域中的 P3.2 与“模数转换模块”区域中的 EOC 端子
用导线相连接。
f) 把“单片机系统”区域中的 P3.3 与“模数转换模块”区域中的 CLK 端子
用导线相连接。
g) 把“模数转换模块”区域中的 A2A1A0 端子用导线连接到“电源模块”区
域中的 GND 端子上。
h) 把“模数转换模块”区域中的 IN0 端子用导线连接到“三路可调电压模
块”区域中的 VR1 端子上。
i) 把“单片机系统”区域中的 P0.0-P0.7 用 8 芯排线连接到“模数转换模
块”区域中的 D0D1D2D3D4D5D6D7 端子上。
4. 程序设计内容
i. 由于 ADC0809 在进行 A/D 转换时需要有 CLK 信号,而此时的 ADC0809
的 CLK 是接在 AT89S51 单片机的 P3.3 端口上,也就是要求从 P3.3 输出 CLK 信号供 ADC0809 使用。因此产生 CLK 信号的方法就得用软 件来产生了。
ii. 由于 ADC0809 的参考电压 VREF=VCC,所以转换之后的数据要经过
数据处理,在数码管上显示出电压值。实际显示的电压值
(D/256*VREF)
5. 汇编源程序
6. C 语言源程序
#include &AT89X52.H&
unsigned char code dispbitcode[]={0xfe,0xfd,0xfb,0xf7,
0xef,0xdf,0xbf,0x7f};
unsigned char code dispcode[]={0x3f,0x06,0x5b,0x4f,0x66,
0x6d,0x7d,0x07,0x7f,0x6f,0x00};
unsigned char dispbuf[8]={10,10,10,10,0,0,0,0};
void main(void) 148
TMOD=0x12;
TH1=()/256;
TL1=()%256;
if(EOC==1)
getdata=P0;
temp=getdata*235;
temp=temp/128;
dispbuf[0]=10;
dispbuf[1]=10;
dispbuf[2]=10;
dispbuf[3]=10;
dispbuf[4]=10;
dispbuf[5]=0;
dispbuf[6]=0;
dispbuf[7]=0;
while(temp/10)
dispbuf[i]=temp%10;
temp=temp/10;
dispbuf[i]=
void t0(void) interrupt 1 using 0
void t1(void) interrupt 3 using 0
TH1=()/256;
TL1=()%256;
P1=dispcode[dispbuf[dispcount]];
P2=dispbitcode[dispcount];
if(dispcount==7)
P1=P1 | 0x80;
dispcount++;
if(dispcount==8)
dispcount=0;
29. 两点间温度控制
1. 实验任务
用可调电阻调节电压值作为模拟温度的输入量,当温度低于 30℃时,发出长 嘀报警声和光报警,当温度高于 60℃时,发出短嘀报警声和光报警。测量的 温度范围在 0-99℃。
2. 电路原理图 150
3. 系统板上硬件连线
a) 把“单片机系统”区域中的 P1.0-P1.7 与“动态数码显示”区域中的
ABCDEFGH 端口用 8 芯排线连接。
b) 把“单片机系统”区域中的 P2.0-P2.7 与“动态数码显示”区域中的
S1S2S3S4S5S6S7S8 端口用 8 芯排线连接。
c) 把“单片机系统”区域中的 P3.0 与“模数转换模块”区域中的 ST 端子
用导线相连接。
151d) 把“单片机系统”区域中的 P3.1 与“模数转换模块”区域中的 OE 端子
用导线相连接。
e) 把“单片机系统”区域中的 P3.2 与“模数转换模块”区域中的 EOC 端子
用导线相连接。
f) 把“单片机系统”区域中的 P3.3 与“模数转换模块”区域中的 CLK 端子
用导线相连接。
g) 把“模数转换模块”区域中的 A2A1A0 端子用导线连接到“电源模块”区
域中的 GND 端子上。
h) 把“模数转换模块”区域中的 IN0 端子用导线连接到“三路可调电压模
块”区域中的 VR1 端子上。
i) 把“单片机系统”区域中的 P0.0-P0.7 用 8 芯排线连接到“模数转换模
块”区域中的 D0D1D2D3D4D5D6D7 端子上。
j) 把“单片机系统”区域中的 P3.6、P3.7 用导线分别连接到“八路发光二
极管指示模块”区域中的 L1、L2 上。
k) 把“单片机系统”区域中的 P3.5 用导线连接到“音频放大模块”区域中
的 SPK IN 端口上。
l) 把“音频放大模块“区域中的 SPK OUT 插入音频喇叭。
4. 汇编源程序
5.C 语言源程序
#include &AT89X52.H&
unsigned char code dispbitcode[]={0xfe,0xfd,0xfb,}

我要回帖

更多关于 模二数 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信