51单片机 按键控制LED状态

51单片机,单个按键按下弹起后,控制LED状态
ledmod==0 长灭
ledmod==1常亮
ledmod==2 呼吸灯
代码,如下,当到mod2的时候,呼吸灯亮了,但再按下键的时候,无法切换模式,
各位学霸帮说一说具体问题,修改下代码能正常执行

#include 
#include "Timer0.h"
void breath();
void Br_dy(unsigned int t)
{
    while(t--);
}

unsigned char Time,Speed;
void Delay(unsigned int xms)
{
    unsigned char i, j;
    while(xms)
    {
        i = 2;
        j = 239;
        do
        {
            while (--j);
        } while (--i);
        xms--;
    }
}

unsigned char ledmod=0,ledcount;
void main()
{
    Timer0Init();
    while(1)
    {
            if(P3_1==0)
            {
                Delay(50);
                while(P3_1==0);
                Delay(50);
                ledmod++;
            }
if(ledmod>=3)
                {
                    ledmod=0;
                }
            }
        
}

void Timer0_Routine() interrupt 1
{
    static unsigned int T0Count;
    TL0 = 0x18;        
    TH0 = 0xFC;        
    T0Count++;        
    if(ledmod==0)    
    {
        P2_0=1;    
    }        
            
    if(ledmod==1)
    {
        P2_0=0;
    }
    if(ledmod==2)
    {
        //ºôÎüµÆÄ£Ê½
        unsigned char Time,Speed;
    
        for(Time=0;Time<100;Time++)
        {
            for(Speed=0;Speed<20;Speed++)
            {
                P2_0=0;
                Br_dy(Time);
                P2_0=1;
                Br_dy(100-Time);
            }

        }
        
        for(Time=100;Time>0;Time--)
        {
            for(Speed=0;Speed<20;Speed++)
            {
                P2_0=0;
                Br_dy(Time);
                P2_0=1;
                Br_dy(100-Time);
            }

        }
    }

    
}

问题如下:
1、在 main 函数中缺少一个对ledmod的判断,导致ledmod会超过3后不会回到0
2、在main函数中缺少 while(1) 死循环,所以程序会在 main 函数执行完后结束
3、Timer0Init() 函数没有定义,需要补充这个函数的实现
4、在 Timer0_Routine 函数中缺少中断标志的清除
5、Br_dy(unsigned int t) 函数的实现不够优秀
修改后的代码如下:


#include <REGX52.H>

unsigned char ledmod=0,ledcount;

void Timer0Init() 
{
    TMOD |= 0x01;
    TH0 = 0xFC;
    TL0 = 0x18;
    TR0 = 1;
    ET0 = 1;
}

void Delay(unsigned int xms)
{
    unsigned int i, j;
    for(i = xms; i > 0; i--)
    {
        for(j = 110; j > 0; j--);
    }
}

void main()
{
    Timer0Init();
    while(1)
    {
        if(P3_1==0)
        {
            Delay(50);
            while(P3_1==0);
            Delay(50);
            ledmod++;
        }
        if(ledmod>=3)
        {
            ledmod=0;
        }
    }
}

void Timer0_Routine() interrupt 1
{
    TH0 = 0xFC;
    TL0 = 0x18;
    if(ledmod==0)    
    {
        P2_0=1;    
    }        
    if(ledmod==1)
    {
        P2_0=0;
    }
    if(ledmod==2)
    {
        //ºôÎüµÆÄ£Ê½
        unsigned char Time,Speed;
        for(Time=0;Time<100;Time++)
        {
            for(Speed=0;Speed<20;Speed++)
            {
                P2_0=0;
                Delay(Time);
                P2_0=1;
                Delay(100-Time);
            }
 
        }
        
        for(Time=100;Time>0;Time--)
        {
            for(Speed=0;Speed<20;Speed++)
            {
                P2_0=0;
                Delay(Time);
                P2_0=1;
                Delay(100-Time);
            }
 
        }
    }
    TF0 = 0;
}

修改后就能正常运行了,你试一试。欢迎点赞

望采纳!!!点击回答右侧采纳即可!!
这段代码中,当按键按下时,ledmod变量的值会加1。当ledmod的值大于等于3时,将其重置为0。在Timer0_Routine中,根据ledmod的值来控制LED的状态。问题在于当ledmod的值等于2时,会进入呼吸灯的模式,但是在呼吸灯模式中,按键按下时并没有进行切换模式的操作,所以ledmod始终等于2。

解决方法:在进入呼吸灯模式时,需要设置一个标记位或计数器,当按键按下时,判断标记位或计数器的值,如果为0则跳出呼吸灯模式,更新ledmod的值。

如:

unsigned char ledmod = 0,ledcount=0;

void main(){
......
if(ledmod == 2){
ledcount = 1; //设置标记位
......
}
......
if(P3_1==0)
{
Delay(50);
while(P3_1==0);
Delay(50);
if(ledcount == 1){ //如果标记位为1则跳出呼吸灯模式
ledcount = 0;
continue;
}
ledmod++;
if(ledmod>=3)
{
ledmod=0;
}
}

}

这样,当进入呼吸灯模式时,设置标记位ledcount为1,按键按下时如果标记位为1则跳出呼吸灯模式并更新ledmod的值。这样就可以正常切换模式了。

我找到几篇相关的内容文章,希望能对你有所帮助
1.51单片机】独立按键控制LED灯(四种形式)
2.51单片机按键控制LED灯状态
3.51单片机独立按键控制led实验_51单片机独立按键控制led实验

这个问题是由于在呼吸灯模式下,按键事件被呼吸灯循环操作占用了,导致按键检测不到。可以在呼吸灯循环里加入一个按键检测,如果按键被按下就退出呼吸灯循环并切换模式。

请修改如下:

if(ledmod==2)
{
    //ºôÎüµÆÄ£Ê½
    unsigned char Time,Speed;

    for(Time=0;Time<100;Time++)
    {
        for(Speed=0;Speed<20;Speed++)
        {
            P2_0=0;
            Br_dy(Time);
            P2_0=1;
            Br_dy(100-Time);
            if(P3_1==0)
            {
                Delay(50);
                while(P3_1==0);
                Delay(50);
                ledmod++;
                break;
            }
        }
        if(ledmod>=3)
        {
            ledmod=0;
            break;
        }
    }

    for(Time=100;Time>0;Time--)


在time中断里面加循环不太好,中断程序应该尽量简洁,短小精悍

在呼吸灯模式下,按键按下事件应该修改ledmod的值,使其切换到下一个模式。
例如在按键按下事件中加入如下代码:
ledmod = (ledmod + 1) % 3;
这样每次按下按键就可以切换到下一个模式了。
另外,如果ledmod==2的时候,呼吸灯的代码不能被打断,需要用定时器实现呼吸灯的效果。

这段代码中,当按键按下时,会改变ledmod的值,分别为0,1,2三种状态。在定时器中断中根据ledmod的值来控制LED。
但是,代码中有一个问题就是在ledmod==2的情况下,会进入一个循环,控制LED呼吸灯效果。但是循环中没有检测按键状态,所以无法切换模式。

修改方法如下:
1.在循环中加入按键检测,如果按键按下,跳出循环。
2.将循环放到main函数中,在定时器中断中调用。
3.在main函数中添加一个ledcount变量,每次按键按下时ledcount++,在定时器中断中判断ledcount是否大于100,若大于100,ledcount=0,ledmod++。

参考代码如下:

#include <REGX52.H>
#include "Timer0.h"
unsigned char ledmod=0,ledcount;
void main()
{
    Timer0Init();
    while(1)
    {
        if(P3_1==0)
        {
            Delay(50);
            while(P3_1==0);
            Delay(50);
            ledmod++;
            ledcount=0;
            if(ledmod>=3)
            {
                ledmod=0;
            }
        }
        if(ledmod==2)
        {
            unsigned char Time,Speed;
            for(Time=0;Time<100;Time++)
            {
                for(Speed=0;Speed<20;Speed++)
                {
                    P2_0=0;
                    Br_dy(Time);
                    P2_0=1;
                    Br_dy(100-Time);
                }
            }
            for(Time=100;Time>0;Time--)
            {
                for(Speed=0;Speed<20;Speed++)
                {
                    P2_0=0;
                    Br_dy(Time);
                    P2_0=1;
                    Br_dy(100-Time);
                }
           

如果您还是不能解决问题,可以试试以下方法:

使用调试工具查看代码执行过程
尝试使用其他类似的代码来检查是否问题出在硬件上
检查按键连接是否正确,是否有杂音
检查定时器配置是否正确
检查中断服务程序是否正确。

望采纳。