這是一個紅外遙控控制繼電器RELAY,并在液晶上顯示遙控編碼,在if(Y0==0x10){RELAY=1;P2=0xff;} else {RELAY=0;led();}中,我設定當遙控按下關閉鍵時關閉繼電器,同時P2全部LED燈關閉,但程序卻無法返回P2=0xff;,我自己大概分析原因應該是led();子函數正常運行,while(1)無法跳出。我用過do while也不行。請問各大神應該怎么修改呢?
- #include <intrins.h>
- #define NOP() _nop_() /* 定義空指令 */
- #define uchar unsigned char
- #define uint unsigned int
- #define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};
- void delay(uchar x); //x*0.14MS
- void delay1(int ms);
- void beep(void);
- void led();
- sbit IRIN = P3^2; //紅外接收器數據線
- sbit RELAY= P1^4; //繼電器驅動線
- sbit BEEP = P1^5; //蜂鳴器驅動線
- uchar IRCOM[7];
- uchar cdis1[] = {" REMOTE CONTROL "};
- uchar cdis2[] = {" IR-CODE: --H"};
- //LCD IO
- sbit LCD_RW = P2^5;
- sbit LCD_RS = P2^6;
- sbit LCD_EN = P2^7;
- unsigned char Y0;
- /*******************************************************************/
- /* */
- /*檢查LCD忙狀態 */
- /*lcd_busy為1時,忙,等待。lcd-busy為0時,閑,可寫指令與數據。 */
- /* */
- /*******************************************************************/
- bit lcd_busy()
- {
- bit result;
- LCD_RS = 0;
- LCD_RW = 1;
- LCD_EN = 1;
- delayNOP();
- result = (bit)(P0&0x80);
- LCD_EN = 0;
- return(result);
- }
- /*******************************************************************/
- /* */
- /*寫指令數據到LCD */
- /*RS=L,RW=L,E=高脈沖,D0-D7=指令碼。 */
- /* */
- /*******************************************************************/
- void lcd_wcmd(uchar cmd)
- {
- while(lcd_busy());
- LCD_RS = 0;
- LCD_RW = 0;
- LCD_EN = 0;
- _nop_();
- _nop_();
- P0 = cmd;
- delayNOP();
- LCD_EN = 1;
- delayNOP();
- LCD_EN = 0;
- }
- /*******************************************************************/
- /* */
- /*寫顯示數據到LCD */
- /*RS=H,RW=L,E=高脈沖,D0-D7=數據。 */
- /* */
- /*******************************************************************/
- void lcd_wdat(uchar dat)
- {
- while(lcd_busy());
- LCD_RS = 1;
- LCD_RW = 0;
- LCD_EN = 0;
- P0 = dat;
- delayNOP();
- LCD_EN = 1;
- delayNOP();
- LCD_EN = 0;
- }
- /*******************************************************************/
- /* */
- /* LCD初始化設定 */
- /* */
- /*******************************************************************/
- void lcd_init()
- {
- delay1(15);
- lcd_wcmd(0x38); //16*2顯示,5*7點陣,8位數據
- delay1(5);
- lcd_wcmd(0x38);
- delay1(5);
- lcd_wcmd(0x38);
- delay1(5);
- lcd_wcmd(0x0c); //顯示開,關光標
- delay1(5);
- lcd_wcmd(0x06); //移動光標
- delay1(5);
- lcd_wcmd(0x01); //清除LCD的顯示內容
- delay1(5);
- }
- /*******************************************************************/
- /* */
- /* 設定顯示位置 */
- /* */
- /*******************************************************************/
- void lcd_pos(uchar pos)
- {
- lcd_wcmd(pos | 0x80); //數據指針=80+地址變量
- }
- /*******************************************************************/
- main()
- {
- uchar m;
- IE = 0x81; //允許總中斷中斷,使能 INT0 外部中斷
- TCON = 0x01; //觸發方式為脈沖負邊沿觸發
- IRIN=1; //I/O口初始化
- BEEP=1;
- RELAY=1;
-
- delay1(10); //延時
- lcd_init(); //初始化LCD
- lcd_pos(0); //設置顯示位置為第一行的第1個字符
- m = 0;
- while(cdis1[m] != '\0')
- { //顯示字符
- lcd_wdat(cdis1[m]);
- m++;
- }
- lcd_pos(0x40); //設置顯示位置為第二行第1個字符
- m = 0;
- while(cdis2[m] != '\0')
- {
- lcd_wdat(cdis2[m]); //顯示字符
- m++;
- }
- while(1);
- } //end main
- /**********************************************************/
- void IR_IN(void) interrupt 0 //外部中斷服務程序
- {
- unsigned char j,k,N=0;
- EX0 = 0;
- delay(15);
- if (IRIN==1)
- { EX0 =1;
- return;
- }
- //確認IR信號出現
- while (!IRIN) //等IR變為高電平,跳過9ms的前導低電平信號。
- {delay(1);}
- for (j=0;j<4;j++) //收集四組數據
- {
- for (k=0;k<8;k++) //每組數據有8位
- {
- while (IRIN) //等 IR 變為低電平,跳過4.5ms的前導高電平信號。
- {delay(1);}
- while (!IRIN) //等 IR 變為高電平
- {delay(1);}
- while (IRIN) //計算IR高電平時長
- {
- delay(1);
- N++;
- if (N>=30)
- { EX0=1;
- return;} //0.14ms計數過長自動離開。
- } //高電平計數完畢
- IRCOM[j]=IRCOM[j] >> 1; //數據最高位補“0”
- if (N>=8) {IRCOM[j] = IRCOM[j] | 0x80;} //數據最高位補“1”
- N=0;
- }//end for k
- }//end for j
- if (IRCOM[2]!=~IRCOM[3])
- { EX0=1;
- return; }
- IRCOM[5]=IRCOM[2] & 0x0F; //取鍵碼的低四位
- IRCOM[6]=IRCOM[2] >> 4; //右移4次,高四位變為低四位
- if(IRCOM[5]>9)
- { IRCOM[5]=IRCOM[5]+0x37;}
- else
- IRCOM[5]=IRCOM[5]+0x30;
- if(IRCOM[6]>9)
- { IRCOM[6]=IRCOM[6]+0x37;}
- else
- IRCOM[6]=IRCOM[6]+0x30;
- lcd_pos(0x4b);
- lcd_wdat(IRCOM[6]); //第一位數顯示
- lcd_pos(0x4c);
- lcd_wdat(IRCOM[5]); //第二位數顯示
- Y0=0;
- switch(IRCOM[2])
- {
- case 0x09: Y0=0x01; break;
- case 0x1D: Y0=0x02; break;
- case 0x1F: Y0=0x03; break;
- case 0x0D: Y0=0x04; break;
- case 0x19: Y0=0x05; break;
- case 0x1B: Y0=0x06; break;
- case 0x11: Y0=0x07; break;
- case 0x15: Y0=0x08; break;
- case 0x17: Y0=0x09; break;
- case 0x45: Y0=0x10; break;
- case 0x13: RELAY=1; break;
- case 0x14: RELAY=1; break;
- case 0x51: RELAY=0; break;
- }
- if(Y0==0x10){RELAY=1;P2=0xff;} //關閉繼電器
- else {RELAY=0;led();} //打開繼電器
- beep();
- EX0 = 1;
- }
- /**********************************************************/
- void beep(void)
- {
- unsigned char i;
- for (i=0;i<100;i++)
- {
- delay(4);
- BEEP=!BEEP; //BEEP取反
- }
- BEEP=1; //關閉蜂鳴器
- }
- void led()
- {
- int i=0;
- uchar a;
- unsigned char ledd[8]={0x7e,0xbd,0xdb,0xe7,0xdb,0xbd,0x7e,0xff};
- //其實就是定義了一個亮燈狀態表
- while(1)
- {
- for(i=0;i<8;i++)
- {
- P2=ledd[i];
- delay1(50);
- }
- //中間往兩邊移動
- a=0xff;
- for(i=0;i<=8;i++)
- {
- P2=a;
- delay1(50);
- a=a>>1;
- //if(a==0x00) break;
- }
- //右移+1
- a=0xff;
- for(i=0;i<8;i++)
- {
- P2=a;
- delay1(50);
- a=a<<1;
- //if(a==0x00) break;
- }
- //左移+1
- a=0x7f;
- for (i = 0 ;i < 8 ; i++)
- {
- P2=a;
- delay1(50);
- a=_cror_(a,1);
- if (a == 0xfe) break;
- }
- for (i = 0 ;i < 8 ; i++)
- {
- P2=a;
- delay1(50);
- a=_crol_(a,1);
- if (a == 0xff) break;
- }
- //循環左右移
- }
- }
- /**********************************************************/
- void delay(unsigned char x) //x*0.14MS
- {
- unsigned char i;
- while(x--)
- {
- for (i = 0; i<13; i++) {}
- }
- }
- /**********************************************************/
- void delay1(int ms)
- {
- unsigned char y;
- while(ms--)
- {
- for(y = 0; y<250; y++)
- {
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- }
- }
- }
復制代碼
|