daemondong 发表于 2020-10-9 19:15 我试着那样去仿真,发现按了呼吸灯的按键后就无法按其他按键了,会一直停留在呼吸灯那里。 |
呼吸比较好实现 定时器中断里面做10毫秒时基,计数延时 ,灯也加上闪烁秒计数2之前亮 到6灭灯清0 就好了 |
呼吸死在 140行 while(1); 修改如下: 1. 去掉 140行 2. 110行 case 3 如下 case 3: //led灯进行闪烁 huxi(); break; |
这种情况下我就不想用定时器了,当然,用定时器延时ok的。既然是51,直接读取按键对应口,根据读取到的值执行不同的程序。所以写四个现象的函数,然后根据IO口读取条件调用 |
武。。。。 发表于 2020-10-7 00:46 上面例程是各一秒左右,修改下参数很容易实现的 |
tyrl800 发表于 2020-10-6 10:10 你好,请问您的呼吸灯部分是亮两秒暗四秒吗? |
//***********硬件底层定义************** #define K1 P14 #define K2 P15 #define K3 P16 #define K4 P17 //***********软件层定义************* #define KEY1_PRES 1 //KEY1按下 #define KEY2_PRES 2 //KEY2按下 #define KEY3_PRES 3 //KEY3按下 #define KEY4_PRES 4 //KEY4按下 #define KEY5_PRES 5 //KEY3和KEY4同时按下 扩展用 //***********按键检测函数************** unsigned char Key_Scan(unsigned char mode) { static unsigned char Key_Up = 1; //按键按松开标志 if(mode) //支持连按 { Key_Up = 1; } if(Key_Up && (K1==0 || K2==0 || K3==0 || K4==0)) { Key_Up = 0; if(K1 == 0) return KEY1_PRES; else if(K2 == 0) return KEY2_PRES; else if(K3 == 0 && K4 == 0) return KEY5_PRES; else if(K3 == 0) return KEY3_PRES; else if(K4 == 0) return KEY4_PRES; } else if(K1 == 1 && K2 == 1 && K3 == 1 && K4 == 1) { Key_Up = 1; } return 0; //无按键按下 } //*************按键处理函数**************** Key_Deal() { key = Key_Scan(1); //key外部变量, 1:支持连按, 0:不支持连按, switch(key) { case 1: KeyFlag = 1; //KeyFlag 外部变量 break; case 2: KeyFlag = 2; break; case 3: KeyFlag = 3; break; case 4: //关定时器,熄灯; break; default: break; } } main() { Key_Deal(); switch(KeyFlag) { case 1: //关定时器 //全亮操作 break; case 2: //关定时器 //跑马灯操作 break; case 3: //呼吸灯,开定时器; break; } } |
你的呼吸灯是通过定时器实现的,开启后,定时器会常态一直工作,当键值改变后,你有判断后去改变 “ET0 = 0; 或者 EA = 0;”操作么? |
#include<reg52.h> #define uchar unsigned char #define uint unsigned int #define Kport P3 #define Ledport P1 uchar code table0[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//LED从低位往高位移 unsigned char kscancnt; //记录进入中断的次数,满一个周期清零 void timer0_init(); //定时器0初始化 void delayMS(uint x); //延时函数 void KeyProcess(uchar Key); //按键处理函数 bit flag; uchar knum; uint F3cnt,F2cnt,Pwmcnt,T0cnt; uchar temp=0xff,temp1; uchar sh_cnt; //延时函数 void delayMS(uint x) { uchar i; while (x--) for(i=0;i<120; i++) ; } /*************************************************** * 定时器0初始化子函数 * 工作方式2,每1000us中断一次 ****************************************************/ void timer0_init(void) { TMOD = 0x01; //采用定时器0,工作方式2, TH0 = (65536-1000)/256; //定时器设置,每隔20us发起一次中断。 TL0 = (65536-1000)%256; ET0 = 1; //开定时器0中断 EA = 1; //开总中断 TR0 = 1; //打开定时器 } //检测按键 uchar GetKey(uchar kscancnt) { uchar ktmp; if(kscancnt==0) { temp=(Kport&0xf0)>>4; ktmp=~temp &(temp1); if(ktmp)knum=ktmp; temp1=temp; } return knum; } //键盘按键处理 void KeyProcess(uchar Key) { switch (Key) { case 1:Ledport=0x00; break; case 2:if(F2cnt==200){sh_cnt=++sh_cnt%8;F2cnt=0;} Ledport=table0[sh_cnt]; break; case 4:if(T0cnt==300) {F3cnt=F3cnt+10;T0cnt=0;} if(F3cnt==130){F3cnt=0;flag=!flag;} Pwmcnt=++Pwmcnt%100; if(flag) {if(Pwmcnt>F3cnt)Ledport=0x00;else Ledport=0xff;} else {if(Pwmcnt>F3cnt)Ledport=0xff;else Ledport=0x00;} break; case 8:Ledport=0xff; //全部关闭 break; } } /*************************************************** * 中断服务子函数 *****************************************************/ void time0(void) interrupt 1 { TH0 = (65536-1000)/256; //定时器设置,每隔20us发起一次中断。 TL0 = (65536-1000)%256; kscancnt=++ kscancnt%10; if(knum==2) {F2cnt++; } if(knum==4) {T0cnt++; } } //-------------------------------------------------------------------- void main(void) { uchar Key; P0=P1=0xFF; timer0_init(); while(1) { Key=GetKey(kscancnt); KeyProcess(Key); } } |