目录
ARM-STM32校园创新大赛 1
题 目: 智能家居环境小护士 1
摘要 1
引言 2
- 系统方案 3
整套系统的工作原理是:单片机是整套系统的控制核心,温湿度传感器负责测试环境中的温湿度;烟雾传感器负责检测空气中的有毒气体,如甲醛和硫氢化物;加湿器负责加湿;当烟雾传感器检测到环境中存在有毒气体时,这个消息被单片机检测到后,单片机就会告诉通讯模块,通讯模块就会发短信通知主人;如果无有毒气体,温湿度传感器测得的温湿度在显示模块上上显示出来,环境中太干时,加湿器就加湿。各个模块各自有各自的任务,互相合作,共同营造一个舒适的环境。 3 - 系统硬件设计 3
2.1温湿度传感器 3
2.2 烟雾传感器 3
2.3加湿器 3
2.4单片机最小系统 3
2.5 矩阵键盘 3
2.6 通信模块 4 - 系统软件设计 4
软件调试 4 - 系统创新 4
- 评测与结论 5
附录 5
1.系统方案
整套系统的工作原理是:单片机是整套系统的控制核心,温湿度传感器负责测试环境中的温湿度;烟雾传感器负责检测空气中的有毒气体,如甲醛和硫氢化物;加湿器负责加湿;当烟雾传感器检测到环境中存在有毒气体时,这个消息被单片机检测到后,单片机就会告诉通讯模块,通讯模块就会发短信通知主人;如果无有毒气体,温湿度传感器测得的温湿度在显示模块上上显示出来,环境中太干时,加湿器就加湿。各个模块各自有各自的任务,互相合作,共同营造一个舒适的环境。
2.系统硬件设计
2.1温湿度传感器
DHT11在整套系统中主要负责对环境中的温度和湿度进行实行检测。
2.2 烟雾传感器
烟雾传感器在整个系统中负责检测环境中的有毒气体。
2.3加湿器
当环境中温度大于某个数值或者湿度小于某个数值时,加湿器就会加湿。下图是从网上买的加湿器套件,然后再焊接成成品。
2.4单片机最小系统
整个系统的控制核心是,数据的发送、接受、显示,通信模块发短信等都是单片机控制的。
2.5 矩阵键盘
矩阵键盘是自己焊接的,主要用于设置任何人的电话号码。
2.6 通信模块
通信模块主要用于当烟雾传感器检测到有毒气体时,发短信通知主人。
3.系统软件设计
软件调试
前边介绍了系统整体的硬件和软件,下面介绍下软件调试。
通讯模块不发短信,刚开始感觉很奇怪,感觉自己硬件也没出错,程序应该也没错,但是通讯模块就是不发短信,后来反复检查硬件,加上个小灯,在排除硬件出错的前提下,反复调试软件,终于发短信了:原来是当烟雾传感器检测到有毒气体时,单片机正在执行别的操作,当单片机回来检查烟雾传感器时,那一瞬间已经过去了,所以不会发短信,加上个中断就可以了。
4.系统创新
整套系统的创新之处在于其智能:当室内有毒气体浓度大于某个浓度时,报警模块可以发出声音,还可以触动通信模块,发短信通知主人,并且可以设置任意人的电话号码,从而减少一些不必要的损失;还有就是加湿器可以根据温湿度传感器测量的温湿度,选择不同的工作模式进行加湿,这也是体现其智能的原因之一;再有,整套系统可以显著得改善环境,这也是其智能的原因。
#include"reg52.h"
#include "uart.c"
#include "delay.h"
#include <intrins.h>
//uchar code PhoneNO[]= "18332211268"; //接收方号码
uchar code PhoneNO[]= "18032837054"; //接收方号码
uchar code Text1[]= "HOME DOCTOR:Harm gas comes out ,please contact 119"; //内容
uchar mq_135_flag;
uchar DHT11[5],RTflag=0;//读取到得数据校验标志
uchar FLAG; //超时标志位
uchar dis_buf; //显示缓存
uchar temp;
uchar key; //键顺序吗
void delay0(uchar x); //x*0.14MS
uchar cdis1[16] = {" KEY NUMBER "};
uchar cdis2[16] = {" KEY-CODE: H "};
uint i;
#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};
//I/O定义
//*********************************************************************/
sbit LED=P2^0;//定义单片机P1口的第1位 (即P1.0)为指示灯端
sbit DOUT=P1^1;//定义单片机P2口的第1位 (即P2.0)为气体传感器的输入端
sbit dat=P2^2;//温湿度数据口
sbit RS=P2^4; //1602读数据
sbit RW=P2^5;//1602写数据
sbit EN=P2^6; //1602读写数据使能口
sbit WET_MOTOR=P2^7;//加湿器控制口
sbit KEY1=P1^2;//夏天与秋天模式
sbit KEY2=P1^3;//春天与冬天模式
sbit KEY3=P1^4;//睡眠模式
sbit flag_sms=P1^4;//短信输入开始按钮
//注意在P1口处添加了数字矩阵键盘,不要冲突
void Delay_t(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 delay(uint z)//1毫秒延时函数
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
/********************************************************
* INT0中断函数 *
********************************************************/
void mq_135_test(void) interrupt 0
{
EX0=0;
mq_135_flag=1; //中断计数
EX0=1;
}
//
// 此下为加湿器动作和模式设置,温湿度显示部分
//
void lcd_write_com(uchar com) //1602写指令
{
RS=0;
RW=0;
EN=1;
P0=com;
delay(1);
EN=0;
}
void lcd_init() //1602初始化
{
}
void lcd_write_data(uchar date)//1602写数据
{
RS=1;
RW=0;
EN=1;
EN=0;
}
void write_str(uchar x,uchar y,uchar *s)//在任意地址写符号字母或数字
{
while(*s)
{
lcd_write_data(*s);
s++;
}
}
void write_shu(uchar x,uchar y,uchar num)//数据显示函数
{
uchar s,g;
if(y==0)
lcd_write_com(0x80+x);
else
lcd_write_com(0xc0+x);
}
uchar scan_key(void) //注意我暂时没有消抖 也没涉及是否支持多个按下,按键要那种不可以弹上来,要自己控制
{
if(KEY1==0)return 1; //夏天与秋天模式
}
void wet_motor(void)//加湿器模式分春天与冬天,夏天与秋天
{
// DHT11[2]=30;//温度整数
// DHT11[0]=10; //湿度整数
uchar a;
a=scan_key();
switch(a)
{
case 1:{if( DHT11[0]>5&&DHT11[2]>10)WET_MOTOR=1;};break;//夏天与秋天模式
case 2:{if( DHT11[0]<10&&DHT11[2]>26)WET_MOTOR=1;};break;//春天与冬天模式
case 3:{if( DHT11[0]>5&&DHT11[2]<25)WET_MOTOR=0;};break;// 睡眠模式
default:WET_MOTOR=1;
}
}
uchar write_byte1() //读一个字节
{
uchar i,comdata,temp1;
for(i=0;i<8;i++)
{
FLAG=2;
while((dat)&&FLAG++);//flag先与后加1 如果dat一直为1 uchar型变量 flag 溢出变为0 再自加1
if(FLAG==1)break; //超时则跳出for循环
comdata<<=1;//左移一位 高位在前 低位在后
comdata|=temp1;
}
return (comdata);
}
void DHT11_5() //读5个字节数据 两个字节为温度数据 两个字节为湿度数据 最后一个字节为校验
{
uchar i,temp;
//主机拉低18ms
dat=0;
Delay_t(180);
dat=1;
//总线由上拉电阻拉高 主机延时20us
Delay_10us();
Delay_10us();
Delay_10us();
Delay_10us();
//主机设为输入 判断从机响应信号
dat=1;
//判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行
if(!dat) //T !
{
FLAG=2; //超时标志位
while((!dat)&&FLAG++);//判断从机是否发出 80us 的低电平响应信号是否结束
FLAG=2;
while((dat)&&FLAG++); //判断从机拉高80us是否结束
for(i=0;i<5;i++)//数据接收状态
{
DHT11[i]=write_byte1();
}
dat=1; //释放数据总线 为下一次读取做好准备
temp=(DHT11[0]+DHT11[1]+DHT11[2]+DHT11[3]);
if(temp==DHT11[4]) //数据校验
{
RTflag=1;
}
if(RTflag==1) //如果RTflag=1 说明读取到得数据正确
{
RTflag=0;
// tm[0]=DATARHT[0]/10;
// tm[1]=DATARHT[0]%10;
// tm[2]=DATARHT[1]/10; //湿度
// tm[3]=DATARHT[2]/10;
// tm[4]=DATARHT[2]%10;
// tm[5]=DATARHT[3]/10; //温度
write_str(0,0,"NOW-RH: ");//第一行显示湿度
write_shu(9,0,DHT11[0]);
write_str(11,0,".");
write_shu(12,0,DHT11[1]);
write_str(13,0,"%");
write_str(14,0,"RH");
write_str(0,1,"NOW-TE: ");//第二行为显示温度
write_shu(9,1,DHT11[2]);
write_str(11,1,".");
write_shu(12,1,DHT11[3]);
write_str(13,1,"^");
write_str(14,1,"C");
// if(DHT11[3]>=30)
// JIASHI=1;
// else
// JIASHI=0;
}
}
}
//
//此下代码为矩阵键盘输入数据的相关函数
//
/*************************************************************/
/* */
/* 设定显示位置 */
/* */
/*************************************************************/
void lcd_pos(uchar pos)
{
lcd_write_com(pos | 0x80); //数据指针=80+地址变量
}
/*************************************************************/
/* */
/* 键扫描子程序 (4*3 的矩阵) P1.4 P1.5 P1.6 P1.7为行 */
/* P1.1 P1.2 P1.3为列 */
/* */
/*************************************************************/
void keyscan(void)
{
}
/*************************************************************/
/* */
/*判断键是否按下 */
/* */
/*************************************************************/
void keydown(void)
{
P1=0xF0;
if(P1!=0xF0) //判断按键是否按下 如果按钮按下 会拉低P1其中的一个端口
{
keyscan();
}
}
void num_key(void) //举证键盘输入数字并显示,先提前测试一下,打算用外部中断来开启这个函数
{
uchar m;
P0=0xFF; //置P0口
P1=0xFF; //置P1口
delay(10); //延时
//lcd_init(); //初始化LCD
lcd_pos(0); //设置显示位置为第一行的第1个字符
m = 0;
while(cdis1[m] != '\0')
{ //显示字符
lcd_write_data(cdis1[m]);
m++;
}
lcd_pos(0x40); //设置显示位置为第二行第1个字符
m = 0;
while(cdis2[m] != '\0')
{
lcd_write_data(cdis2[m]); //显示字符
m++;
}
dis_buf = 0x2d; //显示字符"-"
while(1)
{
keydown();
lcd_pos(0x4c);
lcd_write_data(dis_buf); //第一位数显示
}
}
/********************************************************************
*********************************************************************/
//********************************************************************
void main()
{
//IT0=0; //低电平触发外部中断0优先级最高
IT0=1; //下降沿触发
EA=1;
EX0=1;
lcd_init(); //1602初始化
Uart_init(); //串口初始化,
delay(100);//等待DHT11温湿度传感器数据稳定 开始激活DHT11
while(1)
{
//if(DOUT==0)
//delay_ms(30);
if( mq_135_flag)
{
mq_135_flag=0; //标志清零
SendString("AT+CMGF=1\r\n");
delayms_1000ms();
SendString("AT+CSCS=\"GSM\"\r\n");
delayms_1000ms();
SendString("AT+CMGS="); //信息发送指令 AT+CMGS=//
SendASC('"');
SendString(PhoneNO);
SendASC('"');
SendASC('\r'); //发送回车指令//
SendASC('\n'); //发送回车指令//
delayms_1000ms();
SendString(Text1);
delayms_1000ms();
SendASC(0x1a);
delayms_1000ms();
delayms_1000ms();
delayms_1000ms();
delayms_1000ms();
delayms_1000ms();
LED=1;//熄灭P1.0口灯将来改为火警警告声
for(i==0;i<9;i++)
delayms_1000ms();
}
else
{
LED=0;//点亮P1.0口灯
write_byte1();//读一个字节
DHT11_5(); //读数据
wet_motor();
}
// if(flag_sms==1)
// num_key();
}
}
/*问题:
每次处理完数据。RsPoint是怎样清零的?????在 准备发一个数据,然后接受一个数据 之前
RsBuf[RsPoint++]=SBUF;
RsBuf[RsPoint]=0x00; //将下一个数据清零
如果这个发送没问题。加删除,接收函数,参考桌面上的tc35.c
添加液晶菜单的支持 ,类似手机
*/