STM32小项目之dht11在oled上显示温湿度

前言:

实现一个简单的功能,最终多个功能合起来,就是一个大项目,也叫模块化编程;本篇文章不在讲述oled的用法和代码,因为代码太多了,粘不过来,需要的可以去看我另一篇文章专门讲解oled的。

本文牵扯到的东西

IIC驱动(原理):

https://blog.csdn.net/m0_58832575/article/details/124003619?spm=1001.2014.3001.5501

OLED原理:

https://blog.csdn.net/m0_58832575/article/details/124005237?spm=1001.2014.3001.5501

OLED显示驱动:

https://blog.csdn.net/m0_58832575/article/details/124151411?spm=1001.2014.3001.5501

功能实现:

在oled上显示温湿度

DHT11温湿度传感器模块

 电路连接

dht11三个引脚:Vcc,OUT,GND:

OUT连接GPIOD_Pin_6;

OLED连接:Vcc,GND,SDA,SCL(IIC驱动)

OLED_SCL连接GPIOF_Pin_15;

OLED_SDA连接GPIO_Pin_14;

源码

main.c

#include "stm32f10x.h"                         
#include "oled.h"                  // Device header
#include "Delay.h"                  // Device header
#include "dht11.h"                  // Device header

int main()
{
	DHT11_Data_TypeDef DHT11_Data;

	OLED_Init();
	Delay_ms(200);
	DHT11_Init();
	while(1)
	{
		while( ! DHT11_Read_TempAndHumidity(&DHT11_Data) == SUCCESS);//读取温湿度,并且校验读取的示数是否准确
		OLED_ShowChinese(1,8,0,16);
		OLED_ShowChinese(18,8,1,16);
		OLED_ShowChar(35,8,':',16);
		OLED_ShowNum(44,8,DHT11_Data.temp_int,2,16);
		OLED_ShowChar(61,8,'.',16);
		OLED_ShowNum(70,8,DHT11_Data.temp_deci,2,16);
		
		OLED_ShowChinese(1,30,2,16);
		OLED_ShowChinese(18,30,3,16);
		OLED_ShowChar(35,30,':',16);
		OLED_ShowNum(44,30,DHT11_Data.humi_int,2,16);
		OLED_ShowChar(61,30,'.',16);
		OLED_ShowNum(70,30,DHT11_Data.humi_int,2,16);
		OLED_Refresh();
	}
}

dht11.c

#include "bsp_dht11.h"
#include "Delay.h" 


/* DHT11延时函数使用DWT外设实现,因为SysTick的延时精度被设置为了1ms,不能提供us级别的延时 */

#define DHT11_DELAY_US(us)  Delay_us(us)
#define DHT11_DELAY_MS(ms)  Delay_ms(ms)


static void                           DHT11_GPIO_Config                       ( void );
static void                           DHT11_Mode_IPU                          ( void );
static void                           DHT11_Mode_Out_PP                       ( void );
static uint8_t                        DHT11_ReadByte                          ( void );



 /**
  * @brief  DHT11 初始化函数
  * @param  无
  * @retval 无
  */
void DHT11_Init ( void )
{
	DHT11_GPIO_Config ();
	
	macDHT11_Dout_1;               // 拉高GPIOB10
}


/*
 * 函数名:DHT11_GPIO_Config
 * 描述  :配置DHT11用到的I/O口
 * 输入  :无
 * 输出  :无
 */
static void DHT11_GPIO_Config ( void )
{		
	/*定义一个GPIO_InitTypeDef类型的结构体*/
	GPIO_InitTypeDef GPIO_InitStructure;

	
	/*开启macDHT11_Dout_GPIO_PORT的外设时钟*/
  macDHT11_Dout_SCK_APBxClock_FUN ( macDHT11_Dout_GPIO_CLK, ENABLE );	

	/*选择要控制的macDHT11_Dout_GPIO_PORT引脚*/															   
  	GPIO_InitStructure.GPIO_Pin = macDHT11_Dout_GPIO_PIN;	

	/*设置引脚模式为通用推挽输出*/
  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   

	/*设置引脚速率为50MHz */   
  	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 

	/*调用库函数,初始化macDHT11_Dout_GPIO_PORT*/
  	GPIO_Init ( macDHT11_Dout_GPIO_PORT, &GPIO_InitStructure );		  
	
}


/*
 * 函数名:DHT11_Mode_IPU
 * 描述  :使DHT11-DATA引脚变为上拉输入模式
 * 输入  :无
 * 输出  :无
 */
static void DHT11_Mode_IPU(void)
{
 	  GPIO_InitTypeDef GPIO_InitStructure;

	  	/*选择要控制的macDHT11_Dout_GPIO_PORT引脚*/	
	  GPIO_InitStructure.GPIO_Pin = macDHT11_Dout_GPIO_PIN;

	   /*设置引脚模式为浮空输入模式*/ 
	  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ; 

	  /*调用库函数,初始化macDHT11_Dout_GPIO_PORT*/
	  GPIO_Init(macDHT11_Dout_GPIO_PORT, &GPIO_InitStructure);	 
	
}


/*
 * 函数名:DHT11_Mode_Out_PP
 * 描述  :使DHT11-DATA引脚变为推挽输出模式
 * 输入  :无
 * 输出  :无
 */
static void DHT11_Mode_Out_PP(void)
{
 	GPIO_InitTypeDef GPIO_InitStructure;

	 	/*选择要控制的macDHT11_Dout_GPIO_PORT引脚*/															   
  	GPIO_InitStructure.GPIO_Pin = macDHT11_Dout_GPIO_PIN;	

	/*设置引脚模式为通用推挽输出*/
  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   

	/*设置引脚速率为50MHz */   
  	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

	/*调用库函数,初始化macDHT11_Dout_GPIO_PORT*/
  	GPIO_Init(macDHT11_Dout_GPIO_PORT, &GPIO_InitStructure);	 	 
	
}


/* 
 * 从DHT11读取一个字节,MSB先行
 */
static uint8_t DHT11_ReadByte ( void )
{
	uint8_t i, temp=0;
	

	for(i=0;i<8;i++)    
	{	 
		/*每bit以50us低电平标置开始,轮询直到从机发出 的50us 低电平 结束*/  
		while(macDHT11_Dout_IN()==Bit_RESET);

		/*DHT11 以26~28us的高电平表示“0”,以70us高电平表示“1”,
		 *通过检测 x us后的电平即可区别这两个状 ,x 即下面的延时 
		 */
		DHT11_DELAY_US(40); //延时x us 这个延时需要大于数据0持续的时间即可	   	  

		if(macDHT11_Dout_IN()==Bit_SET)/* x us后仍为高电平表示数据“1” */
		{
			/* 等待数据1的高电平结束 */
			while(macDHT11_Dout_IN()==Bit_SET);

			temp|=(uint8_t)(0x01<<(7-i));  //把第7-i位置1,MSB先行 
		}
		else	 // x us后为低电平表示数据“0”
		{			   
			temp&=(uint8_t)~(0x01<<(7-i)); //把第7-i位置0,MSB先行
		}
	}
	
	return temp;
	
}


/*
 * 一次完整的数据传输为40bit,高位先出
 * 8bit 湿度整数 + 8bit 湿度小数 + 8bit 温度整数 + 8bit 温度小数 + 8bit 校验和 
 */
uint8_t DHT11_Read_TempAndHumidity(DHT11_Data_TypeDef *DHT11_Data)
{  
	/*输出模式*/
	DHT11_Mode_Out_PP();
	/*主机拉低*/
	macDHT11_Dout_0;
	/*延时18ms*/
	DHT11_DELAY_MS(18);

	/*总线拉高 主机延时30us*/
	macDHT11_Dout_1; 

	DHT11_DELAY_US(30);   //延时30us

	/*主机设为输入 判断从机响应信号*/ 
	DHT11_Mode_IPU();

	/*判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行*/   
	if(macDHT11_Dout_IN()==Bit_RESET)     
	{
		/*轮询直到从机发出 的80us 低电平 响应信号结束*/  
		while(macDHT11_Dout_IN()==Bit_RESET);

		/*轮询直到从机发出的 80us 高电平 标置信号结束*/
		while(macDHT11_Dout_IN()==Bit_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();
		/*主机拉高*/
		macDHT11_Dout_1;

		/*检查读取的数据是否正确*/
		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;
	
}

	  


/*************************************END OF FILE******************************/

dht11.h

#ifndef __DHT11_H
#define	__DHT11_H


#include "stm32f10x.h"

/************************** DHT11 数据类型定义********************************/
typedef struct
{
	uint8_t  humi_int;		//湿度的整数部分
	uint8_t  humi_deci;	 	//湿度的小数部分
	uint8_t  temp_int;	 	//温度的整数部分
	uint8_t  temp_deci;	 	//温度的小数部分
	uint8_t  check_sum;	 	//校验和
		                 
} DHT11_Data_TypeDef;


/************************** DHT11 连接引脚定义********************************/
//#define      macDHT11_Dout_SCK_APBxClock_FUN              RCC_APB2PeriphClockCmd
//#define      macDHT11_Dout_GPIO_CLK                       RCC_APB2Periph_GPIOB

//#define      macDHT11_Dout_GPIO_PORT                      GPIOB
//#define      macDHT11_Dout_GPIO_PIN                       GPIO_Pin_10


#define      macDHT11_Dout_SCK_APBxClock_FUN              RCC_APB2PeriphClockCmd
#define      macDHT11_Dout_GPIO_CLK                       RCC_APB2Periph_GPIOD

#define      macDHT11_Dout_GPIO_PORT                      GPIOD
#define      macDHT11_Dout_GPIO_PIN                       GPIO_Pin_6



/************************** DHT11 函数宏定义********************************/
#define macDHT11_Dout_0	   GPIO_ResetBits ( macDHT11_Dout_GPIO_PORT, macDHT11_Dout_GPIO_PIN ) 
#define macDHT11_Dout_1	   GPIO_SetBits ( macDHT11_Dout_GPIO_PORT, macDHT11_Dout_GPIO_PIN ) 

#define macDHT11_Dout_IN() GPIO_ReadInputDataBit ( macDHT11_Dout_GPIO_PORT, macDHT11_Dout_GPIO_PIN ) 



/************************** DHT11 函数声明 ********************************/
void                     DHT11_Init                      ( void );
uint8_t                  DHT11_Read_TempAndHumidity      ( DHT11_Data_TypeDef * DHT11_Data );

;

#endif /* __DHT11_H */







物联沃分享整理
物联沃-IOTWORD物联网 » STM32小项目之dht11在oled上显示温湿度

发表评论