STM32F103ZET6——DHT11温湿度传感器(hal库)

一、CubeMX配置

(1)调试接口配置

        如下图进行调试接口配置,将调试接口设置成SW模式,占用芯片PA13、PA14两个引脚

(2)时钟配置

        如下图分别进行外部高速时钟HSE和时钟树的配置,设置HCLK为72MHz(最高72MHz,也可以配置其他),其配置图如图所示

(3)GPIO配置

        DHT11只有三个引脚VCC——3.3V,GND——GND,数据传输引脚——PA1,这里将PA1设置为输出模式

(4)定时器TIM配置

        这里选择TIM2,设置定时器为内部时钟,由于TIM2的内部时钟CK_INT来自于外设总线APB1提供的定时时钟TIMx_CLK(72MHz),所以经过(72-1)的预分频后刚好是1MHz,也就是1us,后续会在cube中生成的tim.c文件中由程序实现延时函数

(5)USART串口配置

        为了验证程序的可行性,我们利用串口将程序的结果传输到电脑上,这里选择异步模式,串口波特率为115200Bits/s,其USART配置如图所示

(6)

二、程序修改部分

(1)tim.c

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

void Delay_us(uint16_t myus)//基于TIM2定时器的μs延时函数
{
    uint16_t differ = 0xffff-myus-5;         
    HAL_TIM_Base_Start(&htim2);         
    
    while(differ < 0xffff-5)
    {   
        differ = __HAL_TIM_GET_COUNTER(&htim2);   
    }
    HAL_TIM_Base_Stop(&htim2);
}

/* USER CODE END 1 */

 (2)tim.h

/* USER CODE BEGIN Includes */
void delay_us(uint16_t us);
void Delay_us(uint16_t myus);
/* USER CODE END Includes */

(3)DHT11驱动文件

dht11.c

#include "dht11.h"
#include "tim.h"

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

void DHT11_IO_OUT(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.Pin = GPIO_PIN_1;
	GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
	HAL_GPIO_Init(GPIOA,&GPIO_InitStructure);
}


//复位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;
}

//从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;	    
}

//初始化DHT11的IO口 DQ 同时检测DHT11的存在
//返回1:不存在
//返回0:存在     	 
uint8_t DHT11_Init(void)
{ 
  DHT11_Rst();
	return DHT11_Check();
}

dht11.h

#ifndef __DHT11_H__
#define __DHT11_H__
#include "main.h"
#define DHT11_DQ_OUT_HIGH HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET)
#define DHT11_DQ_OUT_LOW 	HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_RESET)
#define DHT11_DQ_IN	 HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)

//IO方向设置
void DS18B20_IO_IN(void);
void DS18B20_IO_OUT(void);
	
uint8_t DHT11_Init(void);//初始化DHT11
uint8_t DHT11_Read_Data(uint16_t *temp,uint16_t *humi);//读取温湿度
uint8_t DHT11_Read_Byte(void);//读出一个字节
uint8_t DHT11_Read_Bit(void);//读出一个位
uint8_t DHT11_Check(void);//检测是否存在DHT11
void DHT11_Rst(void);//复位DHT11  

#endif

(4)在main.c中声明

/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "dht11.h"
/* USER CODE END Includes */

串口重定向函数

/* USER CODE BEGIN PV */
int fputc(int ch,FILE *f)
{
    HAL_UART_Transmit(&huart1,(uint8_t *) &ch,1,HAL_MAX_DELAY);
    return ch;    
}
int fgetc(FILE *f)
{
    uint8_t ch;
    HAL_UART_Receive(&huart1,(uint8_t *)&ch,1,HAL_MAX_DELAY);
    return ch;
}
/* USER CODE END PV */

变量定义

/* USER CODE BEGIN PD */
uint16_t temperature;
uint16_t humidity;
/* USER CODE END PD */

主函数

  /* USER CODE BEGIN 2 */
  while(DHT11_Init())
  {
    printf("DHT11 Checked failed!!!\r\n");
    HAL_Delay(500);
  }
    printf("DHT11 Checked Sucess!!!\r\n");
  /* USER CODE END 2 */

while中

  while (1)
  {
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
	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(1000);
  }

效果展示

打开Use MicroLIB

以下是基于STM32f103zet6dht11湿度传感器数据采集代码,你可以根据自己的实际情况进行修改和调试: ```c #include "stm32f10x.h" #include "dht11.h" #include "delay.h" int main(void) { uint8_t res; uint8_t humi, temp; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能GPIOB时钟 DHT11_Init(); //初始化DHT11 while(1) { res = DHT11_Read_Data(&humi, &temp); //读取湿度数据 if(res == 0) { //读取成功 printf("Temperature: %d.%d *C, Humidity: %d.%d %%\r\n", temp/10, temp%10, humi/10, humi%10); } else { //读取失败 printf("Read error!\r\n"); } Delay_Ms(2000); //延时2s } } ``` 其中,`dht11.h`和`delay.h`是需要自己编写的头文件,可以参考下面的示例代码: ```c #ifndef __DHT11_H #define __DHT11_H #include "stm32f10x.h" #define DHT11_PIN GPIO_Pin_0 #define DHT11_GPIO GPIOB #define DHT11_RCC RCC_APB2Periph_GPIOB void DHT11_Init(void); uint8_t DHT11_Read_Byte(void); uint8_t DHT11_Read_Data(uint8_t *humi, uint8_t *temp); #endif ``` ```c #ifndef __DELAY_H #define __DELAY_H #include "stm32f10x.h" void Delay_Init(void); void Delay_Ms(uint16_t nms); void Delay_Us(uint32_t nus); #endif ``` 以下是`dht11.c`和`delay.c`的代码示例,你可以根据自己的需求进行修改和完善: ```c #include "dht11.h" #include "delay.h" //DHT11初始化 void DHT11_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(DHT11_RCC, ENABLE); //使能GPIOB时钟 GPIO_InitStructure.GPIO_Pin = DHT11_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //输出模式 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //50MHz GPIO_Init(DHT11_GPIO, &GPIO_InitStructure); //初始化GPIO } //DHT11读取一个字节 uint8_t DHT11_Read_Byte(void) { uint8_t i, byte = 0; for(i=0; i<8; i++) { while(!GPIO_ReadInputDataBit(DHT11_GPIO, DHT11_PIN)); //等待高电平 Delay_Us(30); //延时30us if(GPIO_ReadInputDataBit(DHT11_GPIO, DHT11_PIN)) { //如果仍是高电平 byte |= (1<<(7-i)); //写入数据,MSB先传输 while(GPIO_ReadInputDataBit(DHT11_GPIO, DHT11_PIN)); //等待低电平 } } return byte; } //DHT11读取湿度数据 uint8_t DHT11_Read_Data(uint8_t *humi, uint8_t *temp) { uint8_t buf[5], i; GPIO_ResetBits(DHT11_GPIO, DHT11_PIN); //发送起始信号 Delay_Ms(18); GPIO_SetBits(DHT11_GPIO, DHT11_PIN); Delay_Us(30); if(!GPIO_ReadInputDataBit(DHT11_GPIO, DHT11_PIN)) { //等待DHT11响应 while(!GPIO_ReadInputDataBit(DHT11_GPIO, DHT11_PIN)); //等待DHT11响应完成 for(i=0; i<5; i++) { buf[i] = DHT11_Read_Byte(); //读取5个字节的数据 } if((buf[0]+buf[1]+buf[2]+buf[3]) == buf[4]) { //校验和正确 *humi = buf[0]; *temp = buf[2]; return 0; //返回读取成功 } } return 1; //返回读取失败 } ``` ```c #include "delay.h" static uint32_t TimingDelay; //延时初始化 void Delay_Init(void) { SysTick->CTRL = 0x00; SysTick->LOAD = SystemCoreClock / 1000000 - 1; SysTick->VAL = 0x00; SysTick->CTRL = 0x05; } //延时nms void Delay_Ms(uint16_t nms) { TimingDelay = nms; while(TimingDelay != 0); } //延时nus void Delay_Us(uint32_t nus) { uint32_t ticks; ticks = nus * (SystemCoreClock / 1000000); while(ticks--); } //SysTick中断处理函数 void SysTick_Handler(void) { if(TimingDelay != 0x00) { TimingDelay--; } } ```
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值