为什么PA按下相同的按键,PB对应的灯第二次不会灭
ORG 0000H
LJMP MAIN
ORG 0030H
MAIN:
MOV DPTR, #0FEFFH
MOV A, #90H
MOVX @DPTR, A
LOOP1:
MOV 90H,A
MOV DPTR, #3EFFH
MOVX A, @DPTR
CJNE A,#0FFH,LOOP
SJMP LOOP1
LOOP:
MOV DPTR, #3EFFH
MOVX A, @DPTR
CJNE A,90H,LOOP2
SJMP LOOP3
LOOP2:
CPL A
MOV DPTR,#7EFFH
MOVX @DPTR, A
SJMP LOOP1
LOOP3:
MOV A,#0H
MOV DPTR,#7EFFH
MOVX @DPTR, A
SJMP LOOP1
END
不知道你这个问题是否已经解决, 如果还没有解决的话:根据问题描述,相同的PA按键第二次按下后,控制的PB灯没有熄灭,这可能是由于第一次按下后没有及时清除相应的状态导致的。
解决方案: 1. 可以在按下每一个按键时,通过读取PA的状态来确定当前按下的是哪个按钮,然后将相应的PB灯点亮,同时记录状态。 2. 在按钮再次按下时,先读取PA的状态,如果当前状态与上一次相同,就将相应的PB灯熄灭,并清除状态记录。如果当前状态与上一次不同,则执行第一步中的操作,点亮相应的PB灯并记录状态。 3. 在程序结束时,将所有的PB灯熄灭。
代码示例:
// PA口接八个按钮,PB口输出八个LED灯
#include <reg51.h>
#define LedPort P2 // PB口连接的LED灯的地址
unsigned char keyValue = 0xff; // 记录上次按下的按钮状态
void delay(unsigned int i) //延迟函数,i为延迟时间,单位为ms
{
unsigned char j;
while(i--)
{
for(j = 0; j < 120; j++);
}
}
void clearLed() // 关闭所有的LED灯
{
LedPort = 0xff;
}
void main()
{
IE = 0x82; // 初始化中断
TMOD = 0x01;
TH0 = 0xfc; // 定时器初值
TL0 = 0x18; // 定时器初值
clearLed(); // 先关闭所有的LED灯
TR0 = 1; // 启动定时器
while(1)
{
// 在主循环中,等待按键的中断响应
}
}
void t0() interrupt 1 // 定时器中断响应函数
{
static unsigned int count = 0; // 统计定时器中断的次数
if(count == 50) // 1秒钟到达,开始执行任务
{
count = 0; // 计数器归零
clearLed(); // 先关闭所有的LED灯
}
count++;
}
void key() interrupt 0 // 按键中断响应函数
{
unsigned char keyPort = P1; // 读取按键输入的状态
keyValue = (!keyPort)&keyValue; // 确定当前按下的是哪个按钮,并记录状态
// 判断当前按下的是哪个按钮,从而确定点亮哪个LED灯
if(keyValue == 0xfe) LedPort = 0x7f;
else if(keyValue == 0xfd) LedPort = 0xbf;
else if(keyValue == 0xfb) LedPort = 0xdf;
else if(keyValue == 0xf7) LedPort = 0xef;
else if(keyValue == 0xef) LedPort = 0xf7;
else if(keyValue == 0xdf) LedPort = 0xfb;
else if(keyValue == 0xbf) LedPort = 0xfd;
else if(keyValue == 0x7f) LedPort = 0xfe;
}
如上所示,我们用了两个中断函数来实现该程序,其中一个是定时器中断,用于实现LED灯闪烁的效果,另一个是按键中断,用于响应用户的按键操作。通过这两个中断函数的配合,我们可以实现相应按键按下时控制相应的LED灯点亮,并记录下相应的状态,从而下一次按相同的按键时可以将LED灯熄灭并清楚相应的状态记录。最后,我们在程序结束时调用功能函数 clearLed
来关闭所有的LED灯。