进阶五 按键切换不同led流水效果

发布于:2025-06-21 ⋅ 阅读:(18) ⋅ 点赞:(0)

 功能概述

  1. 初始化
    • 初始化外部中断0(INT0)为边沿触发方式。
    • 开启全局中断。
  2. LED显示模式
    • crol():将P1口的LED向左旋转一位。
    • cror():将P1口的LED向右旋转一位。
    • blink():使所有LED闪烁(全亮和全灭交替)。
    • off():关闭所有LED。
  3. 模式切换
    • 每次按下连接到INT0的按钮时,会切换到下一个LED显示模式。
    • 模式循环为:左旋转 -> 右旋转 -> 闪烁 -> 关闭 -> 左旋转 ...

详细分析

  • 中断初始化
    • IT0 = 1;:设置INT0为边沿触发方式。
    • EX0 = 1;:启用INT0中断。
    • EA = 1;:启用全局中断。
  • LED控制函数
    • crol():使用_crol_函数将P1口的值左移一位。
    • cror():使用_cror_函数将P1口的值右移一位。
    • blink():使所有LED闪烁,亮500毫秒,灭500毫秒。
    • off():关闭所有LED。
  • 主循环
    • main()函数中初始化中断后,进入无限循环,调用fst()函数。
    • fst()函数根据count的值选择相应的LED显示模式。
  • 中断服务程序
    • ex0_isr()是INT0的中断服务程序。
    • 包含简单的去抖动处理,通过延时和再次检查引脚状态来防止机械开关的抖动。
    • 每次中断触发时,count递增,并在达到4时重置为0,确保模式循环。

潜在问题和改进建议

  1. 去抖动处理
    • 当前的去抖动处理是简单的延时,可能不够完善。可以考虑使用硬件去抖动或更复杂的软件去抖动算法。
  2. LED状态
    • ex0_isr()中,P1=0x7f;会强制设置P1口的状态,这可能会干扰其他模式。建议移除或根据需要调整。
  3. 模式循环
    • 当前的模式循环是0到3,确保count的范围始终在0到3之间。
#include<reg51.h>
#include<intrins.h>

typedef unsigned char uchar;
typedef unsigned int uint;

volatile uint count = 0;  // Added volatile since it's modified in ISR

void ex0_init(void);
void crol(void);
void cror(void);
void blink(void);
void off(void);
void fst(void);
void delayms(uint);

void delayms(uint x)
{
    uint i;
    while(x--)
    {
        for(i=89;i>0;i--);
    }
}

void crol(void)
{
    P1 = _crol_(P1, 1);
    delayms(500);
}
    
void cror(void)
{
    P1 = _cror_(P1, 1);  // Fixed function name
    delayms(500);
}

void blink(void)
{
	P1=0x00;
	delayms(500);
	P1=0xff;
	delayms(500);
}

void off(void)
{
	
	P1=0xff;
}

void fst(void)
{
    switch(count)
    {
        case 0: crol(); break;
        case 1: cror(); break;
				case 2: blink(); break;
			  case 3:	off();break;
        default: count = 0;
    }
}

void main()
{
    
    ex0_init();  // Initialize external interrupt once
    P1=0x80;
    while(1)
    {
        fst();
    }
}

void ex0_init(void)
{
    IT0 = 1;   // Edge-triggered interrupt
    EX0 = 1;   // Enable EX0 interrupt
    EA = 1;    // Enable global interrupts
}

void ex0_isr(void) interrupt 0
{
    delayms(10);  // 延时去抖动
    if(INT0 == 0)  // 再次检查引脚状态
    {
        count++;
        if(count >= 4)
        {
        count = 0;
        }  
	  }		
		P1=0x7f;
    while(!INT0);

}


网站公告

今日签到

点亮在社区的每一天
去签到