资讯详情

单片机智能家居电路控制程序+Proteus仿真+视频(光烟雾传感器与自动窗帘)

模拟原理图如下(proteus本帖附件可下载仿真工程文件)

4c38c5624fcded38167d49e9d427738f.png

单片机源程序如下:

#include //包含头文件,一般不需要更改。头文件包含特殊功能寄存器的定义

#include "intrins.h"

#define u8 unsigned char

#define u16 unsigned int

#define uchar unsigned char

#define uint unsigned int

uchar yushe_wendu=50; ///温度预设值

uchar yushe_yanwu=100; ///光照预设值

uchar yushe_tianranqi=100; ///天然气预设值

uint wendu; ///温度值全局变量

uchar yanwu; //用于读取ADC数据

uchar tianranqi; //用于读取ADC数据

uint times = 0; //变量times,用于液晶切换显示

uchar shezhi_flag = 0; //变量标志位,天然气预设值用于切换显示设置

//操作模式

uchar Mode=0; //=一是设置温度阀值=光照阀值设置 =0是正常的监控模式

uint Buzzer=0;

uint count = 0;

//管脚声明

sbit Led_Yellow=P2^4; //黄灯

sbit speaker =P2^0; //蜂鸣器

sbit cg=P2^3; //总开关

sbit c1_k=P1^1; //窗帘1开关

sbit c2_k=P1^4; //窗帘2开关

/********************************************************************

* 名称 : delay_1ms()

* 功能 : 延时1ms函数

* 输入 : q

* 输出 : 无

***********************************************************************/

void delay_ms(uint q)

{

uint i,j;

for(i=0;i

for(j=0;j<110;j );

}

/***********************************************************************************************************

LCD1602相关函数

**********************************************************************************************************/

//LCD管脚声明 (RW引脚实物直接接地,因为本设计只用到液晶的写操作,RW引脚一直是低电平)

sbit LCDRS = P2^7;

sbit LCDEN = P2^6;

sbit D0                 = P0^0;

sbit D1                 = P0^1;

sbit D2                 = P0^2;

sbit D3                 = P0^3;

sbit D4                 = P0^4;

sbit D5                 = P0^5;

sbit D6                 = P0^6;

sbit D7                 = P0^7;

//LCD延时

void LCDdelay(uint z)                  //该延时大约100us(不精确,液晶操作的延时不要求很精确)

{

uint x,y;

for(x=z;x>0;x--)

for(y=10;y>0;y--);

}

void LCD_WriteData(u8 dat)

{

if(dat&0x01)D0=1;else D0=0;

if(dat&0x02)D1=1;else D1=0;

if(dat&0x04)D2=1;else D2=0;

if(dat&0x08)D3=1;else D3=0;

if(dat&0x10)D4=1;else D4=0;

if(dat&0x20)D5=1;else D5=0;

if(dat&0x40)D6=1;else D6=0;

if(dat&0x80)D7=1;else D7=0;

}

//写命令

void write_com(uchar com)

{

LCDRS=0;

LCD_WriteData(com);

//  DAT=com;

LCDdelay(5);

LCDEN=1;

LCDdelay(5);

LCDEN=0;

}

//写数据

void write_data(uchar date)

{

LCDRS=1;

LCD_WriteData(date);

//  DAT=date;

LCDdelay(5);

LCDEN=1;

LCDdelay(5);

LCDEN=0;

}

/*------------------------------------------------

选择写入位置

------------------------------------------------*/

void SelectPosition(unsigned char x,unsigned char y)

{

if (x == 0)

{

write_com(0x80 + y);     //表示第一行

}

else

{

write_com(0xC0 + y);      //表示第二行

}

}

/*------------------------------------------------

写入字符串函数

------------------------------------------------*/

void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)

{

SelectPosition(x,y) ;

while (*s)

{

write_data( *s);

s ++;

}

}

//========================================================================

// 函数: void LCD_Write_Char(u8 x,u8 y,u16 s,u8 l)

// 应用: LCD_Write_Char(0,1,366,4) ;

// 描述: 在第0行第一个字节位置显示366的后4位,显示结果为 0366

// 参数: x:行,y:列,s:要显示的字,l:显示的位数

// 返回: none.

// 版本: VER1.0

// 日期: 2013-4-1

// 备注: 最大显示65535

//========================================================================

void LCD_Write_Char(u8 x,u8 y,u16 s,u8 l)

{

SelectPosition(x,y) ;

if(l>=5)

write_data(0x30+s/10000%10);        //万位

if(l>=4)

write_data(0x30+s/1000%10);                //千位

if(l>=3)

write_data(0x30+s/100%10);                //百位

if(l>=2)

write_data(0x30+s/10%10);                        //十位

if(l>=1)

write_data(0x30+s%10);                //个位

}

/*1602指令简介

write_com(0x38);//屏幕初始化

write_com(0x0c);//打开显示 无光标 无光标闪烁

write_com(0x0d);//打开显示 阴影闪烁

write_com(0x0d);//打开显示 阴影闪烁

*/

//1602初始化

void Init1602()

{

uchar i=0;

write_com(0x38);//屏幕初始化

write_com(0x0c);//打开显示 无光标 无光标闪烁

write_com(0x06);//当读或写一个字符是指针后一一位

write_com(0x01);//清屏

}

void Display_1602(yushe_wendu,yushe_yanwu,c,temp)

{

//显示预设温度

LCD_Write_Char(0,6,yushe_wendu,2) ;

//显示预设光照

LCD_Write_Char(0,13,yushe_yanwu,3) ;

//时时温度

LCD_Write_Char(1,6,c/10,2) ;

write_data('.');

LCD_Write_Char(1,9,c%10,1) ;

//时时光照

LCD_Write_Char(1,13,temp,3) ;

}

/***********************************************************************************************************

ADC0832相关函数

***********************************************************************************************************/

sbit ADCS         =P1^5; //ADC0832 片选

sbit ADCLK  =P1^2; //ADC0832 时钟

sbit ADDI         =P1^3; //ADC0832 数据输入                /*因为单片机的管脚是双向的,且ADC0832的数据输入输出不同时进行,

sbit ADDO         =P1^3; //ADC0832 数据输出                /*为节省单片机引脚,简化电路所以输入输出连接在同一个引脚上

//========================================================================

// 函数: unsigned int Adc0832(unsigned char channel)

// 应用:                 temp=Adc0832(0);

// 描述: 读取0通道的AD值

// 参数: channel:通道0和通道1选择

// 返回: 选取通道的AD值

// 版本: VER1.0

// 日期: 2015-05-29

// 备注:

//========================================================================

unsigned int Adc0832(unsigned char channel)

{

uchar i=0;

uchar j;

uint dat=0;

uchar ndat=0;

uchar  Vot=0;

if(channel==0)channel=2;

if(channel==1)channel=3;

ADDI=1;

_nop_();

_nop_();

ADCS=0;//拉低CS端

_nop_();

_nop_();

ADCLK=1;//拉高CLK端

_nop_();

_nop_();

ADCLK=0;//拉低CLK端,形成下降沿1

_nop_();

_nop_();

ADCLK=1;//拉高CLK端

ADDI=channel&0x1;

_nop_();

_nop_();

ADCLK=0;//拉低CLK端,形成下降沿2

_nop_();

_nop_();

ADCLK=1;//拉高CLK端

ADDI=(channel>>1)&0x1;

_nop_();

_nop_();

ADCLK=0;//拉低CLK端,形成下降沿3

ADDI=1;//控制命令结束

_nop_();

_nop_();

dat=0;

for(i=0;i<8;i++)

{

dat|=ADDO;//收数据

ADCLK=1;

_nop_();

_nop_();

ADCLK=0;//形成一次时钟脉冲

_nop_();

_nop_();

dat<<=1;

if(i==7)dat|=ADDO;

}

for(i=0;i<8;i++)

{

j=0;

j=j|ADDO;//收数据

ADCLK=1;

_nop_();

_nop_();

ADCLK=0;//形成一次时钟脉冲

_nop_();

_nop_();

j=j<<7;

ndat=ndat|j;

if(i<7)ndat>>=1;

}

ADCS=1;//拉低CS端

ADCLK=0;//拉低CLK端

ADDO=1;//拉高数据端,回到初始状态

dat<<=8;

dat|=ndat;

return(dat);            //return ad data

}

/***********************************************************************************************************

DS18B20相关函数

***********************************************************************************************************/

sbit DQ = P1^0;                                 //ds18b20的数据引脚

/*****延时子程序:该延时主要用于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--)

{

DQ = 0;     // 给脉冲信号

dat>>=1;

DQ = 1;     // 给脉冲信号

if(DQ)

dat|=0x80;

Delay_DS18B20(4);

}

return(dat);

}

/*****写一个字节*****/

void WriteOneChar(unsigned char dat)

{

unsigned char i=0;

for (i=8; i>0; i--)

{

DQ = 0;

DQ = dat&0x01;

Delay_DS18B20(5);

DQ = 1;

dat>>=1;

}

}

/*****读取温度*****/

unsigned int ReadTemperature(void)

{

unsigned char a=0;

unsigned char b=0;

unsigned int t=0;

float tt=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=t*0.0625;

t= tt*10+0.5;     //放大10倍输出并四舍五入

return(t);

}

//=====================================================================================

//=====================================================================================

//=====================================================================================

/*****校准温度*****/

u16 check_wendu(void)

{

u16 c;

c=ReadTemperature()-5;                          //获取温度值并减去DS18B20的温漂误差

if(c<1) c=0;

if(c>=900) c=0;

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))

{

delay_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;// 无按键按下

}

/*************定时器0初始化程序***************/

void time_init()

{

TMOD=0X01; //定时器0、工作方式1

TH0=(65536-10000)/256;

TL0=(65536-10000)%256;

EA=1; //开总中断

ET0=1; //开定时器0中断

TR0=1; //允许定时器0定时

}

/*************定时器0中断服务程序***************/

void time0_int() interrupt 1

{

TH0 = (65536-1000)/256;

TL0 = (65536-1000)%256;     // 50ms         12M

count++;

if(count>80)

{

count = 0;

wendu=check_wendu();          //读取温度值

yanwu=Adc0832(0);                                //读取光照值

tianranqi=Adc0832(1);                                //读取天然气值

if((wendu>=(yushe_wendu*10))||(tianranqi>yushe_tianranqi))   //温度大于等于预设温度值时(为什么是大于预设值*10:因为我们要显示的温度是有小数点后一位,是一个3位数,25.9°C时实际读的数是259,所以判断预设值时将预设值*10)

{

speaker=0;                                                //打开蜂鸣器报警

Led_Yellow=0;                                        //打开温度报警灯

}

else                                                                                //温度值小于预设值时

{

speaker=1;

Led_Yellow=1;                                        //关闭报警灯

}

if(yanwu>=yushe_yanwu+20)          //光照值大于等于预设值时

{

cg = 0;

c1_k = 1;

c2_k = 0;

delay_ms(50);

c1_k = 0;

c2_k = 0;

}

if(yanwu<=yushe_yanwu-20)          //光照值大于等于预设值时

{

cg = 0;

c1_k = 0;

c2_k = 1;

delay_ms(50);

c1_k = 0;

c2_k = 0;

}

}

}

void main (void)

{

u8 key;

cg = 1;

c1_k = 0;

c2_k = 0;

speaker = 1;

Led_Yellow = 1;

wendu=check_wendu();                  //初始化时调用温度读取函数 防止开机85°C

time_init();

Init1602();                          //调用初始化显示函数

yanwu=Adc0832(0);                                //读取光照值

tianranqi=Adc0832(1);                                //读取天然气值

wendu=check_wendu();          //读取温度值

while (1)                                                //主循环

{

key=Key_Scan();                                        //按键扫描

if(key==KEY_SET)

{

Mode++;

}

switch(Mode)                                                //判断模式的值

{

case 0:                                                                //监控模式

{

times++;                                           //计数

if( times >= 500 )                                //大于500,清零

{

times = 0;

}

if( times <= 300 )                           //小于300,显示光强、温度信息

{

if( times == 1 )

{

LCD_Write_String(0,0,"SET T:00   L:000");  //开机界面

LCD_Write_String(1,0,"NOW T:00.0 L:000");

}

Display_1602(yushe_wendu,yushe_yanwu,wendu,yanwu);  //显示预设温度,预设光照,温度值,光照值

break;

}

else                                                        //大于300,显示天然气信息

{

if( times == 301 )

{

LCD_Write_String(0,0,"SET yanwu:00    ");  //开机界面

LCD_Write_String(1,0,"NOW yanwu:00.0  ");

}

//        Display_1602(yushe_wendu,yushe_yanwu,wendu,yanwu);  //显示预设温度,预设光照,温度值,光照值

LCD_Write_Char(0,10,yushe_tianranqi,3) ;//显示预设光照

LCD_Write_Char(1,10,tianranqi,3) ;//显示预设光照

write_com( 0x80+0x40+10);

write_data( tianranqi/100+0x30);

write_data( tianranqi%100/10+0x30);

write_data( tianranqi%10+0x30);

write_data( ' ');

break;

}

}

case 1://预设温度模式

{

SelectPosition(0,5) ;                                        //指定位置

write_com(0x0d);                                                        //阴影闪烁

if(key==KEY_ADD)                                                        //加键按下

{

yushe_wendu++;                                            //预设温度值(阀值)加1

if(yushe_wendu>=99)                                         //当阀值加到大于等于99时

yushe_wendu=99;                                                         //阀值固定为99

LCD_Write_Char(0,6,yushe_wendu,2) ;//显示预设温度

}

if(key==KEY_MINUS)                                                 //减键按下

{

if(yushe_wendu<=1)                                        //当温度上限值减小到1时

yushe_wendu=1;                          //固定为1

yushe_wendu--;                                                        //预设温度值减一,最小为0

LCD_Write_Char(0,6,yushe_wendu,2) ;//显示预设温度

}

break;                                                                                          //执行后跳出switch

}

case 2:                                //预设光照模式

{

SelectPosition(0,12) ;                                //指定位置

write_com(0x0d);                                                        //打开显示 无光标 光标闪烁

if(key==KEY_ADD)                                                        //加键按下

{

if(yushe_yanwu>=255)        //当阀值加到大于等于255时

yushe_yanwu=254;            //阀值固定为254

yushe_yanwu++;                                            //预设光照值(阀值)加1,最大为255

LCD_Write_Char(0,13,yushe_yanwu,3) ;//显示预设光照

}

if(key==KEY_MINUS)                                                //减键按下

{

if(yushe_yanwu<=1)                                        //当光照上限值减小到1时

yushe_yanwu=1;                  //固定为1

yushe_yanwu--;                                                        //预设温度值减一,最小为0

LCD_Write_Char(0,13,yushe_yanwu,3) ;//显示预设光照

}

break;

}

case 3:                                //预设天然气设置

{

if( shezhi_flag == 0 )

{

LCD_Write_String(0,0,"SET yanwu:      ");  //界面

LCD_Write_String(1,0,"NOW yanwu:      ");

shezhi_flag = 1;

LCD_Write_Char(0,10,yushe_tianranqi,3) ;//显示天然气设置

LCD_Write_Char(1,10,tianranqi,3) ;//显示预设天然气设置

write_com( 0x80+0x40+10);

write_data( tianranqi/100+0x30);

write_data( tianranqi%100/10+0x30);

write_data( tianranqi%10+0x30);

write_data( ' ');

}

SelectPosition(0,9) ;                                //指定位置

write_com(0x0d);                                                        //打开显示 无光标 光标闪烁

if(key==KEY_ADD)                                                        //加键按下

{

if(yushe_tianranqi>=255)        //当阀值加到大于等于255时

yushe_tianranqi=254;            //阀值固定为254

yushe_tianranqi++;                                            //预设天然气设置(阀值)加1,最大为255

LCD_Write_Char(0,10,yushe_tianranqi,3) ;//显示预设天然气设置

}

if(key==KEY_MINUS)                                                //减键按下

{

if(yushe_tianranqi<=1)                                        //当天然气设置上限值减小到1时

yushe_tianranqi=1;                  //固定为1

yushe_tianranqi--;                                                        //预设温度值减一,最小为0

LCD_Write_Char(0,10,yushe_tianranqi,3) ;//显示预设天然气设置

}

break;

}

default        :

{

write_com(0x38);//屏幕初始化

write_com(0x0c);//打开显示 无光标 无光标闪烁

Mode=0;                        //恢复正常模式

shezhi_flag = 0;

times = 0;

break;

}

}

}

}

全部资料51hei下载地址:

单片机智能家居电路控制仿真.7z

(8.33 MB, 下载次数: 225)

2020-5-24 00:41 上传

点击文件名下载附件

评分

黑币 +50

收起

理由

+ 50

共享资料的黑币奖励!

标签: 11ea开关传感器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台