注意:要加上延时消抖功能(我对这个的理解:消抖是消除键盘的抖动,即假性按下键盘;延时是对键长按时,要延时等待键释放,再进行下一步处理)
ORG 0000H
LJMP START
ORG 0030H
START:MOV P0,#0FEH
MOV P2,#0FEH
START0:MOV P1,#0FFH ;读P1口:首先向P1口送1,为读P1口做准备
MOV A,P1
CJNE A,#0FFH,START1 ;判断是否有键按下
AJMP NEXT
START1:ACALL DELAY0 ;延时20ms消抖
MOV P1,#0FFH
MOV A,P1
CJNE A,#0FFH,JP1 ;再次确认是否真的有键按下
AJMP NEXT
JP1:JNB ACC.4,LP1
JNB ACC.5,LP2
JNB ACC.6,LP3
JNB ACC.7,LP4
SJMP NEXT
LP1:MOV A,P0
RR A
MOV P0,A
SJMP NEXT
LP2:MOV A,P0
RL A
MOV P0,A
SJMP NEXT
LP3:MOV A,P2
RR A
MOV P2,A
SJMP NEXT
LP4:MOV A,P2
RL A
MOV P2,A
NEXT:MOV P1,#0FFH
MOV A,P1 ;再读P1的引脚
CJNE A,#0FFH,NEXT ;确认键是否释放,若没释放,则等待键释放
SJMP START0
DELAY0:MOV R2,#70 ;20ms消抖子程序
D01: MOV R3,#100
D02: DJNZ R3,D02
DJNZ R2,D01
RET
END
#include //定义特殊功能寄存器和位寄存器
#include //定义本征库函数,需要使用库中循环左右移位的函数
#define uchar unsigned char
#define uint unsigned int
sbit L_UP = P1^4; //定义按键
sbit L_DOWN = P1^5;
sbit R_UP = P1^6;
sbit R_DOWN = P1^7;
void delay(uint x) //定义延时xms函数
{
uchar i;
while(x--)
{
for(i = 0; i < 120; i++);
}
}
int judge_ac() //定义判断按键是否按下函数
{
if(P1 != 0xFF) return 1; //有键按下
else return 0; //无键按下或者键已释放
}
void main()
{
P0 = 0xFE;P2 = 0xFE; //初始化P0和P2,让第一个灯亮起来
while(1)
{
if(judge_ac()) //有键按下
{
delay(20); //延时20ms消抖
if(judge_ac()) //判断是否真的有键按下
{
if(!L_UP) P0 = _cror_(P0,1);
else if(!L_DOWN) P0 = _crol_(P0,1);
else if(!R_UP) P2 = _cror_(P2,1);
else if(!R_DOWN) P2 = _crol_(P2,1);
while(judge_ac()); //等待键释放
}
}
}
}
注意:在C中用循环位移函数的话,必须要声明本征库函数intrins;且循环位移函数应该使用char型,不是int型