查看芯片手册,最重要的是要根据手册了解,相应的知识,例如:芯片功能,芯片管脚及功能
以及数据如何读等等;
这里需要注意是数字传感器,传出的数据是数字信号,像模拟传感器,传出的就是模拟信号
需要ADC接收转换为数字信号,计算为我们需要的数据。
DHT11温湿度传感器,一种基于单总线通信的传感器模块。
对于单总线而言,主要通过改变DQ的电平状态根据时间进行相应的操作;
查看手册可以发现引脚定义图:
其中的DATA也就是DQ引脚;
其余属于基本引脚,供电,共地引脚等等。
产品参数介绍。介绍了对于湿度,温度在出产时,25°,5v电压下的测量性能;
(对于数据测量有精度要求可以仔细研读)
以及一些测量的电气特性介绍:如工作电压,工作电流,采样周期需要多久;
(需要特别注意采样周期,一般来说数字传感器测量数据无论时I2C还是SPI都需要一定的时间。也就是采样时间);
这里单线双向的意思就是通信双方都可以根据,这根线进行信息交互。
类似于我们I2C当中主机从机交换数据线控制权。
需要注意这里的校验位,等于前面接收的四位8位二进制数据的和,否则数据接收错误;
也就是8位湿度整数int+8位湿度小数crsi+8位温度整数int+8位温度小数crsi=8位校验位;
也就是的单总线DHT11的检验方式。等式不成立即数据读取错误:
手册当中也有例子如下:
下面就是对于单通信的起始信号,响应信号,数据格式,校验位的介绍
手册当中的时序图如下:
1.总过程:
2.起始信号:
2.数据传输:
其中0和1数据传输要求时间不同;
手册当中分开传送
数据1:
下面时基于STM32F10X标准库函数写的读取历程:
DHT11.h
#ifndef __DHT11_H
#define __DHT11_H
#include "stm32f10x.h" // Device header
#include "Serial.h"
#include "Delay.h"
#include "stdio.h"
#define DHT11_CLK RCC_APB2Periph_GPIOC
#define DHT11_CLK_INIT RCC_APB2PeriphClockCmd
#define DHT11_PORT GPIOC
#define DHT11_PIN GPIO_Pin_1
typedef enum{
MODE_IN = 0,
MODE_OUT = 1,
}DHT11_MODE;
#define DHT11_HIGH() GPIO_SetBits(DHT11_PORT,DHT11_PIN)
#define DHT11_LOW() GPIO_ResetBits(DHT11_PORT,DHT11_PIN)
#define DHT11_ReadPin() (GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN))
typedef struct {
uint8_t Tem_H; // 存储从DHT11读取整数温度数据
uint8_t Tem_L; // 存储从DHT11读取小数温度数据
uint8_t Hum_H; // 存储从DHT11读取整数湿度数据
uint8_t Hum_L; // 存储从DHT11读取小数湿度数据
}DHT11_TyDef;
void Change_Dht11Mode(DHT11_MODE flag);
uint8_t Dht11_ReadData(DHT11_TyDef * data);
#endif
DHT11.C文件
#include "DHT11.h"
void Dht11_Config(void)
{
Change_Dht11Mode(MODE_OUT);
DHT11_HIGH();
}
void Change_Dht11Mode(DHT11_MODE flag)
{
GPIO_InitTypeDef GPIO_InitStructure;
DHT11_CLK_INIT(DHT11_CLK, ENABLE);
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = DHT11_PIN;
if(flag == 1)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
else
{
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
}
GPIO_Init(DHT11_PORT, &GPIO_InitStructure);
}
uint8_t Dht11_ReadData(DHT11_TyDef * data)
{
uint8_t retury = 0;
uint8_t i = 0;
uint8_t Data[5] = {0};
Dht11_Config();
//发送起始信号
DHT11_LOW();
Delay_ms(18);
DHT11_HIGH();
Change_Dht11Mode(MODE_IN);
//等待DHT11响应
while(DHT11_ReadPin())
{
retury++;
Delay_us(1);
if(retury > 100) return 0;
}
retury = 0;
//等待响应结束
while(DHT11_ReadPin() == 0)
{
retury++;
Delay_us(1);
if(retury > 100) return 0;
}
retury = 0;
for(i=0; i<40; i++)
{
//判断低电平是否到来
while(DHT11_ReadPin())
{
retury++;
Delay_us(1);
if(retury > 100) return 0;
}
retury = 0;
//等待低电平结束
while(DHT11_ReadPin() == 0)
{
retury++;
Delay_us(1);
if(retury > 100) return 0;
}
retury = 0;
Delay_us(30);
//判断数据
if(DHT11_ReadPin())//收到数据1
{
Data[i/8] |= (1<<(7-i%8));
}
else
{
Data[i/8] &= ~(1<<(7-i%8));
}
}
//校验位计算
if(Data[4] == Data[0]+Data[1]+Data[2]+Data[3])
{
data->Hum_H = Data[0];
data->Hum_L = Data[1];
data->Tem_H = Data[2];
data->Tem_L = Data[3];
return 1;
}
else
{
Serial_Printf("Dht11 Err\r\n");
return 0;
}
}
后续还提供了一种写法.