这是一个红外遥控控制继电器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_();
- }
- }
- }
复制代码
|