目录
一、代码流程
1.模块复位:主机发送开始通信时序,从机做出响应(需检测是否有响应)
2.MCU读取1Bit数据
3.MCU读取1Byte数据
4.MCU读取8Byte数据组成完整Data,每读一次Data前都要开始通信流程
二、模块.c代码
#include "dht11.h"
/********************等待从机响应:返回0表示初始化成功*************************/
uint8_t DHT11_Reset(void)
{
RCC_APB2PeriphClockCmd(DHT11_CLK, ENABLE);
GPIO_InitTypeDef GPIO_InitStruct; //主机控制引脚
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin = DHT11_PIN;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DHT11_PORT, &GPIO_InitStruct);
GPIO_ResetBits(DHT11_PORT, DHT11_PIN); //主机发出开始通信的信号
Delay_ms(20);
GPIO_SetBits(DHT11_PORT, DHT11_PIN);
Delay_us(13);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; //主机释放引脚控制权,转为输入模式监听引脚电平
GPIO_InitStruct.GPIO_Pin = DHT11_PIN;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DHT11_PORT, &GPIO_InitStruct);
uint8_t time = 0;
while( (GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) == 0) && time < 100 ) //检测响应低电平是否正常
{
Delay_us(1);
time++;
}
if(time >= 100)
{
return 1;
}
else
{
time = 0;
}
while( (GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) == 1) && time < 100) //检测响应高电平是否正常
{
Delay_us(1);
time++;
}
if(time >= 100)
{
return 1;
}
else
{
time = 0;
}
return 0;
}
/**************************读1Bit*************************************/
uint8_t MCU_Read_Bit(void)
{
while( GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) == 1 ); //检测低电平到来
while( GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) == 0 ); //检测高电平到来
Delay_us(35);
if( GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) == 1 ) //直接读取35us后的数据
{
return 1;
}
else
{
return 0;
}
}
/**************************读1Byte****************************************/
uint8_t MCU_Read_Byte(void)
{
uint8_t tool = 0x80;
uint8_t Byte = 0;
for(tool = 0x80; tool != 0; tool >>=1 ) //DHT11数据高位先行,故从高位到低位读取数据
{
if( MCU_Read_Bit() == 1 )
Byte |= tool;
else
Byte &= ~tool;
}
return Byte;
}
/*****************读数据:返回0表示读取数据正确***********************/
uint8_t MCU_Read_Data(uint8_t* humidity, uint8_t* temperature)
{
uint8_t Data[5] = {0};
uint8_t i = 0;
if( DHT11_Reset() == 0 ) //每次读数据前都要重新开始通信时序,不然只会有一次数据显示
{
for( i = 0; i < 5; i++)
{
Data[i] = MCU_Read_Byte(); //将数据存入数组
}
if( (Data[0] + Data[1] + Data[2] + Data[3]) == Data[4] ) //如果校验位正确
{
*humidity = Data[0]; //读出数据
*temperature = Data[2];
return 0; //返回0表示读数据正确
}
}
return 1; //返回1表示读数据存在错误
}
三、模块.h代码
#ifndef __DHT11_H
#define __DHT11_H
#include "stm32f10x.h" // Device header
#include "delay.h"
#include "serial.h"
#define DHT11_CLK RCC_APB2Periph_GPIOB
#define DHT11_PORT GPIOB
#define DHT11_PIN GPIO_Pin_14
uint8_t DHT11_Reset(void);
uint8_t MCU_Read_Bit(void);
uint8_t MCU_Read_Byte(void);
uint8_t MCU_Read_Data(uint8_t* humidity, uint8_t* temperature);
#endif
四、主函数代码
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "DHT11.h"
int main(void)
{
OLED_Init();
uint8_t test = 1; //接收DHT11初始化是否成功的返回值
uint8_t humidity = 0, temperature = 0;
while (1)
{
test = MCU_Read_Data(&humidity, &temperature);
if(test == 0)
{
OLED_ShowNum(1, 1, humidity, 2);
OLED_ShowNum(2, 1, temperature, 2);
Delay_ms(500);
}
OLED_ShowHexNum(3, 1, test, 1);
}
}