1、可检测火焰光源; 2、可检测非法入室的人员; 3、可检测可燃气体; 4、发生以上事故可将报警信息远程传输到户主手机上
单片机源程序如下:
- #include "config.h"
- #include "string.h"
- #include "delay.h"
- #include "uart.h"
- #define Buf1_Max 200 //串口2缓存长度
- /************* 本地常量声明 **************/
- sbit RUNING_LED = P2^7; //运行指示灯
- sbit HW = P1^6; //运行指示灯
- static unsigned char *content="8D706C344E86002C5FEB6551706B0021";//发送短信内容 走水了,快救火!
- /************* 本地变量声明 **************/
- xdata u8 Uart1_Buf[Buf1_Max];
- u8 Times=0,First_Int = 0,shijian=0;
- bdata u8 Flag;//定时器标志位
- sbit Timer0_start =Flag^0; //定时器0延时启动计数器
- /************* 本地函数声明 **************/
- void GPIO_config(void); //端口初始化配置
- void Timer0Init(void); //定时器0初始化
- void CLR_Buf1(void); //清除串口2接收缓存
- u8 Find(u8 *a); //查找字符串
- void Second_AT_Command(u8 *b,u8 *a,u8 wait_time); //发送AT指令函数
- void Set_Pdu_Mode(void);//设置短信模式PDU
- void Wait_CREG(void); //查询等待模块注册成功
- void Send_Pdu_Sms(void);//发送一条中文短信
- /************* 外部函数和变量声明*****************/
- u8 yushe_wendu=50; //温度预设值
- u16 wendu; //温度值全局变量
- u8 yushe_yanwu=45; //烟雾预设值
- u8 yanwu; //用于读取ADC数据
- //运行模式
- u8 Mode=0; //=1是设置温度阀值 =2是设置烟雾阀值 =0是正常监控模式
- void Init_Timer0(void);
- bit ReadTempFlag;//定义读时间标志
- //管脚声明
- //sbit Led_Reg =P2^7; //红灯
- sbit Buzzer =P3^3; //蜂鸣器
- sbit DQ = P1^0; //ds18b20的数据引脚
- #define SMG_NUM 4
- u8 code DisplayNum[16]={
- 0xc0, //0
- 0xf9, //1
- 0xa4, //2
- 0xb0, //3
- 0x99, //4
- 0x92, //5
- 0x82, //6
- 0xf8, //7
- 0x80, //8
- 0x90, //9
- 0x88, //A
- 0x83, //b
- 0xc6, //C
- 0xa1, //d
- 0x86, //E
- 0x8e //F
- };
- //对应关系取字: dp g f e d c b a
- //例如 U 1 1 0 0 0 0 0 1
- u8 code DisplayOther[]={
- 0xff, //0 空
- 0x7f, //1 "."
- 0xbf, //2 "-"
- 0xa7, //3 c
- 0xC1, //4 U
- ~0x6e //5 y
- };
- /********************************************************************
- * 名称 : delay_1ms()
- * 功能 : 延时1ms函数
- * 输入 : q
- * 输出 : 无
- ***********************************************************************/
- void delay1_ms(u16 q)
- {
- u16 i,j;
- for(i=0;i<q;i++)
- for(j=0;j<110;j++);
- }
- //数码管位选定义
- sbit smg_we1 = P2^0; //
- sbit smg_we2 = P2^1; //
- sbit smg_we3 = P2^2; //
- sbit smg_we4 = P2^3; //
- /***********************数码位选函数*****************************/
- void smg_we_switch(u8 i)
- {
- smg_we1 = 1;
- smg_we2 = 1;
- smg_we3 = 1;
- smg_we4 = 1;
- switch(i)
- {
- case 0: smg_we1 = 0; break;
- case 1: smg_we2 = 0; break;
- case 2: smg_we3 = 0; break;
- case 3: smg_we4 = 0; break;
- }
- }
- /********************************************************************
- * 名称 : u8 ChangeFor(u8 dat)
- * 功能 : 交换一个字节位的位置,用于数码管显示
- * 输入 : 需要改变的数
- * 输出 : 改变后的数
- ***********************************************************************/
- #define LED_a 0 //数码管段选的a段接在段选IO口的第0位
- #define LED_b 2
- #define LED_c 6
- #define LED_d 4
- #define LED_e 3
- #define LED_f 1
- #define LED_g 7
- #define LED_dp 5
- u8 ChangeFor(u8 dat)
- {
- u8 temp=0;
- if(dat&0x01) //判断数据的第一位是否为1
- temp|=0x01<<LED_a;//如果为1,放到控制数码管a段的位置
- if(dat&0x02)
- temp|=0x01<<LED_b;
- if(dat&0x04)
- temp|=0x01<<LED_c;
- if(dat&0x08)
- temp|=0x01<<LED_d;
- if(dat&0x10)
- temp|=0x01<<LED_e;
- if(dat&0x20)
- temp|=0x01<<LED_f;
- if(dat&0x40)
- temp|=0x01<<LED_g;
- if(dat&0x80)
- temp|=0x01<<LED_dp;
- return temp;
- }
- u8 dis_smg[SMG_NUM]; //显示缓存数组
- /********************************************************************
- * 名称 : display()
- * 功能 : 数码管显示
- * 输入 : 无
- * 输出 : 无
- ***********************************************************************/
- void DisplayScan()
- {
- static u8 i;
- P0 = 0xff; //消隐
- smg_we_switch(i); //位选
- P0 = ChangeFor(dis_smg[i]); //段选
- i++;
- if(i>=SMG_NUM)
- i=0;
- }
- /*****延时子程序:该延时主要用于ds18b20延时*****/
- void Delay_DS18B20(int num)
- {
- while(num--) ;
- }
- /*****初始化DS18B20*****/
- void Init_DS18B20(void)
- {
- unsigned char x=0;
- DQ = 1; //DQ复位
- Delay_DS18B20(8); //稍做延时
- DQ = 0; //单片机将DQ拉低
- Delay_DS18B20(80); //精确延时,大于480us
- DQ = 1; //拉高总线
- Delay_DS18B20(14);
- x = DQ; //稍做延时后,如果x=0则初始化成功,x=1则初始化失败
- Delay_DS18B20(20);
- }
- /*****读一个字节*****/
- unsigned char ReadOneChar(void)
- {
- unsigned char i=0;
- unsigned char dat = 0;
- for (i=8;i>0;i--)
- {
- ET0=0; //定时器中断关闭
- DQ = 0; // 给脉冲信号
- dat>>=1;
- DQ = 1; // 给脉冲信号
- if(DQ)
- dat|=0x80;
- Delay_DS18B20(4);
- ET0=1; //定时器中断打开
- }
- return(dat);
- }
- /*****写一个字节*****/
- void WriteOneChar(unsigned char dat)
- {
- unsigned char i=0;
- for (i=8; i>0; i--)
- {
- ET0=0; //定时器中断关闭
- DQ = 0;
- DQ = dat&0x01;
- Delay_DS18B20(5);
- DQ = 1;
- dat>>=1;
- ET0=1; //定时器中断打开
- }
- }
- u8 tempflag=0; //负号显示
- /*****读取温度*****/
- unsigned int ReadTemperature(void)
- {
- unsigned char a=0;
- unsigned char b=0;
- unsigned int t=0;
- u8 tt=0;
- u8 ttt=0;
- Init_DS18B20();
- WriteOneChar(0xCC); //跳过读序号列号的操作
- WriteOneChar(0x44); //启动温度转换
- Init_DS18B20();
- WriteOneChar(0xCC); //跳过读序号列号的操作
- WriteOneChar(0xBE); //读取温度寄存器
- a=ReadOneChar(); //读低8位
- b=ReadOneChar(); //读高8位
- t=b;
- t<<=8;
- t=t|a; //合并高低位为一个字节
-
- tt=(u8)(t>>4); //得到整数位
- ttt=(u8)((t%16)*0.0625*10); //得到小数位;乘以10代表保留一位小数;
- if(tt&0x80)
- {
- tempflag=1; //负号显示
- tt=~tt+1; //实际温度值为读取值的补码
- }
- else
- tempflag=0; //正号显示
- t= tt*10+ttt; //放大10倍
- return(t);
- }
- /*****校准温度*****/
- u16 check_wendu(void)
- {
- u16 c;
- c=ReadTemperature(); //获取温度值并减去DS18B20的温漂误差
- return c;
- }
- //按键
- sbit Key1=P1^6; //设置键
- sbit Key2=P1^7; //加按键
- sbit Key3=P3^2; //减按键
- #define KEY_SET 1 //设置
- #define KEY_ADD 2 //加
- #define KEY_MINUS 3 //减
- //========================================================================
- // 函数: u8 Key_Scan()
- // 应用: temp=u8 Key_Scan();
- // 描述: 按键扫描并返回按下的键值
- // 参数: NONE
- // 返回: 按下的键值
- // 版本: VER1.0
- // 日期: 2015-05-29
- // 备注: 该函数带松手检测,按下键返回一次键值后返回0,直至第二次按键按下
- //========================================================================
- u8 Key_Scan()
- {
- static u8 key_up=1;//按键按松开标志
- if(key_up&&(Key1==0||Key2==0||Key3==0))
- {
- delay1_ms(10);//去抖动
- key_up=0;
- if(Key1==0) return 1;
- else if(Key2==0)return 2;
- else if(Key3==0)return 3;
- }
- else if(Key1==1&&Key2==1&&Key3==1)
- key_up=1;
- return 0;// 无按键按下
- }
- /***********************************************************************************************************
- ADC0832相关函数
- ***********************************************************************************************************/
- sbit AD0832_CS = P1^5 ; //片选信号
- sbit AD0832_CLK = P1^2; //时钟接口
- sbit AD0832_DI = P1^3; //数据接口 /*因为单片机的管脚是双向的,且ADC0832的数据输入输出不同时进行,为节省单片机引脚,简化电路所以输入输出连接在同一个引脚上*/
- u8 GetAD0832(bit Channel)
- {
- u8 i=0 , Data1 =0 , Data2 = 0 ;
- AD0832_CLK = 0 ; //时钟置低平//时钟12Mhz, 整个转换时间为224us
- //使用芯片准备(参考PDF时序图)
- AD0832_DI = 1 ; //开始信号为高电平
- AD0832_CS = 0 ; //片选信号置低,启动AD转换芯片
- AD0832_CLK = 1 ; //输入开始信号(构成一个正脉冲),时钟上升沿,输入开始信号
- AD0832_CLK = 0 ; //时钟下降沿
- //模拟信号输入模式选择(1:单模信号,0:双模差分信号)
- AD0832_DI = 1 ;
- AD0832_CLK = 1 ; //时钟上升沿,输入开始信号
- AD0832_CLK = 0 ; //时钟下降沿
- //模拟信号输入通道选择(1:通道CH1,0:通道CH0)
- AD0832_DI = Channel ; //选择通道0
- AD0832_CLK = 1; //时钟上升沿,输入开始信号
- AD0832_CLK = 0; //时钟下降沿
- AD0832_DI = 1; //数据线置高,准备接收数据
- for(i=0;i<8;i++) //从高位移入数据
- {
- AD0832_CLK = 1 ;
- AD0832_CLK = 0 ; //时钟下降沿,AD0832输出数据,高位(MSB)先
- Data1 = Data1<<1; //数据左移位,补0
- if(AD0832_DI ==1)
- {
- Data1 = Data1 | 0x01;
- } //如果数据为“1”,移入1,
- } //如果数据为“0”,移入0,
- for(i=0;i<8;i++) //从低位移入数据
- {
- Data2 = Data2>>1; //数据左移位,补0
- if(AD0832_DI ==1)
- {
- Data2 = Data2 | 0x80;
- } //如果数据为“1”,移入1如果数据为“0”,移入0,
- AD0832_CLK = 1;
- AD0832_CLK = 0; //时钟下降沿,AD0832输出数据,高位(MSB)先
- }
- //数据线置高,释放总线,完成一次转换
- AD0832_CLK = 1 ;
- AD0832_DI = 1;
- AD0832_CS = 1;
- if(Data1==Data2) //输出
- {
- return Data2;
- }
- return 0;
- }
- /*******************************************************************************
- * 函数名 : Set_Text_Mode
- * 描述 : 设置短信为TEXT文本模式
- * 输入 :
- * 输出 :
- * 返回 :
- * 注意 :
- *******************************************************************************/
- void Set_Text_Mode(void)
- {
- Second_AT_Command("ATE0","OK",3); //取消回显
- Second_AT_Command("AT+CNMI=3,2,0,0,0","OK",3); //新短信直接输出
- Second_AT_Command("AT+CMGF=1","OK",3); //TEXT模式
- Second_AT_Command("AT+CPMS=\"SM\",\"SM\",\"SM\"","OK",3); //所有操作都在SIM卡中进行
- }
- /*******************************************************************************
- * 函数名 : main
- * 描述 : 主函数
- * 输入 :
- * 输出 :
- * 返回 :
- * 注意 : 串口波特率是9600,GPRS模块默认波特率是115200,需要自己通过串口助手修改
- 为9600方可使用。
- *******************************************************************************/
- void main(void)
- {
- u8 key;
- u8 bj=0;
- u16 i=0;
- Timer0Init(); //初始化定时器0
- dis_smg[0] = DisplayOther[2] ;
- dis_smg[1] = DisplayOther[2] ;
- dis_smg[2] = DisplayOther[2] ;
- dis_smg[3] = DisplayOther[2] ;
- GPIO_config();
- EA=1; //开总中断
- Uart1Init(); //初始化串口9600
- Wait_CREG(); //查询等待模块注册成功
- Set_Text_Mode();//设置短信为TEXT模式
- Buzzer=0; //打开蜂鸣器报警
- wendu=check_wendu(); //初始化时调用温度读取函数 防止开机85°C
- delay1_ms(1000);
- wendu=check_wendu(); //初始化时调用温度读取函数 防止开机85°C
- Buzzer=1; //打开蜂鸣器报警
- while (1) //主循环
- {
- key=Key_Scan(); //按键扫描
- i++;
- if(i>=2000)
- {
- i=0;
- wendu=check_wendu(); //读取温度值
- yanwu=GetAD0832(0)*100/255; //读取烟雾值
- }
- if(key==KEY_SET)
- {
- Mode++;
- }
-
- switch(Mode) //判断模式的值
- {
- case 0: //监控模式
- dis_smg[0] = DisplayNum[wendu/100%10] ;
- dis_smg[1] = DisplayNum[wendu/10%10];
- dis_smg[2] = DisplayNum[yanwu/10%10] ;
- dis_smg[3] = DisplayNum[yanwu%10] ;
-
- if((yanwu<yushe_yanwu)&&(wendu<(yushe_wendu*10))) //当烟雾小于预设值并且温度也小于预设值时 (&&:逻辑与,左右两边的表达式都成立(都为真,也就是1)时,该if语句才成立)
- {
- Buzzer=1; //打开蜂鸣器报警
- bj=0;
- }
- else //温度值小于预设值时
- {
- Buzzer=0; //停止报警
- if(bj==0)
- {
- bj=1;
- Set_Pdu_Mode();//设置短信为PDU模式
- Send_Pdu_Sms();//发送一条短消息
- }
- }
- break;
- case 1://预设温度模式
- {
- dis_smg[0] = DisplayNum[0xc];
- dis_smg[1] = DisplayOther[2] ;
- dis_smg[2] = DisplayNum[yushe_wendu/10%10];
- dis_smg[3] = DisplayNum[yushe_wendu%10] ;
- if(key==KEY_ADD) //加键按下
- {
- yushe_wendu++; //预设温度值(阀值)加1
- if(yushe_wendu>=99) //当阀值加到大于等于99时
- yushe_wendu=99; //阀值固定为99
- }
- if(key==KEY_MINUS) //减键按下
- {
- if(yushe_wendu<=1) //当温度上限值减小到1时
- yushe_wendu=1; //固定为1
- yushe_wendu--; //预设温度值减一,最小为0
- }
- break; //执行后跳出switch
- }
- case 2://预设烟雾模式
- {
- dis_smg[0] = DisplayOther[5];
- dis_smg[1] = DisplayOther[2] ;
- dis_smg[2] = DisplayNum[yushe_yanwu/10%10];
- dis_smg[3] = DisplayNum[yushe_yanwu%10] ;
- if(key==KEY_ADD) //加键按下
- {
- yushe_yanwu++; //预设温度值(阀值)加1
- if(yushe_yanwu>=99) //当阀值加到大于等于99时
- yushe_yanwu=99; //阀值固定为99
- }
- if(key==KEY_MINUS) //减键按下
- {
- if(yushe_yanwu<=1) //当温度上限值减小到1时
- yushe_yanwu=1; //固定为1
- yushe_yanwu--; //预设温度值减一,最小为0
- }
- break; //执行后跳出switch
- }
- default :
- {
- Mode=0; //恢复正常模式
- break;
- }
- }
-
- }
-
- }
- /*******************************************************************************
- * 函数名 : Uart1
- * 描述 : 串口1中断服务入口函数
- * 输入 :
- * 输出 :
- * 返回 :
- * 注意 :
- *******************************************************************************/
- void Uart1() interrupt 4
- {
- if (RI)
- {
- RI = 0; //清除RI位
- Uart1_Buf[First_Int] = SBUF; //将接收到的字符串存到缓存中
- First_Int++; //缓存指针向后移动
- if(First_Int > Buf1_Max) //如果缓存满,将缓存指针指向缓存的首地址
- {
- First_Int = 0;
- }
- }
- if (TI)
- {
- TI = 0; //清除TI位
- }
- }
- /*******************************************************************************
- * 函数名 : Timer0_ISR
- * 描述 : 定时器0中断服务入口函数,20ms中断一次
- * 输入 :
- * 输出 :
- * 返回 :
- * 注意 :
- *******************************************************************************/
- void Timer0_ISR() interrupt 1
- {
- static u16 Time_count=0;
- static u8 i=0;
- TL0 = 0xCD; //设置定时初值
- TH0 = 0xF8; //设置定时初值
- TR0=0;//关定时器
- DisplayScan();// 调用数码管扫描
- i++;
- if(i>=10)
- {
- i=0;
- Time_count++;
- if(Time_count>=50)
- {
- Time_count = 0;
- RUNING_LED =~RUNING_LED;
- }
- if(count_20ms) //20ms延时计数器
- count_20ms--;
- if(Timer0_start)
- Times++;
- if(Times > (50*shijian))
- {
- Timer0_start = 0;
- Times = 0;
- }
- }
- TR0=1;//开定时器
- }
- /*******************************************************************************
- * 函数名 : GPIO_config
- * 描述 : IO口配置函数
- * 输入 :
- * 输出 :
- * 返回 :
- * 注意 :
- *******************************************************************************/
- void GPIO_config(void)
- {
- RUNING_LED=0;
- }
- /*******************************************************************************
- * 函数名 : Timer0Init
- * 描述 : 定时器0初始化,20ms定时
- * 输入 :
- * 输出 :
- * 返回 :
- * 注意 :
- *******************************************************************************/
- void Timer0Init(void) //20毫秒@11.0592MHz
- {
- AUXR &= 0x7F; //定时器时钟12T模式
- TMOD &= 0xF0; //
- TMOD |= 0x01; //设置定时器模式,16位定时器
- TL0 = 0xCD; //设置定时初值
- TH0 = 0xF8; //设置定时初值
- TF0 = 0; //清TF0标志
- TR0 = 1; //定时器0开始计时
- ET0 = 1; //使能定时器0中断
- }
- /*******************************************************************************
- * 函数名 : CLR_Buf1
- * 描述 : 清除串口2缓存数据
- * 输入 :
- * 输出 :
- * 返回 :
- * 注意 :
- *******************************************************************************/
- void CLR_Buf1(void)
- {
- u16 k;
- for(k=0;k<Buf1_Max;k++) //将缓存内容清零
- {
- Uart1_Buf[k] = 0x00;
- }
- First_Int = 0; //接收字符串的起始存储位置
- }
- /*******************************************************************************
- * 函数名 : Find
- * 描述 : 判断缓存中是否含有指定的字符串
- * 输入 :
- * 输出 :
- * 返回 : unsigned char:1 找到指定字符,0 未找到指定字符
- * 注意 :
- *******************************************************************************/
- u8 Find(u8 *a)
- {
- if(strstr(Uart1_Buf,a)!=NULL)
- return 1;
- else
- return 0;
- }
- /*******************************************************************************
- * 函数名 : Second_AT_Command
- * 描述 : 发送AT指令函数
- * 输入 : 发送数据的指针、发送等待时间(单位:S)
- * 输出 :
- * 返回 :
- * 注意 :
- *******************************************************************************/
- void Second_AT_Command(u8 *b,u8 *a,u8 wait_time)
- {
- u8 i;
- u8 *c;
- c = b; //保存字符串地址到c
- CLR_Buf1();
- i = 0;
- while(i == 0)
- {
- if(!Find(a)) //查找需要应答的字符
- {
- if(Timer0_start == 0)//超时重新发送命令
- {
- b = c; //将字符串地址给b
- for (b; *b!='\0';b++)
- {
- UART1_SendData(*b);
- }
- UART1_SendLR();
- Times = 0;
- shijian = wait_time;
- Timer0_start = 1; //开始计时
- }
- }
- else
- {
- i = 1;
- Timer0_start = 0;
- }
- }
- CLR_Buf1();
- }
- /*******************************************************************************
- * 函数名 : Set_Pdu_Mode
- * 描述 : 设置短信为TEXT文本模式
- * 输入 :
- * 输出 :
- * 返回 :
- * 注意 :
- *******************************************************************************/
- void Set_Pdu_Mode(void)
- {
- Second_AT_Command("ATE0","OK",3); //取消回显
- Second_AT_Command("AT+CMGF=1","OK",3); //设置为文本模式
- Second_AT_Command("AT+CSMP=17,167,2,25","OK",3); //设置文本模式参数
- }
- /*******************************************************************************
- * 函数名 : Send_Pdu_Sms
- * 描述 : 发送PDU文本短信
- * 输入 :
- * 输出 :
- * 返回 :
- * 注意 :
- *******************************************************************************/
- void Send_Pdu_Sms(void)
- {
- Second_AT_Command("AT+CSCS=\"UCS2\"","OK",3); //设置为 UCS2 编码字符集
- Second_AT_Command("AT+CMGS=\"00310033003200340033003100360031003500360035\"",">",3);
- UART1_SendString(content); //发送短信内容
- UART1_SendData(0X1A); //发送结束符
- }
- /*******************************************************************************
- * 函数名 : Wait_CREG
- * 描述 : 等待模块注册成功
- * 输入 :
- * 输出 :
- * 返回 :
- * 注意 :
- *******************************************************************************/
- void Wait_CREG(void)
- {
- u8 i;
- u8 k;
- i = 0;
- CLR_Buf1();
- while(i == 0)
- {
- CLR_Buf1();
- UART1_SendString("AT+CREG");//查询模块网络注册状态
- UART1_SendLR();
- delay_ms(250);
- for(k=0;k<Buf1_Max;k++)
- {
- if(Uart1_Buf[k] == ':')
- {
- if((Uart1_Buf[k+4] == '2')||(Uart1_Buf[k+4] == '5')) //表明网络注册成功
- {
- i = 1;
- break;
- }
- }
- }
- }
- }
复制代码
原理图,代码:
定做资料.zip
(432.64 KB, 下载次数: 190)
|