再使用DHT11与指南针连接采取温度的时候出现一个问题就是我每次运行程序的时候再刚开始会提示读取数据失败再过了几秒,又能读取到温度和湿度。这个是怎么回事呢?
我的DHT11处理函数
#include "DHT11.h"
#include "stm32f1xx_hal.h"
#include "gpio.h"
// DHT11初始化函数
//static void DHT11_GPIO_Config(void);
static void DHT11_Mode_OUT_PP(void);
static void DHT_Mode_IPU(void);
static uint8_t DHT11_ReadByte(void);
//// 定义一个us级的延时
//static void DHT11_Delay(uint16_t time)
//{
// uint8_t i;
// while(time)
// {
// for(i = 0;i < 10;i++)
// {
//
// }
// time--;
// }
//
//}
void delay_us(uint32_t us)
{
uint32_t delay = (HAL_RCC_GetHCLKFreq() / 4000000 * us);
while (delay--)
{
;
}
}
//粗延时函数,微秒
//void delay_us(uint16_t time)
//{
// uint16_t i=0;
// while(time--)
// {
// i=10;
// while(i--) ;
// }
//}
void DHT11_Init(void)
{
__HAL_RCC_GPIOE_CLK_ENABLE();
// 空闲模式下输出高电平
DHT11_Mode_OUT_PP();
DHT11_Dout_High();
}
//static void DHT11_GPIO_Config(void)
//{
// GPIO_InitTypeDef GPIO_InitStructure;
// // 打开DHT11 GPIO的时钟
// __HAL_RCC_GPIOE_CLK_ENABLE();
// GPIO_InitStructure.Pin = DHT11_OUT_Pin;
//
// // 设置引脚为通用推挽输出
// GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
// GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
// GPIO_InitStructure.Pull = GPIO_NOPULL;
//
// HAL_GPIO_Init(GPIOE,&GPIO_InitStructure);
//}
/*
* 函数名:DHT11_Mode_IPU
* 描述 :使DHT11-DATA引脚变为上拉输入模式
* 输入 :无
* 输出 :无
*/
static void DHT_Mode_IPU(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Pin = DHT11_OUT_Pin;
GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
GPIO_InitStructure.Pull = GPIO_PULLUP;
HAL_GPIO_Init(DHT11_OUT_GPIO_Port,&GPIO_InitStructure);
}
/*
* 函数名:DHT11_Mode_OUT_PP
* 描述 :使DHT11-DATA引脚变为通用推挽输出模式
* 输入 :无
* 输出 :无
*/
static void DHT11_Mode_OUT_PP(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Pin = DHT11_OUT_Pin;
GPIO_InitStructure.Mode =GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(DHT11_OUT_GPIO_Port,&GPIO_InitStructure);
}
/*
函数功能:从DHT11读取一个字节MSB先行
*/
static uint8_t DHT11_ReadByte(void)
{
uint8_t i,tmpValue;
for(i = 0;i < 8;i++)
{
/*检测引脚的电平 每一bit数据都以50us低电平时隙开始,直到50us的低电平结束*/
while( DHT11_Dout_IN() == GPIO_PIN_RESET);
/*DHT11 以26~28us的高电平表示“0”,以70us高电平表示“1”,
*通过检测 x us后的电平即可区别这两个状 ,x 即下面的延时
*/
delay_us(40); // 该值大于数据为0持续的时间即可
if(DHT11_Dout_IN() == GPIO_PIN_SET) // 如果该电平还是高电平表示数据为1
{
while(DHT11_Dout_IN() == GPIO_PIN_SET); // 等待数据1的时间结束
tmpValue |= (uint8_t)(0x01 << (7-i)); //把第最高位置1
}
else
{
// 这里的数据将不是1而是0
tmpValue &= ~(uint8_t)(0x01 << (7-i)); // 把最高位置0,MSB先行的模式
}
}
return tmpValue;
}
/*
* 一次完整的数据传输为40bit,高位先出
* 8bit 湿度整数 + 8bit 湿度小数 + 8bit 温度整数 + 8bit 温度小数 + 8bit 校验和
*/
uint8_t DHT11_Read_TempAndHumidity(DHT11_Data_TypeDef *DHT11_Data)
{
// 先设为输出模式
DHT11_Mode_OUT_PP();
// 发送开始信号拉低
DHT11_Dout_Low();
// 延时18ms
HAL_Delay(18);
// 主机拉高
DHT11_Dout_High();
// 延时20-40us
delay_us(40);
// 主机设置成输入模式
DHT_Mode_IPU();
// 判断是否有低电平的信号
if(DHT11_Dout_IN() == GPIO_PIN_RESET)
{
/*轮询直到从机发出 的80us 低电平 响应信号结束*/
while(DHT11_Dout_IN() == GPIO_PIN_RESET);
/*轮询直到从机发出 的80us 低电平 标志信号结束*/
while(DHT11_Dout_IN() == GPIO_PIN_SET);
//开始接受数据了
DHT11_Data->humi_int = DHT11_ReadByte();
DHT11_Data->humi_deci = DHT11_ReadByte();
DHT11_Data->temp_int = DHT11_ReadByte();
DHT11_Data->temp_deci = DHT11_ReadByte();
DHT11_Data->check_sum = DHT11_ReadByte();
// 读结束后设置为输出模式
DHT11_Mode_OUT_PP();
// 输出一个高电平
DHT11_Dout_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;
}
下面是main函数通过串口打印读取带的温度和湿度
int main(void)
{
/* USER CODE BEGIN 1 */
DHT11_Data_TypeDef DHT11_Data;
/* 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_FSMC_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
ILI9341_Init();
HAL_SRAM_MspInit(&hsram1);
//ILI9341_OpenWindow(0,0,240,320);
// ILI9341_DrawRectangle(160,240,160,240,RED);
// ILI9341_DispString_EN(0,0,&quot;hello world&quot;);
//ILI9341_DrawPic(0,0,240,313,gImage_name);
DHT11_Init();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
/*调用DHT11_Read_TempAndHumidity读取温湿度,若成功则输出该信息*/
if( DHT11_Read_TempAndHumidity ( & DHT11_Data ) == SUCCESS)
{
printf(&quot;\r\n读取DHT11成功!\r\n\r\n湿度为%d.%d %RH ,温度为 %d.%d℃ \r\n&quot;,\
DHT11_Data.humi_int,DHT11_Data.humi_deci,DHT11_Data.temp_int,DHT11_Data.temp_deci);
}
else
{
printf(&quot;Read DHT11 ERROR!\r\n&quot;);
}
HAL_Delay(1500);
}
/* USER CODE END 3 */
}
一下是程序的结果
Read DHT11 ERROR!
Read DHT11 ERROR!
Read DHT11 ERROR!
Read DHT11 ERROR!
Read DHT11 ERROR!
Read DHT11 ERROR!
Read DHT11 ERROR!
Read DHT11 ERROR!
Read DHT11 ERROR!
读取DHT11成功!
湿度为35.0 %RH ,温度为 22.5℃
读取DHT11成功!
湿度为34.0 %RH ,温度为 22.5℃
读取DHT11成功!
湿度为34.0 %RH ,温度为 22.5℃
读取DHT11成功!
湿度为34.0 %RH ,温度为 22.5℃ |