单片机
返回首页

51单片机的二氧化碳、温湿度检测系统

2020-09-23 来源:51hei

基于51单片机的二氧化碳、温湿度检测系统设计。采用LCD1602显示,CO2传感器使用MH-Z19B,温湿度传感器使用DHT11

制作出来的实物图如下:
 

Altium Designer画的原理图和PCB图如下:(51hei附件中可下载工程文件)
 


单片机源程序如下:

/********************************** (C) COPYRIGHT *******************************

* File Name        : main.C

* Author                :

* License                : MIT

* Version                : V1.0

* Date                        : 2019/04/12

* Description                : 51温湿度二氧化碳检测

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

#include

#include '1602.h'

#include 'dht.h'

#include '2402.h'


#define uchar unsigned char

#define uint  unsigned int

#define ulong unsigned long

       

//定义三个LED灯

sbit Led_qushi = P1^0;                  //去湿灯

sbit Led_jiangwen = P1^1;                //降温灯

sbit led_CO2 = P1^2;        //二氧化碳控制灯

//定义蜂鸣器

sbit fmq = P2^3;        //蜂鸣器

//定义设置键、调整键

sbit Key_TH1 = P3^0;//温度上限值调整按键

sbit Key_TH2 = P3^1;

sbit Key_HH1 = P3^2;//湿度上限值调整按键

sbit Key_HH2 = P3^3;

sbit shezhi  = P2^7;//设置键

sbit Key_CH1 = P2^6;//二氧化碳上限值调整按键

sbit Key_CH2 = P2^5;


//二氧化碳发送指令

uchar  code tab[9]={0xff,0x01,0x86,0x00,0x00,0x00,0x00,0x00,0x79};

uchar  date[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};


//定义标识

volatile bit FlagStartRH = 0;  //开始温湿度转换标志

volatile bit FlagKeyPress = 0; //有键按下

volatile bit fmqt = 0;

volatile bit fmqh = 0;

volatile bit fmqc = 0;

//定义温湿度传感器用外部变量

extern U8  U8FLAG,k;

extern U8  U8count,U8temp;

extern U8  U8T_data_H,U8T_data_L,U8RH_data_H,U8RH_data_L,U8checkdata;

extern U8  U8T_data_H_temp,U8T_data_L_temp,U8RH_data_H_temp,U8RH_data_L_temp,U8checkdata_temp;

extern U8  U8comdata;

extern U8  count, count_r;

U16 temp;

S16 temperature, humidity;

S16 idata TH, HH, ch;  //温度上限和湿度上限//二氧化碳上限值

char * pSave;

U8 keyvalue, keyTH1, keyTH2, keyHH1, keyHH2, keyCH1, keyCH2;

unsigned char moshi=0;

//定义变量

U16 RHCounter;


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

    延时子程序

        延时时间(xms*1)ms

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

void delayms(uint xms)

{

        uint x,y;

        for(x=xms;x>0;x--)

                for(y=110;y>0;y--);

}

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

*  功    能          :  串口发送

*  注意事项          :  

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

void send(uchar dat)         //发送一字节   

{

  SBUF=dat;

  while(!TI);

  TI=0;

}

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

*  功    能          :  数据初始化程序

*  注意事项          :  

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

void Data_Init()

{

   RHCounter = 0;

   Led_qushi = 1;

   Led_jiangwen = 1;

   led_CO2 = 1;

   TH = 40;  //温度初始上限值

   HH = 85;  //湿度初始上限限制

         ch = 25;  //二氧化碳初始上限值

   keyvalue = 0;

   keyTH1 = 1;

   keyTH2 = 1;

   keyHH1 = 1;

   keyHH2 = 1;

         keyCH1 = 1;

         keyCH2 = 1;

}


//定时器0初始化

void Timer0_Init()

{

        ET0 = 1;        //允许定时器0中断

        TMOD = 1;       //定时器工作方式选择

        TL0 = 0x06;     

        TH0 = 0xf8;     //定时器赋予初值

        TR0 = 1;        //启动定时器

}


//存入设定值、

void Save_Setting()

{

   pSave =  (char *)&TH;          //地址低位对应低8位,高位对应高8位

   wrteeprom(0, *pSave);          //存温度上限值TH低8位

   DELAY(300);

   pSave ++;

   wrteeprom(1, *pSave);          //存温度上限值TH高8位

   DELAY(300);

   pSave =  (char *)&HH;

   wrteeprom(2, *pSave);          //存湿度上限值RH低8位

   DELAY(300);

   pSave ++;

   wrteeprom(3, *pSave);          //存湿度上限值RH高8位

   DELAY(300);

         pSave =  (char *)&ch;

   wrteeprom(4, *pSave);          //存CO2上限值RH低8位

   DELAY(300);

   pSave ++;

   wrteeprom(5, *pSave);          //存CO2上限值RH高8位

   DELAY(300);

}


//载入设定值、

void Load_Setting()

{

   pSave =  (char *)&TH;

   *pSave++ = rdeeprom(0);

   *pSave = rdeeprom(1);

   pSave = (char *)&HH;

   *pSave++ = rdeeprom(2);

   *pSave = rdeeprom(3);

         pSave = (char *)&ch;

   *pSave++ = rdeeprom(4);

   *pSave = rdeeprom(5);

   if ((TH>99)||(TH<0)) TH = 40;

   if ((HH>99)||(HH<0)) HH = 85;

         if ((ch>50)||(ch<0)) ch = 25;

}

//按键扫描程序

void Key_set_scan()

{

  if(shezhi==0)

          {

           delayms(10);

                if(shezhi==0)

                {  

                   while(!shezhi);

                   L1602_init(); //初始化液晶

                   moshi++;

                   if(moshi >= 2)moshi = 0;

                   if(moshi == 0)

                   {

                                L1602_string(1,1,'Te:   C  ');

                                L1602_string(1,9,'Hu:   %  ');

                                L1602_string(2,1,'PPM:   ');            

                   }

                   else if(moshi == 1)

                   {

                                L1602_string(1,1,'TH:');

                                L1602_string(1,9,'HH:');

                                L1602_string(2,1,'CH:');

                                L1602_string(2,8,'0');  

                                L1602_string(2,9,'0');

                   }                                            

                }

        }

}       

//按键加减设定值

void KeyProcess(uint num)

{                       

   switch (num)

   {

      case 1:

             if (TH<99) TH++;

             L1602_char(1, 5, TH/10+48);

             L1602_char(1, 6, TH%10+48);

             break;

          case 2:

             if (TH>1) TH--;

             L1602_char(1, 5, TH/10+48);

             L1602_char(1, 6, TH%10+48);

             break;

          case 3:

             if (HH<99) HH++;

             L1602_char(1, 13, HH/10+48);

             L1602_char(1, 14, HH%10+48);

             break;

          case 4:

             if (HH>1) HH--;

             L1602_char(1, 13, HH/10+48);

             L1602_char(1, 14, HH%10+48);

             break;

         case 5:

             if (ch<50) ch++;

             L1602_char(2, 6, ch/10+48);

             L1602_char(2, 7, ch%10+48);

             break;

         case 6:

             if (ch>1) ch--;

             L1602_char(2, 6, ch/10+48);

             L1602_char(2, 7, ch%10+48);

             break;

          default:

             break;

   }

   Save_Setting();


}


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

* 函 数 名         :  main

* 函数功能                     : 主函数

* 输    入         : 无

* 输    出         : 无

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

void main()

{

          U16 testnum;

                uint  tmp;

                uchar m;

          EA = 0;

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

    Data_Init();

                EA = 1;


                TMOD=0x20;         // T1定时方式2

                SCON=0x40;//串行工作 方式1

                PCON=0x00; //不加倍

                TH1=TL1=0xfd; //定时器1赋初值  保证波特率9600

                TR1=1;                  //开定时器1

                REN=1;                  //允许串口接收

                delayms(10);

                ES=1;                  //打开串口中断

                EA=1;                  //开总中断


          L1602_init();

          Load_Setting();

        while(1)

        {               

                for(m=0;m<9;m++)  //向co2传感器发送数据

                {

                                send(tab[m]);

                }

                 delayms(100);  //延时0.1s  刷新测得数据

                 tmp=date[2]*256+date[3];        //计算出co2浓度值

               

       //温湿度转换标志检查

                 if (FlagStartRH == 1)

                 {

                     TR0 = 0;

         testnum = RH();

                         FlagStartRH = 0;

                         TR0 = 1;

             //读出温湿度,只取整数部分

                         humidity = U8RH_data_H;

                         temperature = U8T_data_H;

                }

                //温湿度控制

                if (temperature > TH)

                {

                Led_jiangwen = 0;

                fmqt=1;

                }

                else

                {

                Led_jiangwen = 1;

                fmqt=0;

                }                                //降温

                if (humidity > HH)

                {

                Led_qushi = 0;

                fmqh=1;

                }

                else

                {

                Led_qushi = 1;

                fmqh=0;

                }                                                //去湿

                if (tmp/100 > ch)

                {

                led_CO2 = 0;

                fmqc=1;

                }

                else

                {

                led_CO2 = 1;

                fmqc=0;

                }                                                //CO2

                if((fmqt==1)||(fmqh==1)||(fmqc==1))

                fmq=0;

                else

                fmq=1;

               

               

                Key_set_scan();//按键扫描

                 if(moshi == 0)          //设置模式切换

                {

                        delayms(50);

                        L1602_string(1,1,'Te:   C  ');

                        L1602_string(1,9,'Hu:   %  ');

                        L1602_string(2,1,'PPM:   ');   

                        if(tmp>9999)

                        tmp=0;   

                        L1602_int(2,5,tmp);

                        if((tmp/1000)>0)               

                        L1602_int(2,5,tmp/1000);       

                        //显示温湿度

                        L1602_int(1,3, temperature);

                        L1602_int(1,11,humidity);

                }

                else if(moshi == 1)        //设置上限模式

                {

                        L1602_char(1, 5,  TH/10+48);

                        L1602_char(1, 6,  TH%10+48);

                        L1602_char(1, 13, HH/10+48);

                        L1602_char(1, 14, HH%10+48);

                        L1602_char(2, 6,  ch/10+48);

            L1602_char(2, 7,  ch%10+48);

                }                       

               

    //U8 keyvalue, keyTH1, keyTH2, keyHH1, keyHH2, keyCH1, keyCH2;

                //键盘查询,在弹起时响应

                if ((Key_TH1)&&(keyTH1==0)) {FlagKeyPress = 1; keyvalue = 1;}

                        else if ((Key_TH2)&&(keyTH2==0)) {FlagKeyPress = 1; keyvalue = 2;}

                        else if ((Key_HH1)&&(keyHH1==0)) {FlagKeyPress = 1; keyvalue = 3;}

                        else if ((Key_HH2)&&(keyHH2==0)) {FlagKeyPress = 1; keyvalue = 4;}

                        else if ((Key_CH1)&&(keyCH1==0)) {FlagKeyPress = 1; keyvalue = 5;}

                        else if ((Key_CH2)&&(keyCH2==0)) {FlagKeyPress = 1; keyvalue = 6;}

                if (FlagKeyPress == 1)

                {

                          KeyProcess(keyvalue);

                          FlagKeyPress = 0;           

                }

        if (!Key_TH1) keyTH1 = 0;

                else keyTH1 = 1;

        if (!Key_TH2) keyTH2 = 0;

                else keyTH2 = 1;

        if (!Key_HH1) keyHH1 = 0;

                else keyHH1 = 1;

        if (!Key_HH2) keyHH2 = 0;

                else keyHH2 = 1;

               

                    if (!Key_CH1) keyCH1 = 0;

                else keyCH1 = 1;

        if (!Key_CH2) keyCH2 = 0;

                else keyCH2 = 1;

                 

        }       

}

//定时器0中断

void Timer0_ISR (void) interrupt 1

{

        TL0 = 0x06;

        TH0 = 0xf8;     //定时器赋予初值


        //每2秒钟启动一次温湿度转换

    RHCounter ++;

    if (RHCounter >= 1000)

    {

       FlagStartRH = 1;

             RHCounter = 0;

    }

}


//串口中断服务函数

void serial()interrupt 4               

{

                static uchar j;

                ES=0;                         //禁止中断

                if(!RI);

                RI=0;                    //清楚接收完毕标志

                date[j]=SBUF;

                if(date[0]==0xff)  //判断接收到的第一位为传感器所发数据

                j++;

                else

                j=0;

                if(j==9)                   //接收传感器所发数据9字节

                j=0;

                ES=1;                  //允许串口中断

}



进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 用数字电路CD4069制作的万能遥控轻触开关

  • 红外线探测报警器

  • 短波AM发射器电路设计图

  • RS-485基础知识:处理空闲总线条件的两种常见方法

  • 带有短路保护系统的5V直流稳压电源电路图

  • 基于ICL296的大电流开关稳压器电源电路

    相关电子头条文章