![]() |
發布時間: 2020-10-5 10:32
正文摘要:本帖最后由 武。。。。 于 2020-10-5 16:07 編輯 按下按鍵一后(短按),8個led燈全部亮(死循環);按下按鍵二后,8個led燈進行流水(死循環);按下按鍵三后,8個led燈同時做呼吸(2秒亮,4秒暗)(利用pwm占空 ... |
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); } } |