目录
设备选型
单片机选型:STM32F103C8T6 其实其它型号的单片机操作也是一样的
温湿度传感器:DHT11
设备原型与电路设计
先看一下DHT11温湿度长的样子。
电路设计如下:
也可购买模块如下:
温湿度传感器介绍
DHT11 是广州奥松有限公司生产的一款湿温度一体化的数字传感器。该传感器包括一个电阻式测湿元件和一个 NTC 测温元件,并与一个高性能 8 位单片机相连接。通过单片机等微处理器简单的电路连接就能够实时的采集本地湿度和温度。 DHT11 与单片机之间能采用简单的单总线进行通信,仅仅需要一个I/O 口。传感器内部湿度和温度数据 40Bit 的数据一次性传给单片机,数据采用校验和方式进行校验,有效的保证数据传输的准确性。 DHT11 功耗很低, 5V 电源电压下,工作平均最大电流 0.5mA。
温湿度传感器特点及数据结构
工作电压范围:3.3V-5.5V
工作电流 :平均0.5mA
输出:单总线数字信号
测量范围:湿度20~90%RH,温度0~50℃
精度 :湿度±5%,温度±2℃
分辨率 :湿度1%,温度1℃
DHT11数字湿温度传感器采用单总线数据格式。单个数据引脚端口完成输入输出双向传输。
其数据包由5Byte(40Bit)组成。数据分小数部分和整数部分,一次完整的数据传输为40bit,高位先出。
DHT11的数据格式为:8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据+8bit校验和。
其中校验和数据为前四个字节相加。 传感器数据输出的是未编码的二进制数据。数据(湿度、温度、整数、小数)之间应该分开处理。
传感器数据输出的是未编码的二进制数据。数据(湿度、温度、整数、小数)之间应该分开处理。
温湿度传感器工作时序
DHT11 开始发送数据流程
主机发送开始信号后,延时等待 20us-40us 后读取 DH11T 的回应信号,读取总线为低电平,说明 DHT11 发送响应信号, DHT11 发送响应信号后,再把总线拉高,准备发送数据,每一 bit 数据都以低电平开始,格式见下面图示。如果读取响应信号为高电平,则 DHT11 没有响应,请检查线路是否连接正常。
首先主机发送开始信号,即:拉低数据线,保持t1(至少18ms)时间,然后拉高数据线t2(20~40us)时间,然后读取DHT11的响应,正常的话,DHT11会拉低数据线,保持t3(40~50us)时间,作为响应信号,然后DHT11拉高数据线,保t4(40~50us)时间后,开始输出数据。
主机复位信号和 DHT11 响应信号
数字‘ 0’信号表示方法
程序要区分数据0和数据1的格式:先判断此时引脚的电平状态,如果是低电平就一直循环等待,直到高电平出现,高电平出现后延时40us,并读取延时后的电平状态,如果此时是高电平,则数据为1,否则为0
传输完40位数据后,传感器再次输出一个50us的低电平后,将数据总线释放,采集过程结束。
与单片机接线表设计
选用的单片机型号:STM32F103C8 其实哪个单片机无所谓的,主要是温湿度模块的实现
接线:PA0接在模块的DATA口上,其实接在哪个引脚并不重要
序号 | 模块 | 单片机 |
1 | GND | GND |
2 | VCC | 3.3V/5V |
3 | DATA | PA0 |
4 | - | PA9(串口1 RX) |
5 | - | PA10(串口1 TX) |
标准库实现
dht11.c
#include "stm32f10x.h"
#include "dht11.h"
uint8_t U8FLAG,k;
uint8_t U8count,U8temp;
uint8_t U8T_data_H,U8T_data_L,U8RH_data_H,U8RH_data_L,U8checkdata;
uint8_t U8T_data_H_temp,U8T_data_L_temp,U8RH_data_H_temp,U8RH_data_L_temp,U8checkdata_temp;
uint8_t U8comdata;
void dht11_Init(void) //配置端口PA6
{
GPIO_InitTypeDef GPIO_InitStructure; // 结构体变量的定义或声明
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //使能PA端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //PA0端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; // 开漏输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOC
GPIO_ResetBits(GPIOA,GPIO_Pin_0); //输出低电平
}
void COM(void) //启动 读取
{
uint8_t i;
for(i=0;i<8;i++)
{
U8FLAG=2; //初始化数
while((!DHT11_SDA_READ())&&U8FLAG++); //读端口采集,低电平表示起始信号
dht11_delay_us(10);
dht11_delay_us(10);
dht11_delay_us(10); //等待
U8temp=0;
if(DHT11_SDA_READ())U8temp=1; //有数据来
U8FLAG=2;
while((DHT11_SDA_READ())&&U8FLAG++); //读取
if(U8FLAG==1)break;
U8comdata<<=1;
U8comdata|=U8temp;
}
}
void RH(void) //
{
DHT11_SDA_L(); //拉低
dht11_delay_ms(18);
DHT11_SDA_H(); //拉高
dht11_delay_us(10);
dht11_delay_us(10);
dht11_delay_us(10);
dht11_delay_us(10); //等待
if(!DHT11_SDA_READ()) //低电平进入
{
U8FLAG=2;
while((!DHT11_SDA_READ())&&U8FLAG++);//数据等待
U8FLAG=2;
while((DHT11_SDA_READ())&&U8FLAG++); //启动
COM(); //
U8RH_data_H_temp=U8comdata; //读取湿度高位
COM();
U8RH_data_L_temp=U8comdata; //读取湿度低位
COM();
U8T_data_H_temp=U8comdata; //读取温度高位
COM();
U8T_data_L_temp=U8comdata; //读取温度低位
COM();
U8checkdata_temp=U8comdata; //校验位
DHT11_SDA_H();
U8temp=(U8T_data_H_temp+U8T_data_L_temp+U8RH_data_H_temp+U8RH_data_L_temp);//40位数据相加
if(U8temp==U8checkdata_temp) //数据校验 对比
{
U8RH_data_H=U8RH_data_H_temp; //把读取值付出
U8RH_data_L=U8RH_data_L_temp;
U8T_data_H=U8T_data_H_temp;
U8T_data_L=U8T_data_L_temp;
U8checkdata=U8checkdata_temp;
}
}
}
main.c
int main(void)
{
int temperature = 0;
int humidity = 0;
int i = 0;
char temStr[50] = "";
char humStr[50] = "";
delay_init(); // 延时函数初始化
uart_init(9600); // 串口1函数初始化
dht11_Init(); //
/* Infinite loop */
while (1)
{
RH(); // 读取温湿度
温度计算
sprintf(temStr,"温度:%d.%d\r\n",U8T_data_H,U8T_data_L);
for(i=0;i<strlen(temStr);i++)
{
USART_SendData(USART1, temStr[i]);
delay_ms(1);
}
湿度计算
sprintf(humStr,"湿度:%d.%d\r\n",U8RH_data_H,U8RH_data_L);
for(i=0;i<strlen(humStr);i++)
{
USART_SendData(USART1, humStr[i]);
delay_ms(1);
}
delay_ms(100);
}
}
实现效果:
HAL库实现
main.c
int main(void)
{
/* USER CODE BEGIN 1 */
int temperature = 0;
int humidity = 0;
char temStr[50] = "";
char humStr[50] = "";
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
RH(); // 读取温湿度
温度计算
sprintf(temStr,"温度:%d.%d\r\n",U8T_data_H,U8T_data_L);
while(HAL_OK != HAL_UART_Transmit(&huart1, (uint8_t *)temStr, strlen(temStr), 0XFFFF));
湿度计算
sprintf(humStr,"湿度:%d.%d\r\n",U8RH_data_H,U8RH_data_L);
while(HAL_OK != HAL_UART_Transmit(&huart1, (uint8_t *)humStr, strlen(humStr), 0XFFFF));
delay_ms(100);
}
/* USER CODE END 3 */
}
dht11.c
#include "dht11.h"
uint8_t U8FLAG,k;
uint8_t U8count,U8temp;
uint8_t U8T_data_H,U8T_data_L,U8RH_data_H,U8RH_data_L,U8checkdata;
uint8_t U8T_data_H_temp,U8T_data_L_temp,U8RH_data_H_temp,U8RH_data_L_temp,U8checkdata_temp;
uint8_t U8comdata;
void COM(void) //启动 读取
{
uint8_t i;
for(i=0;i<8;i++)
{
U8FLAG=2; //初始化数
while((!DHT11_SDA_READ())&&U8FLAG++); //读端口采集,低电平表示起始信号
delay_us(10);
delay_us(10);
delay_us(10); //等待
U8temp=0;
if(DHT11_SDA_READ())U8temp=1; //有数据来
U8FLAG=2;
while((DHT11_SDA_READ())&&U8FLAG++); //读取
if(U8FLAG==1)break;
U8comdata<<=1;
U8comdata|=U8temp;
}
}
void RH(void) //
{
DHT11_SDA_L(); //拉低
delay_ms(18);
DHT11_SDA_H(); //拉高
delay_us(10);
delay_us(10);
delay_us(10);
delay_us(10); //等待
if(!DHT11_SDA_READ()) //低电平进入
{
U8FLAG=2;
while((!DHT11_SDA_READ())&&U8FLAG++);//数据等待
U8FLAG=2;
while((DHT11_SDA_READ())&&U8FLAG++); //启动
COM(); //
U8RH_data_H_temp=U8comdata; //读取湿度高位
COM();
U8RH_data_L_temp=U8comdata; //读取湿度低位
COM();
U8T_data_H_temp=U8comdata; //读取温度高位
COM();
U8T_data_L_temp=U8comdata; //读取温度低位
COM();
U8checkdata_temp=U8comdata; //校验位
DHT11_SDA_H();
U8temp=(U8T_data_H_temp+U8T_data_L_temp+U8RH_data_H_temp+U8RH_data_L_temp);//40位数据相加
if(U8temp==U8checkdata_temp) //数据校验 对比
{
U8RH_data_H=U8RH_data_H_temp; //把读取值付出
U8RH_data_L=U8RH_data_L_temp;
U8T_data_H=U8T_data_H_temp;
U8T_data_L=U8T_data_L_temp;
U8checkdata=U8checkdata_temp;
}
}
}
实现效果:
有问题可私聊,可远程进行代码调试,互相学习互相进步!!!
源码下载链接: