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; //允许串口中断 }
上一篇:单片机+VB上位机温湿度检测制作
下一篇:Sdcc编译环境下中断函数的编写