51单片机温湿度调节系统

简介: 51单片机温湿度调节系统

电路:微信图片_20221012192836.png微信图片_20221012192839.png

程序:一个主函数,三个头文件分别对应设计中用到的三个主要元件

//主函数
#include<reg52.h>
#include <intrins.h>
#include <math.h>   
#include <stdio.h>
#include <1602.h>
#include <sht11.h>
#include <24c02.h>     
#define uchar unsigned char
#define uint  unsigned  int
#define W_cmd 0xa0   //24c02写指令
#define R_cmd 0xa1
uint temp,humi; 
value humi_val,temp_val;     //定义两个共同体,一个用于湿度,一个用于温度
uchar error;                 //用于检验是否出现错误
uchar checksum;              //CRC
uchar TEMP_data[7];          //用于记录实测的温度
uchar HUMI_data[6];          //用于记录实测的湿度
uchar show_temp[5];           //显示设定的温度
uchar show_humi[4];           //显示设定的湿度
uchar data temp_humi_cache[4]; //温湿度设置缓存
uchar temp_set;                 //保存温度变量
uchar humi_set;          //保存湿度变量
uchar presskeynum;    //按键次数变量
uchar nn;            //用于蜂鸣器
uchar code word1[]={"  a product of  "};
uchar code word2[]={"UNITED ELECTRONS"};
uchar code word3[]={" Welcome........"};
sbit k1=P2^0; //选择按键
sbit k2=P2^1; //增加按键
sbit k3=P2^2; //减小按键
sbit k4=P2^3;// 确认按键
sbit led1=P1^4;  //温度过低指示灯
sbit led2=P1^5; //  温度过高
sbit led3=P1^6; //湿度低于下限值,报警,加湿。
sbit led4=P1^7; //湿度过高,报警,不调湿
sbit motor1=P1^0;
sbit motor2=P1^1;
sbit motor3=P1^2;
sbit motor4=P1^3;
sbit P2_6=P2^6;
//********延时函数*********
void delay(uint z)  //z为毫秒数
{
     int a,b;
     for(a=z;a>0;a--)
     for(b=120;b>0;b--);
}
void key()
{
     uchar m;
     if (k1==0) //调整按键检测
     {
         delay(5);
         if (k1==0)
         {
             presskeynum++;
             if(presskeynum==3)
             presskeynum=0;
             while(k1==0);   //若一直按下,循环
             LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN);   //清屏
         }
     }
     if(presskeynum==1)//温度设置
     {
         if(k2==0)    // 加
         {
             delay(300);
             temp_set++;
             if (temp_set>30)
             temp_set=30;
             while(k2==0);       //加上此句必须松按键才处理
          }
          if(k3==0)//减
          {
               delay(300);
                temp_set--;
                if (temp_set<18)
                temp_set=18;
                while(k3==0);       //加上此句必须松按键才处理
           }
       }
         if(presskeynum==2)//湿度设置
         {
              if(k2==0)// 加
              {
                  delay(300);
                  humi_set++;
                  if (humi_set>99)
                  humi_set=99;
                  while(k2==0);
                }
                if(k3==0)//减
                {
                    delay(300);
                    humi_set--;
                    if (humi_set<1)
                    humi_set=1;
                  }
           }
       if(k4==0)// 退出键
       {
            delay(10);
            if(k4==0)
            {
                while(k4==0);
                presskeynum=0;
                temp_humi_cache[0]=temp_set/10;
                temp_humi_cache[1]=temp_set%10;
                temp_humi_cache[2]=humi_set/10;
                temp_humi_cache[3]=humi_set%10;
                for(m=0;m<4;m++)
                {  
                     WriteIIC(W_cmd,0x00+m,temp_humi_cache[m]);      //设定值写入24c02
                }
                LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN);   //清屏
             }
        }
}
//主函数
void main()
{ 
   uchar t;
     k1=k2=k3=k4=1;
   motor1=motor2=motor3=motor4=0;
   P2_6=0;
     for (t=0;t<4;t++)
     temp_humi_cache[t]=ReadIIC(W_cmd,0x00+t,R_cmd);  //读入24c02设定的值
     temp_set=temp_humi_cache[0]*10+temp_humi_cache[1];
     humi_set=temp_humi_cache[2]*10+temp_humi_cache[3];
     LCD_Initial();    //液晶初始化
     GotoXY(0,0);
     Print_slow(word1);
     GotoXY(0,1);
     Print_slow(word2);
     LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN);   //清屏
     GotoXY(0,0);
     Print_slow(word3);
     LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN);   //清屏                     
     while(1)
        {
         key();
             if(presskeynum==0)  //测量温湿度
             {                                                                  
             s_connectionreset(); //启动连接复位
             error=0;                                           //初始化error=0,即没有错误
             error+=s_measure((unsigned char*)&temp_val.i,&checksum,TEMP); //温度测量
             error+=s_measure((unsigned char*)&humi_val.i,&checksum,HUMI); //湿度测量
             if(error!=0)
       s_connectionreset();                 //如果发生错误,系统复位
             else
                 { 
                      humi_val.f=(float)humi_val.i;                   //转换为浮点数
                      temp_val.f=(float)temp_val.i;                   //转换为浮点数
                      calc_sth10(&humi_val.f,&temp_val.f);            //修正相对湿度及温度
                      temp=temp_val.f*10;
                      humi=humi_val.f*10;
            GotoXY(0,0);                                       //选择温度显示位置
                      Print("Temp:      C");                             //5格空格
                      GotoXY(0,1);                                       //选择湿度显示位置
                      Print("Humi:      %");                            //5格空格                            
                      GotoXY(5,0);                                      //设置温度显示位置
                      TEMP_data[0]=temp/1000+'0';                     //温度百位 
                      if (TEMP_data[0]==0x30) 
            TEMP_data[0]=0x20;
                      TEMP_data[1]=temp%1000/100+'0';                //温度十位      
                      if (TEMP_data[1]==0x30 && TEMP_data[0]!=0x30) 
            TEMP_data[1]=0x20;
                      TEMP_data[2]=temp%100/10+'0';                   //温度个位
                      TEMP_data[3]=0x2e;                              //小数点
                      TEMP_data[4]=temp%10+'0';                       //温度小数点后第一位            
                      TEMP_data[5]=0xdf;                              //显示温度符号℃
                      TEMP_data[6]='\0';
                      Print(TEMP_data);                                //输出温度                
                      GotoXY(5,1);                                    //设置湿度显示位置
            HUMI_data[0]=humi/1000+'0';                     //湿度百位                           
                      if (HUMI_data[0]==0x30)
            HUMI_data[0]=0x20;
                      HUMI_data[1]=humi%1000/100+'0';          //湿度十位      
                      HUMI_data[2]=humi%100/10+'0';            //湿度个位
                      HUMI_data[3]='.' ;                       //小数点
                      HUMI_data[4]=humi%10+'0';                //湿度小数点后第一位    
                      HUMI_data[5]='\0';
                      Print(HUMI_data);                         //输出湿度                     
            if ((temp/10)<temp_set)
            {
               led1=0; //加热
             motor1=1;
             led2=1;
             motor2=0;        
                         if((temp/10)==temp_set)
                         {
                  led1=1;
              motor1=0;
               }
             }
                      else if ((temp/10)>temp_set)
                      {
                led2=0; //制冷
              motor2=1;
              led1=1;
              motor1=0;
                          if ((temp/10)==temp_set)
              {
                              led2=1;
                motor2=0;
               }
             }
                      if ((humi/10)<humi_set)
                      {
                led3=0; //加湿
              motor3=1;
              led4=1;
              motor4=0;
                          if ((humi/10)==humi_set)
                          {
                   led3=1;
                 motor3=0;
               }
            }
                      else if ((humi/10)>humi_set)
                      {
                led4=0; //干燥
              motor4=1;
              led3=1;
              motor3=0;
                          if ((humi/10)==humi_set)
                          { 
                   led4=1;
                 motor4=0;
              }
             }
               }  //else
       }  //if
               if(presskeynum==1)  //设定温度时显示的内容
               {
                   show_temp[0]=temp_set/10+0x30;
                   show_temp[1]=temp_set%10+0x30;
                   show_temp[2]=0xdf;
                   show_temp[3]='C';
                   show_temp[4]='\0';
                   GotoXY (0,0);
                   Print("SET TEMP:");
                   GotoXY (0,1);
                   Print(show_temp);
               }
              if(presskeynum==2)                      //设定湿度时显示的内容
              {
                    show_humi[0]=humi_set/10+0x30;
                    show_humi[1]=humi_set%10+0x30;
                    show_humi[2]='%';
                    show_humi[3]='\0';
                    GotoXY (0,0);
                    Print("SET HUMI:");
                    GotoXY (0,1);
                    Print(show_humi);
               }
         }//while
}   //mian
//****************************24C02程序部分******************************************
#include <reg52.h>
#include <intrins.h>
#define uint  unsigned int 
#define uchar unsigned char
sbit  SCL=P3^0;// AT24C02时钟输入脚;
sbit  SDA=P3^1; // AT24C02 数据端
void Delay24(void) 
{
    unsigned char i;
    for(i=0;i<20;i++); 
}
void Delay24_10ms(void)
{
   unsigned int i;
   for(i=0;i<500;i++);
}
void start24(void)      
{ Delay24();
  SDA=0;            
  Delay24();
  SCL=0;
  Delay24();           //产生开始时序
}
void stop24(void)
{ Delay24();
  SCL=1;
  Delay24();
  SDA=1;
  Delay24();           //产生结束时序
}
 unsigned char ReadByte(void)
{
     unsigned char i,j;
     for(i=0;i<8;i++)      //循环读8位
     {
      SDA=1;         //置高,不影响后续读取
      Delay24();
      SCL=1;
      Delay24();
      j<<=1;
      j|=(bit)SDA;   //读1位
      Delay24();
      SCL=0;
      Delay24();
     }
   SDA=0;
   return(j);
}
void SendByte(unsigned char SendDat)
{
   unsigned char i,j;
   for(i=0;i<8;i++)       //循环8次
    {j=SendDat;
     SDA=j&0x80;          //送出1位
     Delay24();
     SCL=1;
     Delay24();
     SCL=0;
     SendDat<<=1;         //为下一位做准备
    }
   SDA=1;
   Delay24();
   SCL=1;
   Delay24();
   while(SDA==1);         //等待应答
   SCL=0;
   Delay24();
   SDA=0;
   Delay24();
}
//****写一字节***************************************************************
void WriteIIC(unsigned char Wcmd,add,dat)
{ 
   SDA=1;
   SCL=1;
   Delay24();
   start24();            //开始
   SendByte(Wcmd);      //命令
   SendByte(add);       //地址
   SendByte(dat);       //数据
   stop24();
   Delay24_10ms();
}
//****读一字节************************************
unsigned char ReadIIC(unsigned char Wcmd,add,Rcmd)
{  
   unsigned char i;
   SDA=1;
   SCL=1;
   Delay24();
   start24();            //开始
   SendByte(Wcmd);      //命令
   SendByte(add);       //地址
   SDA=1;
   SCL=1;
   start24();
   SendByte(Rcmd);      //读取
   i=ReadByte();
   stop24();  
   return(i);
}
#include<reg52.h>
#include <intrins.h>
#include <math.h>     
#include <stdio.h>  
sbit RS  = P2^4;
sbit RW  = P2^5;
sbit E  = P2^7;
sfr DBPort=0x80; //P0=0x80,数据端口
//********     1602函数声明     ********/
void LCD_Initial();
void GotoXY(unsigned char x, unsigned char y);
void Print(unsigned char *str);
void LCD_Write(bit style, unsigned char input);
void delay2()
{
  unsigned int i,j;
  for (i=0;i<100;i++)
  for (j=0;j<150;j++);
}
//1602程序
//内部等待函数*************************************************************
unsigned char LCD_Wait(void)
{
    RS=0;
    RW=1;    
  _nop_();
    E=1;   
   _nop_();           
    E=0;
    return DBPort;  
}
//向LCD写入命令或数据********************************************************
#define LCD_COMMAND         0      // Command
#define LCD_DATA            1      // Data
#define LCD_CLEAR_SCREEN    0x01      // 清屏
#define LCD_HOMING          0x02      // 光标返回原点
void LCD_Write(bit style, unsigned char input)
{
    E=0;
    RS=style;
    RW=0;       
  _nop_();
    DBPort=input;  
  _nop_();
    E=1;      
  _nop_();
    E=0;  
  _nop_();
    LCD_Wait(); 
}
//设置显示模式************************************************************
#define LCD_SHOW            0x04    //显示开
#define LCD_HIDE            0x00    //显示关 
#define LCD_CURSOR          0x02    //显示光标
#define LCD_NO_CURSOR       0x00    //无光标        
#define LCD_FLASH           0x01    //光标闪动
#define LCD_NO_FLASH        0x00    //光标不闪动
void LCD_SetDisplay(unsigned char DisplayMode)
{
    LCD_Write(LCD_COMMAND, 0x08|DisplayMode); 
}
//设置输入模式************************************************************
#define LCD_AC_UP       0x02
#define LCD_AC_DOWN     0x00      // default
#define LCD_MOVE        0x01      // 画面可平移
#define LCD_NO_MOVE     0x00      //default
void LCD_SetInput(unsigned char InputMode)
{
    LCD_Write(LCD_COMMAND, 0x04|InputMode);
}
//初始化LCD************************************************************
void LCD_Initial()
{
    E=0;
    LCD_Write(LCD_COMMAND,0x38);           //8位数据端口,2行显示,5*7点阵
    LCD_Write(LCD_COMMAND,0x38);
    LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR);    //开启显示, 无光标
    LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN);   //清屏
    LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE);       //AC递增, 画面不动
}
//液晶字符输入的位置************************
void GotoXY(unsigned char x, unsigned char y)
{
    if(y==0)
        LCD_Write(LCD_COMMAND,0x80|x);
    if(y==1)
        LCD_Write(LCD_COMMAND,0x80|(x-0x40));
}
//将字符输出到液晶显示
void Print(unsigned char *str)
{
    while(*str!='\0')
    {
        LCD_Write(LCD_DATA,*str);
        str++;
    }
}
//慢速显示字符
void Print_slow(unsigned char *str)
{
    while(*str!='\0')
    {
        LCD_Write(LCD_DATA,*str);
        str++;
    delay2();
    }
}
#include<reg52.h>
#include <intrins.h>
#include <math.h>    //Keil library 
#include <stdio.h>   //Keil library
#define uchar unsigned char
typedef union      //定义共同类型
{ unsigned int i;    //i表示测量得到的温湿度数据(int 形式保存的数据) 
 float f;        //f表示测量得到的温湿度数据(float 形式保存的数据)
} value;
enum {TEMP,HUMI};
sbit DATA = P3^3;
sbit SCK = P3^2;
//********     SHT11函数声明      ********/
void s_connectionreset(void);
char s_measure(unsigned char *p_value, unsigned char *p_checksum, unsigned char mode);
void calc_sth10(float *p_humidity ,float *p_temperature);
//*************************************************************************************/
//SHT11程序
#define noACK 0       //继续传输数据,用于判断是否结束通讯
#define ACK   1             //结束数据传输;
              //地址  命令  读/写
#define STATUS_REG_W 0x06   //000   0011    0
#define STATUS_REG_R 0x07   //000   0011    1
#define MEASURE_TEMP 0x03   //000   0001    1
#define MEASURE_HUMI 0x05   //000   0010    1
#define RESET        0x1e   //000   1111    0
//写字节程序
char s_write_byte(unsigned char value)   
{ 
  unsigned char i,error=0; 
  for (i=0x80;i>0;i/=2)             //shift bit for masking 高位为1,循环右移
  { 
    if (i&value) DATA=1;          //和要发送的数相与,结果为发送的位
      else DATA=0;                        
      SCK=1;                          
      _nop_();_nop_();_nop_();        //延时3us 
      SCK=0;
  }
  DATA=1;                           //释放数据线
  SCK=1;                            
  error=DATA;                       //检查应答信号,确认通讯正常
  _nop_();_nop_();_nop_();
  SCK=0;        
  DATA=1;
  return error;                     //error=1 通讯错误
}
//读字节程序
char s_read_byte(unsigned char ack)
//----------------------------------------------------------------------------------
{ 
  unsigned char i,val=0;
  DATA=1;                           //释放数据线
  for(i=0x80;i>0;i>>=1)             //高位为1,循环右移
  { 
    SCK=1;                         
      if(DATA) val=(val|i);        //读一位数据线的值 
      SCK=0;       
  }
  DATA=!ack;                        //如果是校验,读取完后结束通讯;
  SCK=1;                            
  _nop_();_nop_();_nop_();          //延时3us 
  SCK=0;   
  _nop_();_nop_();_nop_();       
  DATA=1;                           //释放数据线
  return val;
}
//启动传输
void s_transstart(void)
// generates a transmission start 
//       _____         ________
// DATA:      |_______|
//           ___     ___
// SCK : ___|   |___|   |______
{ 
    DATA=1; SCK=0;                   //准备
    _nop_();
    SCK=1;
    _nop_();
    DATA=0;
    _nop_();
    SCK=0; 
     _nop_();_nop_();_nop_();
    SCK=1;
    _nop_();
    DATA=1;     
    _nop_();
    SCK=0;     
}
//连接复位
void s_connectionreset(void)
// communication reset: DATA-line=1 and at least 9 SCK cycles followed by transstart
//       _____________________________________________________         ________
// DATA:                                                      |_______|
//          _    _    _    _    _    _    _    _    _        ___     ___
// SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______|   |___|   |______
{ 
  unsigned char i; 
  DATA=1; SCK=0;                    //准备
  for(i=0;i<9;i++)                  //DATA保持高,SCK时钟触发9次,发送启动传输,通迅即复位
  { 
    SCK=1;
      SCK=0;
  }
  s_transstart();                   //启动传输
}
//软复位程序
char s_softreset(void)
// resets the sensor by a softreset 
{ 
  unsigned char error=0; 
  s_connectionreset();              //启动连接复位
  error+=s_write_byte(RESET);       //发送复位命令
  return error;                     //error=1 通讯错误
}
//温湿度测量
char s_measure(unsigned char *p_value, unsigned char *p_checksum, unsigned char mode)
// 进行温度或者湿度转换,由参数mode决定转换内容;
{ 
//  enum {TEMP,HUMI};    //已经在头文件中定义
  unsigned error=0;
  unsigned int i;
  s_transstart();                   //启动传输
  switch(mode)                     //选择发送命令
    { 
    case TEMP : error+=s_write_byte(MEASURE_TEMP); break;      //测量温度
      case HUMI : error+=s_write_byte(MEASURE_HUMI); break;      //测量湿度
      default     : break; 
  }
  for (i=0;i<65535;i++) if(DATA==0) break; //等待测量结束
  if(DATA) error+=1;                // 如果长时间数据线没有拉低,说明测量错误 
  *(p_value) =s_read_byte(ACK);    //读第一个字节,高字节 (MSB)
  *(p_value+1)=s_read_byte(ACK);    //读第二个字节,低字节 (LSB)
  *p_checksum =s_read_byte(noACK); //read CRC校验码
  return error;          // error=1 通讯错误
}
//温湿度值标度变换及温度补偿
void calc_sth10(float *p_humidity ,float *p_temperature)
{ 
  const float C1=-4.0;              // 12位湿度精度 修正公式
  const float C2=+0.0405;           // 12位湿度精度 修正公式
  const float C3=-0.0000028;        // 12位湿度精度 修正公式
  const float T1=+0.01;             // 14位温度精度 5V条件  修正公式
  const float T2=+0.00008;          // 14位温度精度 5V条件  修正公式
  float rh=*p_humidity;             // rh:      12位 湿度 
  float t=*p_temperature;           // t:       14位 温度
  float rh_lin;                     // rh_lin: 湿度 linear值
  float rh_true;                    // rh_true: 湿度 ture值
  float t_C;                        // t_C   : 温度 ℃
  t_C=t*0.01 - 40;                  //补偿温度
  rh_lin=C3*rh*rh + C2*rh + C1;     //相对湿度非线性补偿
  rh_true=(t_C-25)*(T1+T2*rh)+rh_lin;   //相对湿度对于温度依赖性补偿
  if(rh_true>100)rh_true=100;       //湿度最大修正
  if(rh_true<0.1)rh_true=0.1;       //湿度最小修正
  *p_temperature=t_C;               //返回温度结果
  *p_humidity=rh_true;              //返回湿度结果
}
相关文章
|
6天前
|
传感器 编解码 人机交互
基于51单片机的温室大棚环境检测系统
基于51单片机的温室大棚环境检测系统
24 0
|
5月前
|
传感器 数据采集 监控
LabVIEW单片机的废气再循环EGR检测系统
LabVIEW单片机的废气再循环EGR检测系统
43 0
|
5月前
|
传感器
基于51单片机的车辆倒车雷达报警系统
该文描述了一个基于51单片机的超声波倒车雷达系统设计,要求包括:2cm至4m的测量范围,3mm精度,集成DS18B20温度传感器以校准声速,使用LCD1602显示距离和温度,具备按键设置预警距离及蜂鸣器报警功能。系统由AT89C51单片机、HC-SR04超声波模块、DS18B20温度模块、报警电路和LCD显示电路组成。文中还展示了Proteus仿真电路图和部分仿真结果分析,包括LCD显示示例和预警距离设置操作。
78 4
【期末不挂科-单片机考前速过系列P5】(第五章:11题速过中断系统和中断系统结构)经典例题盘点(带图解析)
【期末不挂科-单片机考前速过系列P5】(第五章:11题速过中断系统和中断系统结构)经典例题盘点(带图解析)
|
5月前
|
传感器 安全 物联网
单片机在智能家居系统中的应用研究
单片机在智能家居系统中的应用研究
172 1
|
5月前
|
芯片
AT89S52单片机的最小应用系统
AT89S52单片机的最小应用系统
85 0
|
5月前
|
传感器 数据处理 芯片
基于51单片机的自动售货机系统
该项目设计了一个基于AT89C51单片机的自动售货机系统,采用4×4矩阵键盘选择货物和投入货币,LCD1602液晶显示购物状态和货币状态,LED显示货物选择和出货情况。系统通过货币传感器检测投入的真伪和金额,根据商品价格进行找零。功能包括选择货物、货币识别、自动计算总价、出货与找零。仿真电路展示了从欢迎界面到购物、投币、出货或找零的过程。程序设计中包含了状态定义和延时函数等。
58 0
|
5月前
|
存储
【51单片机】初学者必读的一文【探究定时计数器与中断系统是如何配合起来的?】(9)
【51单片机】初学者必读的一文【探究定时计数器与中断系统是如何配合起来的?】(9)
【期末不挂科-单片机考前速过系列P10】(第十章:11题中断系统的工作原理及应用)经典例题盘点(带图解析)
【期末不挂科-单片机考前速过系列P10】(第十章:11题中断系统的工作原理及应用)经典例题盘点(带图解析)
|
5月前
2-1 51单片机最小系统构成
2-1 51单片机最小系统构成
56 0

热门文章

最新文章