STM32F103+DHT11模块+DS18B20模块 显示实时温湿度并高温高湿报警

@

前言

参考资料:
    YL-47 DHT11 使用说明--.pdf
    DHT11说明书最新版--.pdf
    DHT11模块--.pdf
    DHT11模块使用说明书
    DS18B20.pdf
    ds18b20中文资料详解
源码参考:
    野火dht11温湿度传感器测试实验
    正点原子TFTLCD显示实验
    正点原子18B20数字温度传感器实验
    正点原子按键实验
    正点原子蜂鸣器实验
开发板:正点原子 STM32F103 精英版
语言:C语言
开发环境:Keil5
开发板使用了 LED KEY BEEP TFTLCD USART DHT11模块 DS18B20模块

代码下载:

码云 GitHub

功能介绍:

1、LED0约2秒一闪,表示程序运行中。
2、LCD和串口显示实时的温湿度,2秒一循环。上面一个temp是DS18B20,下面的是DHT11。%RH 相对湿度, CEL 摄氏度(ps:不接入DS18B20的话会循环等待)
3、按键都会翻转LED1,KEY1 开启报警模式,KEY0关闭报警模式。(按键10ms一巡检)
4、报警模式下:当温度不低于85摄氏度或者湿度不低于90%RH,蜂鸣器报警。可以通过按下KEY0关闭报警模式。(报警串口会有打印,LCD也会有提示)

接线

DS18B20

VCC -》 3.3V
DQ -》 PG11
GND -》 GND
在这里插入图片描述

DHT11

VCC -》 3.3V
DATA -》 PB10
GND -》 GND
在这里插入图片描述

效果图

普通环境

普通版main.c

在这里插入图片描述

升级版

在这里插入图片描述
在这里插入图片描述

哈热气

普通版

我这哈了3下
在这里插入图片描述

然后持续手扇风
在这里插入图片描述
ok,温湿度降下来了。

升级版

在这里插入图片描述

搓手捂热

手有汗,湿度也上来了
(下图是旧的,仅供参考)
在这里插入图片描述
在这里插入图片描述
最后本来应该整个打火机的,可惜没有。夹咯吱窝下(仅DHT11 旧图)
在这里插入图片描述
最后来个鼻息
在这里插入图片描述

核心代码

普通版main.c

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "lcd.h"
#include "usart.h"
#include "bsp_dht11.h"
#include "ds18b20.h"

DHT11_Data_TypeDef DHT11_Data;

/*
	DS18B20
	供电电压:3 - 5.5V
	接线:DQ -》 PG11 (IO口)
	
	DHT11
	供电电压:3.3 - 5V
	接线:DATA -》 PB10 (IO口)
*/

int main(void)
{
	u8 str[100] = {0};
	// DS18B20用变量
	short temperature;
	delay_init();	    	 //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	 //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
	uart_init(115200);	 	//串口初始化为115200
 	LED_Init();			     //LED端口初始化
	LCD_Init();				 // LCD初始化
	DHT11_GPIO_Config();     // 初始化DTT11的引脚 DATA -> PB10
	LED0 = 0;
	POINT_COLOR = WHITE;
	BACK_COLOR = BLACK;
	LCD_Clear(BLACK); 
	while(DS18B20_Init())	//DS18B20初始化	
	{
		LCD_ShowString(10,70,200,16,16,"DS18B20 Error");
		delay_ms(200);
		LCD_Fill(10,70,239,130+16,WHITE);
 		delay_ms(200);
	}
	LCD_ShowString(10,90,200,16,16,"Temp:   . CEL"); 
  	while(1) 
	{
		POINT_COLOR = WHITE;
		
		// DS18B20
		temperature = DS18B20_Get_Temp();	
		if(temperature < 0)
		{
			LCD_ShowChar(10+40, 90, '-', 16, 0);			//显示负号
			temperature = -temperature;					    //转为正数
		}else LCD_ShowChar(10+40,90,' ', 16, 0);			//去掉负号
		LCD_ShowNum(10+40+8, 90, temperature/10, 2, 16);	//显示正数部分	    
		LCD_ShowNum(10+40+32, 90,temperature%10, 1, 16);	//显示小数部分
		printf("温度为 %u.%u℃ 
",temperature/10, temperature%10);
		
		// DHT11
		// 调用Read_DHT11读取温湿度,若成功则输出该信息
		if( Read_DHT11(&DHT11_Data) == SUCCESS)
		{
			printf("湿度为%d.%d %RH ,温度为 %d.%d℃ 
", DHT11_Data.humi_int, DHT11_Data.humi_deci, DHT11_Data.temp_int, DHT11_Data.temp_deci);
			sprintf((char*)str, "HUM: %d.%d%%RH  ", DHT11_Data.humi_int, DHT11_Data.humi_deci);
			LCD_ShowString(10,130,200,24,24, str);
			sprintf((char*)str, "TEMP: %d.%dCEL ", DHT11_Data.temp_int, DHT11_Data.temp_deci);
			LCD_ShowString(10,170,200,24,24, str);
			//printf("
 湿度:%d,温度:%d 
" ,DHT11_Data.humi_int,DHT11_Data.temp_int);
		}
		else
		{
			printf("Read DHT11 ERROR!
");
		}
		LED0 = !LED0;
		// 采样周期不得低于1秒,否则会读取失败
		delay_ms(1000);
		delay_ms(1000);
	} 
}
 

升级版main.c

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "lcd.h"
#include "usart.h"
#include "bsp_dht11.h"
#include "ds18b20.h"
#include "key.h"
#include "beep.h"

DHT11_Data_TypeDef DHT11_Data;

/*
	DS18B20
	供电电压:3 - 5.5V
	接线:DQ -》 PG11 (IO口)
	
	DHT11
	供电电压:3.3 - 5V
	接线:DATA -》 PB10 (IO口)
*/

int main(void)
{
	u8 str[100] = {0};
	// 蜂鸣器报警标志位
	u8 flag = 0;
	// 报警模式
	u8 mode = 0;
	vu8 key = 0;
	// 循环计数
	u8 time = 0;
	// DS18B20用变量
	short temperature;
	delay_init();	    	 //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	 //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
	uart_init(115200);	 	 //串口初始化为115200
 	LED_Init();			     //LED端口初始化
	LCD_Init();				 // LCD初始化
	KEY_Init();				 // KEY初始化
	BEEP_Init();			 // BEEP初始化
	DHT11_GPIO_Config();     // 初始化DTT11的引脚 DATA -> PB10
	LED0 = 0;
	LED1 = 0;
	POINT_COLOR = WHITE;
	BACK_COLOR = BLACK;
	LCD_Clear(BLACK); 
	while(DS18B20_Init())	//DS18B20初始化	
	{
		LCD_ShowString(10,70,200,16,16,"DS18B20 Error");
		delay_ms(200);
		LCD_Fill(10,70,239,130+16, BLACK);
 		delay_ms(200);
	}
	LCD_ShowString(10,90,200,16,16,"Temp:   . CEL"); 
	LCD_ShowString(10,220,220,12,12,"TOUCH KEY0 CLOSE ALARM MODE"); 
	LCD_ShowString(10,240,220,12,12,"TOUCH KEY1 OPEN ALARM MODE"); 
	POINT_COLOR = RED;
	LCD_ShowString(10,260,100,12,12,"ALARM MODE: OFF"); 
	POINT_COLOR = WHITE;
  	while(1) 
	{
		flag = 2;
		POINT_COLOR = WHITE;
		
		key = KEY_Scan(0); //得到键值
		if (key)
		{
			switch (key)
			{
				case WKUP_PRES: 
					LED1 = !LED1;
					break;
				// KEY1 按下 开启报警模式
				case KEY1_PRES: 
					mode = 1;
					LED1 = !LED1;
					LCD_ShowString(80,260,100,12,12,"ON  "); 
					printf("开启报警模式
");
					break;
				// KEY1 按下 关闭报警模式
				case KEY0_PRES: 
					mode = 0;
					LED1 = !LED1;
					LCD_ShowString(80,260,100,12,12,"OFF "); 
					printf("关闭报警模式
");
					break;
			}
		}
		
		// 约2秒一次
		if(time % 200 == 0)
		{
			// DS18B20
			temperature = DS18B20_Get_Temp();	
			if(temperature < 0)
			{
				LCD_ShowChar(10+40, 90, '-', 16, 0);			//显示负号
				temperature = -temperature;					    //转为正数
			}else LCD_ShowChar(10+40,90,' ', 16, 0);			//去掉负号
			LCD_ShowNum(10+40+8, 90, temperature/10, 2, 16);	//显示正数部分	    
			LCD_ShowNum(10+40+32, 90,temperature%10, 1, 16);	//显示小数部分
			printf("温度为 %u.%u℃ 
",temperature/10, temperature%10);
			
			// DHT11
			// 调用Read_DHT11读取温湿度,若成功则输出该信息 采样周期不得低于1秒,否则会读取失败
			if( Read_DHT11(&DHT11_Data) == SUCCESS)
			{
				printf("湿度为%d.%d %RH ,温度为 %d.%d℃ 
", DHT11_Data.humi_int, DHT11_Data.humi_deci, DHT11_Data.temp_int, DHT11_Data.temp_deci);
				sprintf((char*)str, "HUM: %d.%d%%RH  ", DHT11_Data.humi_int, DHT11_Data.humi_deci);
				LCD_ShowString(10,130,200,24,24, str);
				sprintf((char*)str, "TEMP: %d.%dCEL ", DHT11_Data.temp_int, DHT11_Data.temp_deci);
				LCD_ShowString(10,170,200,24,24, str);
				//printf("
 湿度:%d,温度:%d 
" ,DHT11_Data.humi_int,DHT11_Data.temp_int);
			}
			else
			{
				printf("Read DHT11 ERROR!
");
			}
			
			// 判断温度是否不低于85摄氏度
			if(temperature >= 850 || DHT11_Data.temp_int >= 85)
			{
				printf("温度过高!!!
");
				flag++;
			}
			else
			{
				flag--;
			}
			
			// 判断湿度是否高于90%RH
			if(DHT11_Data.humi_int >= 90)
			{
				printf("湿度过高!!!
");
				flag++;
			}
			else
			{
				flag--;
			}
			
			// 判断是否需要报警
			if(flag >= 2 && mode == 1)
			{
				LCD_ShowString(10,200,200,16,16,"BEEP!!!(>__<)"); 
				printf("BEEP!!!(>__<)
");
				BEEP = 1;
			}
			
			if(flag < 2)
			{
				LCD_ShowString(10,200,200,16,16,"     (- v -)    "); 
				BEEP = 0;
			}
			
			// 重新置零
			time = 0;
			
			LED0 = !LED0;
		}
		
		if(mode == 0)
		{
			LCD_ShowString(10,200,200,16,16,"     (- v -)    "); 
			BEEP = 0;
		}
		
		time++;
		delay_ms(10);
	} 
}
 

bsp_dht11.h

#ifndef __DHT11_H
#define	__DHT11_H

#include "stm32f10x.h"
#include "delay.h"

#define HIGH  1
#define LOW   0

#define DHT11_CLK     RCC_APB2Periph_GPIOB
#define DHT11_PIN     GPIO_Pin_10                  
#define DHT11_PORT		GPIOB 

//带参宏,可以像内联函数一样使用,输出高电平或低电平
#define DHT11_DATA_OUT(a)	if (a)	
					GPIO_SetBits(GPIOB,GPIO_Pin_10);
					else		
					GPIO_ResetBits(GPIOB,GPIO_Pin_10)
 //读取引脚的电平
#define  DHT11_DATA_IN()	   GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10)

typedef struct
{
	uint8_t  humi_int;		//湿度的整数部分
	uint8_t  humi_deci;	 	//湿度的小数部分
	uint8_t  temp_int;	 	//温度的整数部分
	uint8_t  temp_deci;	 	//温度的小数部分
	uint8_t  check_sum;	 	//校验和
		                 
}DHT11_Data_TypeDef;

void DHT11_GPIO_Config(void);
static void DHT11_Mode_IPU(void);
static void DHT11_Mode_Out_PP(void);
uint8_t Read_DHT11(DHT11_Data_TypeDef *DHT11_Data);
static uint8_t Read_Byte(void);

#endif /* __DHT11_H */

bsp_dht11.c

#include "bsp_dht11.h"

/*
 * 函数名:DHT11_GPIO_Config
 * 描述  :配置DHT11用到的I/O口
 * 输入  :无
 * 输出  :无
 */
void DHT11_GPIO_Config(void)
{		
	/*定义一个GPIO_InitTypeDef类型的结构体*/
	GPIO_InitTypeDef GPIO_InitStructure;

	/*开启DHT11_PORT的外设时钟*/
	RCC_APB2PeriphClockCmd(DHT11_CLK, ENABLE); 

	/*选择要控制的DHT11_PORT引脚*/															   
  	GPIO_InitStructure.GPIO_Pin = DHT11_PIN;	

	/*设置引脚模式为通用推挽输出*/
  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   

	/*设置引脚速率为50MHz */   
  	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 

	/*调用库函数,初始化DHT11_PORT*/
  	GPIO_Init(DHT11_PORT, &GPIO_InitStructure);		  

	/* 拉高GPIOB10	*/
	GPIO_SetBits(DHT11_PORT, GPIO_Pin_10);	 
}

/*
 * 函数名:DHT11_Mode_IPU
 * 描述  :使DHT11-DATA引脚变为上拉输入模式
 * 输入  :无
 * 输出  :无
 */
static void DHT11_Mode_IPU(void)
{
 	  GPIO_InitTypeDef GPIO_InitStructure;

	  	/*选择要控制的DHT11_PORT引脚*/	
	  GPIO_InitStructure.GPIO_Pin = DHT11_PIN;

	   /*设置引脚模式为浮空输入模式*/ 
	  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ; 

	  /*调用库函数,初始化DHT11_PORT*/
	  GPIO_Init(DHT11_PORT, &GPIO_InitStructure);	 
}

/*
 * 函数名:DHT11_Mode_Out_PP
 * 描述  :使DHT11-DATA引脚变为推挽输出模式
 * 输入  :无
 * 输出  :无
 */
static void DHT11_Mode_Out_PP(void)
{
 	GPIO_InitTypeDef GPIO_InitStructure;

	 	/*选择要控制的DHT11_PORT引脚*/															   
  	GPIO_InitStructure.GPIO_Pin = DHT11_PIN;	

	/*设置引脚模式为通用推挽输出*/
  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   

	/*设置引脚速率为50MHz */   
  	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

	/*调用库函数,初始化DHT11_PORT*/
  	GPIO_Init(DHT11_PORT, &GPIO_InitStructure);	 	 
}

/* 
 * 从DHT11读取一个字节,MSB先行
 */
static uint8_t Read_Byte(void)
{
	uint8_t i, temp=0;

	for(i=0;i<8;i++)    
	{	 
		/*每bit以50us低电平标置开始,轮询直到从机发出 的50us 低电平 结束*/  
		while(DHT11_DATA_IN()==Bit_RESET);

		/*DHT11 以26~28us的高电平表示“0”,以70us高电平表示“1”,
		 *通过检测 x us后的电平即可区别这两个状 ,x 即下面的延时 
		 */
		delay_us(40); //延时x us 这个延时需要大于数据0持续的时间即可	   	  

		if(DHT11_DATA_IN()==Bit_SET)/* x us后仍为高电平表示数据“1” */
		{
			/* 等待数据1的高电平结束 */
			while(DHT11_DATA_IN()==Bit_SET);

			temp|=(uint8_t)(0x01<<(7-i));  //把第7-i位置1,MSB先行 
		}
		else	 // x us后为低电平表示数据“0”
		{			   
			temp&=(uint8_t)~(0x01<<(7-i)); //把第7-i位置0,MSB先行
		}
	}
	return temp;
}
/*
 * 一次完整的数据传输为40bit,高位先出
 * 8bit 湿度整数 + 8bit 湿度小数 + 8bit 温度整数 + 8bit 温度小数 + 8bit 校验和 
 */
uint8_t Read_DHT11(DHT11_Data_TypeDef *DHT11_Data)
{  
	/*输出模式*/
	DHT11_Mode_Out_PP();
	/*主机拉低*/
	DHT11_DATA_OUT(LOW);
	/*延时18ms*/
	delay_ms(18);

	/*总线拉高 主机延时30us*/
	DHT11_DATA_OUT(HIGH); 

	delay_us(30);   //延时30us

	/*主机设为输入 判断从机响应信号*/ 
	DHT11_Mode_IPU();

	/*判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行*/   
	if(DHT11_DATA_IN() == Bit_RESET)     
	{
		/*轮询直到从机发出 的80us 低电平 响应信号结束*/  
		while(DHT11_DATA_IN()==Bit_RESET);

		/*轮询直到从机发出的 80us 高电平 标置信号结束*/
		while(DHT11_DATA_IN()==Bit_SET);

		/*开始接收数据*/   
		DHT11_Data->humi_int= Read_Byte();

		DHT11_Data->humi_deci= Read_Byte();

		DHT11_Data->temp_int= Read_Byte();

		DHT11_Data->temp_deci= Read_Byte();

		DHT11_Data->check_sum= Read_Byte();


		/*读取结束,引脚改为输出模式*/
		DHT11_Mode_Out_PP();
		/*主机拉高*/
		DHT11_DATA_OUT(HIGH);

		/*检查读取的数据是否正确*/
		if(DHT11_Data->check_sum == DHT11_Data->humi_int + DHT11_Data->humi_deci + DHT11_Data->temp_int+ DHT11_Data->temp_deci)
			return SUCCESS;
		else 
			return ERROR;
	}
	else
	{		
		return ERROR;
	}   
}


ds18b20.h

#ifndef __DS18B20_H
#define __DS18B20_H 
#include "sys.h"   
//////////////////////////////////////////////////////////////////////////////////	 
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK战舰STM32开发板
//DS18B20驱动代码	   
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2012/9/12
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
//All rights reserved									  
//////////////////////////////////////////////////////////////////////////////////

//IO方向设置
#define DS18B20_IO_IN()  {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=8<<12;}
#define DS18B20_IO_OUT() {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=3<<12;}
////IO操作函数											   
#define	DS18B20_DQ_OUT PGout(11) //数据端口	PA0 
#define	DS18B20_DQ_IN  PGin(11)  //数据端口	PA0 
   	
u8 DS18B20_Init(void);//初始化DS18B20
short DS18B20_Get_Temp(void);//获取温度
void DS18B20_Start(void);//开始温度转换
void DS18B20_Write_Byte(u8 dat);//写入一个字节
u8 DS18B20_Read_Byte(void);//读出一个字节
u8 DS18B20_Read_Bit(void);//读出一个位
u8 DS18B20_Check(void);//检测是否存在DS18B20
void DS18B20_Rst(void);//复位DS18B20    
#endif

ds18b20.c

#include "ds18b20.h"
#include "delay.h"	
//////////////////////////////////////////////////////////////////////////////////	 
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK精英STM32开发板
//DS18B20驱动代码	   
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2012/9/12
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
//All rights reserved									  
//////////////////////////////////////////////////////////////////////////////////
  


//复位DS18B20
void DS18B20_Rst(void)	   
{                 
	DS18B20_IO_OUT(); 	//SET PG11 OUTPUT
    DS18B20_DQ_OUT=0; 	//拉低DQ
    delay_us(750);    	//拉低750us
    DS18B20_DQ_OUT=1; 	//DQ=1 
	delay_us(15);     	//15US
}
//等待DS18B20的回应
//返回1:未检测到DS18B20的存在
//返回0:存在
u8 DS18B20_Check(void) 	   
{   
	u8 retry=0;
	DS18B20_IO_IN();	//SET PG11 INPUT	 
    while (DS18B20_DQ_IN&&retry<200)
	{
		retry++;
		delay_us(1);
	};	 
	if(retry>=200)return 1;
	else retry=0;
    while (!DS18B20_DQ_IN&&retry<240)
	{
		retry++;
		delay_us(1);
	};
	if(retry>=240)return 1;	    
	return 0;
}
//从DS18B20读取一个位
//返回值:1/0
u8 DS18B20_Read_Bit(void) 	 
{
    u8 data;
	DS18B20_IO_OUT();	//SET PG11 OUTPUT
    DS18B20_DQ_OUT=0; 
	delay_us(2);
    DS18B20_DQ_OUT=1; 
	DS18B20_IO_IN();	//SET PG11 INPUT
	delay_us(12);
	if(DS18B20_DQ_IN)data=1;
    else data=0;	 
    delay_us(50);           
    return data;
}
//从DS18B20读取一个字节
//返回值:读到的数据
u8 DS18B20_Read_Byte(void)     
{        
    u8 i,j,dat;
    dat=0;
	for (i=1;i<=8;i++) 
	{
        j=DS18B20_Read_Bit();
        dat=(j<<7)|(dat>>1);
    }						    
    return dat;
}
//写一个字节到DS18B20
//dat:要写入的字节
void DS18B20_Write_Byte(u8 dat)     
 {             
    u8 j;
    u8 testb;
	DS18B20_IO_OUT();	//SET PG11 OUTPUT;
    for (j=1;j<=8;j++) 
	{
        testb=dat&0x01;
        dat=dat>>1;
        if (testb) 
        {
            DS18B20_DQ_OUT=0;	// Write 1
            delay_us(2);                            
            DS18B20_DQ_OUT=1;
            delay_us(60);             
        }
        else 
        {
            DS18B20_DQ_OUT=0;	// Write 0
            delay_us(60);             
            DS18B20_DQ_OUT=1;
            delay_us(2);                          
        }
    }
}
//开始温度转换
void DS18B20_Start(void) 
{   						               
    DS18B20_Rst();	   
	DS18B20_Check();	 
    DS18B20_Write_Byte(0xcc);	// skip rom
    DS18B20_Write_Byte(0x44);	// convert
} 

//初始化DS18B20的IO口 DQ 同时检测DS的存在
//返回1:不存在
//返回0:存在    	 
u8 DS18B20_Init(void)
{
 	GPIO_InitTypeDef  GPIO_InitStructure;
 	
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE);	 //使能PORTG口时钟 
	
 	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;				//PORTG.11 推挽输出
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		  
 	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 	GPIO_Init(GPIOG, &GPIO_InitStructure);

 	GPIO_SetBits(GPIOG,GPIO_Pin_11);    //输出1

	DS18B20_Rst();

	return DS18B20_Check();
}  
//从ds18b20得到温度值
//精度:0.1C
//返回值:温度值 (-550~1250) 
short DS18B20_Get_Temp(void)
{
    u8 temp;
    u8 TL,TH;
	short tem;
    DS18B20_Start ();  			// ds1820 start convert
    DS18B20_Rst();
    DS18B20_Check();	 
    DS18B20_Write_Byte(0xcc);	// skip rom
    DS18B20_Write_Byte(0xbe);	// convert	    
    TL=DS18B20_Read_Byte(); 	// LSB   
    TH=DS18B20_Read_Byte(); 	// MSB  
	    	  
    if(TH>7)
    {
        TH=~TH;
        TL=~TL; 
        temp=0;					//温度为负  
    }else temp=1;				//温度为正	  	  
    tem=TH; 					//获得高八位
    tem<<=8;    
    tem+=TL;					//获得底八位
    tem=(float)tem*0.625;		//转换     
	if(temp)return tem; 		//返回温度值
	else return -tem;    
}

参考用图

DHT11

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

DS18B20

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

原文地址:https://www.cnblogs.com/ikaros-521/p/15323406.html