仿真软件测试燃气报警器,单片机传感器设计 火灾报警器 Proteus仿真 含程序.hex文件,仿真图...

#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;                                //烟雾预设值

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

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

//运行模式

uchar Mode=0;                                                                 //=1是设置温度阀值  =2是设置烟雾阀值        =0是正常监控模式

//管脚声明

sbit Led_Reg                 =P2^2;                                 //红灯

sbit Led_Yellow  =P2^4;                                 //黄灯

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

sbit Fan                      =P3^3;                                 //

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

* 名称 : delay_1ms()

* 功能 : 延时1ms函数

* 输入 : q

* 输出 : 无

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

void delay_ms(uint q)

{

uint i,j;

for(i=0;i

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

}

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

LCD1602相关函数

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

//LCD管脚声明

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>=999) c=999;

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

}

void main (void)

{

u8 key;

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

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

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

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

delay_ms(1000);

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

while (1)                                                //主循环

{

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

yanwu=Adc0832(0);                                //读取烟雾值

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

if(key==KEY_SET)

{

Mode++;

}

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

{

case 0:                                                                //监控模式

{

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

if(yanwu>=yushe_yanwu)          //烟雾值大于等于预设值时

{

Led_Reg=0;                                          //烟雾指示灯亮

Fan=0;

Buzzer=0;                                                  //蜂鸣器报警

}

else                                                                                  //烟雾值小于预设值时

{

Led_Reg=1;                                          //关掉报警灯

Fan=1;

}

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

{

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

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

}

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

{

Led_Yellow=1;                                          //关闭报警灯

}

if((yanwu

{

Buzzer=1;                                                  //停止报警

}

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;

}

default        :

{

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

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

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

break;

}

}

}

}

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值