基于51单片机的八路温度检测系统(仿真+实物)

        基于51单片机的八路温度检测系统利用AT89C51作为系统主控,利用8个DS18B20进行温度的获取,使用LCD1602进行温度显示,利用蜂鸣器和Led灯进行报警,使用按键进行显示切换和阈值调节,实现整个系统功能。

一、原理图绘制

         1、51单片机最小系统板        

                本次设计利用AT89C51作为系统主控,于是我们需要设计51单片机最小系统板,大致分为晶振电路、复位电路、芯片三部分,电路图如下:

2、LCD显示模块

        LCD模块比较简单,它是一种并口传输的模块,优点是简单,但是IO口占用比较多,如下图:

3、报警模块

        报警模块使用Led灯和蜂鸣器,其中LED使用低电平点亮的连接方式,蜂鸣器使用PNP的连接方式,为低电平点亮。如下:

4、八路温度模块

        因为Wire总线支持多设备挂载,于是,我们只需要将这八个DS18B20的数据IO口连接到同一个单片机IO口就行了。如下图:

5、按键模块

        按键模块非常简单,只需要将按键一端连接到GND,另一端连接到IO口就行了,如下图:

二、原理分析

        1、OneWire协议

                Oneware单总线是Maxim全资子公司Dallas的一项专有技术。与目前多数标准串行数据通信方式,如SPI / I2C不同,它采用单根信号线,既传输时钟,又传输数据,而且数据传输是双向的。它具有节省I/O口线资源、结构简单、成本低廉、便于总线扩展和维护等诸多优点。

(1)复位和应答:

(2)读写时序

综合上面时序,我们写出如下代码:

#include <REGX52.H>

sbit OneWire_DQ=P3^7;

unsigned char OneWire_Init()
{
	unsigned char i;
	unsigned char AckBit;
	OneWire_DQ=1;
	OneWire_DQ=0;
	i = 247;while (--i);	//delay 500us
	OneWire_DQ=1;
	i = 32;while (--i);		//delay 70us
	AckBit=OneWire_DQ;
	i = 247;while (--i);	//delay 500us
	return AckBit;
}

void OneWire_SendBit(unsigned char Bit)
{
	unsigned char i;
	OneWire_DQ=0;
	i=4;while(--i);		//delay 10us
	OneWire_DQ=Bit;
	i=24;while(--i);	//delay 50us
	OneWire_DQ=1;
}	

unsigned char OneWire_ReceiveBit()
{
	unsigned char i;
	unsigned char Bit;
	OneWire_DQ=0;
	i=2;while(--i);		//delay 5us
	OneWire_DQ=1;
	i=2;while(--i);		//dealy 5us
	Bit=OneWire_DQ;
	i=24;while(--i);	//delay 50us
	return Bit;
}	

void OneWire_SendByte(unsigned char Byte)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		OneWire_SendBit(Byte&(0x01<<i));
	}
}	

unsigned char OneWire_ReceiveByte()
{
	unsigned char i;
	unsigned char Byte=0x00;
	for(i=0;i<8;i++)
	{
		if(OneWire_ReceiveBit()){Byte|=(0x01<<i);}
	}
	return Byte;
}	
	




        2、DS18B20读取

                DS18B20的指令一般分三步:

                       (1) 初始化

                        (2)ROM指令

                        (3)功能指令

                本次设计也大致遵循该步骤,由于此前已经进行过初始化,所以本次设计读取数据的步骤大致上是 匹配ROM -> 读暂存存储器 -> 读出数据。如下代码:

//通过rom匹配
void DS18B20_Read_Temperature(u8 *rom,u16 *dat){
	
	u8 LSB = 0,MSB = 0; 
	u16 Temp = 0;
	//温度转换
	DS18B20_Match_Rom(rom);//匹配ROM
	OneWire_SendByte(0X44);//温度变换
//	delay(750);
	DS18B20_Match_Rom(rom);
	OneWire_SendByte(0XBE);//读暂存存储器
	
	LSB =  OneWire_ReceiveByte();
	MSB =  OneWire_ReceiveByte();
	
	Temp = (MSB<<8) | LSB;//数据合并为16位
	
	if((Temp&0XF800) == 0XF800){ //负温度;s=1	正温度: s=0
	
		*dat =(((~Temp+0X01)* -0.0625)+0.5)*10.0;
	}
	else{
		
		*dat =((Temp*0.0625)+0.5)*10.0;
	}
}

三、程序设计

1、获取DS18B20的ROM

        常规的DS18B20在读取数据的时候经常会执行 DS18B20_SKIP_ROM 指令,而本次设计需要实现OneWire总线挂载多设备,这一步是不能执行的。 但是在使用ROM进行多设备读取的时候首先需要获取每个DS18B20的ROM,每个DS18B20出厂的时候都有一个唯一的ROM,一般会在其丝印上。如下图

但是这个丝印一般比较小,并不方便查看,有没有什么方法可以让DS18B20自动将其ROM发送给我们呢,答案是肯定的。如下代码:

void DS18B20_ReadRom(unsigned char *rom)
{
	unsigned char i=0;
	OneWire_Init();//启动信号
	OneWire_SendByte(0x33);//读ROM
	
	for(i=0;i<8;i++){
		rom[i] = OneWire_ReceiveByte();//读取一个
	}
}

我们可以借助串口首先将每个DS18B20的ROM信息读出来放入数组,然后我们再通过DS18B20的ROM读出这八个传感器的数据。

2、DS18B20读取数据

        获取到DS18B20的数据后,我们可以使用该ROM去获取每一个DS18B20的数据了,通过如下代码:

//通过rom匹配
void DS18B20_Read_Temperature(u8 *rom,u16 *dat){
	
	u8 LSB = 0,MSB = 0; 
	u16 Temp = 0;
	//温度转换
	DS18B20_Match_Rom(rom);//匹配ROM
	OneWire_SendByte(0X44);//温度变换
//	delay(750);
	DS18B20_Match_Rom(rom);
	OneWire_SendByte(0XBE);//读暂存存储器
	
	LSB =  OneWire_ReceiveByte();
	MSB =  OneWire_ReceiveByte();
	
	Temp = (MSB<<8) | LSB;//数据合并为16位
	
	if((Temp&0XF800) == 0XF800){ //负温度;s=1	正温度: s=0
	
		*dat =(((~Temp+0X01)* -0.0625)+0.5)*10.0;
	}
	else{
		
		*dat =((Temp*0.0625)+0.5)*10.0;
	}
}

3、主程序设计

        住程序比较简单,就是将DS18B20的数据读出,然后显示。将按键调节显示、DS18B20温度的阈值。

#include <REGX52.H>
#include "LCD1602.H"
#include "delay.h"
#include "DS18B20.h"
#include "UART.h"
#include "KEY.h"

unsigned char i=0;
unsigned char room[8];

sbit Led=P1^4;
sbit Buz=P1^5;

unsigned char code room1[8] = {0x28, 0x12, 0x1A, 0x81, 0x25, 0x23, 0x0B, 0xA9 };
unsigned char code room2[8] = {0x28, 0x5C, 0x01, 0xB0, 0x25, 0x23, 0x0B, 0x04 };
unsigned char code room3[8] = {0x28, 0xEE, 0x75, 0xAD, 0x25, 0x23, 0x0B, 0xBA };
unsigned char code room4[8] = {0x28, 0x45, 0x1B, 0xC6, 0x25, 0x23, 0x0B, 0xA9 };
unsigned char code room5[8] = {0x28, 0x6F, 0x02, 0x99, 0x25, 0x23, 0x0B, 0x1D };
unsigned char code room6[8] = {0x28, 0x2D, 0xAD, 0xB4, 0x25, 0x23, 0x0B, 0xB7 };
unsigned char code room7[8] = {0x28, 0x96, 0x0C, 0x82, 0x25, 0x23, 0x0B, 0xF7 };
unsigned char code room8[8] = {0x28, 0xC5, 0xD0, 0x86, 0x25, 0x23, 0x0B, 0xF1 };
 
u8 keyNum=0;
u8 mode=0;
u8 flag=1;
u16 tem1=0;
u16 tem2=0;
u16 tem3=0;
u16 tem4=0;
u16 tem5=0;
u16 tem6=0;
u16 tem7=0;
u16 tem8=0;
u16 tem_th=31;
u16 cnt=0;

void main()
{
    LCD_Init();
	UART_Init(); 
	while(1)
    {     
		keyNum = KEY();
		
		if(keyNum==1){
			mode++;
			mode%=2;
		}
		
		if(mode==0){		
			//清除显示
			if(flag==1){
				LCD_Clear();
				flag=0;
			}
			
			//修改报警值
			if(keyNum==2){
				tem_th--;
			}
			else if(keyNum==3){
				tem_th++;
			}
			
			//显示阈值信息
			LCD_ShowString(1, 14, "th:");
			LCD_ShowNum(2, 14, tem_th, 2);				
		}
		
		else if(mode==1){
			DS18B20_Read_Temperature(room1, &tem1);
			tem1 /=10;
			LCD_ShowNum(1, 1, tem1, 2);
			
			DS18B20_Read_Temperature(room2, &tem2);
			tem2 /=10;
			LCD_ShowNum(1, 4, tem2, 2);
			
			DS18B20_Read_Temperature(room3, &tem3);
			tem3 /=10;
			LCD_ShowNum(1, 7, tem3, 2);
			
			DS18B20_Read_Temperature(room4, &tem4);
			tem4 /=10;
			LCD_ShowNum(1, 10, tem4, 2);
			
			DS18B20_Read_Temperature(room5, &tem5);
			tem5 /=10;
			LCD_ShowNum(2, 1, tem5, 2);
			
			DS18B20_Read_Temperature(room6, &tem6);
			tem6 /=10;
			LCD_ShowNum(2, 4, tem6, 2);
			
			DS18B20_Read_Temperature(room7, &tem7);
			tem7 /=10;
			LCD_ShowNum(2, 7, tem7, 2);
			
			DS18B20_Read_Temperature(room8, &tem8);
			tem8 /=10;
			LCD_ShowNum(2, 10, tem8, 2);	

			LCD_ShowString(1, 14, "th:");
			LCD_ShowNum(2, 14, tem_th, 2);
			
			if(tem1 >= tem_th || tem2 >= tem_th  || tem3 >= tem_th  || tem4 >= tem_th  ||  \
				tem5 >= tem_th  || tem6 >= tem_th  || tem7 >= tem_th  || tem8 >= tem_th 	\
				){
				if(++cnt>=2){
					cnt=0;
					Led=~Led;
				}
				Buz=0;
				
			}
			else{
				Led=1;
				Buz=1;
			}
			delay(10);
			flag=1;
		}
    }
}               

四、PCB设计

五、项目总结

        通过仿真、代码、PCB设计,本次简单项目已经完成,通过八路DS18B20获取八路温度,使用按键调节阈值,八路中任意一路超过阈值,LED亮起、蜂鸣器进行报警。演示地址如下: 

51单片机八路温度监测系统_哔哩哔哩_bilibili

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值