设计一款显示按键序列号的电子键盘,要求如下:
1、设计一个电子键盘,利用给定键盘的8个键发出8种不同的音调,并在LED数码管上显示相应的音调。
2、要求按下按钮发出声音,延时一段时间后松开停止; 如果在前一个按键发声时按下另一个键,前一个按键的声音将停止,后一个按键的声音将开始。
3. 控制按钮简单。
电路设计
如图所示:
电子键盘有8个按钮,每个按钮代表8个音符,分别连接到P3口的8个接口。 共阳极数码管连接到P2端口,声音模块连接到P1.4端口。
编程
我们可以利用单片机的定时器/计数器T0来产生不同频率的方波信号。 每个按钮对应不同的定时器预设值和不同的提示音。
先说一下定时器中断的理解:CPU执行一个机器周期时,最后会自动检查中断是否打开,即每隔几微秒检查一次中断是否打开。 当我们的按钮按下时,TR0置1,中断打开,CPU检测到,调用我们的中断服务程序,并给定时器的高低8位分配一个时间预设值。 时间预设值到达定时器结束。 扬声器没有接收到电压的一段时间。 当定时时间到时,调用CPL P1.4将扬声器接口反转,即给扬声器接口分配高电平。 在中断服务程序中重新分配高八位和低八位。 由于按钮仍然按下并且中断仍然打开,因此重新安装中断服务程序并继续计时。 在此期间,扬声器接口有电压。 定时器结束后,反转,扬声器接口给低电平。 由于CPU执行指令的速度非常快,因此在预设值期间会产生高电平节拍,在定时期间会产生低电平节拍。 这是频率,因为我们定义每个按钮的预设值不同,节拍不同,频率不同,电压的占空比不同,所以可以通过PWM来调节蜂鸣器,所以不同的音调被生产。
定义一个按键扫描函数,在主程序中不断调用按键扫描函数来检测是否有按键被按下。 8个按钮对应8种情况,每种情况有7种按下第二个键的情况。 通过将所有高电平分配给P3端口,当按下按钮时,接口将变为低电平。 当检测到接口为低电平时,循环判断自身接口是否变为高电平。 如果一直按下该键,则一直为低电平,并处于循环状态。 循环过程中,判断是否有其他接口变为低电平。 如果有其他接口变为低电平,则重新分配定时器的高八位和第八位,从而达到同时按下第二位的目的。 当按下该键时,会发出第二个按键的提示音; 如果松开按键,则跳出循环,并调用延迟1s的函数,实现延迟播放功能。 然后关闭中断。 一旦中断设置为0,中断就结束。 扬声器接口将不再倒置,也不会产生频率。 不过,此时的扬声器接口可能处于高电平。 调用延迟函数后,扬声器接口必须设置为0。 ,关闭声音。
实际焊接情况如下:
C语言编程
#include//包含头文件
#define uint unsigned int
#define uchar unsigned char//宏定义
//喇叭引脚定义
sbit speaker=P1^4;
//按钮引脚定义
sbit key1 = P3^0;
sbit key2 = P3^1;
sbit key3 = P3^2;
sbit key4 = P3^3;
sbit key5 = P3^4;
sbit key6 = P3^5;
sbit key7 = P3^6;
sbit key8 = P3^7;
//声明两个无符号字符型变量,用于定时器初值的赋值
uchar a;
uchar b;
//延时函数(用于按键松开后延时播放音调)
void delay(uint temp)
{
uint i, j;
for (i = 0; i <= temp; i++)
for (j = 0; j <= 120; j++);
}
void check_key()
{
P3=0xff;//先赋给P3组口高电平
switch(P3)//当有按键按下,P3口的状态就会改变
{
case 0xfe: //11111110,第一次扫描到按键1
P2 = 0xfc; //11111100 数字1
a = 0xfb; //高八位赋时间预设值
b = 0xe9; //低八位赋时间预设值
EA = 1; //开中断
//发声按下的第二个按键(按下第一个按键的后同时按第二个键,发声第二个键的音调)
//每个case里面循环判断自己的按键是否松开,如果一直被按着,则判断其他7个按键是否按下并改变中断的预初始值。
while (key1==0)
{
//先按1的同时再按下2
if(key2==0)
{
P2 = 0xa2;
a = 0xfc;
b = 0x5c;
}
//先按1的同时再按下3
if (key3 == 0)
{
P2 = 0xb0;
a = 0xfc;
b = 0xc1;
}
//先按1的同时再按下4
if (key4 == 0)
{
P2 = 0x9c;
a = 0xfc;
b = 0xef;
}
//先按1的同时再按下5
if (key5 == 0)
{
P2 = 0x91;
a = 0xfd;
b = 0x45;
}
//先按1的同时再按下6
if (key6 == 0)
{
P2 = 0x81;
a = 0xfd;
b = 0x92;
}
//先按1的同时再按下7
if (key7 == 0)
{
P2 = 0xf8;
a = 0xfd;
b = 0xd0;
}
//先按1的同时再按下8
if (key8 == 0)
{
P2 = 0x80;
a = 0xfd;
b = 0xee;
}
}
//当按键1松开
P2= 0xff; //数码管不显示
delay(800);//延时一段时间
EA = 0; //关中断
speaker = 0; //关声音
break;//当第一个按键按下,P3口状态就是11111110,也就是0xfe,就执行后面的P2口点亮对应的LED,并给定时器赋初值,打开中断系统总开关
case 0xfd: //11111101,当按下按键2
P2=0xa2; //10100010 ,数码管显示数字2
a=0xfc;
b=0x5c;
EA=1;
while (key2 == 0)
{
//先按2的同时再按下1
if(key1 == 0)
{
P2 = 0xfc;
a = 0xfb;
b = 0xe9;
}
//先按2的同时再按下3
if (key3 == 0)
{
P2 = 0xb0;
a = 0xfc;
b = 0xc1;
}
//先按2的同时再按下4
if (key4 == 0)
{
P2 = 0x9c;
a = 0xfc;
b = 0xef;
}
//先按2的同时再按下5
if (key5 == 0)
{
P2 = 0x91;
a = 0xfd;
b = 0x45;
}
//先按2的同时再按下6
if (key6 == 0)
{
P2 = 0x81;
a = 0xfd;
b = 0x92;
}
//先按2的同时再按下7
if (key7 == 0)
{
P2 = 0xf8;
a = 0xfd;
b = 0xd0;
}
//先按2的同时再按下8
if (key8 == 0)
{
P2 = 0x80;
a = 0xfd;
b = 0xee;
}
}
//当按键2松开
P2 = 0xff; //数码管不显示
delay(800);//延时一段时间
EA = 0; //关中断
speaker = 0; //关声音
break;
case 0xfb: //11111011
P2=0xb0; //10110000 数字3
a=0xfc;
b=0xc1;
EA=1;
while (key3 == 0)
{
//先按3的同时再按下1
if(key1 == 0)
{
P2 = 0xfc;
a = 0xfb;
b = 0xe9;
}
//先按3的同时再按下2
if(key2 == 0)
{
P2 = 0xa2;
a = 0xfc;
b = 0x5c;
}
//先按3的同时再按下4
if (key4 == 0)
{
P2 = 0x9c;
a = 0xfc;
b = 0xef;
}
//先按3的同时再按下5
if (key5 == 0)
{
P2 = 0x91;
a = 0xfd;
b = 0x45;
}
//先按3的同时再按下6
if (key6 == 0)
{
P2 = 0x81;
a = 0xfd;
b = 0x92;
}
//先按3的同时再按下7
if (key7 == 0)
{
P2 = 0xf8;
a = 0xfd;
b = 0xd0;
}
//先按3的同时再按下8
if (key8 == 0)
{
P2 = 0x80;
a = 0xfd;
b = 0xee;
}
}
//当按键3松开
P2 = 0xff; //数码管不显示
delay(800);//延时一段时间
EA = 0; //关中断
speaker = 0; //关声音
break;//同上
case 0xf7: //11110111
P2=0x9c; //10011100 数字4
a=0xfc;
b=0xef;
EA=1;
while (key4 == 0)
{
//先按4的同时再按下1
if(key1 == 0)
{
P2 = 0xfc;
a = 0xfb;
b = 0xe9;
}
//先按4的同时再按下2
if(key2 == 0)
{
P2 = 0xa2;
a = 0xfc;
b = 0x5c;
}
//先按4的同时再按下3
if (key3 == 0)
{
P2 = 0xb0;
a = 0xfc;
b = 0xc1;
}
//先按4的同时再按下5
if (key5 == 0)
{
P2 = 0x91;
a = 0xfd;
b = 0x45;
}
//先按4的同时再按下6
if (key6 == 0)
{
P2 = 0x81;
a = 0xfd;
b = 0x92;
}
//先按4的同时再按下7
if (key7 == 0)
{
P2 = 0xf8;
a = 0xfd;
b = 0xd0;
}
//先按4的同时再按下8
if (key8 == 0)
{
P2 = 0x80;
a = 0xfd;
b = 0xee;
}
}
//当按键4松开
P2 = 0xff; //数码管不显示
delay(800);//延时一段时间
EA = 0; //关中断
speaker = 0; //关声音
break;
case 0xef: //11101111,当按下按键5
P2=0x91; //10010001 ,数码管显示数字5
a=0xfd;
b=0x45;
EA=1;
while (key5 == 0)
{
//先按5的同时再按下1
if(key1 == 0)
{
P2 = 0xfc;
a = 0xfb;
b = 0xe9;
}
//先按5的同时再按下2
if(key2 == 0)
{
P2 = 0xa2;
a = 0xfc;
b = 0x5c;
}
//先按5的同时再按下3
if (key3 == 0)
{
P2 = 0xb0;
a = 0xfc;
b = 0xc1;
}
//先按5的同时再按下4
if (key4 == 0)
{
P2 = 0x9c;
a = 0xfc;
b = 0xef;
}
//先按5的同时再按下6
if (key6 == 0)
{
P2 = 0x81;
a = 0xfd;
b = 0x92;
}
//先按5的同时再按下7
if (key7 == 0)
{
P2 = 0xf8;
a = 0xfd;
b = 0xd0;
}
//先按5的同时再按下8
if (key8 == 0)
{
P2 = 0x80;
a = 0xfd;
b = 0xee;
}
}
//当按键5松开
P2 = 0xff; //数码管不显示
delay(800);//延时一段时间
EA = 0; //关中断
speaker = 0; //关声音
break;//P2组为发光二极管组
case 0xdf: //11011111,当按下按键6
P2=0x81; //10000001 ,数码管显示数字6
a=0xfd;
b=0x92;
EA=1;
while (key6 == 0)
{
//先按6的同时再按下1
if(key1 == 0)
{
P2 = 0xfc;
a = 0xfb;
b = 0xe9;
}
//先按6的同时再按下2
if(key2 == 0)
{
P2 = 0xa2;
a = 0xfc;
b = 0x5c;
}
//先按6的同时再按下3
if (key3 == 0)
{
P2 = 0xb0;
a = 0xfc;
b = 0xc1;
}
//先按6的同时再按下4
if (key4 == 0)
{
P2 = 0x9c;
a = 0xfc;
b = 0xef;
}
//先按6的同时再按下5
if (key5 == 0)
{
P2 = 0x91;
a = 0xfd;
b = 0x45;
}
//先按6的同时再按下7
if (key7 == 0)
{
P2 = 0xf8;
a = 0xfd;
b = 0xd0;
}
//先按6的同时再按下8
if (key8 == 0)
{
P2 = 0x80;
a = 0xfd;
b = 0xee;
}
}
//当按键6松开
P2 = 0xff; //数码管不显示
delay(800);//延时一段时间
EA = 0; //关中断
speaker = 0; //关声音
break;//注意:EA不能改为TR0
case 0xbf: //10111111,当按下按钮7
P2=0xf8; //11111000 ,数码管显示数字7
a=0xfd;
b=0xd0;
EA=1;
while (key7 == 0)
{
//先按7的同时再按下1
if(key1 == 0)
{
P2 = 0xfc;
a = 0xfb;
b = 0xe9;
}
//先按7的同时再按下2
if(key2 == 0)
{
P2 = 0xa2;
a = 0xfc;
b = 0x5c;
}
//先按7的同时再按下3
if (key3 == 0)
{
P2 = 0xb0;
a = 0xfc;
b = 0xc1;
}
//先按7的同时再按下4
if (key4 == 0)
{
P2 = 0x9c;
a = 0xfc;
b = 0xef;
}
//先按7的同时再按下5
if (key5 == 0)
{
P2 = 0x91;
a = 0xfd;
b = 0x45;
}
//先按7的同时再按下6
if (key6 == 0)
{
P2 = 0x81;
a = 0xfd;
b = 0x92;
}
//先按7的同时再按下8
if (key8 == 0)
{
P2 = 0x80;
a = 0xfd;
b = 0xee;
}
}
//当按键7松开
P2 = 0xff; //数码管不显示
delay(800);//延时一段时间
EA = 0; //关中断
speaker = 0; //关声音
break;
case 0x7f: //11111111,当按下按钮8
P2=0x80; //10000000, 数码管显示数字8
a=0xfd;
b=0xee;
EA=1;
while (key8 == 0)
{
//先按8的同时再按下1
if(key1 == 0)
{
P2 = 0xfc;
a = 0xfb;
b = 0xe9;
}
//先按8的同时再按下2
if(key2 == 0)
{
P2 = 0xa2;
a = 0xfc;
b = 0x5c;
}
//先按8的同时再按下3
if (key3 == 0)
{
P2 = 0xb0;
a = 0xfc;
b = 0xc1;
}
//先按8的同时再按下4
if (key4 == 0)
{
P2 = 0x9c;
a = 0xfc;
b = 0xef;
}
//先按8的同时再按下5
if (key5 == 0)
{
P2 = 0x91;
a = 0xfd;
b = 0x45;
}
//先按8的同时再按下6
if (key6 == 0)
{
P2 = 0x81;
a = 0xfd;
b = 0x92;
}
//先按8的同时再按下7
if (key7 == 0)
{
P2 = 0xf8;
a = 0xfd;
b = 0xd0;
}
}
//当按键8松开
P2 = 0xff; //数码管不显示
delay(800);//延时一段时间
EA = 0; //关中断
speaker = 0; //关声音
break;
//当什么都没按下
default:
EA=0;
speaker=0;
P2=0xff;//当P3口为其他状态时(包括无按键按下和多按键按下)关闭声音输出和LED
}
}
//中断初始化函数
void init()
{
TMOD=0x01;//定时器工作方式1
TH0=a;//定时器0初值的高八位
TL0=b;//定时器0初值的低八位
ET0=1;//允许中断
TR0=1;//打开定时器
EA=0;
}
//主函数
void main()
{
init();
while(1)//进入循环
{
check_key();//扫描按键
}
}
//中断服务程序
void time0() interrupt 1//定时器工作函数
{
TH0=a;//定时器高八位赋初值
TL0=b;//定时器低八位赋初值
speaker=~speaker;//喇叭引脚取反
}
汇编编程
ORG 0000H
AJMP INIT ;初始化程序
ORG 00BH
AJMP INQP ;中断程序
ORG 0030H
;初始化
INIT: MOV TMOD,#01H ;设置定时器工作方式1
SETB ET0
SETB TR0
CLR EA
;主程序
LOOP: LCALL CHECK ;调用按键扫描程序
SJMP LOOP ;循环
;按键检查函数
CHECK: MOV P3,#0FFH
;如果按键被按下,则跳转到相应的CASE
JNB P3.0,CASE1
JNB P3.1,CASE2
JNB P3.2,CASE3
JNB P3.3,CASE4
JNB P3.4,CASE5
JNB P3.5,CASE6
JNB P3.6,CASE7
JNB P3.7,CASE8
LJMP None
RET
;由于JNB指令只能跳转到-128~128B之间,所以用CASE的程序LJMP过渡到KEY来执行
CASE1: LJMP KEY1
RET
CASE2: LJMP KEY2
RET
CASE3: LJMP KEY3
RET
CASE4: LJMP KEY4
RET
CASE5: LJMP KEY5
RET
CASE6: LJMP KEY6
RET
CASE7: LJMP KEY7
RET
CASE8: LJMP KEY8
RET
;扫描到按键1被按下
KEY1: MOV P2,#0FCH ;数码管显示数字1
MOV R0,#0FBH ;定时器高八位赋值
MOV R1,#0E9H ;定时器低八位赋值
SETB EA ;打开中断,播放声音
;函数名First表示第一个按键被按下,后面的数字是是否有其他按键被按下
First1: JB P3.0,Disable1 ;判断当前按键是否松开,如果松开跳转到DISABLE1函数(延时和关中断)
;在第一个按键被按下的情况下判断其他按键是否被按下
;判断第二个按键是否被按下
JB P3.1,First3 ;如果没有被按下则跳到判断下一个按键的函数
MOV P2,#0A2H ;如果第二个按键被按下,数码管显示数字2
MOV R0,#0FCH ;中断预设值赋值
MOV R1,#05CH ;之后循序执行到SJMP First1,再次不断循环自己判断
;判断第三个按键是否被按下
First3: JB P3.2,First4 ;如果没有被按下则跳到判断下一个按键的函数
MOV P2,#0B0H ;如果第3个按键被按下,数码管显示数字3
MOV R0,#0FCH ;中断预设值赋值
MOV R1,#0C1H ;之后循序执行到SJMP CASE1,再次不断循环自己判断
;判断第四个按键是否被按下
First4: JB P3.3,First5 ;与上面一样
MOV P2,#09CH
MOV R0,#0FCH
MOV R1,#0EFH
;判断第五个按键是否被按下
First5: JB P3.4,First6
MOV P2,#091H
MOV R0,#0FDH
MOV R1,#045H
;判断第六个按键是否被按下
First6: JB P3.5,First7
MOV P2,#081H
MOV R0,#0FDH
MOV R1,#092H
;判断第七个按键是否被按下
First7: JB P3.6,First8
MOV P2,#0F8H
MOV R0,#0FDH
MOV R1,#0D0H
;判断第八个按键是否被按下
First8: JB P3.7,First1 ;如果第8个键也没有被按下,则跳转到First1循环重新执行
MOV P2,#080H
MOV R0,#0FDH
MOV R1,#0EEH
;循环扫描自己的按键
SJMP First1
;JB指令只能跳转到-128~123B直接,所以用DISABLE1过渡到DISABLE来延时声音与清除
Disable1: LJMP Disable ;按键松开,调用关闭声音和中断和延时
RET
;扫描到按键2被按下
KEY2: MOV P2,#0A2H ;数码管显示数字2
MOV R0,#0FCH ;定时器高八位赋值
MOV R1,#05CH ;定时器低八位赋值
SETB EA ;打开中断,播放声音
Second2: JB P3.1,Disable2 ;判断当前按键是否松开,如果松开跳转到Disable2函数(延时和关中断)
;在第二个按键被按下的情况下判断其他按键是否被按下
;判断第1个按键是否被按下
JB P3.0,Second3
MOV P2,#0FCH
MOV R0,#0FBH
MOV R1,#0E9H
;判断第3个按键是否被按下
Second3: JB P3.2,Second4
MOV P2,#0B0H
MOV R0,#0FCH
MOV R1,#0C1H
;判断第4个按键是否被按下
Second4: JB P3.3,Second5
MOV P2,#09CH
MOV R0,#0FCH
MOV R1,#0EFH
;判断第5个按键是否被按下
Second5: JB P3.4,Second6
MOV P2,#091H
MOV R0,#0FDH
MOV R1,#045H
;判断第6个按键是否被按下
Second6: JB P3.5,Second7
MOV P2,#081H
MOV R0,#0FDH
MOV R1,#092H
;判断第7个按键是否被按下
Second7: JB P3.6,Second8
MOV P2,#0F8H
MOV R0,#0FDH
MOV R1,#0D0H
;判断第8个按键是否被按下
Second8: JB P3.7,Second2 ;如果第8个键也没有被按下,则跳转到Second2循环重新执行
MOV P2,#080H
MOV R0,#0FDH
MOV R1,#0EEH
;跳转到Second2循环重新执行
SJMP Second2
Disable2: LJMP Disable
RET
;扫描到按键3被按下
KEY3: MOV P2,#0B0H ;数码管显示数字3
MOV R0,#0FCH ;定时器高八位赋值
MOV R1,#0C1H ;定时器低八位赋值
SETB EA ;打开中断,播放声音
Third3: JB P3.2,Disable3
;在第三个按键被按下的情况下判断其他按键是否被按下
;判断第1个按键是否被按下
JB P3.0,Third2
MOV P2,#0FCH
MOV R0,#0FBH
MOV R1,#0E9H
;判断第2个按键是否被按下
Third2: JB P3.1,Third4
MOV P2,#0A2H
MOV R0,#0FCH
MOV R1,#05CH
;判断第4个按键是否被按下
Third4: JB P3.3,Third5
MOV P2,#09CH
MOV R0,#0FCH
MOV R1,#0EFH
;判断第5个按键是否被按下
Third5: JB P3.4,Third6
MOV P2,#091H
MOV R0,#0FDH
MOV R1,#045H
;判断第6个按键是否被按下
Third6: JB P3.5,Third7
MOV P2,#081H
MOV R0,#0FDH
MOV R1,#092H
;判断第7个按键是否被按下
Third7: JB P3.6,Third8
MOV P2,#0F8H
MOV R0,#0FDH
MOV R1,#0D0H
;判断第8个按键是否被按下
Third8: JB P3.7,Third3 ;如果第8个键也没有被按下,则跳转到Third3循环重新执行
MOV P2,#080H
MOV R0,#0FDH
MOV R1,#0EEH
;跳转到Third3循环重新执行
SJMP Third3
Disable3: LJMP Disable
RET
;扫描到按键4被按下
KEY4: MOV P2,#09CH
MOV R0,#0FCH
MOV R1,#0EFH
SETB EA
Forth4: JB P3.3,Disable4
;在第4个按键被按下的情况下判断其他按键是否被按下
;判断第1个按键是否被按下
JB P3.0,Forth2
MOV P2,#0FCH
MOV R0,#0FBH
MOV R1,#0E9H
;判断第2个按键是否被按下
Forth2: JB P3.1,Forth3
MOV P2,#0A2H
MOV R0,#0FCH
MOV R1,#05CH
;判断第3个按键是否被按下
Forth3: JB P3.2,Forth5
MOV P2,#0B0H
MOV R0,#0FCH
MOV R1,#0C1H
;判断第5个按键是否被按下
Forth5: JB P3.4,Forth6
MOV P2,#091H
MOV R0,#0FDH
MOV R1,#045H
;判断第6个按键是否被按下
Forth6: JB P3.5,Forth7
MOV P2,#081H
MOV R0,#0FDH
MOV R1,#092H
;判断第7个按键是否被按下
Forth7: JB P3.6,Forth8
MOV P2,#0F8H
MOV R0,#0FDH
MOV R1,#0D0H
;判断第8个按键是否被按下
Forth8: JB P3.7,Forth4 ;如果第8个键也没有被按下,则跳转到Forth4循环重新执行
MOV P2,#080H
MOV R0,#0FDH
MOV R1,#0EEH
SJMP Forth4
Disable4: LJMP Disable
RET
;扫描到按键5被按下
KEY5: MOV P2,#091H
MOV R0,#0FDH
MOV R1,#045H
SETB EA
Fifth5: JB P3.4,Disable5
;在第5个按键被按下的情况下判断其他按键是否被按下
;判断第1个按键是否被按下
JB P3.0,Fifth2
MOV P2,#0FCH
MOV R0,#0FBH
MOV R1,#0E9H
;判断第2个按键是否被按下
Fifth2: JB P3.1,Fifth3
MOV P2,#0A2H
MOV R0,#0FCH
MOV R1,#05CH
;判断第3个按键是否被按下
Fifth3: JB P3.2,Fifth4
MOV P2,#0B0H
MOV R0,#0FCH
MOV R1,#0C1H
;判断第4个按键是否被按下
Fifth4: JB P3.3,Fifth6
MOV P2,#09CH
MOV R0,#0FCH
MOV R1,#0EFH
;判断第6个按键是否被按下
Fifth6: JB P3.5,Fifth7
MOV P2,#081H
MOV R0,#0FDH
MOV R1,#092H
;判断第7个按键是否被按下
Fifth7: JB P3.6,Fifth8
MOV P2,#0F8H
MOV R0,#0FDH
MOV R1,#0D0H
;判断第8个按键是否被按下
Fifth8: JB P3.7,Fifth5
MOV P2,#080H
MOV R0,#0FDH
MOV R1,#0EEH
SJMP Fifth5
Disable5: LJMP Disable
RET
;扫描到按键6被按下
KEY6: MOV P2,#081H
MOV R0,#0FDH
MOV R1,#092H
SETB EA
Sixth6: JB P3.5,Disable6
;在第6个按键被按下的情况下判断其他按键是否被按下
;判断第1个按键是否被按下
JB P3.0,Sixth2
MOV P2,#0FCH
MOV R0,#0FBH
MOV R1,#0E9H
;判断第2个按键是否被按下
Sixth2: JB P3.1,Sixth3
MOV P2,#0A2H
MOV R0,#0FCH
MOV R1,#05CH
;判断第3个按键是否被按下
Sixth3: JB P3.2,Sixth4
MOV P2,#0B0H
MOV R0,#0FCH
MOV R1,#0C1H
;判断第4个按键是否被按下
Sixth4: JB P3.3,Sixth5
MOV P2,#09CH
MOV R0,#0FCH
MOV R1,#0EFH
;判断第5个按键是否被按下
Sixth5: JB P3.4,Sixth7
MOV P2,#091H
MOV R0,#0FDH
MOV R1,#045H
;判断第7个按键是否被按下
Sixth7: JB P3.6,Sixth8
MOV P2,#0F8H
MOV R0,#0FDH
MOV R1,#0D0H
;判断第8个按键是否被按下
Sixth8: JB P3.7,Sixth6
MOV P2,#080H
MOV R0,#0FDH
MOV R1,#0EEH
SJMP Sixth6
Disable6: LJMP Disable
RET
;扫描到按键7被按下
KEY7: MOV P2,#0F8H
MOV R0,#0FDH
MOV R1,#0D0H
SETB EA
Seventh7: JB P3.6,Disable7
;在第7个按键被按下的情况下判断其他按键是否被按下
;判断第1个按键是否被按下
JB P3.0,Seventh2
MOV P2,#0FCH
MOV R0,#0FBH
MOV R1,#0E9H
;判断第2个按键是否被按下
Seventh2: JB P3.1,Seventh3
MOV P2,#0A2H
MOV R0,#0FCH
MOV R1,#05CH
;判断第3个按键是否被按下
Seventh3: JB P3.2,Seventh4
MOV P2,#0B0H
MOV R0,#0FCH
MOV R1,#0C1H
;判断第4个按键是否被按下
Seventh4: JB P3.3,Seventh5
MOV P2,#09CH
MOV R0,#0FCH
MOV R1,#0EFH
;判断第5个按键是否被按下
Seventh5: JB P3.4,Seventh6
MOV P2,#091H
MOV R0,#0FDH
MOV R1,#045H
;判断第6个按键是否被按下
Seventh6: JB P3.5,Seventh8
MOV P2,#081H
MOV R0,#0FDH
MOV R1,#092H
;判断第8个按键是否被按下
Seventh8: JB P3.7,Seventh7
MOV P2,#080H
MOV R0,#0FDH
MOV R1,#0EEH
SJMP Seventh7
Disable7: SJMP Disable
RET
;扫描到按键8被按下
KEY8: MOV P2,#080H
MOV R0,#0FDH
MOV R1,#0EEH
SETB EA
Eighth8: JB P3.7,Disable8
;在第8个按键被按下的情况下判断其他按键是否被按下
;判断第1个按键是否被按下
JB P3.0,Eighth2
MOV P2,#0FCH
MOV R0,#0FBH
MOV R1,#0E9H
;判断第2个按键是否被按下
Eighth2: JB P3.1,Eighth3
MOV P2,#0A2H
MOV R0,#0FCH
MOV R1,#05CH
;判断第3个按键是否被按下
Eighth3: JB P3.2,Eighth4
MOV P2,#0B0H
MOV R0,#0FCH
MOV R1,#0C1H
;判断第4个按键是否被按下
Eighth4: JB P3.3,Eighth5
MOV P2,#09CH
MOV R0,#0FCH
MOV R1,#0EFH
;判断第5个按键是否被按下
Eighth5: JB P3.4,Eighth6
MOV P2,#091H
MOV R0,#0FDH
MOV R1,#045H
;判断第6个按键是否被按下
Eighth6: JB P3.5,Eighth7
MOV P2,#081H
MOV R0,#0FDH
MOV R1,#092H
;判断第7个按键是否被按下
Eighth7: JB P3.6,Eighth8
MOV P2,#0F8H
MOV R0,#0FDH
MOV R1,#0D0H
SJMP Eighth8
Disable8: SJMP Disable
RET
;没有按键被按下
None: CLR EA
CLR P1.4
MOV P2,#0FFH
RET
;延时1s子程序
DELAY: MOV R7,#10
DL1: MOV R6,#150
DL2: MOV R5,#200
DJNZ R5,$
DJNZ R6,DL2
DJNZ R7,DL1
RET
;当按下的键松开时调用此函数
Disable: MOV P2,#0FFH ;清除数码管的显示
LCALL DELAY ;调用延时函数,此时的中断仍然是打开的,即延时期间播放音调
CLR EA ;关闭中断
CLR P1.4 ;断开声音
RET
;中断服务程序
INQP: MOV TH0,R0
MOV TL0,R1
CPL P1.4
RETI
END