基于stm32的温湿度检测案例(一)

系列文章目录

一、基于stm32的温度检测案例(一)

文章目录

目录

系列文章目录

一、基于stm32的温度检测案例(一)

文章目录

前言

一、实验器材简介

1.1、基于STM32F042F6P6的最小单片机系统

1.2、串口通信工具CH340G(USB转TTL)​编辑

1.3、仿真器(ST-LINK V2)

二、检测STM32F042F6P6功能是否正常

2.1、程序验证

 2.2、上电验证

三、代码演示

3.1、时钟树

3.2、Systick配置(Cortex--M0)

3.3、GPIO配置

3.2.1、方法功能测试

3.3、串口调试

3.3.1、串口配置

四、DHT11温湿度检测模块

4.1、引脚与接口

4.2、内部结构

4.3、根据时序写代码

4.2.1、时钟、端口、引脚、高低电平的配置

4.2.2、通讯过程

前言

使用基于stm32f042F6P6的最小单片机系统通过单总线与DHT11温湿度检测传感器通信,实现对当前环境下的温湿度检测。使用串口通信将DHT11模块检测到的数据在PC上显示。

一、实验器材简介

1.1、基于STM32F042F6P6的最小单片机系统

1.2、串口通信工具CH340G(USB转TTL)

1.3、仿真器(ST-LINK V2)

二、检测STM32F042F6P6功能是否正常

2.1、程序验证

通过观看原理图发现板子上有两个灯,一个电源指示灯与一个接在PB1引脚上的led。编写代码驱动接在PB1上的 LED,检查LED是否正常工作从而推论硬件是否有问题(量产的板子一般"冒得问题”)。

1、二极管工作原理:从标有三角那一端(P),流向标一横那一端(N)。实物:从标有“+”号那一端流向标有“-”号那一端。正向导通(P->N),反向截止(N->p)。

2、拉电流”,是指驱动LED负载的电流方向为  从电路输出端流向LED负载.  单片机给管脚高电平(推),LED熄灭
3、灌电流”是指驱动LED负载的电流方向为    从LED负载流向电路输出端。   单片机给管脚低电平 (挽),LED点亮

4、推挽输出(英语:Push–pull output)是一种使用一对选择性地从相连负载灌电流或者拉电流的器件的电路。它常常使用一对参数相同的功率三极管或MOSFET管,以推挽方式存在于电路中。

5、补充:推挽电路使用两个参数相同的三极管或MOSFET,以推挽方式存在于电路中。电路工作时,两只对称的开关管每次只有一个导通,所以导通损耗小、效率高。输出既可以向负载灌电流,也可以从负载抽取电流。推拉式输出级既提高电路的负载能力,又提高开关速度。

6、I/o口默认输出为高电平状态。

 2.2、上电验证

用ST_LINK V2连接板子与电脑,通过电脑的USB口给板子供电,查看板子上的电源指示灯是否正常点亮。(电脑的usb口输出5v左右的电压,不可作为驱动高于5v的板子的电源,会烧电脑usb口甚至电脑主板)。

三、代码演示

3.1、时钟树

3.2、Systick配置(Cortex--M0)

#include "public.h"
	//    us延时倍乘数			
static st_u8  fac_us=0;	

	//    ms延时倍乘数
static st_u16 fac_ms=0;						
/*********************************************************************************
                                 初始化延迟函数
SYSCLK:系统时钟频率
*********************************************************************************/
void SysTick_Init(st_u8 SYSCLK)
{
	//   SYSTICK的时钟固定为AHB时钟的1/8     6M
	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); 
	fac_us=SYSCLK/8;					
	fac_ms=(st_u16)fac_us*1000;		// 6000us  		   
}								    


		
/*********************************************************************************
                              延时nus
                              nus为要延时的us数.
*********************************************************************************/
void delay_us(st_u32 nus)
{		
	st_u32 temp;	    	 
	SysTick->LOAD=nus*fac_us; 					      //    时间加载	  		 
	SysTick->VAL=0x00;        					      //    清空计数器
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;	//    开始倒数	  
	do
	{
		temp=SysTick->CTRL;
	}while((temp&0x01)&&!(temp&(1<<16)));		  //  等待时间到达   
	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;	//  关闭计数器
	SysTick->VAL =0X00;      					        //  清空计数器	 
}


/*********************************************************************************
                   延时nms
                 鈔ms的范围SysTick->LOAD为24位寄存器,所以,最大延时为:nms<=0xffffff*8*1000/SYSCLK
                 SYSCLK单位为Hz,nms单位为ms
                     对72M条件下,nms<=1864 
                      对24M条件下,nms<=5592
*********************************************************************************/
void delay_ms(st_u16 nms)
{	 		  	  
	st_u32 temp;		   
	SysTick->LOAD=(st_u32)nms*fac_ms;				   //  时间加载(SysTick->LOAD为24bit)
	SysTick->VAL =0x00;							           //  清空计数器
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;	 //  开始倒数  
	do
	{
		temp=SysTick->CTRL;
	}while((temp&0x01)&&!(temp&(1<<16)));		  //  等待时间到达   
	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;	//  关闭计数器
	SysTick->VAL =0X00;       				      	//  清空计数器	  	    
} 


3.3、GPIO配置

/*********************************************GPIO配置部分*********************************************/
/*********************************************
                  GPIO输出封装
1、时钟 RCC_AHBPeriph_x
2、端口 GPIOx
3、引脚 GPIO_PIN
4、输出模式  GPIOMode
5、输出类型  GPIOOType
5、指定所选引脚的操作上拉/下拉  GPIOPuPd
*********************************************/
void GPIOInit_Dout(st_u32 RCC_AHBPeriph_x,GPIO_TypeDef* GPIOx,st_u32 GPIO_PIN,GPIOMode_TypeDef GPIOMode,
	GPIOOType_TypeDef GPIOOType,GPIOPuPd_TypeDef GPIOPuPd)
{
	 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_x, ENABLE);      //  使能端口时钟
	
	GPIO_InitTypeDef GPIO_InitStructure;
 
  /* Configure PC10 and PC11 in output pushpull mode */
  GPIO_InitStructure.GPIO_Pin = GPIO_PIN;              //  引脚
  GPIO_InitStructure.GPIO_Mode = GPIOMode;             //  输入/输出模式
  GPIO_InitStructure.GPIO_OType = GPIOOType;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIOPuPd;            	//  上拉 or 下拉
  GPIO_Init(GPIOx, &GPIO_InitStructure);
}

/*********************************************
                  GPIO输入封装
1、时钟  RCC_AHBPeriph_x
2、端口  GPIOx
3、引脚  GPIO_PIN
4、输入模式  GPIOMode
5、指定所选引脚的操作上拉/下拉  GPIOPuPd
*********************************************/
void GPIOInit_Din(st_u32 RCC_AHBPeriph_x,GPIO_TypeDef* GPIOx,st_u32 GPIO_PIN,GPIOMode_TypeDef GPIOMode,GPIOPuPd_TypeDef GPIOPuPd)
{
	GPIO_InitTypeDef GPIO_InitStructure;
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_x, ENABLE);     //  使能时钟
  /* Configure PC10 and PC11 in output pushpull mode */
  GPIO_InitStructure.GPIO_Pin = GPIO_PIN;              //  引脚
  GPIO_InitStructure.GPIO_Mode = GPIOMode;             //  输入/输出模式
  //GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIOPuPd;            	//  上拉 or 下拉
  GPIO_Init(GPIOx, &GPIO_InitStructure);
}

3.2.1、方法功能测试

通过一个LED的来验证,函数功能是否正常

//  LED初始化
void LED_Init(void)
{
	// 时钟  端口  引脚  输出模式   推挽输出类型  上拉/下拉
  GPIOInit_Dout(LED_RCC,LED_PORT,LED_PIN,GPIO_Mode_OUT,GPIO_OType_PP,GPIO_PuPd_NOPULL);
	GPIO_SetBits(LED_PORT,LED_PIN);    //  初始化后默认PB1输出高电平
}
//  测试LED  高低电频每隔500ms交替一次  低电平期间LED点亮  高电平期间LED熄灭
void LED_Test(void)
{
       delay_ms(500);
		LED_L;
		delay_ms(500);
		LED_H;
}

.h文件中定义

#ifndef _LED_H
#define _LED_H
/*********************************************
     时钟  端口  引脚宏定义
*********************************************/
#define LED_RCC   RCC_AHBPeriph_GPIOB
#define LED_PORT  GPIOB 
#define LED_PIN   GPIO_Pin_1

#define LED_H    GPIO_SetBits(LED_PORT,LED_PIN)    //  高电平
#define LED_L    GPIO_ResetBits(LED_PORT,LED_PIN)  //  低电平

extern void LED_Init(void);
extern void  LED_Test(void);
#endif 
 

主函数

#define ROOT
#include "public.h"

int main(void)
{
//  初始化systick
	SysTick_Init(48);
	LED_Init();
	//Uart2_Init1();
	while(1)
	{
    LED_Test();
		//Uart2_Test();
	}
}

void SystemInit(void)
{

}

3.3、串口调试

外接5电源到板子,串口调试工具与板子供地共GND,串口调试工具的RX、TX与板子的RX、TX交叉相接能正常收发数据。 

3.3.1、串口配置

库函数配置串口


/*********************************************  
中断优先级配置
cortex-m0 智能配置 0~3
********************************************/
void NVIC_Config(st_u8 IRQn,st_u8 IRQChannelPriority)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  NVIC_InitStructure.NVIC_IRQChannel = IRQn;
	
	NVIC_InitStructure.NVIC_IRQChannelPriority = IRQChannelPriority;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
}

/*********************************************串口配置*********************************************/
/**********
STM32共有两种串口通信接口,分别是:UART通用异步收发器,USART:通用同步异步收发器
单工:数据传输只支持数据在一个方向上传输   一个通道
半双工:允许数据在两个方向上传输,但是,在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信;  两个通道
全双工:允许数据同时在两个方向上传输,因此,全双工通信是两个单工通信方式的结合,它要求发送设备和接收设备都有独立的接收和发送能力。  两个通道

同步通信与异步通信
同步通信指的是带有时钟同步信号,比如:SPI通信、IIC通信;
异步通信指的是不带时钟同步信号比如:UART(通用异步收发器),单总线
**********/
void USART_Config(USART_TypeDef* USARTx,st_u32 Baudrate)
{
	if(USARTx==USART1)
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	else
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
	
	USART_InitTypeDef USART_InitStructure;
  USART_InitStructure.USART_BaudRate = 9600;
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
  USART_InitStructure.USART_Parity = USART_Parity_No;
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  USART_Init(USARTx, &USART_InitStructure);
	
  USART_ITConfig(USARTx, USART_IT_RXNE, ENABLE);
  USART_Cmd(USARTx, ENABLE);
  }

/*********************************************
	          串口2通信初始化1
	*********************************************/
void Uart2_Init1(void)
{
  NVIC_Config(USART2_IRQn,0x00);
	//  TX        时钟                端口   引脚      复用模式     推挽输出       上拉/下拉
	//  推(拉电流) 驱动负载的电流方向为  从电路输出端流向负载
	//  挽(灌电流) 驱动负载的电流方向为  从负载流向电路输出端 
	GPIOInit_Dout(RCC_AHBPeriph_GPIOA,GPIOA,GPIO_Pin_2|GPIO_Pin_3,GPIO_Mode_AF,GPIO_OType_PP ,GPIO_PuPd_NOPULL);
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_1);     // USART2_Tx
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_1);     // USART2_Rx
	USART_Config(USART2,9600);
}

中断服务函数

#include "public.h"

//  加入以下代码,支持printf函数,而不需要选择use MicroLIB	
#if 1
//#pragma import(__use_no_semihosting) 
#pragma import(__use_no_semihosting_swi)

struct  __FILE {st_32 handle;};   //  标准库需要的支持函数

FILE  _stdout;

void sys_exit(st_32 x){             // 定义_sys_exit()以避免使用半主机模式 
   x=x;
}
//  发送数据
//  重定向 c 库函数 printf 到串口,重定向后可使用 printf 函数
int fputc(int ch,FILE*p)
{
	//#if 1
  USART_SendData(USART2,(st_u8)ch);
	// USART_FLAG_TXE  数据寄存器为空的标记
	while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);
	return ch;
	//#else
	//while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
 // USART1->TDR = (st_u8) ch;      
	//return ch;
	//#endif

}

//  接收数据
//  重定向 c 库函数 scanf 到串口,重写向后可使用 scanf、getchar 等函数
 int fgetc(FILE *f)
 {
 // 等待串口输入数据 
 while (USART_GetFlagStatus(USART2, USART_IT_RXNE) == RESET);
 return (st_32)USART_ReceiveData(USART2);
 }
 
 //  发送字符
void Usart_SendByte( USART_TypeDef * pUSARTx,st_u8 ch)
{
 
USART_SendData(pUSARTx,ch);
 while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
}

//  发送字符串
void Usart_SendString( USART_TypeDef * pUSARTx, char *str)
{
  st_u32 k=0;
  do {
   Usart_SendByte( pUSARTx, *(str + k));
   k++;
} while (*(str + k)!='\0');
 while (USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET) { /* 等待发送完成 */
   }
 }
#endif
 
 /*********************************************第一种方式*********************************************/
 #if USART2_RX_EN
  //USART2_RX_BUF[USART2_REC_LEN];
 // USART2_RX_STA=0;

 
 void USART2_IRQHandler(void)
 {
	INTX_DISABLE();  //  中断屏蔽
  st_u8 r;
	if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)  //接收中断
	{
		r =USART_ReceiveData(USART2);//(USART1->DR);	//读取接收到的数据
		if((USART2_RX_STA&0x8000)==0)//接收未完成
		{
			if(USART2_RX_STA&0x4000)//接收到了0x0d
			{
				if(r!=0x0a)USART2_RX_STA=0;//接收错误,重新开始
				else USART2_RX_STA|=0x8000;	//接收完成了 
			}
			else //还没收到0X0D
			{	
				if(r==0x0d)USART2_RX_STA|=0x4000;
				else
				{
					USART2_RX_BUF[USART2_RX_STA&0X3FFF]=r;
					USART2_RX_STA++;
					if(USART2_RX_STA>(USART2_REC_LEN-1))USART2_RX_STA=0;//接收数据错误,重新开始接收	  
				}		 
			}
		}   		 
	} 
	INTX_ENABLE();  //  放开中断屏蔽
 }
 #endif

 

四、DHT11温湿度检测模块

4.1、引脚与接口

  • VCC:DTH11的供电电压为 3-5.5V。传感器上电后,要等待 1s 以越过不稳定状态在此期间无需发送任何指令。
  • DATA:mcu与DHT11单总线通信引脚。一次通讯时间4ms左右,数据分小数部分和整数部分.
  • GND:接地。

DTH11工作流程:

  • MCU发送一次开始信号后,DHT11从低功耗模式转换到高速模式,等待主机开始信号结束后,
  • DHT11发送响应信号,送出40bit的数据,并触发一次信号采集, 用户可选择读取部分数据.
  • 从模式下,DHT11接收到开始信号触发一次温湿度采集, 如果没有接收到主机发送开始信号,DHT11不会主动进行温湿度采集.采集数据后转换到低速模式。

4.2、内部结构

传感器包括一个电阻式感湿元件和一个NTC测 温元件,并与一个高性能8位单片机相连接。

4.3、根据时序写代码

4.2.1、时钟、端口、引脚、高低电平的配置

#ifndef  _DHT_11
#define  _DHT_11 
//  时钟  端口  引脚   
#define DHT11_RCC RCC_AHBPeriph_GPIOA
#define DHT11_PORT GPIOA
#define DHT11_PIN GPIO_Pin_7


#define DHT11_H    GPIO_SetBits(DHT11_PORT,DHT11_PIN)    //  高电平
#define DHT11_L    GPIO_ResetBits(DHT11_PORT,DHT11_PIN)  //  低电平



#endif
int8_t GPIOSet(GPIO_TypeDef* GPIOx, uint16_t GPIOPin, uint16_t GPIOMode)
{
	if(GPIOMode == 0)
	{
		GPIO_ResetBits(GPIOx,GPIOPin);
	}
	else
	{
		GPIO_SetBits(GPIOx,GPIOPin);
	}
	return GPIOMode;
}

//  uint8_t GPIOGet(GPIO_TypeDef* GPIOx, uint16_t GPIOPin)
uint8_t GPIOGet(GPIO_TypeDef* GPIOx, uint16_t GPIOPin)
{
	return (GPIO_ReadInputDataBit(GPIOx, GPIOPin));
}
//  输出配置
void DHT11_GPIO_Out(void)
{
	//  时钟   端口  引脚  输出模式  推挽输出   不上拉/不下拉
  GPIOInit_Dout(DHT11_RCC,DHT11_PORT,DHT11_PIN,GPIO_Mode_OUT,GPIO_OType_PP,GPIO_PuPd_NOPULL);
}

//  输入配置
void DHT11_GPIO_In(void)
{
	
	//   时钟  端口  引脚  输入模式   上拉输入
  GPIOInit_Din(DHT11_RCC,DHT11_PORT,DHT11_PIN,GPIO_Mode_IN,GPIO_PuPd_UP);
}

4.2.2、通讯过程

三种写时序的方式


//  输出配置
void DHT11_GPIO_Out(void)
{
	//  时钟   端口  引脚  输出模式  推挽输出   不上拉/不下拉
  GPIOInit_Dout(DHT11_RCC,DHT11_PORT,DHT11_PIN,GPIO_Mode_OUT,GPIO_OType_PP,GPIO_PuPd_NOPULL);
}

//  输入配置
void DHT11_GPIO_In(void)
{
	 //  
	 // GPIOInit_Din(DHT11_RCC,DHT11_PORT,DHT11_PIN,GPIO_Mode_IN,GPIO_PuPd_DOWN);
	
	  //GPIOInit_Din(DHT11_RCC,DHT11_PORT,DHT11_PIN,GPIO_Mode_IN,GPIO_PuPd_NOPULL);
	
	 //   时钟  端口  引脚  输入模式   上拉输入    经过测试此处必须设置为上拉才能上数据
    GPIOInit_Din(DHT11_RCC,DHT11_PORT,DHT11_PIN,GPIO_Mode_IN,GPIO_PuPd_UP);
	
}

void DHT11_Init(void)
{
  DHT11_GPIO_Out();
	DHT11_H;
	
}

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

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

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

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

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

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

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

	delay_ms(30);   //延时30us

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

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

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

		/*检查读取的数据是否正确*/
		// 一次完整的数据传输为40bit,高位先出。数据格式:8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据+8bit校验和
		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;
	
}
#elif select1
//从DHT11读取一个位
//返回值:1/0
st_u8 DHT11_Read_Bit(void) 			 
{
 	st_u8 retry=0;
	while(DHT11_Input==0 &&retry<100)//等待变为低电平 12-14us 开始
	{
		retry++;
		delay_us(1);
	}
	retry=0;
	while(!DHT11_Input&&retry<100)//等待变高电平	 26-28us表示0,116-118us表示1
	{
		retry++;
		delay_us(1);
	}
	delay_us(40);//等待40us
	if(DHT11_Input)return 1;
	else return 0;		   
}

//从DHT11读取一个字节
//返回值:读到的数据
st_u8 DHT11_Read_Byte(void)    
{        
    st_u8 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,读取失败
st_u8 DHT11_Read_Data(st_u8 *temp,st_u8 *humi)    
{        
 	st_u8 buf[5];
	st_u8 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];
			*temp=buf[2];
		}
		
	}else return 1;
	return 0;	    
}
#else
// 转译采集DHT11发送给IO口的电平信号(8位)
// 从DHT11读取一位(8字节)信号
st_u8 DHT11_Read_Byte(void)
{
   st_u8 ReadData = 0; // 存放8bit数据,即8个单次读取的1bit数据的组合
	 st_u8 temp;         // 临时存放信号电平(0或1)
	 st_u8 retry =0;     //  retry用于防止卡死
	 st_u8 i;
	for(i=0;i<8;i++)      // 一次温湿度信号读取八位
	{
	    while(DHT11_Input==0&&retry<100)
			{
			  // 等待直到DHT11输出高电平:
				// 当PA7=1,上升沿,表示开始接受数据,可以判断0 or 1,跳出循环,执行后续判断(若PA7=0,将一直循环等待)
			   delay_us(1);
				 retry++;
			};
			 retry=0;
			delay_us(40);
			//  根据时序图,DHT传回高电平信号维持26us~28us表示0,	维持70us表示1
		  //  延时30us后,如果IO读取到仍是高电平,说明采集到1;如果IO读取到低电平,说明采集到0
			//  读取电平信号暂存temp内,随后会压入ReadData中
     while(DHT11_Input==1&&retry<100)
		 {
			  delay_us(1);
				 retry++;
		 };
		 retry=0;
		 ReadData <<=1;  //  ReadData内信号先全部左移一位,空出末尾位置
		 ReadData|=temp;
	}
	return ReadData;
}

st_u8 DHT_Read(void)
{
	 st_u8 retry=0;
	 st_u8 i;
		
	 DHT11_GPIO_Out();    //IO设置为输出模式。在传输的最开始,MCU要向DHT11发送信号
	 DHT11_L;   //IO->DHT11:先拉低电平18ms(应时序要求)
	 delay_us(18);
	DHT11_H;   //IO->DHT11:随后拉高电平20us
	 delay_us(20);
	
	//MCU通过IO向DHT11发送请求完毕。接下来DHT11向IO发送响应,IO转为输入模式。在这之后就开始信号的转译读取。
	DHT11_GPIO_In();
	delay_us(20);
	if(DHT11_Input==0) //DHT11发回低电平响应(读取到低电平,说明DHT11有响应)
	{
		//接下来,DHT11拉低电平一段时间后拉高电平一段时间
		while(DHT11_Input==0 && retry<100)  
		{
		   delay_us(1);
			 retry++;
		}
		 retry=0;
		while(DHT11_Input==1 && retry<100) 
		{
		   delay_us(1);
			 retry++;
		}
		retry=0;
		
		//一共传输40位,一次DHT_Read_Byte返回8位,共读取5次。存储在Data[]中。(Data[]定义为全局)
		for(i=0; i<5; i++)
		{
			 Data[i] = DHT11_Read_Byte();  //每次读取一字节(8位)
		}
		delay_us(50);
		//说明:Data[0]湿度, Data[2]温度。Data[1]和Data[3]分别为0和2的小数位。Data[4]用于校验。
	}
	 st_u32 sum=Data[0]+Data[1]+Data[2]+Data[3];  //校验
	 if((sum)==Data[4])    return 1;  
	   else   return 0;
}
#endif
  • 9
    点赞
  • 125
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
首先应该介绍STM32F411RET6的内部温度传感器: 首先此温度传感器主要用于测量设备所处环境的周围温度。 当没有使用此温度传感器时,传感器将处于断电模式。 主要的性能: •所支持的温度范围:-40℃到125℃ •测量的精度:±1.5℃ 然后是读取芯片内部的温度传感器: ①选择ADC1_IN18作为输入通道。 ②选择一个采样的时间,但必须要大于用户参考手册上所指定的最小采样时间。 ③通过置位ADC_CCR寄存器中的TSVREFE标志位,使得温度传感器从掉电模式唤醒。 ④开始ADC传唤通过置位SWSTART(或者通过外部的触发) ⑤读取ADC数据寄存中的数值 ⑥使用下面的公式来计算温度: Tempereture={(V_SENSE-V25)/Avg_Slope}+25 在这个公式里面: —V25在25℃下的值 —Avg_Slope为给定的温度的斜率 通过查看电气特性手册来获得给定的V25和Avg_Slope的值 注意: 传感器在他能够正确的范围内输出V_SENSE之前,从掉电模式到唤醒有一个起始的时间。同样,ADC的上电也有一个起始的时间,因此为了使这个延时最小化,ADON和TSCREFE标志位可以在同一个时间被置位。 温度传感器的输出电压的改变与温度是呈现出线性关系的。这个线性函数的偏移是依赖于每一个芯片上处理器的不同。 内部温度传感器更加适合与那些用来察觉温度不差异的应用中,而非用于获取绝对的温度值,如果想要获取到精确的温度值,请使用一个外部的温度传感器来代替。 现在是相关的ADC初始化的代码和获取温度代码部分截图: 然后是主函数的读取,并且串口打印出来: 最后是套入用户手册所给出公式计算出的温度的结果: 然后下一步是调试W5500进行网络连接,并把温度数据上传到网络
基于STM32温湿度检测与报警系统的设计温湿度检测与报警系统是一种用于监测环境温湿度并及时报警的设备。基于STM32设计能够提高系统的可靠性和稳定性。 首先,系统需要通过传感器获取环境温度和湿度数据。可以选择市场上常用的温湿度传感器,如DHT11或DHT22。通过STM32的GPIO接口连接传感器,使用相应的引脚进行数据采集。 其次,通过STM32的模数转换器(ADC)将传感器采集到的模拟信号转换为数字信号。可以使用STM32的内置ADC模块,通过编程配置ADC通道和采样频率,实现将模拟信号转换为数字值。 然后,使用STM32的串行通信接口(例如UART)将温湿度数据发送给外部设备,如计算机或显示屏。可以通过编程配置UART串口的波特率和数据格式,实现与外部设备的通信。 最后,设计温湿度报警功能。通过对比获取的温湿度数据与预设的报警阈值,判断是否触发报警。当温度或湿度超过预设的阈值时,STM32将触发报警信号。可以使用STM32的GPIO接口连接蜂鸣器或LED灯,实现报警的声音或灯光提示。 此外,可以进一步完善系统的功能。例如,可以添加数据存储功能,将获取的温湿度数据保存在闪存中,以备后续分析和查询。还可以添加通信模块(如以太网或WiFi模块),实现对温湿度数据的远程监测和控制。 综上所述,基于STM32温湿度检测与报警系统设计包括传感器的选择和连接、ADC的使用、UART的通信配置以及报警功能的实现。该系统能够实时监测环境温湿度,并根据预设的阈值及时报警,具有较高的可靠性和稳定性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

旭日初扬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值