STM32应用(八)数字温度传感器DS18B20、数字温湿度传感器DHT11(软件模拟I2C)

这两个传感器F4的开发板上都没有,如果要阅读此博客,请先买好传感器哟(^U^)ノYO

1.DS18B20 数字温度传感器实验

1.1 DS18B20简介

在这里插入图片描述

1.2 硬件与IO口配置

在这里插入图片描述

在这里插入图片描述
将 DS18B20 传感器插入到这个上面就可以通过 STM32 来读取 DS18B20 的温度了。
在这里插入图片描述

1.3 实物图与接线

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

1.4 工程配置

1.开启GPIOG_9
在这里插入图片描述

2.开启串口
在这里插入图片描述
3.开启TIMX,实现us级定时
在这里插入图片描述
在tim.c文件中加入:

/* USER CODE BEGIN 1 */
void delay_us(uint16_t us){
	uint16_t differ = 0xffff-us-5;				
	__HAL_TIM_SET_COUNTER(&htim7,differ);	
	HAL_TIM_Base_Start(&htim7);		
	
	while(differ < 0xffff-5){	
		differ = __HAL_TIM_GET_COUNTER(&htim7);		
	}
	HAL_TIM_Base_Stop(&htim7);
}
/* USER CODE END 1 */

1.5 驱动和检测代码编写

驱动代码移植原子哥。驱动代码有很多,可以自行修改。

1.5.1 ds18b20.c

#include "ds18b20.h"

void DS18B20_IO_IN(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.Pin = GPIO_PIN_9;
	GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
	HAL_GPIO_Init(GPIOG,&GPIO_InitStructure);
}

void DS18B20_IO_OUT(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.Pin = GPIO_PIN_9;
	GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
	HAL_GPIO_Init(GPIOG,&GPIO_InitStructure);
}
//复位DS18B20
void DS18B20_Rst(void)
{
	DS18B20_IO_OUT();
	DS18B20_DQ_OUT_LOW;
	delay_us(750);
	DS18B20_DQ_OUT_HIGH;
	delay_us(15);
}
//等待DS18B20的回应
//返回1:未检测到DS18B20的存在
//返回0:存在	
uint8_t DS18B20_Check(void)
{
	uint8_t retry = 0;
	DS18B20_IO_IN();
	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
uint8_t DS18B20_Read_Bit(void)
{
	uint8_t data;
	DS18B20_IO_OUT();
	DS18B20_DQ_OUT_LOW;
	delay_us(2);
	DS18B20_DQ_OUT_HIGH;
	DS18B20_IO_IN();
	delay_us(12);
	
	if(DS18B20_DQ_IN)
		data = 1;
	else
		data = 0;
	
	delay_us(50);
	return data;
}
//从DS18B20读取一个字节
//返回值:读到的数据
uint8_t DS18B20_Read_Byte(void)
{
	uint8_t i,j,data;
	data = 0;
	for(i=1;i<=8;i++)
	{
		j = DS18B20_Read_Bit();
		data = (j<<7)|(data>>1);
	}
	return data;
}
//写一个字节到DS18B20
//dat:要写入的字节
void DS18B20_Write_Byte(uint8_t data)
{
	uint8_t j;
	uint8_t testb;
	DS18B20_IO_OUT();
	for(j=1;j<=8;j++)
	{
		testb=data&0x01;
		data=data>>1;
		if(testb)
		{
			DS18B20_DQ_OUT_LOW;
			delay_us(2);
			DS18B20_DQ_OUT_HIGH;
			delay_us(60);
		}
		else
		{
			DS18B20_DQ_OUT_LOW;
			delay_us(60);
			DS18B20_DQ_OUT_HIGH;
			delay_us(2);
		}
	}
}
//开始温度转换
void DS18B20_Start(void)
{
	DS18B20_Rst();
	DS18B20_Check();
	DS18B20_Write_Byte(0xcc);
	DS18B20_Write_Byte(0x44);
}

uint8_t DS18B20_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.Pin = GPIO_PIN_9;
	GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStructure.Pull = GPIO_PULLUP;
	GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
	HAL_GPIO_Init(GPIOG,&GPIO_InitStructure);
	
	DS18B20_Rst();
	return DS18B20_Check();
}
//初始化DS18B20的IO口 DQ 同时检测DS的存在
//返回1:不存在
//返回0:存在   
short DS18B20_Get_Temperature(void)
{
	uint8_t t;
	uint8_t TL,TH;
	short temperature;
	
	DS18B20_Start();
	DS18B20_Rst();
	DS18B20_Check();
	DS18B20_Write_Byte(0xcc);
	DS18B20_Write_Byte(0xbe);
	TL = DS18B20_Read_Byte();
	TH = DS18B20_Read_Byte();
	
	if(TH>7)
	{
		TH = ~TH;
		TL = ~TL;
		t = 0;
	}
	else
		t = 1;
	
	temperature = TH;
	temperature <<= 8;
	temperature += TL;
	temperature = (short)temperature*0.625;
	if(temperature)
		return temperature;
	else
		return -temperature;
}

DS18B20读取温度需要发送一些命令,
温度转换指令:0x44(启动Ds18b20启动转换温度)。
读暂存器指令:0xBE(读取暂存器中的九字节数据)。

1.5.2 ds18b20.h

#ifndef __DS18B20_H
#define __DS18B20_H 

#include "main.h"
#include "tim.h"

#define DS18B20_DQ_OUT_HIGH HAL_GPIO_WritePin(GPIOG,GPIO_PIN_9,GPIO_PIN_SET)
#define DS18B20_DQ_OUT_LOW 	HAL_GPIO_WritePin(GPIOG,GPIO_PIN_9,GPIO_PIN_RESET)

#define DS18B20_DQ_IN	 HAL_GPIO_ReadPin(GPIOG,GPIO_PIN_11)


void DS18B20_IO_IN(void);
void DS18B20_IO_OUT(void);

uint8_t DS18B20_Init(void);	//初始化DS18B20
void DS18B20_Rst(void);			//复位DS18B20 
uint8_t DS18B20_Check(void);//检测是否存在DS18B20

uint8_t DS18B20_Read_Bit(void);//读出一个位
uint8_t DS18B20_Read_Byte(void);//读出一个字节
void DS18B20_Write_Byte(uint8_t data);//写入一个字节

void DS18B20_Start(void);//开始温度转换
short DS18B20_Get_Temperature(void);	//获取温度

#endif

1.5.3 main测试

  /* USER CODE BEGIN 2 */
	printf("DS18B20 Test!\r\n");
	while(DS18B20_Init())
	{
  	printf("DS18B20 checked failed!!!\r\n");
		HAL_Delay(500);
  }
	//DS18B20_Init();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		temperature=DS18B20_Get_Temperature();	
				if(temperature < 0)
			printf("temperature = -%.2f degree\r\n",temperature/10);
		else
			printf("temperature = %.2f degree\r\n",temperature/10);
		HAL_Delay(200);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

1.6 测试结果

在这里插入图片描述

2.DHT11 数字温湿度传感器实验

在此将介绍数字温湿度传感器DHT11 的使用,该传感器不但能测温度,还能测湿度。

2.1 DHT11简介和接线

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

DHT11 和 DS18B20 的接口是共用一个的,不过 DHT11 有 4 条腿,需要把 U12 的 4 个接口都用上, 将 DHT11 传感器插入到这个上面就可以通过 STM32F4来读取温湿度值了。
在这里插入图片描述

2.2 通信时序简述

以下内容来自客服给的DHT11说明书。

2.2.1 数据格式

微处理器与 DHT11之间的通讯和同步,采用单总线数据格式,一次通讯时间4ms左右,数据分小数部分和整数部分,具体格式在下面说明,当前小数部分用于以后扩展,现读出为零.操作流程如下:
一次完整的数据传输为40bit,高位先出。
数据格式: 8bit湿度整数数据+8bit湿度小数数据
+8bi温度整数数据+8bit温度小数数据
+8bit校验和
在这里插入图片描述

据传送正确时校验和数据等于 “8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据” 所得结果的末8位。

2.2.2 通讯时序

通讯过程如图:
在这里插入图片描述
总线空闲状态为高电平,主机把总线拉低等待DHT11响应,主机把总线拉低必须大于18毫秒,保证DHT11能检测到起始信号。 DHT11接收到主机的开始信号后,等待主机开始信号结束,然后发送80us低电平响应信号。主机发送开始信号结束后,延时等待20-40us后,读取DHT11的响应信号,主机发送开始信号后,可以切换到输入模式,或者输出高电平均可,总线由上拉电阻拉高。
开始传输信号:

在这里插入图片描述
总线为低电平,说明DHT11发送响应信号,DHT11发送响应信号后,再把总线拉高80us,准备发送数据,每一bit数据都以50us低电平时隙开始,高电平的长短定了数据位是0还是1。

2.3.2 数字信号0/1表示方式

在这里插入图片描述

在这里插入图片描述

2.3工程配置

2.2.1 输出GPIO_PG_11

在这里插入图片描述

2.2.2 打开串口USART1

在这里插入图片描述

2.2.3 开启TIM7,与1.4相同

在这里插入图片描述

2.4 编写代码

依据时序图,编写程序。

2.4.1 初始化、封装IO的输入输出

由于是一个IO口,要满足输出和检测电平,所以用两个函数来切换引脚的模式,可以使引脚在输出和输入之间切换

//初始化DHT11的IO口 DQ 同时检测DHT11的存在
//返回1:不存在
//返回0:存在     	 
uint8_t DHT11_Init(void)
{ 
  DHT11_Rst();
	return DHT11_Check();
}
#define DHT11_DQ_OUT_HIGH HAL_GPIO_WritePin(GPIOG,GPIO_PIN_11,GPIO_PIN_SET)
#define DHT11_DQ_OUT_LOW 	HAL_GPIO_WritePin(GPIOG,GPIO_PIN_11,GPIO_PIN_RESET)
#define DHT11_DQ_IN	 HAL_GPIO_ReadPin(GPIOG,GPIO_PIN_11)

void DHT11_IO_IN(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.Pin = GPIO_PIN_11;
	GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
	HAL_GPIO_Init(GPIOG,&GPIO_InitStructure);
}

void DHT11_IO_OUT(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.Pin = GPIO_PIN_11;
	GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
	HAL_GPIO_Init(GPIOG,&GPIO_Ini

2.4.2 复位和响应模块

//复位DHT11
void DHT11_Rst(void)	   
{                 
	DHT11_IO_OUT(); 	//设置为输出
	DHT11_DQ_OUT_LOW; 	//拉低DQ
	HAL_Delay(20);    	//拉低至少18ms
	DHT11_DQ_OUT_HIGH; 	//DQ=1 
	delay_us(30);     	//主机拉高20~40us
}

//等待DHT11的回应
//返回1:未检测到DHT11的存在
//返回0:存在
uint8_t DHT11_Check(void) 	   
{   
	uint8_t retry=0;
	DHT11_IO_IN();      //设置为输出	 
	while (DHT11_DQ_IN&&retry<100)//DHT11会拉低40~80us
	{
		retry++;
		delay_us(1);
	};	 
	if(retry>=100)return 1;
	else retry=0;
	while (!DHT11_DQ_IN&&retry<100)//DHT11拉低后会再次拉高40~80us
	{
		retry++;
		delay_us(1);
	};
	if(retry>=100)return 1;	    
	return 0;
}

//从DHT11读取一个位
//返回值:1/0
uint8_t DHT11_Read_Bit(void) 			 
{
 	uint8_t retry=0;
	while(DHT11_DQ_IN&&retry<100)//等待变为低电平
	{
		retry++;
		delay_us(1);
	}
	retry=0;
	while(!DHT11_DQ_IN&&retry<100)//等待变高电平
	{
		retry++;
		delay_us(1);
	}
	delay_us(40);//等待40us
	if(DHT11_DQ_IN)return 1;
	else return 0;		   
}

//从DHT11读取一个字节
//返回值:读到的数据
uint8_t DHT11_Read_Byte(void)    
{        
	uint8_t i,dat;
	dat=0;
	for (i=0;i<8;i++) 
	{
   		dat<<=1; 
	    dat|=DHT11_Read_Bit();
    }						    
    return dat;
}

2.4.3 数据的解算

//从DHT11读取一次数据
//temp:温度值(范围:0~50°)
//humi:湿度值(范围:20%~90%)
//返回值:0,正常;1,读取失败
uint8_t DHT11_Read_Data(uint16_t *temp,uint16_t *humi)    
{        
 	uint8_t buf[5];
	uint8_t i;
	DHT11_Rst();
	if(DHT11_Check()==0)
	{
		for(i=0;i<5;i++)//读取40位数据
		{
			buf[i]=DHT11_Read_Byte();
		}
		if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
		{
			*humi=(buf[0]<<8) + buf[1];
			*temp=(buf[2]<<8) + buf[3];
		}
	}else return 1;
	return 0;	    
}

2.4.4 测试代码

uint16_t temperature;
uint16_t humidity;
	while(DHT11_Init())
	{
		printf("DHT11 Checked failed!!!\r\n");
		HAL_Delay(200);
	}
	printf("DHT11 Checked Sucess!!!\r\n");
while (1)
{
	DHT11_Read_Data(&temperature,&humidity);
	printf("DHT11 Temperature = %d.%d degree\r\n",temperature>>8,temperature&0xff);
	printf("DHT11 Humidity = %d.%d%%\r\n",humidity>>8,humidity&0xff);
	HAL_Delay(200);
}

2.5 测试结果

在这里插入图片描述

  • 10
    点赞
  • 104
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
以下是使用STM32DS18B20进行度测量的C代码: #include "stm32f10x.h" #include "delay.h" #define DS18B20_GPIO GPIOB #define DS18B20_PIN GPIO_Pin_12 void DS18B20_Init(void); void DS18B20_Start(void); void DS18B20_WriteByte(u8 data); u8 DS18B20_ReadByte(void); float DS18B20_GetTemp(void); int main(void) { float temp; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); DS18B20_Init(); while(1) { DS18B20_Start(); DS18B20_WriteByte(0xCC); DS18B20_WriteByte(0x44); delay_us(1000000); temp = DS18B20_GetTemp(); // 在这里处理度数据 } } void DS18B20_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = DS18B20_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(DS18B20_GPIO, &GPIO_InitStructure); GPIO_SetBits(DS18B20_GPIO, DS18B20_PIN); } void DS18B20_Start(void) { GPIO_ResetBits(DS18B20_GPIO, DS18B20_PIN); delay_us(500); GPIO_SetBits(DS18B20_GPIO, DS18B20_PIN); delay_us(80); } void DS18B20_WriteByte(u8 data) { u8 i; for(i = 0; i < 8; i++) { if((data & (1 << i)) != 0) { GPIO_ResetBits(DS18B20_GPIO, DS18B20_PIN); delay_us(2); GPIO_SetBits(DS18B20_GPIO, DS18B20_PIN); delay_us(60); } else { GPIO_ResetBits(DS18B20_GPIO, DS18B20_PIN); delay_us(60); GPIO_SetBits(DS18B20_GPIO, DS18B20_PIN); delay_us(2); } } } u8 DS18B20_ReadByte(void) { u8 i, data = 0; for(i = 0; i < 8; i++) { GPIO_ResetBits(DS18B20_GPIO, DS18B20_PIN); delay_us(2); GPIO_SetBits(DS18B20_GPIO, DS18B20_PIN); delay_us(8); if(GPIO_ReadInputDataBit(DS18B20_GPIO, DS18B20_PIN) != RESET) { data |= 1 << i; } delay_us(50); } return data; } float DS18B20_GetTemp(void) { u8 temp_l, temp_h; int temp; float ftemp; DS18B20_Start(); DS18B20_WriteByte(0xCC); DS18B20_WriteByte(0xBE); temp_l = DS18B20_ReadByte(); temp_h = DS18B20_ReadByte(); temp = (temp_h << 8) | temp_l; ftemp = temp * 0.0625; return ftemp; } 请注意,此代码仅用于示例目的,实际应用中可能需要进行更多的错误处理和数据处理。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值