|
该项目主要是对山体环境进行监控,监控环境中的温湿度,火灾发生时火焰监测,以及燃烧所产生的烟雾进行监测报警,将所有监测到的数据以及火灾报警通过5110显示屏进行显示。
所用到的硬件及传感器:
1.STC12最小系统板
2.火焰监测模块
3.MQ-2烟雾报警器
4.DHT11
5.诺基亚5110显示屏
功能如下:
1.DHT11温湿度采集
2.火焰传感器的火焰监测(模块输入的高低电平)
3.51单片机ADC采集MQ-2的AD输出
4.5110显示温湿度,烟雾传感器的AD值,火焰传感器是否进行报警显示
STC12单片机最小系统原理图如下:
首先是DHT11的驱动程序,其采用的是单线通信,单片机驱动程序如下:
- #include <STC12C5A60S2.H>
- #include "dht11.h"
- #include "intrins.h"
- #define ulong unsigned long
- #define uchar unsigned char
- #define uint unsigned int
- unsigned char status;
- unsigned char DHT11T_Data_H, DHT11T_Data_L, DHT11RH_Data_H, DHT11RH_Data_L,CheckData_temp;//存放五字节数据
- /*可在其他的文件引用温湿度值,实际是温度的整数的10倍如dht11读回的温度是26,则wendu = 260, 湿度同理*/
- void Delay_ms(uint ms)
- {
- unsigned char i, j;
- while(ms)
- {
- _nop_();
- i = 11;
- j = 190;
- do
- {
- while (--j);
- } while (--i);
- ms--;
- }
- }
- void Delay_us(uint us) //2us
- {
- while(us)
- {
- _nop_();
- us--;
- }
- }
- unsigned char start_DHT11(unsigned int *temperature, unsigned int *RH)
- {
- unsigned char TData_H_temp,TData_L_temp,RHData_H_temp,RHData_L_temp,checktemp;
- unsigned char presence,flag = 0;
- unsigned int count;
-
- DHT11_OUTPUT;
- DHT11_L; //拉低18ms以上
- Delay_ms(20);
- DHT11_H;
-
- DHT11_INPUT;
- Delay_us(30);
- presence=DHT11_IN;
-
- if(!presence)
- {
- count=2;
- while((!DHT11_IN)&&count++);//等待低电平
- count=2;
- while((DHT11_IN)&&count++);//等待高电平
-
- RHData_H_temp = DHT11_ReadChar();
- RHData_L_temp = DHT11_ReadChar();
- TData_H_temp = DHT11_ReadChar();
- TData_L_temp = DHT11_ReadChar();
- CheckData_temp = DHT11_ReadChar();
-
- DHT11_OUTPUT;
- DHT11_H;
-
- checktemp = RHData_H_temp + RHData_L_temp + TData_H_temp + TData_L_temp;
-
- if ((checktemp == CheckData_temp) && (CheckData_temp != 0))
- {
- DHT11RH_Data_H = RHData_H_temp;
- DHT11RH_Data_L = RHData_L_temp;
- DHT11T_Data_H = TData_H_temp;
- DHT11T_Data_L = TData_L_temp;
- *temperature = TData_H_temp;
- *RH = RHData_H_temp;
- flag=1;
- }
- }
- return flag;
- }
- uchar DHT11_ReadChar(void)
- {
- unsigned char dat;
- unsigned int count; //计数防止死等
- unsigned char i;
- for(i=0;i<8;i++)
- {
- count=2;
- DHT11_INPUT;
- while((!DHT11_IN)&&count++); //等待50us低电平结束
- Delay_us(40); //40us
- dat <<= 1; //50us低电平+28us高电平表示'0'
- if(DHT11_IN) //50us低电平+70us高电平表示'1'
- dat |= 1;
- count=2;
- while((DHT11_IN)&&count++);
- if(count==1)break; //超时则跳出for循环
- }
- return dat;
- }
复制代码 然后是5110的驱动程序,通信方式采用的是SPI:
- #include "LCD_5110_Font.h"
- #include "LCD_5110.h"
- #include "delay.h"
- /*******************************************************************************
- * 函 数 名 : LCD_write_byte
- * 函数功能 : 使用SPI接口写数据到LCD
- * 输 入 : 写数据/命令选择;
- * 输 出 : 无
- *******************************************************************************/
- void LCD_write_byte(unsigned char dt, unsigned char command)
- {
- unsigned char i;
- LCD_5110_CSN = 0;// 片选
- LCD_5110_dc=command;
- for(i=0; i<8; i++)
- {
- if(dt&0x80)
- LCD_5110_sdin=1;
- else
- LCD_5110_sdin=0;
- dt=dt<<1;
- LCD_5110_sclk=0;
- Delay1us(1);
- LCD_5110_sclk=1;
- }
- LCD_5110_dc=1;
- Delay1us(1);
- LCD_5110_CSN = 1;
- Delay1us(1);
- LCD_5110_sdin=1;
- }
- /*******************************************************************************
- * 函 数 名 : LCD_init
- * 函数功能 : LCD初始化函数
- * 输 入 : 无
- * 输 出 : 无
- * 说 明 : 如果5110,显示全黑或者,模糊,可以调节初始化程序中,//设定液晶偏置电压
- *******************************************************************************/
- void LCD_init(void)
- {
- P0M0 = 0x04;
- LCD_5110_res=0;
- Delay1ms(2);
- LCD_5110_res=1;
- LCD_write_byte(0x21,0); //初始化Lcd,功能设定使用扩充指令
- // LCD_write_byte(0xA5,0); //设定液晶偏置电压
- // LCD_write_byte(0x20,0); //使用基本指令
- // LCD_write_byte(0x0C,0); //设定显示模式,正常显示
- LCD_write_byte(0xC5,0); //设定液晶偏置电压
- LCD_write_byte(0x06, 0); // 温度校正
- LCD_write_byte(0xC5, 0); // 1:48
- LCD_write_byte(0x20,0); //使用基本指令
- LCD_write_byte(0x0C,0); //设定显示模式,正常显示
- LCD_clear(); //清屏
- LCD5110_Light = 1; //
- }
- /*******************************************************************************
- * 函 数 名 : LCD_set_XY
- * 函数功能 : 设置LCD坐标函数
- * 输 入 : 0-83 Y:0-5
- * 输 出 : 无
- *******************************************************************************/
- void LCD_set_XY(unsigned char X, unsigned char Y)
- {
- LCD_write_byte(0x40 | Y, 0);// column
- LCD_write_byte(0x80 | X, 0);// row
- }
- /*******************************************************************************
- * 函 数 名 : LCD_clear
- * 函数功能 : LCD清屏函数
- * 输 入 : 无
- * 输 出 : 无
- *******************************************************************************/
- void LCD_clear(void)
- {
- unsigned char t;
- unsigned char k;
- LCD_set_XY(0,0);
- for(t=0; t<6; t++)
- {
- for(k=0; k<84; k++)
- {
- LCD_write_byte(0x00,1);
- }
- }
- }
- /*******************************************************************************
- * 函 数 名 : LCD_write_Zifu
- * 函数功能 : 显示8(宽)*16(高)点阵列数字字母符号等半角类
- * 输 入 : c:显示的字符 row:列 page:页
- * 输 出 : 无
- *******************************************************************************/
- //void LCD_write_Zifu(unsigned char row, unsigned char page,unsigned char c)
- //{
- // unsigned char i;
- // c = c-32;
- // LCD_set_XY(row*8, page);// 列,页
- // for(i=0; i<8; i++)
- // {
- // LCD_write_byte(Zifu[c*16+i],1);
- // }
- // LCD_set_XY(row*8, page+1);// 列,页
- // for(i=8; i<16; i++)
- // {
- // LCD_write_byte(Zifu[c*16+i],1);
- // }
- //}
- /*******************************************************************************
- * 函 数 名 : LCD_write_hanzi
- * 函数功能 : 显示16(宽)*16(高)点阵列汉字等半角类
- * 输 入 : c:显示的字符 row:列 page:页
- * 输 出 : 无
- *******************************************************************************/
- void LCD_write_hanzi(unsigned char row, unsigned char page,unsigned char c)
- {
- unsigned char i;
- LCD_set_XY(row*8, page); // 列,页
- for(i=0; i<16; i++)
- {
- LCD_write_byte(hanzi[c*32+i],1);
- }
- LCD_set_XY(row*8, page+1); // 列,页
- for(i=16; i<32; i++)
- {
- LCD_write_byte(hanzi[c*32+i],1);
- }
- }
- /*******************************************************************************
- * 函 数 名 : Init_LCD5110
- * 函数功能 : 应用型初始化
- * 输 入 : 无
- * 输 出 : 无
- *******************************************************************************/
- void Init_LCD5110(void)
- {
- unsigned char k;
- LCD_5110_res=0;
- for(k=0; k<250; k++);
- LCD_5110_res=1;
- //如果5110,显示全黑或者,模糊,可以调节初始化程序中,//设定液晶偏置电压
- LCD_init(); //初始化LCD模块
- LCD_clear(); //清屏幕
- LCD5110_Light = 1;
- }
- /*******************************************************************************
- * 函 数 名 : Test_LCD
- * 函数功能 : 5110液晶测试程序
- * 输 入 : 无
- * 输 出 : 无
- *******************************************************************************/
- void Test_LCD(void)
- {
- unsigned char k;
- LCD_5110_res=0;
- for(k=0; k<250; k++);
- LCD_5110_res=1;
- LCD_init(); //初始化LCD模块
- LCD_clear(); //清屏幕
- LCD_write_hanzi(1,0,0); //山
- LCD_write_hanzi(3,0,1); //体
- LCD_write_hanzi(5,0,2); //检
- LCD_write_hanzi(7,0,3); //测
- LCD_ShowString(0, 2, "R: %", 16);
- LCD_ShowString(42, 2, "T: C", 16);
- LCD_ShowString(0, 4, "M: ", 16);
- //LCD_write_hanzi(9,0,4); //检
- // LCD_write_hanzi(4,2,5); //测
- // LCD_write_hanzi(6,2,6); //预
- //
- // LCD_write_hanzi(6,2,7); //预
- // LCD_write_hanzi(6,2,8); //预
- // LCD_write_hanzi(6,2,9); //预
- //// LCD_ShowString(0,4,"CUIT",16);
- // LCD_write_hanzi(4,4,10); //张
- // LCD_write_hanzi(6,4,11); //媛
- // LCD_write_hanzi(8,4,11); //媛
- }
- //在指定位置显示一个字符,包括部分字符
- //mode:0,反白显示;1,正常显示
- //size:选择字体 16/12
- void LCD_ShowChar(unsigned char x,unsigned char y,unsigned char chr, unsigned char font_size)
- {
- unsigned char c=0,i=0;
- c=chr-' ';//得到偏移后的值
- if(x>Max_Column-1) {
- x=0;
- y=y+2;
- }
- if(font_size ==16)
- {
- LCD_set_XY(x,y);
- if((chr<='9')&&(chr >= '0'))
- {
- for(i=0; i<6; i++)
- LCD_write_byte(F8X16[c*16+i],LCD_DATA);
- LCD_set_XY(x,y+1);
- for(i=0; i<6; i++)
- LCD_write_byte(F8X16[c*16+i+8],LCD_DATA);
- }
- else
- {
- for(i=0; i<8; i++)
- LCD_write_byte(F8X16[c*16+i],LCD_DATA);
- LCD_set_XY(x,y+1);
- for(i=0; i<8; i++)
- LCD_write_byte(F8X16[c*16+i+8],LCD_DATA);
- }
- }
- else {
- LCD_set_XY(x,y);
- for(i=0; i<6; i++) {
- LCD_write_byte(F6x8[c][i],LCD_DATA);
- }
- }
- }
- //显示一个字符号串
- void LCD_ShowString(unsigned char x,unsigned char y,unsigned char *chr, unsigned char font_size)
- {
- unsigned char j=0;
- while (chr[j]!='\0')
- {
- LCD_ShowChar(x,y,chr[j], font_size);
- if(font_size == 16)
- {
- if((chr[j] >= '0')&&(chr[j] <= '9'))
- {
- x+=5;
- } else
- x+=8;
- if(x>72) {
- x=0;
- y+=2;
- }
- }
- else
- {
- x+=6;
- if(x>78) {
- x=0;
- y+=1;
- }
- }
- j++;
- }
- }
- //m^n函数
- unsigned long oled_pow(unsigned char m,unsigned char n)
- {
- unsigned long result=1;
- while(n--)result*=m;
- return result;
- }
- //显示2个数字
- //x,y :起点坐标
- //len :数字的位数
- //size:字体大小
- //mode:模式 0,填充模式;1,叠加模式
- //num:数值(0~4294967295);
- void LCD_ShowNum(unsigned char x,unsigned char y,unsigned long num,unsigned char len)
- {
- /* unsigned char t,temp;
- unsigned char enshow=0;
- for(t=0; t<len; t++)
- {
- temp=(num/oled_pow(10,len-t-1))%10;
- if(enshow==0&&t<(len-1))
- {
- if(temp==0)
- {
- // LCD_ShowChar(x+(size/2)*t,y,' ');
- LCD_ShowChar(x+6*t,y,'0', 6);
- continue;
- } else enshow=1;
- }
- // LCD_ShowChar(x+(size/2)*t,y,temp+'0');
- LCD_ShowChar(x+6*t,y,temp+'0', 6);
- }
- */
- ////////////////////
- unsigned char t,temp;
- unsigned char enshow=0;
- for(t=0; t<len; t++)
- {
- temp=(num/oled_pow(10,len-t-1))%10;
- if(enshow==0&&t<(len-1))
- {
- if(temp==0)
- {
- LCD_ShowChar(x+6*t,y,' ',6);
- continue;
- } else enshow=1;
- }
- LCD_ShowChar(x+6*t,y,temp+'0',6);
- }
- }
- void LCD_ugm3(unsigned char x,unsigned char y)
- {
- unsigned i;
- LCD_set_XY(x,y);
- for(i = 0; i < 13; i++)
- {
- LCD_write_byte(ugm3[0][i],LCD_DATA);
- }
- LCD_set_XY(x,y+1);
- for(i = 0; i < 13; i++)
- {
- LCD_write_byte(ugm3[1][i],LCD_DATA);
- }
- }
- void System_runing(unsigned char x,unsigned char y)
- {
- static bit temp = 0;
- temp = ~temp;
- LCD_set_XY(x,y);
- if(temp)
- LCD_write_byte(0x80, LCD_DATA);
- else
- LCD_write_byte(0x00, LCD_DATA);
- }
- void Show_Back(void)
- {
- LCD_clear(); //清屏
- LCD_ShowString(0, 1, "T: ", 1);
- LCD_ShowString(18, 1, "C ", 1);
- LCD_ShowString(27, 1, "CH2O: ", 1);
- LCD_ShowString(0, 3, "R: ", 1);
- LCD_ShowString(6, 3, ": ", 1);
- LCD_ShowString(18, 3, "% ", 1);
- LCD_ShowString(27, 3, "PM2.5: ", 1);
- LCD_ShowString(47, 3, "5: ", 1);
- LCD_ugm3(70,0);
- LCD_ugm3(70,2);
- }
复制代码 MQ-2烟雾传感器模块的驱动代码主要是通过12单片机自带的ADC采集读取模块所输出的AD值进而判断是否有烟雾生成
- /********************* 做一次ADC转换 *******************/
- uint adc10_start(uchar channel) //channel = 0~7
- {
- uint adc;
- uchar i;
- ADC_RES = 0;
- ADC_RESL = 0;
- ADC_CONTR = (ADC_CONTR & 0xe0) | ADC_START | channel;
- i = 250;
- do{
- if(ADC_CONTR & ADC_FLAG)
- {
- ADC_CONTR &= ~ADC_FLAG;
- adc = (uint)ADC_RES;
- adc = (adc << 2) | (ADC_RESL & 3);
- return adc;
- }
- }while(--i); //超时检测
- return 1024;
- }
复制代码 火焰传感器监测比较简单,即通过读取模块输出的高低电平进行判断即可知道模块是否监测到火光。
主函数如下,主要显示所采集的传感器数据,然后对火焰传感器的是否监测到火警进行判断,显示当前是安全还是火警
- /********************* 主函数 *************************/
- void main(void)
- {
- uchar i;
- uint j; //烟雾浓度缓存
- char show_temp[20] = {0}; //液晶显示缓存
- unsigned int Temp1, RH1; //温度、湿度缓存
- Uart1_Init(); //串口初始化
- LCD_init(); //lcd初始化
- Test_LCD(); //开机界面
- //Show_Back();
- //PrintString("****** STC12C5A60S2系列ADC程序 2011-02-27 ******\r\n"); //上电后串口发送一条提示信息
- P1ASF = 0xff; //12C5A60AD/S2系列模拟输入(AD)选择
- ADC_CONTR = ADC_360T | ADC_ON;
-
- while(1)
- {
- start_DHT11(&Temp1, &RH1); //读取DHT11温湿度值
- j = adc10_start(1); //读取烟雾浓度值
- sprintf(show_temp, "%d",j);
- LCD_ShowString(13, 4, show_temp, 16); //显示烟雾浓度
- sprintf(show_temp, "%d",RH1);
- LCD_ShowString(12, 2, show_temp, 16); //显示湿度
- sprintf(show_temp, "%d",Temp1);
- LCD_ShowString(55, 2, show_temp, 16); //显示温度
- if (beep == 0) //火焰报警
- {
- LCD_ShowString(48, 4, "Fire", 16);
- }
- else
- {
- LCD_ShowString(48, 4, "Safe", 16);
- }
- // start_DHT11(&Temp1, &RH1);
- // sprintf(show_temp, "%02d",Temp1);
- // UART1_SendString(show_temp);
- // UART1_SendString("\r\n");
- // sprintf(show_temp, "%02d",RH1);
- //UART1_SendData(j);
- UART1_SendData(j/1000 + '0');
- UART1_SendData(j%1000/100 + '0');
- UART1_SendData(j%100/10 + '0');
- UART1_SendData(j%10 + '0');
- UART1_SendString("\r\n");
- delay_dms(250);
- }
- }
复制代码
此项目还可以进行物联网改造实现远程对环境进行监测,若后续有条件会进一步开发(采用4g或者NB-IOT模块,在手机安卓端做监测APP实现远程监控)
上图Keil代码工程下载:
程序.zip
(118.6 KB, 下载次数: 56)
|
评分
-
查看全部评分
|