串口接收温度数据,用红外遥控来调整温度上下限,有报警功能。目前问题很大,请各位帮帮我

求各位看看,可以用红外遥控器收发信息,但只能对温度上下限改变一次,而且蜂鸣器完全不响,电脑发送9600波特率的数据也无法接收,非常疑惑

/*****************************  

*****************************/
#include "reg51.h"
#include <intrins.H>

typedef unsigned char uchar;
typedef unsigned int  uint;
typedef unsigned char u8;
typedef unsigned int  u16;

char buff[2];




//LCD定义
#define LCD_DB P0 
sbit LCD_RS=P2^6;   
sbit LCD_RW=P2^5;  
sbit LCD_E=P2^7;  
sbit IRED=P3^2;
//sbit K1=P3^1; 
//sbit K2=P3^0;  
//sbit K3=P3^2;  
//sbit K4=P3^3;  
bit flag=1;
extern uchar gired_data[4];
uchar gired_data[4];
sbit BEEP=P2^5;  
//sbit LED=P3^4;  

uchar Temp=0;


uchar H=60;
uchar L=20;
/*-------------------------------------
               函数申明
---------------------------------------*/
void InitUART();
void LCD_init(void);                          //初始化函数 
void LCD_write_command(uchar command);        //写指令函数 
void LCD_write_data(uchar dat);               //写数据函数  
void LCD_disp_char(uchar x,uchar y,uchar dat);//在某个屏幕位置上显示一个字符,X(0-15),y(1-2)  
void LCD_disp_str(uchar x,uchar y,uchar *str); //LCD1602显示字符串函数 
void delay_n10us(uint n);                     //延时函数
/*----------------------------
    UART1初始化
-----------------------------*/
void InitUART(void)
{
    TMOD = 0x20;
    SCON = 0x50;
      PCON = 0x80;
    TH1 = 0xF3;
    TL1 = 0xF3;
    EA = 1;
    ES = 1;
    TR1 = 1;
}


/*----------------------------
UART 中断服务程序
-----------------------------*/
void UARTInterrupt(void) interrupt 4
{
   if(RI)
   {
      RI = 0;
      buff[0]=SBUF;
         
        Temp=buff[0];
    }    
   else
       TI = 0;
}

void ired_init(void)
{
    IT0=1;    //下降沿触发
    EX0=1;    //打开中断0允许
    EA=1;    //打开总中断
    IRED=1;    //初始化端口
}
/*-------------------------------------
               LCD1602子程序
---------------------------------------*/
void LCD_init(void) 
{  
    delay_n10us(10);  
    LCD_write_command(0x38);//设置8位格式,2行,5x7 
    delay_n10us(10);  LCD_write_command(0x0c);//开显示,关光标,不闪烁 
    delay_n10us(10);  LCD_write_command(0x06);//设定输入方式,增量不移位 
    delay_n10us(10);  LCD_write_command(0x01);//清除屏幕显示  
    delay_n10us(100);       //延时清屏,延时函数,延时约n个10us 
}

void LCD_write_command(uchar dat) 
{  
    delay_n10us(10);  
    LCD_RS=0;         //指令 
    LCD_RW=0;         //写入 
    LCD_E=1;          //允许 
    LCD_DB=dat;  delay_n10us(10);  //实践证明,我的LCD1602上,用for循环1次就能完成普通写指令。 
    LCD_E=0;  delay_n10us(10);  //实践证明,我的LCD1602上,用for循环1次就能完成普通写指令。 
}

void LCD_write_data(uchar dat) 
{  
    delay_n10us(10);  
    LCD_RS=1;          //数据 
    LCD_RW=0;           //写入
    LCD_E=1;           //允许 
    LCD_DB=dat; delay_n10us(10);
     LCD_E=0;  delay_n10us(10); 
}

void LCD_disp_char(uchar x,uchar y,uchar dat) 
{    
    uchar address;   
    if(y==1)           
    address=0x80+x;  
    else           
    address=0xc0+x;    
    LCD_write_command(address);   
    LCD_write_data(dat); 
}

void LCD_disp_str(uchar x,uchar y,uchar *str) 
{    
    uchar address;   
    if(y==1)           
    address=0x80+x;   
    else           
    address=0xc0+x;    
    LCD_write_command(address);   
    while(*str!='\0')   
        {       
        LCD_write_data(*str);
        str++;
        }
}

void delay_n10us(uint n)  //延时 
{                 
    uint i;                    
    for(i=n;i>0;i--)            
     {         
     nop_();_nop_();_nop_();_nop_();_nop_();_nop_();    
     } 
}

//void key()
//{
//    if(K1==0)
//    {
//        if(flag==1)
//        {
//            flag=0;
//            if(H<128)
//            {
//                H++;
//            }
//        }
//    }
//    else if(K2==0)
//    {
//        if(flag==1)
//        {
//            flag=0;
//            if(H>L+1)
//            {
//                H--;
//            }
//        }
//    }
//    else if(K3==0)
//    {
//        if(flag==1)
//        {
//            flag=0;
//            if(L<H-1)
//            {
//                L++;
//            }
//        }
//    }
//    else if(K4==0)
//    {
//        if(flag==1)
//        {
//            flag=0;
//            if(L>0)
//            {
//                L--;
//            }
//        }
//    }
//    else
//    {
//        flag=1;
//    }
//}

void beep_alarm(u16 time,u16 fre)
{
    while(time--)
    {
        BEEP=!BEEP;
        delay_n10us(fre);    
    }        
}
/*****************************  
        主函数
*****************************/
void main()
{
//    FMQ=1;  
//    LED=1; 
    InitUART();
    LCD_init();//LCD初始化              
    LCD_disp_str(0,1,"   Temp:   c    "); //显示 温度
    LCD_disp_str(0,2,"H:000c    L:000c"); //显示 湿度
    ired_init();
    flag = 1; // 设置计数器为1
  while(1)
    {
            flag = 1; // 设置计数器为1
          switch(gired_data[2]) 
{
    case 0x18:  //判断用户是否选择形式1
  { 
            if(flag==1)
        {
            flag=0;
            if(H<128)
            {
                H++;
            }
        }

    
    break;
  }
  case 0x52:   //判断用户是否选择形式2
  { 
         if(flag==1)
        {
            flag=0;
            if(H>L+1)
            {
                H--;
            }
        }
    
    break;
  }
  case 0x08:   //判断用户是否选择形式3
  { 
        if(flag==1)
        {
            flag=0;
            if(L<H-1)
            {
                L++;
            }
        }

    break;
  }
  case 0x5A: //判断用户是否选择形式4   
  { 
  
        if(flag==1)
        {
            flag=0;
            if(L>0)
            {
                L--;
            }
        }

    break;
  }
  
    
}
        LCD_disp_char(8,1,Temp/100+'0'); //显示 温度
        LCD_disp_char(9,1,Temp/10%10+'0'); //显示 温度
        LCD_disp_char(10,1,Temp%10+'0'); //显示 温度
        
        
        LCD_disp_char(2,2,H/100+'0'); 
        LCD_disp_char(3,2,H/10%10+'0'); 
        LCD_disp_char(4,2,H%10+'0'); 
        
        
        LCD_disp_char(12,2,L/100+'0'); 
        LCD_disp_char(13,2,L/10%10+'0'); 
        LCD_disp_char(14,2,L%10+'0'); 
        
     if(Temp<L || Temp>H)
     {
         beep_alarm(100,10);

        }
     else
     {
         beep_alarm(100,10);

        }
    }
}

void ired() interrupt 0    //外部中断0服务函数
{
    u8 ired_high_time=0;
    u16 time_cnt=0;
    u8 i=0,j=0;

    if(IRED==0)
    {
        time_cnt=1000;
        while((!IRED)&&(time_cnt))//等待引导信号9ms低电平结束,若超过10ms强制退出
        {
            delay_n10us(1);//延时约10us
            time_cnt--;
            if(time_cnt==0)return;        
        }
        if(IRED)//引导信号9ms低电平已过,进入4.5ms高电平
        {
            time_cnt=500;
            while(IRED&&time_cnt)//等待引导信号4.5ms高电平结束,若超过5ms强制退出
            {
                delay_n10us(1);
                time_cnt--;
                if(time_cnt==0)return;    
            }
            for(i=0;i<4;i++)//循环4次,读取4个字节数据
            {
                for(j=0;j<8;j++)//循环8次读取每位数据即一个字节
                {
                    time_cnt=600;
                    while((IRED==0)&&time_cnt)//等待数据1或0前面的0.56ms结束,若超过6ms强制退出
                    {
                        delay_n10us(1);
                        time_cnt--;
                        if(time_cnt==0)return;    
                    }
                    time_cnt=20;
                    while(IRED)//等待数据1或0后面的高电平结束,若超过2ms强制退出
                    {
                        delay_n10us(10);//约0.1ms
                        ired_high_time++;
                        if(ired_high_time>20)return;    
                    }
                    gired_data[i]>>=1;//先读取的为低位,然后是高位
                    if(ired_high_time>=8)//如果高电平时间大于0.8ms,数据则为1,否则为0
                        gired_data[i]|=0x80;
                    ired_high_time=0;//重新清零,等待下一次计算时间
                }
            }
        }
        if(gired_data[2]!=~gired_data[3])//校验控制码与反码,错误则返回
        {
            for(i=0;i<4;i++)
                gired_data[i]=0;
            return;    
        }
    }        
}




img

img

img


板子是普中A2的板子,求各位帮帮我!

逻辑错误比较明显 首先第一点你要了解 void UARTInterrupt(void) interrupt 4 这段函数的意思 我先指出来错误,正确应该这样写

void UARTInterrupt(void) interrupt 4
{
   if(RI) //这段if语句的意思是 只要收到了数据就把数据取出来 存到BUFF里边,之后清0好为下一位数据的接收做准备
   {
      RI = 0;
      buff[0]=SBUF;
         
        Temp=buff[0];
    }    
      while(!TI)//这句话意思是 如果数据没有发送完成就要一直等待
    TI = 0;//发完之后清楚标志位,好继续发送
}

至于你说的按键只能调一次 这个错误很明显


 case 0x5A: //判断用户是否选择形式4   
  { 
        if(flag==1)
        {
            flag=0;
            if(L>0)
            {
                L--;
            }
        }
    break;
  }

当你遥控器按下时,判断的第一个if语句是判断flag是否等于1 ,如果等于1就把flag至0,但是你至0之后并没有重新至1,这就导致了按键只能调一次 正确的做法应该是在switch语句最后default之前加上flag=1;

串口通讯参数是否配置正确

建议先单独调试各个功能模块,串口,红外,蜂鸣器。

您好,我是有问必答小助手,您的问题已经有小伙伴帮您解答,感谢您对有问必答的支持与关注!
PS:问答VIP年卡 【限时加赠:IT技术图书免费领】,了解详情>>> https://vip.csdn.net/askvip?utm_source=1146287632