基于51单片机的温控系统设计_DS18B20工作原理及电路图

基于51单片机的温控系统设计_DS18B20工作原理及电路图基于51单片机的温控系统本文是基于STC89C52单片机的温度控制系统,主要由主控模块、显示模块及外围电路几个部分组成

基于51单片机的温控系统

本文是基于STC89C52单片机的温度控制系统,主要由主控模块、显示模块及外围电路几个部分组成。
通过DS18B20检测外部温度,通过LCD1602显示,按键可调节上下限。当温度超过上限或低于下限,蜂鸣器均会报警。当温度超过上限时,电机会开始工作,模拟风扇,起到降温作用。LED灯电路模拟家用电灯,由两个开关对其进行控制。
删除线格式 该温控系统可以模拟简易智能家居系统。

系统硬件设计

整体电路原理图设计
在这里插入图片描述
该系统由51单片机作为主控模块,通过DS18B20检测温度,由LCD1602显示,并加外围电路组成。
测温显示模块
在这里插入图片描述
蜂鸣器报警及电机模块
在这里插入图片描述

系统软件设计

单片机IO口定义

sbit beep = P1^7;  //定义蜂鸣器IO口

sbit LED1 = P1^0;  //定义灯IO口
sbit LED2 = P1^1;
sbit k1 = P1^2;  //定义灯开关IO口
sbit k2 = P1^3;

sbit MOTOR = P1^4;  //定义电机
sbit BUTTON_RUN = P1^5;  //定义电机启动按钮
sbit BUTTON_STOP = P1^6;  //定义电机关闭按钮

sbit RS = P2^7;
sbit RW = P2^6;
sbit EN = P2^5;
sbit K1 = P2^0;
sbit K2 = P2^1;  //上限加
sbit K3 = P2^2;  //下限减

sbit DQ = P2^3;  //DS18B20数据端

LCD1602初始化及读/写数据

void lcd_init()
{ 
   
	uint8 i;
	RW = 0;
	lcd_order(0x38);  //设置显示光标功能
	delay(100);
	lcd_order(0x0e);  //显示开及光标设置
	delay(100);
	lcd_order(0x06);  //显示光标移动设置
	delay(100);
	lcd_order(0x01);  //显示清屏
	delay(100);
	lcd_order(0x80);
	for(i=0;i<16;i++)
		lcd_data(hodometer[i]);
}

void write_1602(uint8 add,uint8 daa)
{ 
   
	lcd_order(0x80+add);
	lcd_data(0x30+daa/10);
	lcd_data(0x30+daa%10);
}

void lcd_order(uint8 date)  //LCD1602写指令
{ 
   
	RS = 0;  //选择写指令
	RW = 0;  //使能初始化
	P0 = date;  //发送指令
	EN = 1;  //开使能
	delay(100);  //延时
	EN = 0;  //关使能
}

void lcd_data(uint8 date)  //LCD1602写数据
{ 
   
	RS = 1;  //选择写数据
	RW = 0;  //使能初始化
	P0 = date;  //发送指令
	EN = 1;  //开使能
	delay(100);  //延时
	EN = 0;  //关使能
}

DS18B20初始化及读/写数据

uint8 DS18B20_init()
{ 
   
	uint8 ans;
	DQ = 1;
	delay(1);
	DQ = 0;
	delay(100);
	DQ = 1;
	delay(6);
	ans = DQ;
	delay(100);
	if(!ans)
		return 1;
	else
		return 0;
}

void DS18B20_write(uint8 date)
{ 
   
	uint8 i;
	DQ = 1;
	delay(1);
	for(i=0;i<8;i++)  //根据时序将数据从低到高一位一位发送出来
	{ 
   
		DQ = 0;
		if(date&0x01)  //从低到高取出数据的每位
			DQ = 1;
		else
			DQ = 0;
		delay(10);
		DQ = 1;
		date >>= 1;
		delay(1);
	}
}

uint8 DS18B20_read()
{ 
   
	uint8 i,date = 0;
	DQ = 1;  //释放总线
	delay(1);
	for(i=0;i<8;i++)  //根据时序将数据从低到高一位一位接收
	{ 
   
		DQ = 0;
		date >>= 1;
		DQ = 1;
		if(DQ)
			date |= 0x80;  //将data的一位置1
		delay(8);
		DQ = 1;
		delay(1);
	}
	return date;  //返回读出的数
}

void DS18B20_check()
{ 
   
	uint8 date1,date2;
	float ta;
	if(DS18B20_init())
	{ 
   
		DS18B20_write(0xcc);  //跳过序列号
		DS18B20_write(0x44);  //启动温度转换
		DS18B20_init();  //复位
		DS18B20_write(0xcc);  //跳过序列号
		DS18B20_write(0xbe);  //启动读取温度
		date1 = DS18B20_read();  //读取两个温度字节
		date2 = DS18B20_read();
		tmp = date2;
		tmp <<= 8;
		tmp = tmp|date1;
		ta = tmp*0.0625;
		tmp = ta*1000;
	}
}

温度上下限调节函数

void KEY()
{ 
   
	uint8 jj;
	uint8 i = 0;
	beep = 1;
	if(K1==0)
	{ 
   
		while(!K1);
		while(1)
		{ 
   
			lcd_order(0x0f);  //开启光标显示
			lcd_order(0x80+5);  //光标显示位置
			if(K2==0)  //判断加按键按下
			{ 
   
				while(K2==0);  //等待按键释放
					t_h++;  //温度上限加1
					write_1602(4,t_h);  //显示温度上限
			}
			if(K3==0)  //判断减按键按下
			{ 
   
				while(K3==0);  //等待按键释放
				if(t_h>t_l)  //判断温度上限大于温度下限
					t_h--;
				write_1602(4,t_h);  //显示温度上限
			}
			if(K1==0)
			{ 
   
				while(K1==0);
				while(1)
				{ 
   
					lcd_order(0x0f);
					lcd_order(0x80+13);
					if(K2==0)
					{ 
   
						while(K2==0);
						if(t_l<t_h&&t_l>=0)
						{ 
   
							lcd_order(0x80+11);
							lcd_data(' ');
							t_l++;
							write_1602(12,t_l);
						}
						else
						{ 
   
							t_l++;
							jj =~ t_l;
							write_1602(12,jj);
						}
					}
					if(K3==0)
					{ 
   
						while(K3==0);
						if(t_l>(-50))
						{ 
   
							t_l--;
							if(t_l<0)
								jj =~ t_l;
						}
						if(t_l>=0)
						{ 
   
							lcd_order(0x80+11);
							lcd_data(' ');
							write_1602(12,t_l);
						}
						if(t_l<0)
						{ 
   
							write_1602(12,jj);
							lcd_order(0x80+11);
							lcd_data('-');
						}
					}
					if(K1==0)
					{ 
   
						while(K1==0);
						goto loop;
					}
				}
			}
		}
	}
	loop:beep = 1;
}

完整程序展示

#include<reg52.h>
#include"stdio.h"

#define uint unsigned int
#define uchar unsigned char

typedef unsigned char uint8;
typedef unsigned int uint16;

sbit beep = P1^7;  //定义蜂鸣器IO口

sbit LED1 = P1^0;  //定义灯IO口
sbit LED2 = P1^1;
sbit k1 = P1^2;  //定义灯开关IO口
sbit k2 = P1^3;

sbit MOTOR = P1^4;  //定义电机
sbit BUTTON_RUN = P1^5;  //定义电机启动按钮
sbit BUTTON_STOP = P1^6;  //定义电机关闭按钮

sbit RS = P2^7;
sbit RW = P2^6;
sbit EN = P2^5;
sbit K1 = P2^0;
sbit K2 = P2^1;  //加
sbit K3 = P2^2;  //减
sbit DQ = P2^3;  //DS18B20数据端

//void delay(uint xms);
void motor_run();
void motor_stop();

void LED1_SWITCH();
void LED2_SWITCH();

void init();

void delay(uint16 time);
void lcd_init();  //LCD1602初始化
void lcd_order(uint8 date);  //向LCD1602写一个指令
void lcd_data(uint8 date);  //向LCD1602写一个指令
void write_1602(uint8 add,uint8 daa);  //写数据

void display();  //显示温度

uint8 DS18B20_init();  //DS18B20初始化
void DS18B20_write(uint8 date);  //向DS18B20中写入一个数据
uint8 DS18B20_read();  //从DS18B20中读一个数据并返回
void DS18B20_check();  //启动DS18B20进行温度采集,并返回当前温度

void KEY();  //修改报警范围

long tmp = 0;  //存储温度值
long t_h = 37,t_l = 10;  //温度上限 温度下限

bit tmp_hb = 0;  tmp_lb = 0;  //温度上下限调节指示变量

void judge();  //判断报警

uint8 hodometer[] = " H:00 L:00 ";
uint8 temp[]=	   " wendu:00.00 ";
uint16 ji = 0;
uint8 ku = 0;  //标志位

void main()
{ 
   
	init();
	lcd_init();  //LCD1602初始化
	DS18B20_init();  //DS18B20初始化
	DS18B20_write(0xcc);  //跳过序列号
	DS18B20_write(0x44);  //启动温度转换
	write_1602(4,t_h);
	write_1602(12,t_l);
	while(1)
	{ 
   		
		LED1_SWITCH();
		LED2_SWITCH();
		motor_run();
		motor_stop();
		DS18B20_check();  //从DS18B20中读取温度
		display();
		KEY();
		judge();
	}
}

void write_1602(uint8 add,uint8 daa)
{ 
   
	lcd_order(0x80+add);
	lcd_data(0x30+daa/10);
	lcd_data(0x30+daa%10);
}

void judge()  //判断是否在报警范围
{ 
   
	if(tmp<(t_l*1000)||tmp>(t_h*1000)&&t_l>=0)
	{ 
   
		beep = 0;
		delay(10);
		MOTOR = 1;
	}
	else if(t_l<0&&tmp>(t_h*1000))
	{ 
   
		beep = 1;
		MOTOR = 0;
	}
	else
	{ 
   
		beep = 1;
		MOTOR = 0;
	}
}

void KEY()
{ 
   
	uint8 jj;
	uint8 i = 0;
	beep = 1;
	if(K1==0)
	{ 
   
		while(!K1);
		while(1)
		{ 
   
			lcd_order(0x0f);  //开启光标显示
			lcd_order(0x80+5);  //光标显示位置
			if(K2==0)  //判断加按键按下
			{ 
   
				while(K2==0);  //等待按键释放
					t_h++;  //温度上限加1
					write_1602(4,t_h);  //显示温度上限
			}
			if(K3==0)  //判断减按键按下
			{ 
   
				while(K3==0);  //等待按键释放
				if(t_h>t_l)  //判断温度上限大于温度下限
					t_h--;
				write_1602(4,t_h);  //显示温度上限
			}
			if(K1==0)
			{ 
   
				while(K1==0);
				while(1)
				{ 
   
					lcd_order(0x0f);
					lcd_order(0x80+13);
					if(K2==0)
					{ 
   
						while(K2==0);
						if(t_l<t_h&&t_l>=0)
						{ 
   
							lcd_order(0x80+11);
							lcd_data(' ');
							t_l++;
							write_1602(12,t_l);
						}
						else
						{ 
   
							t_l++;
							jj =~ t_l;
							write_1602(12,jj);
						}
					}
					if(K3==0)
					{ 
   
						while(K3==0);
						if(t_l>(-50))
						{ 
   
							t_l--;
							if(t_l<0)
								jj =~ t_l;
						}
						if(t_l>=0)
						{ 
   
							lcd_order(0x80+11);
							lcd_data(' ');
							write_1602(12,t_l);
						}
						if(t_l<0)
						{ 
   
							write_1602(12,jj);
							lcd_order(0x80+11);
							lcd_data('-');
						}
					}
					if(K1==0)
					{ 
   
						while(K1==0);
						goto loop;
					}
				}
			}
		}
	}
	loop:beep = 1;
}

//void delay(uint xms) //延时
//{ 
   
// uint i,j;
// for(i=xms;i>0;i--)
// for(j=110;j>0;j--) ;
//}

void delay(uint16 time)
{ 
   
	while(time--);
}

void lcd_init()
{ 
   
	uint8 i;
	RW = 0;
	lcd_order(0x38);  //设置显示光标功能
	delay(100);
	lcd_order(0x0e);  //显示开及光标设置
	delay(100);
	lcd_order(0x06);  //显示光标移动设置
	delay(100);
	lcd_order(0x01);  //显示清屏
	delay(100);
	lcd_order(0x80);
	for(i=0;i<16;i++)
		lcd_data(hodometer[i]);
}

void lcd_order(uint8 date)  //LCD1602写指令
{ 
   
	RS = 0;  //选择写指令
	RW = 0;  //使能初始化
	P0 = date;  //发送指令
	EN = 1;  //开使能
	delay(100);  //延时
	EN = 0;  //关使能
}

void lcd_data(uint8 date)  //LCD1602写数据
{ 
   
	RS = 1;  //选择写数据
	RW = 0;  //使能初始化
	P0 = date;  //发送指令
	EN = 1;  //开使能
	delay(100);  //延时
	EN = 0;  //关使能
}

uint8 DS18B20_init()
{ 
   
	uint8 ans;
	DQ = 1;
	delay(1);
	DQ = 0;
	delay(100);
	DQ = 1;
	delay(6);
	ans = DQ;
	delay(100);
	if(!ans)
		return 1;
	else
		return 0;
}

void DS18B20_write(uint8 date)
{ 
   
	uint8 i;
	DQ = 1;
	delay(1);
	for(i=0;i<8;i++)  //根据时序将数据从低到高一位一位发送出来
	{ 
   
		DQ = 0;
		if(date&0x01)  //从低到高取出数据的每位
			DQ = 1;
		else
			DQ = 0;
		delay(10);
		DQ = 1;
		date >>= 1;
		delay(1);
	}
}

uint8 DS18B20_read()
{ 
   
	uint8 i,date = 0;
	DQ = 1;  //释放总线
	delay(1);
	for(i=0;i<8;i++)  //根据时序将数据从低到高一位一位接收
	{ 
   
		DQ = 0;
		date >>= 1;
		DQ = 1;
		if(DQ)
			date |= 0x80;  //将data的一位置1
		delay(8);
		DQ = 1;
		delay(1);
	}
	return date;  //返回读出的数
}

void DS18B20_check()
{ 
   
	uint8 date1,date2;
	float ta;
	if(DS18B20_init())
	{ 
   
		DS18B20_write(0xcc);  //跳过序列号
		DS18B20_write(0x44);  //启动温度转换
		DS18B20_init();  //复位
		DS18B20_write(0xcc);  //跳过序列号
		DS18B20_write(0xbe);  //启动读取温度
		date1 = DS18B20_read();  //读取两个温度字节
		date2 = DS18B20_read();
		tmp = date2;
		tmp <<= 8;
		tmp = tmp|date1;
		ta = tmp*0.0625;
		tmp = ta*1000;
	}
}

void display()
{ 
   
	uint8 i;
	temp[8] = 0x30+tmp/10000;
	temp[9] = 0x30+tmp/1000%10;
	temp[11] = 0x30+tmp/100%10;
	temp[12] = 0x30+tmp/10%10;
	temp[13] = 0x30+tmp%10;
	lcd_order(0x80+0x40);
	for(i=0;i<16;i++)
		lcd_data(temp[i]) ;
}

void init()  //初始化函数
{ 
   
	BUTTON_RUN = 1;  
	BUTTON_STOP = 1;
	MOTOR = 0;
	beep = 0;
	delay(50);
}

void motor_run()  //打开电机
{ 
   
	if(BUTTON_RUN==0)
	{ 
   
		delay(10);
		if(BUTTON_RUN==0)
		{ 
   
			while(1)
			{ 
   
				MOTOR = 1;
				if(BUTTON_STOP==0)
				{ 
   
					delay(5);
					if(BUTTON_STOP==0)
					{ 
   
						break;
					}
				}
			}
		}
	}
}

void motor_stop()  //关闭电机
{ 
   
	if(BUTTON_STOP==0)
	{ 
   
		delay(10);
		if(BUTTON_STOP==0)
		{ 
   
				MOTOR = 0;
		}
	}
}

void LED1_SWITCH()  //LED1开关
{ 
   
	if(k1==0)
		LED1 = 0;
	else if(k1==1)
		LED1 = 1;
}

void LED2_SWITCH()  //LED2开关
{ 
   
	if(k2==0)
		LED2 = 0;
	else if(k2==1)
		LED2 = 1;
}

使用Proteus仿真
在这里插入图片描述

整体电路PCB设计
在这里插入图片描述
51单片机温控系统程序(电机模拟风扇 可调上下限)Proteus仿真 DS18B20+LCD1602显示
原理图+程序+仿真图
HappyFrankie的公众号

今天的文章基于51单片机的温控系统设计_DS18B20工作原理及电路图分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/70512.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注