51单片机 Proteus仿真 温度上下限 报警器 数码管

在这里插入图片描述

#include <reg52.h>                                                                      /* 调用单片机头文件 */
#define uchar	unsigned char                                                           /* 无符号字符型 宏定义	变量范围0~255 */
#define uint	unsigned int                                                            /* 无符号整型 宏定义	变量范围0~65535 */

/* 数码管段选定义      0     1    2    3    4    5	6	 7	  8	   9 */
uchar code smg_du[] = { 0x28, 0xee, 0x32, 0xa2, 0xe4, 0xa1, 0x21, 0xea, 0x20, 0xa0 };   /* 断码 */
/* 数码管位选定义 */
uchar code	smg_we[] = { 0xef, 0xdf, 0xbf, 0x7f };
uchar		dis_smg[4] = { 0 };

sbit	dq	= P2 ^ 4;                                                               /* 18b20 IO口的定义 */
sbit	beep	= P2 ^ 3;                                                               /* 蜂鸣器IO口定义 */

bit	flag_lj_en;                                                                     /*按键连加使能 */
bit	flag_lj_3_en;                                                                   /*按键连3次连加后使能  加的数就越大了 */
uchar	key_time, key_value;                                                            /* 用做连加的中间变量 */
bit	key_500ms;


uint	temperature;                                                                    /*  */
bit	flag_300ms;
uchar	menu_1;                                                                         /* 菜单设计的变量 */
uint	t_high = 350, t_low = 100;                                                      /* 温度上下限报警值 */

/***********************1ms延时函数*****************************/
void delay_1ms( uint q )
{
	uint i, j;
	for ( i = 0; i < q; i++ )
		for ( j = 0; j < 120; j++ )
			;
}


/***********************小延时函数*****************************/
void delay_uint( uint q )
{
	while ( q-- )
		;
}


/***********************数码显示函数*****************************/
void display()
{
	static uchar i;
	i++;
	if ( i >= 4 )
		i = 0;
	P1	= 0xff;         /* 消隐 */
	P3	= smg_we[i];    /* 位选 */
	P1	= dis_smg[i];   /* 段选 */
}


/***********************18b20初始化函数*****************************/
void init_18b20()
{
	bit q;
	dq = 1; /* 把总线拿高 */
	delay_uint( 1 );
	dq = 0; /* 给复位脉冲 */
	delay_uint( 80 );
	dq = 1; /* 把总线拿高 等待 */
	delay_uint( 10 );
	q = dq; /* 读取18b20初始化信号 */
	delay_uint( 20 );
	dq = 1; /* 把总线拿高 释放总线 */
}


/*************写18b20内的数据***************/
void write_18b20( uchar dat )
{
	uchar i;
	for ( i = 0; i < 8; i++ )
	{                               /* 写数据是低位开始 */
		dq	= 0;            /* 把总线拿低写时间隙开始 */
		dq	= dat & 0x01;   /* 向18b20总线写数据了 */
		delay_uint( 5 );
		dq	= 1;            /* 释放总线 */
		dat	>>= 1;
	}
}


/*************读取18b20内的数据***************/
uchar read_18b20()
{
	uchar i, value;
	for ( i = 0; i < 8; i++ )
	{
		dq	= 0;    /* 把总线拿低读时间隙开始 */
		value	>>= 1;  /* 读数据是低位开始 */
		dq	= 1;    /* 释放总线 */
		if ( dq == 1 )  /* 开始读写数据 */
			value |= 0x80;
		delay_uint( 5 );
	}
	return(value);          /* 返回数据 */
}


/*************读取温度的值 读出来的是小数***************/
uint read_temp()
{
	uint	value;
	uchar	low;                                            /* 在读取温度的时候如果中断的太频繁了,就应该把中断给关了,否则会影响到18b20的时序 */
	init_18b20();                                           /* 初始化18b20 */
	write_18b20( 0xcc );                                    /* 跳过64位ROM */
	write_18b20( 0x44 );                                    /* 启动一次温度转换命令 */
	delay_uint( 50 );

	init_18b20();                                           /* 初始化18b20 */

	write_18b20( 0xcc );                                    /* 跳过64位ROM */
	write_18b20( 0xbe );                                    /* 发出读取暂存器命令 */

	EA	= 0;
	low	= read_18b20();                                 /* 读温度低字节 */
	value	= read_18b20();                                 /* 读温度高字节 */
	EA	= 1;
	value	<<= 8;                                          /* 把温度的高位左移8位 */
	value	|= low;                                         /* 把读出的温度低位放到value的低八位中 */
	value	*= 0.625;                                       /* 转换到温度值 小数 */
	return(value);                                          /* 返回读出的温度 带小数 */
}


/*************定时器0初始化程序***************/
void time_init()
{
	EA	= 1;                                            /* 开总中断 */
	TMOD	= 0X01;                                         /* 定时器0、定时器1工作方式1 */
	ET0	= 1;                                            /* 开定时器0中断 */
	TR0	= 1;                                            /* 允许定时器0定时 */
}


/********************独立按键程序*****************/
uchar key_can;                                                  /*按键值 */

void key()                                                      /* 独立按键程序 */
{
	static uchar key_new;
	key_can = 0;                                            /*按键值还原 */
	P2	|= 0x07;
	if ( (P2 & 0x07) != 0x07 )                              /*按键按下 */
	{
		if ( key_500ms == 1 )                           /* 连加 */
		{
			key_500ms	= 0;
			key_new		= 1;
		}
		delay_1ms( 1 );                                 /*按键消抖动 */
		if ( ( (P2 & 0x07) != 0x07) && (key_new == 1) )
		{                                               /* 确认是按键按下 */
			key_new = 0;
			switch ( P2 & 0x07 )
			{
			case 0x06: key_can	= 3; break;     /* 得到k2键值 */
			case 0x05: key_can	= 2; break;     /* 得到k3键值 */
			case 0x03: key_can	= 1; break;     /* 得到k4键值 */
			}
			flag_lj_en = 1;                         /* 连加使能 */
		}
	}else  {
		key_new		= 1;
		flag_lj_en	= 0;                            /* 关闭连加使能 */
		flag_lj_3_en	= 0;                            /* 关闭3秒后使能 */
		key_value	= 0;                            /* 清零 */
		key_time	= 0;
		key_500ms	= 0;
	}
}


/****************按键处理数码管显示函数***************/
void key_with()
{
	if ( key_can == 1 ) /* 设置键 */
	{
		menu_1++;
		if ( menu_1 >= 3 )
		{
			menu_1 = 0;
		}
	}
	if ( menu_1 == 1 )                                              /* 设置高温报警 */
	{
		if ( key_can == 2 )
		{
			if ( flag_lj_3_en == 0 )
				t_high++;                               /*按键按下未松开自动加三次 */
			else
				t_high += 10;                           /*按键按下未松开自动加三次之后每次自动加10 */
			if ( t_high > 990 )
				t_high = 990;
		}
		if ( key_can == 3 )
		{
			if ( flag_lj_3_en == 0 )
				t_high--;                               /*按键按下未松开自动减三次 */
			else
				t_high -= 10;                           /*按键按下未松开自动减三次之后每次自动减10 */
			if ( t_high <= t_low )
				t_high = t_low + 1;
		}
		dis_smg[0]	= smg_du[t_high % 10];                  /* 取小数显示 */
		dis_smg[1]	= smg_du[t_high / 10 % 10] & 0xdf;      /* 取个位显示 */
		dis_smg[2]	= smg_du[t_high / 100 % 10];            /* 取十位显示 */
		dis_smg[3]	= 0x64;                                 /* H */
	}
	if ( menu_1 == 2 )                                              /* 设置低温报警 */
	{
		if ( key_can == 2 )
		{
			if ( flag_lj_3_en == 0 )
				t_low++;                                /*按键按下未松开自动加三次 */
			else
				t_low += 10;                            /*按键按下未松开自动加三次之后每次自动加10 */
			if ( t_low >= t_high )
				t_low = t_high - 1;
		}
		if ( key_can == 3 )
		{
			if ( flag_lj_3_en == 0 )
				t_low--;                                /*按键按下未松开自动减三次 */
			else
				t_low -= 10;                            /*按键按下未松开自动加三次之后每次自动加10 */
			if ( t_low <= 10 )
				t_low = 10;
		}
		dis_smg[0]	= smg_du[t_low % 10];                   /* 取小数显示 */
		dis_smg[1]	= smg_du[t_low / 10 % 10] & 0xdf;       /* 取个位显示 */
		dis_smg[2]	= smg_du[t_low / 100 % 10];             /* 取十位显示 */
		dis_smg[3]	= 0x3D;                                 /* L */
	}
}


/****************报警函数***************/
void clock_h_l()
{
	if ( (temperature <= t_low) || (temperature >= t_high) )
	{
		beep = ~beep; /* 蜂鸣器报警 */
	}else   {
		beep = 1;
	}
}


/****************主函数***************/
void main()
{
	beep = 0;                                                                       /* 开机叫一声 */
	delay_1ms( 150 );
	P0		= P1 = P2 = P3 = 0xff;
	temperature	= read_temp();                                                  /* 先读出温度的值 */
	delay_1ms( 750 );
	temperature	= read_temp();                                                  /* 先读出温度的值 */
	dis_smg[0]	= smg_du[temperature % 10];                                     /* 取温度的小数显示 */
	dis_smg[1]	= smg_du[temperature / 10 % 10] & 0xdf;                         /* 取温度的个位显示 */
	dis_smg[2]	= smg_du[temperature / 100 % 10];                               /* 取温度的十位显示 */
	dis_smg[3]	= 0xFF;
	time_init();                                                                    /* 初始化定时器 */
	while ( 1 )
	{
		key();                                                                  /*按键程序 */
		if ( key_can != 0 )
		{
			key_with();                                                     /* 设置报警温度 */
		}
		if ( flag_300ms == 1 )                                                  /* 300ms 处理一次温度程序 */
		{
			flag_300ms	= 0;
			temperature	= read_temp();                                  /* 先读出温度的值 */
			clock_h_l();                                                    /* 报警函数 */
			if ( menu_1 == 0 )
			{
				dis_smg[0]	= smg_du[temperature % 10];             /* 取温度的小数显示 */
				dis_smg[1]	= smg_du[temperature / 10 % 10] & 0xdf; /* 取温度的个位显示 */
				dis_smg[2]	= smg_du[temperature / 100 % 10];       /* 取温度的十位显示 */
				dis_smg[3]	= 0xFF;
			}
		}
	}
}


/*************定时器0中断服务程序***************/
void time0_int() interrupt 1
{
	static uchar value;                             /* 定时2ms中断一次 */
	TH0	= 0xf8;
	TL0	= 0x30;                                 /* 2ms */
	display();                                      /* 数码管显示函数 */
	value++;
	if ( value >= 150 )
	{
		value		= 0;
		flag_300ms	= 1;
	}
	if ( flag_lj_en == 1 )                          /*按下按键使能 */
	{
		key_time++;
		if ( key_time >= 250 )                  /* 500ms */
		{
			key_time	= 0;
			key_500ms	= 1;            /* 500ms */
			key_value++;
			if ( key_value > 3 )
			{
				key_value	= 10;
				flag_lj_3_en	= 1;    /* 3次后1.5秒连加大些 */
			}
		}
	}
}

猜你喜欢

转载自blog.csdn.net/x1131230123/article/details/107323897