请朋友们改下这段彩灯控制器程序

问题如下,能自动循环,按下按键手动切换花式

img

程序在这

#include <REGX51.H>


#define Led    P2

unsigned int time=0;     //延时时长变量

void InitTimer0(void)     //10ms
{
    TMOD = 0x01;         //定时器模式1
    //赋值
    TH0 = 0xDC;
    TL0 = 0x00;
    EA = 1;                 //开总中断
    ET0 = 1;             //开定时器0中断
}

void delay(unsigned int ms_10)           //延时函数
{
     time=ms_10;                       //给time赋予具体延时时间的数值
     TR0 = 1;                           //打开定时器0
     while(time);                       //等待延时结束
     TR0 = 0;                           //关闭定时器0
}

void light_water()                       //流水灯函数
{
    int i=0,Led_H=0,Led_L=0,temp=0x06,num=0;     //Led_H存储P2高8位Led_L存储P2低8位
    Led=0x01;
    delay(10);//100ms
    for(i=0;i < 7;i++)      //单个左移
    {
        Led=Led<<1;                             //P2数值左移
        delay(10);//100ms    
    }
    for(i=0;i < 7;i++)      //单个右移
    {
        Led=Led>>1;                             //P2数值右移
        delay(10);//100ms    
    }
    for(i=0;i < 7;i++)      //依次向左点亮
    {
        Led=Led<<1|0x01;                         //P2数值左移并将最低位置为1
        delay(10);//100ms    
    }
    for(i=0;i < 7;i++)      //依次向右点亮
    {
        Led=Led>>1;                             //P2数值右移,依次将位1清零
        delay(10);//100ms    
    }
    Led=0x00;
    for(i=0;i < 7;i++)      //两端向内依次点亮
    {
        Led_L=Led<<1|0x01&0x0f;                 //取出P2的低4位,并将其左移最低位置1
        Led_H=((Led&0xf0)>>1)^0x80;             //取出P2的高4位,并将其右移最高位置1
        Led=Led|Led_L;                             //将低4位赋予P2
        Led=Led|Led_H;                             //将高4位赋予P2
        delay(10);//100ms    
    }
    for(i=0;i < 7;i++)      //由内向两端依次点亮
    {
        Led_L=(Led&0x0f)>>1;                     //取P2低4位并右移
        Led_H=(Led&0xf0)<<1;                     //取P2高4位并左移
        Led=Led&Led_L;                             //将低4位赋予P2
        Led=Led^Led_H;                             //将高4位赋予P2
        delay(10);//100ms    
    }
    Led=0x00;
    for(i=0;i < 10;i++)      //依次向左点亮2个灯
    {
        num=Led<<1|0x01;                         //P2数值左移并最低位置1
        if(num>=0x06)                         //23个灯亮后,以2个灯为主体向左移动
        {
            Led=num&temp;
            temp=temp<<1;    
        }
        else 
            Led=num;
        delay(7);//100ms    
    }
    Led=0x00;
    temp=0xc0;
    for(i=0;i < 10;i++)      //依次向右点亮2个灯
    {
        num=Led>>1|0x80;                        //将P2数值右移并最高位置1
        if(num>=temp)                            //67个灯亮时以两个灯为整体向右移动
        {
            Led=num&temp;
            temp=temp>>1;
        }
        else
            Led=num;
        delay(7);//100ms    
    }
}

void main(void)
{
    InitTimer0();             //定时器初始化
    while(1)
    {
        light_water();
    }
}

void Timer0Interrupt(void) interrupt 1
{
    TH0 = 0xDC;
    TL0 = 0x00;
    time--;
    if(time < 0)
    {
        time = 0;              //time为0时不在减
    }
}


#include <reg51.h>

#define Led    P2

unsigned int time=0;     //延时时长变量

void InitTimer0(void)     //10ms
{
    TMOD = 0x01;         //定时器模式1
    //赋值
    TH0 = 0xDC;
    TL0 = 0x00;
    EA = 1;                 //开总中断
    ET0 = 1;             //开定时器0中断
}

void delay(unsigned int ms_10)           //延时函数
{
     time=ms_10;                       //给time赋予具体延时时间的数值
     TR0 = 1;                           //打开定时器0
     while(time);                       //等待延时结束
     TR0 = 0;                           //关闭定时器0
}

void light_water()                       //流水灯函数
{
    int i=0,Led_H=0,Led_L=0,temp=0x06,num=0;     //Led_H存储P2高8位Led_L存储P2低8位
    Led=0x01;
    delay(10);//100ms
    for(i=0;i < 7;i++)      //单个左移
    {
        Led=Led<<1;                             //P2数值左移
        delay(10);//100ms    
    }
    for(i=0;i < 7;i++)      //单个右移
    {
        Led=Led>>1;                             //P2数值右移
        delay(10);//100ms    
    }
    for(i=0;i < 7;i++)      //依次向左点亮
    {
        Led=Led<<1|0x01;                         //P2数值左移并将最低位置为1
        delay(10);//100ms    
    }
    for(i=0;i < 7;i++)      //依次向右点亮
    {
        Led=Led>>1;                             //P2数值右移,依次将位1清零
        delay(10);//100ms    
    }
    Led=0x00;
    for(i=0;i < 7;i++)      //两端向内依次点亮
    {
        Led_L=Led<<1|0x01&0x0f;                 //取出P2的低4位,并将其左移最低位置1
        Led_H=((Led&0xf0)>>1)^0x80;             //取出P2的高4位,并将其右移最高位置1
        Led=Led|Led_L;                             //将低4位赋予P2
        Led=Led|Led_H;                             //将高4位赋予P2
        delay(10);//100ms    
    }
    for(i=0;i < 7;i++)      //由内向两端依次点亮
    {
        Led_L=(Led&0x0f)>>1;                     //取P2低4位并右移
        Led_H=(Led&0xf0)<<1;                     //取P2高4位并左移
        Led=Led&Led_L;                             //将低4位赋予P2
        Led=Led^Led_H;                             //将高4位赋予P2
        delay(10);//100ms    
    }
    Led=0x00;
    for(i=0;i < 10;i++)      //依次向左点亮2个灯
    {
        num=Led<<1|0x01;                         //P2数值左移并最低位置1
        if(num>=0x06)                         //23个灯亮后,以2个灯为主体向左移动
        {
            Led=num&temp;
            temp=temp<<1;    
        }
        else 
            Led=num;
        delay(7);//100ms    
    }
    Led=0x00;
    temp=0xc0;
    for(i=0;i < 10;i++)      //依次向右点亮2个灯
    {
        num=Led>>1|0x80;                        //将P2数值右移并最高位置1
        if(num>=temp)                            //67个灯亮时以两个灯为整体向右移动
        {
            Led=num&temp;
            temp=temp>>1;
        }
        else
            Led=num;
        delay(7);//100ms    
    }
}

void main(void)
{
    InitTimer0();             //定时器初始化
    while(1)
    {
        light_water();
    }
}

void Timer0Interrupt(void) interrupt 1
{
    TH0 = 0xDC;
    TL0 = 0x00;
    time--;
    if(time < 0)
    {
        time = 0;              //time为0时不在减
    }
}



【以下回答由 GPT 生成】

### 改进建议:

1. 添加一个全局变量 `autoMode` 来表示程序的运行模式,0表示自动模式,1表示手动模式。初始化时将其设为0。

2.`InitTimer0` 函数中添加一个外部中断0(INT0)的初始化,使其能够接收按键的输入。

```cpp
void InitTimer0(void) // 10ms
{
    TMOD = 0x01; // 定时器模式1
    // 赋值
    TH0 = 0xDC;
    TL0 = 0x00;
    EA = 1; // 开总中断
    ET0 = 1; // 开定时器0中断

    // 初始化外部中断0(INT0)
    EX0 = 1; // 开外部中断0
    IT0 = 1; // 设置外部中断0为下降沿触发
}
  1. 修改 light_water 函数,将其中的延时函数 delay 替换为一个新的函数 delay_100ms,用于控制按键的响应速度。
void delay_100ms(void) // 100ms 延时函数
{
    unsigned int i, j;
    for(i = 0; i < 10; i++)
    {
        for(j = 0; j < 8000; j++);
    }
}
  1. 添加一个新的函数 setPattern 用于手动选择不同的花式。在函数中可以使用外部中断0的中断服务程序来切换程序的运行模式。
void setPattern(void) // 手动选择花式
{
    if(autoMode == 1) // 如果当前是手动模式,切换到自动模式
    {
        autoMode = 0;
        light_water(); // 执行一次自动循环
    }
    else // 如果当前是自动模式,切换到手动模式
    {
        autoMode = 1;
    }
}

void INT0_ISR(void) interrupt 0 // 外部中断0的中断服务程序
{
    setPattern();
}
  1. 修改 light_water 函数,将其中的 delay(10) 替换为 delay_100ms(),并添加一个条件判断,根据程序的运行模式选择是否运行循环。
void light_water() // 流水灯函数
{
    int i = 0, Led_H = 0, Led_L = 0, temp = 0x06, num = 0; // Led_H存储P2高8位,Led_L存储P2低8位
    Led = 0x01;
    delay_100ms(); // 100ms

    while(1) // 循环执行
    {
        if(autoMode == 1) // 如果是手动模式,跳出循环
        {
            break;
        }

        for(i = 0; i < 7; i++) // 单个左移
        {
            Led = Led << 1; // P2数值左移
            delay_100ms(); // 100ms
        }
        for(i = 0; i < 7; i++) // 单个右移
        {
            Led = Led >> 1; // P2数值右移
            delay_100ms(); // 100ms
        }
        for(i = 0; i < 7; i++) // 依次向左点亮
        {
            Led = Led << 1 | 0x01; // P2数值左移并将最低位置为1
            delay_100ms(); // 100ms
        }
        // ...
    }
}

以上是对彩灯控制器程序改进的具体方案。根据需求,我添加了一个全局变量 autoMode 来表示程序的运行模式,并初始化为0(自动模式)。通过外部中断0来切换程序的运行模式。在 light_water 函数中,根据程序的运行模式选择是否运行循环。如果是手动模式,程序会跳出循环,等待下一次外部中断来切换回自动模式并执行循环。请根据需要适当调整修改方案,并进行测试验证。 ```



【相关推荐】



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