感冒灵糖浆 2021-09-14 18:40 采纳率: 0%
浏览 146
已结题

51单片机温湿度控制

51单片机温湿度控制,温度达到范围led灯和继电器没有运作,请问是什么地方出了问题?谢谢大家!

#include <reg52.h>
#include <intrins.h>
#include <absacc.h>
#include <math.h>               //包含头文件
  
#define uchar unsigned char
#define uint unsigned int       //宏定义

//定义四个输出端口
sbit Led_fengshan1=P3^2;    
sbit Led_fengshan2=P3^3;
sbit Led_fengshan3=P3^4;
sbit Led_penwu=P3^6;        
//定义24C02数据口
sbit SCL = P1^0;
sbit SDA = P1^1;
//定义DHT11数据口
sbit DATA = P1^7;

//定义LCD1602端口
sbit E=P1^3;        //1602使能引脚
//sbit RW=P2^6;        //1602读写引脚     我们只需要向液晶里写数据,不需要读取数据,所以就把读写引脚直接接地,程序里就不用单独控制了
sbit RS=P1^2;        //1602数据/命令选择引脚
//定义全局变量
uchar U8FLAG,U8temp,U8comdata,U8RH_data_H_temp,U8RH_data_L_temp,U8T_data_H_temp,U8T_data_L_temp,U8checkdata_temp;    //定义读取温湿度变量
uchar U8RH_data_H,U8RH_data_L,U8T_data_H,U8T_data_L,U8checkdata;
uchar Mode,humidity,temperature;                                                                                    //设置模式、读取到的湿度温度数据存储变量
bit bdata FlagStartRH,hot,cold,humid,dry;                                                                             //开启转换温湿度标志位、热冷湿干

//定时器0初始化
void Timer0_Init()
{
    ET0 = 1;        //允许定时器0中断
    TMOD = 0x11;       //定时器工作方式选择
    TL0 = 0xb0;     
    TH0 = 0x3c;     //定时器赋予初值50ms
    TR0 = 1;        //启动定时器T0
}

//定时器0中断
void Timer0_ISR (void) interrupt 1 using 0
{
    uchar RHCounter;                 //定义计数变量
    TL0 = 0xb0;
    TH0 = 0x3c;     //定时器赋予初值
    RHCounter++;                     //每进一次中断就是50ms,此变量加一
    if(RHCounter%10==0)                 //加到10的整数倍 
    //每2秒钟启动一次温湿度转换
    if (RHCounter >= 40)             //计数到40次,就是2s,启动一次温湿度转换
    {
       FlagStartRH = 1;                 //启动转换变量置1
       RHCounter = 0;                 //计数变量清零
    }
}

/*以下程序为24c02的程序,都是官方的实例程序,可以参考时序图理解,都是固定的*/

/*********************************
      BASE  DRIVE
**********************************/
void DELAY(unsigned int t)              //延时函数
{
    while(t!=0)
    t--;
}

/******************************
      IIC  DRIVE
******************************/
void IICStart(void)                     //24c02的开始函数,关于24c02的函数多看下24c02的手册
{
     SCL=0;                           //SCL引脚拉低
      DELAY(1);                         //短延时
     SDA=1; SCL=1; DELAY(1);         //SDA拉高,SCL拉高,短延时
     SDA=0; DELAY(1);                 //SDA拉低,短延时
     SCL=0;                          //SCL拉低
}

void IICStop(void)                     //停止
{
     SDA=0;SCL=1; DELAY(1);             //注释略
     SDA=1; DELAY(1);
     SCL=0;     
}
void SEND0(void)                     //发送
{
    SDA=0;
    SCL=1;
    DELAY(1);
    SCL=0;
}

void SEND1(void)
{
    SDA=1;
    DELAY(1);
    SCL=1;
    DELAY(1);
    SCL=0;
}

bit Check_Ack(void)                        //应答
{
    unsigned char errtime=250;            //定义变量
    DELAY(1);                        
    SCL=1; 
    DELAY(1);
    CY=SDA;                                //SDA引脚高电平就是1,低电平就是0,赋值给CY
    while(CY)                            //如果CY为1,就执行此while
    {
        errtime--;                         //变量减
        CY=SDA;                            //赋值
        if (!errtime)                    //判断有没有减到0
        {
            IICStop();                    //停止24C02
            return 1;                    //返回1
        }
    }
    DELAY(1);
    SCL=0; 
    return 0;
}

void Write_byte(unsigned char dat) 
{
    unsigned char i;
    for(i=0;i<8;i++)
    {    
        if((dat<<i)&0x80)
        SEND1();
        else
        SEND0();
    }
}

unsigned char Read_byte(void)
{
    unsigned char i,temp=0;     
    for(i=0;i<8;i++)
    {
        SDA=1;
        SCL=1;
        DELAY(1);  
        if(SDA==1)
        {
            temp=temp<<1;
            temp=temp|0x01;
        }
        else
        temp=temp<<1;
         SCL=0;    
      }
      return temp;
}

/************************************
      EEPROM  DRIVE
      Addr:from 0x00-->
*************************************/
unsigned char rdeeprom(unsigned char addr)
{ 
        unsigned char temp=0;
        bit flag=0;
        IICStart();
        Write_byte(0xa0);
        Check_Ack();
        Write_byte(addr);
        Check_Ack();
        IICStart();
        Write_byte(0xa1);
        Check_Ack();
        temp=Read_byte();
        SEND1();
        IICStop();
         return temp;   
}  
    
   
void wrteeprom(unsigned char addr,unsigned char dat)
{
           IICStart();
        Write_byte(0xa0);
        Check_Ack();
        Write_byte(addr);
        Check_Ack();
        Write_byte(dat);
        Check_Ack();
        IICStop();
}

/*以下程序为DHT11温湿度传感器程序,官方的实例程序*/


void Delay1(uint j)            //延时程序
{
    uchar i;
    for(;j>0;j--)
    {     
        for(i=0;i<27;i++);
    }
} 

void  Delay_10us(void)          //延时函数,大约10us,不精确
{
    uchar i;
    i--;
    i--;
    i--;
    i--;
    i--;
    i--;
}    

void  COM(void)                                     //读取温湿度函数
{
    uchar i;
    for(i=0;i<8;i++)       
    {
          U8FLAG=2;
           while((!DATA)&&U8FLAG++);
        Delay_10us();
        Delay_10us();
        Delay_10us();
          U8temp=0;
        if(DATA)U8temp=1;
            U8FLAG=2;
        while((DATA)&&U8FLAG++);
           //超时则跳出for循环          
           if(U8FLAG==1)break;
           //判断数据位是0还是1     
              
        // 如果高电平高过预定0高电平值则数据位为 1 
            
        U8comdata<<=1;
           U8comdata|=U8temp;        //0
    }//rof
}

//--------------------------------
//-----温湿度读取子程序 ------------
//--------------------------------
//----以下变量均为全局变量--------
//----温度高8位== U8T_data_H------
//----温度低8位== U8T_data_L------
//----湿度高8位== U8RH_data_H-----
//----湿度低8位== U8RH_data_L-----
//----校验 8位 == U8checkdata-----
//----调用相关子程序如下----------
//---- Delay();, Delay_10us();,COM(); 
//--------------------------------
uchar RH(void)
{
    //主机拉低18ms 
    DATA=0;
    Delay1(180);  //原来为5
    DATA=1;
    //总线由上拉电阻拉高 主机延时20us
    Delay_10us();
    Delay_10us();
    Delay_10us();
    Delay_10us();
    //主机设为输入 判断从机响应信号 
    DATA=1;
    //判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行      
    if(!DATA)         //T !      
    {
        U8FLAG=2;
        //判断从机是否发出 80us 的低电平响应信号是否结束     
        while((!DATA)&&U8FLAG++);
        U8FLAG=2;
        //判断从机是否发出 80us 的高电平,如发出则进入数据接收状态
        while((DATA)&&U8FLAG++);
        //数据接收状态         
        COM();
        U8RH_data_H_temp=U8comdata;
        COM();
        U8RH_data_L_temp=U8comdata;
        COM();
        U8T_data_H_temp=U8comdata;
        COM();
        U8T_data_L_temp=U8comdata;
        COM();
        U8checkdata_temp=U8comdata;
        DATA=1;
        //数据校验 
        U8temp=(U8T_data_H_temp+U8T_data_L_temp+U8RH_data_H_temp+U8RH_data_L_temp);
        if(U8temp==U8checkdata_temp)
        {
              U8RH_data_H=U8RH_data_H_temp;
              U8RH_data_L=U8RH_data_L_temp;
              U8T_data_H=U8T_data_H_temp;
              U8T_data_L=U8T_data_L_temp;
              U8checkdata=U8checkdata_temp;
        }
        return 1;
    }
    else   //传感器不响应
    {
       return 0;
    }
}

/********************************************************************
* 文件名  : 液晶1602显示.c
* 描述    :  该程序实现了对液晶1602的控制。
***********************************************************************/


/********************************************************************
* 名称 : delay()
* 功能 : 延时,延时时间大概为140US。
* 输入 : 无
* 输出 : 无
***********************************************************************/

void delay()                             
{
    int i,j;
    for(i=0; i<=10; i++)
    for(j=0; j<=2; j++);
}      
    
/********************************************************************
* 名称 : enable(uchar del)
* 功能 : 1602命令函数
* 输入 : 输入的命令值
* 输出 : 无
***********************************************************************/

void enable(uchar del)
{
    P0 = del;                      //数据发送到P0口
    RS = 0;                          //RS引脚拉低
    E = 1;                          //E引脚高电平
    delay();                      //延时
    E = 0;                          //E引脚低电平
    delay();                      //延时
}

/********************************************************************
* 名称 : write(uchar del)
* 功能 : 1602写数据函数
* 输入 : 需要写入1602的数据
* 输出 : 无
***********************************************************************/

void write(uchar del)
{
    P0 = del;                       //同上
    RS = 1;
    E = 1;
    delay();
    E = 0;
    delay();
}

/********************************************************************
* 名称 : L1602_init()
* 功能 : 1602初始化,请参考1602的资料
* 输入 : 无
* 输出 : 无
***********************************************************************/
void L1602_init(void)
{
    
    enable(0x38);          //设置液晶工作模式,意思:16*2行显示,5*7点阵,8位数据
    enable(0x0c);          //开显示不显示光标
    enable(0x06);           //整屏不移动,光标自动右移
    enable(0x01);         //清屏
}

/********************************************************************
* 名称 : L1602_char(uchar hang,uchar lie,char sign)
* 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符显示"b" ,调用该函数如下
         L1602_char(1,5,'b')
* 输入 : 行,列,需要输入1602的数据
* 输出 : 无
***********************************************************************/
void L1602_char(uchar hang,uchar lie,char sign)
{
    uchar a;                                     //定义变量
    if(hang == 1) a = 0x80;                         //如果hang变量为1,让地址数据为0x80就是第一行的
    if(hang == 2) a = 0xc0;                         //如果hang变量为0,让地址数据为0xc0就是第二行的
    a = a + lie - 1;                             //列数据减一,因为液晶屏的列是从0开始的
    enable(a);                                     //发送行和列数据
    write(sign);                                 //写显示内容
}

/********************************************************************
* 名称 : L1602_string(uchar hang,uchar lie,uchar *p)
* 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符开始显示"ab cd ef" ,调用该函数如下
          L1602_string(1,5,"ab cd ef;")
* 输入 : 行,列,需要输入1602的数据
* 输出 : 无
***********************************************************************/
void L1602_string(uchar hang,uchar lie,uchar *p)
{
    uchar a;
    if(hang == 1) a = 0x80;                 //第一行地址
    if(hang == 2) a = 0xc0;                 //第二行地址
    a = a + lie - 1;                     //行和列数据加一起
    enable(a);                             //发送行列数据
    while(1)                             //进入循环
    {
        if(*p == '\0') break;             //发送完字符串后跳出while循环
        write(*p);                         //没发送完就继续发
        p++;                             //字符串指针地址加1
    }
}

//显示整型的温湿度数据用,共占用4位,其中一位符号位
void L1602_int(uchar hang, uchar lie, int num)
{
   uint temp;
   uint gewei,shiwei,baiwei,sign;
   if (num >= 0)                             //如果温度值大于等于0
   sign = 0;                                 //符号为正
   else                                         //反之
   sign = 1;                                 //符号为负
   temp = abs(num);                             //温度值取绝对值
   baiwei = temp / 100;                         //除以100得到温度值百位
   temp = temp - baiwei*100;                 //温度值减去百位得到十位和个位的数
   shiwei = temp / 10;                         //除以10得到十位的数据
   gewei = temp - shiwei*10;                 //减去十位的数据得到个位的数
   num = abs(num);                             //温度取绝对值
   if (num>=100)                             //如果温度大于100
   {
   //   L1602_char(hang, lie+1, baiwei+48);  
      L1602_char(hang, lie+2, shiwei+48);       //显示十位和个位
      L1602_char(hang, lie+3, gewei+48);  
   }
   else if (num>=10)                         //温度大于10
   {
      if (sign == 1)                            //负数时
      L1602_char(hang, lie+1, '-');             //显示负号
      L1602_char(hang, lie+2, shiwei+48);       //显示十位和个位数
      L1602_char(hang, lie+3, gewei+48);
   }
   else                                         //温度小于10
   {
      if (sign == 1)                            //负数时
      L1602_char(hang, lie+2, '-');             //显示负号
      else                                     //正数
      L1602_char(hang, lie+2, ' ');             //十位不显示
      L1602_char(hang, lie+3, gewei+48);       //显示个位数
   }
}

void display()                                             //显示函数
{                                                         
    if(Mode==0)                                             //不是设置状态
    {
        L1602_int(1,3,temperature);                         //显示温度数据
        L1602_char(1,7,0xdf);                             //显示摄氏度的°
        L1602_int(1,12,humidity);                          //显示湿度数据

        if(hot==1&&cold==0&&humid==0&&dry==0)             //温度过高
        {L1602_string(2,1," It's very hot! ");}          //显示热
        else if(hot==1&&cold==0&&humid==1&&dry==0)         //温度高,湿度高
        {L1602_string(2,1," Hot and humid! ");}             //显示热 ,湿
        else if(hot==1&&cold==0&&humid==0&&dry==1)         //温度高 ,湿度低
        {L1602_string(2,1,"  Hot and dry!  ");}             //显示热 ,干
        else if(hot==0&&cold==1&&humid==0&&dry==0)         //温度低
        {L1602_string(2,1," It's very cold!");}             //显示冷
        else if(hot==0&&cold==1&&humid==1&&dry==0)         //温度低 ,湿度高
        {L1602_string(2,1," Cold and humid!");}             //显示冷 ,湿
        else if(hot==0&&cold==1&&humid==0&&dry==1)         //温度低 ,湿度低
        {L1602_string(2,1,"  Cold and dry! ");}             //显示冷 ,干
        else if(hot==0&&cold==0&&humid==1&&dry==0)         //湿度高
        {L1602_string(2,1,"It's very humid!");}             //显示潮湿
        else if(hot==0&&cold==0&&humid==0&&dry==1)         //湿度低
        {L1602_string(2,1," It's very dry! ");}             //显示干燥
        else if(hot==0&&cold==0&&humid==0&&dry==0)         //都在范围内
        {L1602_string(2,1,"Good environment");}             //显示环境好
    }                                      
}

//数据初始化
void Data_Init()
{
   Led_fengshan1 = 1;
   Led_fengshan2 = 1;
   Led_fengshan3 = 1;
   Led_penwu = 1;                //熄灭四个继电器
}

/********************************************************************
* 名称 : Main()
* 功能 : 主函数
***********************************************************************/
void main()
{
    uint i, j, testnum;

    EA = 0;                         //关闭定时器

    Timer0_Init();  //定时器0初始化

    Data_Init();                    //数据初始化
    EA = 1;                            //打开定时器

    L1602_init();                             //液晶屏初始化
    L1602_string(1,1," Welcome to T&H ");
    L1602_string(2,1," Control System!");     //开机显示界面
    //延时
    for (i=0;i<1000;i++)                     //延时
       for (j=0;j<100;j++)
       {;}
    //清屏
    L1602_string(1,1,"                ");
    L1602_string(2,1,"                ");
    L1602_string(1,1,"Tem:   C Hum:  %");
    L1602_string(2,1,"Good environment");     //显示待机界面
    
    while(1)                                 //进入while循环
    {
       
         if (FlagStartRH == 1)     //温湿度转换标志检查
         {
             TR0 = 0;                         //关闭定时器
             testnum = RH();                 //读取温湿度
              FlagStartRH = 0;                 //转换标志清零
             TR0 = 1;                         //打开定时器
             humidity = U8RH_data_H;     //读出湿度,只取整数部分
             temperature = U8T_data_H;      //读出温度

             
             if(Mode==0)        //温湿度控制
             {
                if (humidity > 90)
                {
                    humid=1;
                    dry=0;
                }
                else if(humidity<25)
                {
                    dry=1;
                    humid=0;
                }
                
                    
                if (temperature < 25)         
                {
                    Led_fengshan1 = 1;         
                    Led_fengshan2 = 1;        
                    Led_fengshan3 = 1;
                    Led_penwu = 1;
                    hot=0;                                        
                    cold=0;                
                }
                else if(25 < temperature < 30)    
                {
                    Led_fengshan1 = 0;        
                    Led_fengshan2 = 1;        
                    Led_fengshan3 = 1;
                    Led_penwu = 1;
                    hot=1;                                         
                    cold=0;                     
                }
                else if(30 < temperature < 32)         
                {
                    Led_fengshan1 = 0;
                    Led_fengshan2 = 1;
                    Led_fengshan3 = 1;
                    Led_penwu = 0;
                    hot=1;
                    cold=0;
                }              
                else if(32 < temperature < 34)         
                {
                    Led_fengshan1 = 0;
                    Led_fengshan2 = 0;
                    Led_fengshan3 = 1;
                    Led_penwu = 0;
                    hot=1;
                    cold=0;
                }                  
                else if(temperature > 34)                 
                {
                    Led_fengshan1=0;
                    Led_fengshan2=0;
                    Led_fengshan3=0;
                    Led_penwu=0;
                    hot=1;
                    cold=0;
                }
    
                else                     
                {
                    humid=0;
                    dry=0;
                }    
             }
        }
        display();                    
    }    
}


  • 写回答

1条回答 默认 最新

  • _WindChimes 2021-09-15 15:42
    关注
    1. 可以设置断点或者打印看看程序是否运行你预想的地方;
    2. 如果第一条满足:需要测试管脚是否焊接良好或者管教是否损坏[主要用万用表测试通断/电平];如果都是正常的,需要考虑下你设计的电路有没有问题了
      注:以上是解决问题的思路
    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 3月9日
  • 创建了问题 9月14日

悬赏问题

  • ¥15 MATLAB怎么通过柱坐标变换画开口是圆形的旋转抛物面?
  • ¥15 寻一个支付宝扫码远程授权登录的软件助手app
  • ¥15 解riccati方程组
  • ¥15 display:none;样式在嵌套结构中的已设置了display样式的元素上不起作用?
  • ¥30 用arduino开发esp32控制ps2手柄一直报错
  • ¥15 使用rabbitMQ 消息队列作为url源进行多线程爬取时,总有几个url没有处理的问题。
  • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决
  • ¥50 树莓派安卓APK系统签名
  • ¥65 汇编语言除法溢出问题
  • ¥15 Visual Studio问题