基于51单片机的物联网安防系统(Proteus+Python脚本+阿里云)

基于51单片机的物联网安防系统使用Proteus进行仿真,LCD12864进行数据显示,集成了温湿度传感器、烟雾、甲烷传感器,执行器件是风扇,采用L298进行驱动,按键实现用户交互,蜂鸣器报警,红外检测人员状态,同时虚拟串口连接到我们的Python脚本,实现数据上传。

一、硬件设计

1、TLC549

TLC549是德州仪器(Texas Instruments)推出的一款高性能、低功耗的8位逐次逼近型模拟数字转换器(A/D Converter)。它采用串行接口,与微控制器的连接简单,特别适用于需要节省引脚数量和成本的单片机系统。TLC549以其卓越的转换速度、优秀的分辨率和低功耗特性,成为众多电子设计中的理想选择。

2、LCD12864

CD12864是一种常见的液晶显示屏(Liquid Crystal Display)模块,具有128列和64行的点阵显示能力,总点数达到8192点。这种显示屏通常采用超扭曲向列(Super Twisted Nematic, STN)技术,适用于显示文本、图形以及简单动画。LCD12864模块通常内置有汉字和ASCII字符的字符库,支持多种接口方式,包括4位或8位并行接口以及2线或3线串行接口,使得它可以轻松地与不同的微控制器或其他数字系统连接。

3、温湿度传感器

DHT11是一款常用的数字温湿度传感器,它能够提供经过校准的数字信号输出,适用于各种环境监测应用。DHT11传感器包含一个电阻式湿度传感元件和一个NTC温度传感元件,这些元件与一个高性能的8位单片机相连,确保了产品的可靠性和长期稳定性。

二、软件设计

1、TLC549驱动代码

cpp 复制代码
#include "TLC549.h"
#include <REGX52.H>
#include <intrins.H>

sbit DI  = P2^4;
sbit CS  = P2^5;
sbit CLK = P2^6;

sbit DI2  = P2^0;
sbit CS2  = P2^1;
sbit CLK2 = P2^2;

//-----------------------------------------
//            TLC549模数转换
//-----------------------------------------
uchar TLC549_ADC(void)
{
	   uchar n, tmp;

        CS  = 1;                     //CS置高,片选无效
        CLK = 0;

        CS  = 0;                     //CS置低,片选有效,同时DO输出高位
        _nop_();
        _nop_();                     //适当延迟时间1.4us Setup Time

        for(n = 0; n < 8; n++) //串行数据移位输入
        { 
                tmp <<= 1;
                tmp |=  DI;

                CLK = 1;        //0.4us
                _nop_();        //延迟0.1us
                CLK = 0;        //0.4us
        }
        CS = 1;            //CS置高,片选无效
        for(n = 17; n != 0; n--) _nop_();  //下一次转换需要延迟17us
        return (tmp);

}

//-----------------------------------------
//            TLC549模数转换
//-----------------------------------------
uchar TLC549_ADC2(void)
{
	   uchar n, tmp;

        CS2  = 1;                     //CS置高,片选无效
        CLK2 = 0;

        CS2  = 0;                     //CS置低,片选有效,同时DO输出高位
        _nop_();
        _nop_();                     //适当延迟时间1.4us Setup Time

        for(n = 0; n < 8; n++) //串行数据移位输入
        { 
                tmp <<= 1;
                tmp |=  DI2;

                CLK2 = 1;        //0.4us
                _nop_();        //延迟0.1us
                CLK2 = 0;        //0.4us
        }
        CS2 = 1;            //CS置高,片选无效
        for(n = 17; n != 0; n--) _nop_();  //下一次转换需要延迟17us
        return (tmp);

}

2、LCD12864驱动代码

cpp 复制代码
#include "12864.h"
#include "ziku.h"

void Delay_ms(unsigned int xms)  //@11.0592MHz
{
  unsigned int i,j;
	  for(i=xms;i>0;i--)    
		for(j=112;j>0;j--);  
}

static void LCD12864_Write(bit COM_Data,unsigned char  dat)  //12864操作函数 
{
  LCD12864_RS=COM_Data;   //指令 0 数据 1
	LCDData_Pro=dat;        //数据传输至P0扣
	LCD12864_EN=1;          //置1
	_nop_();
	LCD12864_EN=0;          //置0   产生下降沿
}

void LCD12864_Init(void)   //12864初始化
{
	Delay_ms(300);   //等待系统上电稳定
/******************************************************************************/
  LCD12864_EN=1;                       
  LCD12864_RS=1;                       
	LCD12864_CS1=1;  //仿真 0 实物 1   
	LCD12864_CS2=1;  //仿真 0 实物 1   
	Delay_ms(10);
/******************************************************************************/
	LCD12864_Write(LCD12864_COM,0x3f);   //开显示
	/*
	LCD12864_Write(LCD12864_COM,0xc0);   //这段不写也可以正常显示
	LCD12864_Write(LCD12864_COM,0xb8);
	LCD12864_Write(LCD12864_COM,0x40);
	*/
	LCD12864_Write(LCD12864_COM,0x30);   //打开基本指令
	LCD_Clear();                         //清屏
}
/*****************************************************************************
函数功能:清平函数
入口参数:空
说    明:清空整个屏幕数据
版    本:V1.0
时    间:2020年5月9日
*****************************************************************************/
void LCD_Clear(void)
{
	unsigned char  i,j; 
#if LCD_Mode
  LCD12864_CS1=1;   //选中左半屏
	LCD12864_CS2=1;   //选中右半屏
#else 
  LCD12864_CS1=0;   //选中左半屏
	LCD12864_CS2=0;   //选中右半屏
#endif
	LCD12864_Write(LCD12864_COM,0xc0);  //行
  for(i=0;i<8;i++)
	{
	  LCD12864_Write(LCD12864_COM,0xb8+i); //页
		for(j=0;j<64;j++)
		{
		  LCD12864_Write(LCD12864_COM,0x40+j); //列
			LCD12864_Write(LCD12864_DATA,0x00);
			Delay_ms(5);    //方便看清屏效果
		}
	}
}
/*****************************************************************************
函数功能:地址写入函数
入口参数:X,Y
说    明:根据地址自动切换左、右屏
版    本:V1.0
时    间:2020年5月9日
*****************************************************************************/
void LCD12864_X_Y(unsigned char X,unsigned char Y)
{
  Y=Y&0x7f;   //限定范围,列不能超过127     
	X=X&0x07;	  //限定范围,行不能超过7
	if(Y<64)
	{
#if LCD_Mode
		 LCD12864_CS1=1;   //选中左半屏
		 LCD12864_CS2=0;	 //关闭右半屏
#else
		 LCD12864_CS1=0;   //选中左半屏
		 LCD12864_CS2=1;	 //关闭右半屏
#endif
		 LCD12864_Write(LCD12864_COM,0x40+Y);  //选择列基地址+Y 一共64行
		 if(Y==63) Y=64;
	}
	else
	{
#if LCD_Mode
	  LCD12864_CS1=0;   //关闭左半屏
		LCD12864_CS2=1;	  //选中右半屏
#else
    LCD12864_CS1=1;   //关闭左半屏
		LCD12864_CS2=0;	  //选中右半屏
#endif
		Y&=0x3f;
	  LCD12864_Write(LCD12864_COM,0x40+Y);  //选择列基地址+Y   一共64列
	}
	  LCD12864_Write(LCD12864_COM,0xb8+X);  //选择页基地址+X   一共7页  
}
/*****************************************************************************
函数功能:6*16数值写入函数
入口参数:X,Y,num,*dat
说    明:X_横坐标 Y_纵坐标 num_数组的第num个数 *day_需要显示的数组
版    本:V1.5
修改时间:2022年7月10日
新    增:可实现跨左右屏
*****************************************************************************/
void LCD12864_Write_Number(unsigned char X,unsigned char Y,unsigned char num,unsigned char *dat)
{
	unsigned char  i; 
  for(i=0;i<6;i++)                
	{
	  LCD12864_X_Y(X,Y+i);                          //每写一个字节 更新一次Y 防止不能出现跨屏
		LCD12864_Write(LCD12864_DATA,dat[num*12+i]);  //写上半字 共写6个字节
	} 
  for(i=0;i<6;i++) 
	{
	  LCD12864_X_Y(X+1,Y+i);                         //同上
		LCD12864_Write(LCD12864_DATA,dat[num*12+6+i]); //写下半字 共写6个字节
	}
}
/*****************************************************************************
函数功能:变量显示函数
入口参数:X,Y,num,len
说    明:在第X行的第Y个位置显示len个num数值
版    本:V1.2
修改时间:2022年7月10日
新    增:自动计算变量长度 最大计数99999
*****************************************************************************/
void LCD12864_Num(unsigned char X,unsigned char Y,unsigned int num)
{
	unsigned char i; 
  unsigned char Len;	
  unsigned char Dis[5];
	unsigned char Buf[5];
	
	sprintf(Buf,"%d",num);   //将数值转换成字符串
	Len=strlen(Buf);         //计算字符串长度
	
  if(Len>4)Dis[Len-5]=num/10000     ;    //若数据更大 按照规律写即可
  if(Len>3)Dis[Len-4]=num%10000/1000;
  if(Len>2)Dis[Len-3]=num%1000/100  ;
  if(Len>1)Dis[Len-2]=num%100/10    ;
  if(Len>0)Dis[Len-1]=num%10        ;
	
  for(i=0;i<Len;i++) LCD12864_Write_Number(X,Y+(i*6),Dis[i],Num);
}

/*****************************************************************************
函数功能:12*16汉字写入函数
入口参数:X,Y,num,*dat
说    明:X_横坐标 Y_纵坐标 num_数组的第num个数 *day_需要显示的数组
版    本:V1.5
修改时间:2022年7月10日
新    增:左右跨屏
*****************************************************************************/
void LCD12864_Write_Chinese(unsigned char X,unsigned char Y,unsigned char num,unsigned char *dat)
{
	unsigned char  i;
  for(i=0;i<12;i++) 
	{
		LCD12864_X_Y(X,Y+i);                         //跨屏重要函数  勿删除
		LCD12864_Write(LCD12864_DATA,dat[num*24+i]); //写上半字 共写12个字节
	}
  for(i=0;i<12;i++) 
	{
	  LCD12864_X_Y(X+1,Y+i);                          //同上
		LCD12864_Write(LCD12864_DATA,dat[num*24+12+i]); //写下半字 共写12个字节
	}
}
/*****************************************************************************
函数功能:英文字母显示函数
入口参数:X,Y,*dat
说    明:X_横坐标 Y_纵坐标 *dat_需要显示的英文字母
版    本:V1.0
修改时间:2022年7月10日
注    明:带字库索引功能
*****************************************************************************/
void LCD12864_Write_English(unsigned char X,unsigned char Y,unsigned char *dat)
{
	unsigned char i,j;
	unsigned char Len;
	
	Len=strlen(dat);        //获取数据长度
		
  for(j=0;j<Len;j++)      
	{
	  for(i=0; ;i++)  if(English_Buf[i]==*dat) {dat++; break;}  //查找字库索引列表
	  LCD12864_Write_Number(X,Y+(j*6),i,English);               //写数据
	}
}
///*****************************************************************************
//函数功能:汉字显示函数
//入口参数:X,Y,*dat
//说    明:X_横坐标 Y_纵坐标 *dat_需要显示的汉字
//版    本:V1.0
//修改时间:2022年7月10日
//注    明:带字库索引功能

//注意:存在Bug 暂未修复
//*****************************************************************************/
//void LCD12864_Write_String(unsigned char X,unsigned char Y,unsigned char *dat)
//{
//	unsigned char i,j;
//	unsigned char Len;
//	
//	Len=(strlen(dat))/2;  //1个汉字2个字节  所以要除以2
//	
//   for(j=0;j<Len;j++) 
//	{
//	  for(i=0; ;i++)  if(Chinese_Buf[i]==*dat) {dat++; break;}   //存在Bug不能显示第4个汉字
//	  LCD12864_Write_Chinese(X,Y+(j*12),i,Chinese);
//	}
//}

3、DHT11驱动代码

cpp 复制代码
#include "DHT11.h"

sbit Data=P3^2; //数据线
uchar rec_dat[9]; //储存数据
void DHT11_delay_us(uchar n)
{
    while(--n);
}
void DHT11_delay_ms(uint z)
{
   uint i,j;
   for(i=z;i>0;i--)
      for(j=110;j>0;j--);
}

/*
主机(单片机)发送起始信号:
1.主机先拉高data。
2.拉低data延迟18ms。
3.拉高data并延迟等待(通过此操作将单片机引脚设置为输入)。
*/
void DHT11_start()
{
   Data=1;
   DHT11_delay_us(2);
   Data=0;
   DHT11_delay_ms(25);   //拉低延时18ms以上
   Data=1;
   DHT11_delay_us(30);   //拉高 延时 20~40us,取中间值 30us
}

/*------------------------------------------------
              接收八位二进制
------------------------------------------------*/
uchar DHT11_rec_byte()      //接收一个字节
{
  unsigned char i,dat=0;
  for(i=0;i<8;i++)    //从高到低依次接收8位数据
   {          
      while(Data);   //等待进入低电平
      while(!Data);   //等待50us低电平过去
      DHT11_delay_us(8);     //延时60us,如果还为高则数据为1,否则为0 
      dat<<=1;//移位(低位补零)使正确接收8位数据,数据为0时直接移位
      if(Data==1)    //数据为1时,使dat加1来接收数据1
        dat+=1;
      while(Data);  //等待数据线拉低    
   }  
    return dat;
}


/*------------------------------------------------
              接收40bit数据(具体的温湿度)
1.主机先把data线拉高(io设置为输入)。
2.从机把data线拉低,主机读取data线电平,直到低电平结束(大约50us)
  从机拉高data线后,延迟40us左右(28~70us之间)主机再次读取data线电平,如果为低电平,则为"0",如果为高电平,则为"1"。
3.继续重复上述1,2步骤累计40次。
------------------------------------------------*/
uchar T_H;
int tem, hum;
void DHT11_receive()      //接收40位的数据
{
    uchar R_H,R_L,T_L,RH,RL,TH,TL,revise; 
    DHT11_start();//发送起始信号:
    if(Data==0)
    {
        while(Data==0);   //等待拉高     
        DHT11_delay_us(40);  //拉高后延时80us
			
        R_H=DHT11_rec_byte();    //接收湿度高八位  
        R_L=DHT11_rec_byte();    //接收湿度低八位  
        T_H=DHT11_rec_byte();    //接收温度高八位  
        T_L=DHT11_rec_byte();    //接收温度低八位
        revise=DHT11_rec_byte(); //接收校正位

        DHT11_delay_us(25);    //结束

        if((R_H+R_L+T_H+T_L)==revise)      //最后一字节为校验位,校验是否正确
        {
            RH=R_H;
            RL=R_L;
            TH=T_H;
            TL=T_L;
        } 
		
		tem	= TH;
		hum = RH;
        /*数据处理,转换为字符,方便显示*/
			  //湿度
		rec_dat[0]=(RH/10);
        rec_dat[1]=(RH%10);
				rec_dat[2]=' ';
				rec_dat[3]=' ';
				
				//温度
        rec_dat[4]=(TH/10);
        rec_dat[5]=(TH%10); 
		    rec_dat[6]=' ';
			
    }
}

三、项目演示

(1) 首先运行仿真的Python脚本,可以看到如下:

此时设备已经在线

(2)按下布防按键,布防指示灯亮起,此时如果红外检测到人,报警灯亮起,否则报警灯熄灭,如下:

(3)按下调整切换,调整位置的数据持续闪烁,此时按加减可以操作数据,如下:

(4)当湿度超过阈值的时候,风扇转动,进行降湿,当Mq02超过阈值时,表示发生了火灾,此时蜂鸣器进行报警。

(5)同时,数据会上传到阿里云平台,如图:

四、项目总结

本次项目使用温湿度、烟雾、甲烷、红外传感器,结合阿里云物联网平台设计了一个安防系统,系统通过我们的python脚本,利用电脑的网络资源,将仿真数据上传到阿里云平台,实现仿真上实现物联网安防系统。

相关推荐
NEWEVA__zzera2224 分钟前
利用光耦来隔离485芯片与串口引脚,实现自动收发485电路
单片机·嵌入式硬件
m0_7482405429 分钟前
STM32第十一课:STM32-基于标准库的42步进电机的简单IO控制(附电机教程,看到即赚到)
stm32·单片机·嵌入式硬件
中科岩创30 分钟前
中科岩创桥梁自动化监测解决方案
大数据·网络·物联网
沐欣工作室_lvyiyi1 小时前
基于单片机的多功能智能小车(论文+源码)
stm32·单片机·嵌入式硬件·毕业设计·单片机毕业设计
lucy153027510792 小时前
MCU 功耗基准测试
科技·单片机·嵌入式硬件·智能家居·信号处理·工控主板
m0_748240913 小时前
OpenMV与STM32通信全面指南
stm32·单片机·嵌入式硬件
Cchengzu5 小时前
阿里巴巴2017实习生笔试题(二)
stm32·单片机·嵌入式硬件
重生之我是数学王子9 小时前
单片机 STM32入门
stm32·单片机·嵌入式硬件
qq_4597300312 小时前
4-3 MCU中ARM存储器的作用
arm开发·单片机·嵌入式硬件
中科岩创12 小时前
中科岩创边坡自动化监测解决方案
大数据·网络·物联网