51单片机接8255,PA输入外接八个按钮,控制PB输出外接八个LED

为什么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

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 以下回答来自chatgpt:

    根据问题描述,相同的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灯。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^