STM32串口显示DHT11温湿度数据,YL-69土壤湿度

用的控制器是STM32F103C8T6,如果你用STMF103的其他芯片来跑这个代码也能跑通,基本配置都是一样的。

先介绍DHT11温湿度数据的采集,有两个文件,一个DHT11.c,还有一个DHT11.h
我的DHT11是三线的,没有一个DATA数据接口,接单片机的PB14引脚。
DHT11.c代码如下

#include "dht11.h"
//	 
#include "delay.h"								  
//

//复位DHT11
void DHT11_Rst(void)	   
{                 
	DHT11_IO_OUT(); 	//SET OUTPUT
    DHT11_DQ_OUT=0; 	//拉低DQ
    delay_ms(20);    	//拉低至少18ms
    DHT11_DQ_OUT=1; 	//DQ=1 
	delay_us(30);     	//主机拉高20~40us
}
//等待DHT11的回应
//返回1:未检测到DHT11的存在
//返回0:存在
u8 DHT11_Check(void) 	   
{   
	u8 retry=0;
	DHT11_IO_IN();//SET INPUT	 
    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
u8 DHT11_Read_Bit(void) 			 
{
 	u8 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读取一个字节
//返回值:读到的数据
u8 DHT11_Read_Byte(void)    
{        
    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,读取失败
u8 DHT11_Read_Data(u8 *temp,u8 *humi)    
{        
 	u8 buf[5];
	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;	    
}
//初始化DHT11的IO口 DQ 同时检测DHT11的存在
//返回1:不存在
//返回0:存在    	 
u8 DHT11_Init(void)
{	 
 	GPIO_InitTypeDef  GPIO_InitStructure;
 	
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	 //使能PB端口时钟
	
 	GPIO_InitStructure.GPIO_Pin = DHT11_PIN;				 //PG11端口配置
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
 	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 	GPIO_Init(DHT11_IO, &GPIO_InitStructure);				 //初始化IO口
 	GPIO_SetBits(DHT11_IO,DHT11_PIN);						 //PG11 输出高
			    
	DHT11_Rst();  //复位DHT11
	return DHT11_Check();//等待DHT11的回应
} 

//DHT11_Read_Data(&temperature,&hum);	
//printf("%d  %d\r\n",temperature,hum);




代码比较简单,每个函数的作用都在上面注释了,看注释即可

DHT11.h如下:

#ifndef __DHT11_H
#define __DHT11_H 
#include "sys.h"   
//	 
									  
//

#define DHT11_IO    GPIOB
#define DHT11_PIN   GPIO_Pin_14
//IO方向设置
#define DHT11_IO_IN()  {DHT11_IO->CRH&=0XF0FFFFFF;DHT11_IO->CRH|=8<<24;}
#define DHT11_IO_OUT() {DHT11_IO->CRH&=0XF0FFFFFF;DHT11_IO->CRH|=3<<24;}
IO操作函数											   
#define	DHT11_DQ_OUT PBout(14) //数据端口	PA0 
#define	DHT11_DQ_IN  PBin(14)  //数据端口	PA0 


u8 DHT11_Init(void);//初始化DHT11
u8 DHT11_Read_Data(u8 *temp,u8 *humi);//读取温湿度
u8 DHT11_Read_Byte(void);//读出一个字节
u8 DHT11_Read_Bit(void);//读出一个位
u8 DHT11_Check(void);//检测是否存在DHT11
void DHT11_Rst(void);//复位DHT11    
#endif


然后就是土壤湿度模块,也是两个代码,我有一篇博客是单独介绍这个模块的,有兴趣可以看一下:STM32的串口打印土壤湿度传感器(YL-69)数据
上面这个是课程设计用的。土壤湿度有两个文件里面的函数比较简单,先是读取ADC的数据,然后将读取出来的数据转换成常见的湿度数据。
adc.c如下

#include "adc.h"
#include "delay.h"

int shidu1;
void Adc_Init(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;
	ADC_InitTypeDef		ADC_InitStruct;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1,ENABLE);
/*PA_1设置为模拟输入*/
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;				 // 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; 		 //模拟输入
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
	GPIO_Init(GPIOA, &GPIO_InitStructure);	

	RCC_ADCCLKConfig(RCC_PCLK2_Div6);//设置ADC分频因子
	
	ADC_DeInit(ADC1);//复位ADC
	
	//初始化ADC参数
	ADC_InitStruct.ADC_ContinuousConvMode=DISABLE;
	ADC_InitStruct.ADC_DataAlign=ADC_DataAlign_Right;
	ADC_InitStruct.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;
	ADC_InitStruct.ADC_Mode=ADC_Mode_Independent;
	ADC_InitStruct.ADC_NbrOfChannel=1;
	ADC_InitStruct.ADC_ScanConvMode=DISABLE;
	
	ADC_Init(ADC1, &ADC_InitStruct);
	
	ADC_Cmd(ADC1,ENABLE);//使能ADC1
	
	ADC_ResetCalibration(ADC1);	//使能复位校准  
	 
	while(ADC_GetResetCalibrationStatus(ADC1));	//等待复位校准结束
	
	ADC_StartCalibration(ADC1);	 //开启AD校准
 
	while(ADC_GetCalibrationStatus(ADC1));	 //等待校准结束
		

}

u16  Get_Adc(u8 ch)  //获取ADC数据
{
	
	ADC_RegularChannelConfig(ADC1,ch,1, ADC_SampleTime_239Cycles5);
	
	ADC_SoftwareStartConvCmd(ADC1,ENABLE);
	
	while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));
	
	return ADC_GetConversionValue(ADC1);
}

u16 Get_Adc_Average(u8 ch,u8 times)  //获取土壤湿度数据并返回给主函数
{
	u32 temp_val=0;
	u8 t;
	for(t=0;t<times;t++)
	{
		temp_val+=Get_Adc(ch);
		delay_ms(1);
	}
	temp_avrg=temp_val/times;
	shidu1=(4092-temp_avrg)/3292*100;
	return shidu1;
}

adc.h如下:

#ifndef __ADC_H
#define __ADC_H	
#include "sys.h"
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK战舰STM32开发板
//ADC 代码	   
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2012/9/7
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
//All rights reserved									  
// 

void Adc_Init(void);
u16  Get_Adc(u8 ch); 
u16 Get_Adc_Average(u8 ch,u8 times);
extern float temp_avrg;
extern int shidu;
 
#endif 


最后就是程序的主函数main.c

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "stdio.h"
#include "dht11.h"
#include "adc.h"

int shidu;

float temp_avrg=0;
u8 buff[30];                //参数显示缓存数组
u8 DHT11_Temp,DHT11_Hum;		//温湿度

int main(void)
{	
	delay_init();	    //延时函数初始化
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
	DHT11_Init();
    Adc_Init();
	uart_init(9600);
while(1)
		{   
            shidu=Get_Adc_Average(1,10);
			DHT11_Read_Data(&DHT11_Temp,&DHT11_Hum);	
            printf("当前温度:%d  当前湿度:%d   土壤湿度:%d\r\n",DHT11_Temp,DHT11_Hum,shidu);
			delay_ms(100);		
		}
	}


目前关于这两个传感器的代码就介绍完了,至于工程里的其他代码,都是STM32官方的库函数,直接调用就行。上面的代码是串口显示空气温湿度,土壤湿度的数据。显示结果如下
在这里插入图片描述

完整工程在这:
串口显示温湿度,土壤湿度
链接:https://pan.baidu.com/s/1VgSWDUvCquRCRD8bmRpndA
提取码:7vsg

这个代码是根据一个串口显示温湿度添加的,原代码只能显示DHT11的温湿度数据,然后我手动加了土壤湿度的
之前只能显示温湿度的工程如下(从其他论坛下载的):
链接:https://pan.baidu.com/s/1Q_f7t5DiAR8t2ZqghbNaZA
提取码:8n50

还有一个只能显示土壤湿度的湿度的工程:

链接:https://pan.baidu.com/s/1v6FBqHxaiMLEHFfaoBBnYQ
提取码:hj5d

其实改来改去就这几行代码,很简单的。

有问题欢迎评论区交流。

  • 22
    点赞
  • 186
    收藏
    觉得还不错? 一键收藏
  • 35
    评论
好的,下面是stm32f103通过usart2采集dht11温湿度数据并发送到串口助手的完整代码示例: ``` #include "stm32f10x.h" #include <stdio.h> // 定义DHT11数据引脚 #define DHT11_DATA_PIN GPIO_Pin_0 #define DHT11_DATA_PORT GPIOA // 定义USART2发送函数 void USART2_SendData(uint8_t data) { while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET); // 等待发送缓冲区为空 USART_SendData(USART2, data); // 发送数据 } // 初始化USART2 void USART2_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO | RCC_APB2Periph_USART1, ENABLE); // 使能USART2时钟和GPIOA时钟 // 配置PA2为USART2的Tx引脚 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // 配置PA3为USART2的Rx引脚 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); // USART2初始化设置 USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate = 9600; // 波特率设置为9600 USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 字长为8位数据格式 USART_InitStructure.USART_StopBits = USART_StopBits_1; // 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(USART2, &USART_InitStructure); // 初始化USART2 USART_Cmd(USART2, ENABLE); // 使能USART2 } // 初始化DHT11 void DHT11_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 使能GPIOA时钟 // 配置DHT11数据引脚为GPIO输出模式 GPIO_InitStructure.GPIO_Pin = DHT11_DATA_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(DHT11_DATA_PORT, &GPIO_InitStructure); GPIO_SetBits(DHT11_DATA_PORT, DHT11_DATA_PIN); // 将DHT11数据引脚输出高电平 } // 从DHT11读取数据 void DHT11_ReadData(uint8_t *temp, uint8_t *humi) { uint8_t buffer[5] = {0}; uint8_t i = 0, j = 0; GPIO_ResetBits(DHT11_DATA_PORT, DHT11_DATA_PIN); // 发送起始信号 delay_ms(18); GPIO_SetBits(DHT11_DATA_PORT, DHT11_DATA_PIN); delay_us(30); GPIO_ResetBits(DHT11_DATA_PORT, DHT11_DATA_PIN); // 接收响应信号 delay_us(40); GPIO_SetBits(DHT11_DATA_PORT, DHT11_DATA_PIN); delay_us(10); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 切换DHT11数据引脚为输入模式 GPIO_Init(DHT11_DATA_PORT, &GPIO_InitStructure); while (GPIO_ReadInputDataBit(DHT11_DATA_PORT, DHT11_DATA_PIN) == SET); // 等待DHT11拉低数据引脚 while (GPIO_ReadInputDataBit(DHT11_DATA_PORT, DHT11_DATA_PIN) == RESET); // 跳过DHT11的低电平响应信号 while (GPIO_ReadInputDataBit(DHT11_DATA_PORT, DHT11_DATA_PIN) == SET); // 接收数据 for (j = 0; j < 5; j++) { for (i = 0; i < 8; i++) { while (GPIO_ReadInputDataBit(DHT11_DATA_PORT, DHT11_DATA_PIN) == RESET); // 跳过每个数据位的低电平 delay_us(40); // 等待数据位的高电平持续时间 if (GPIO_ReadInputDataBit(DHT11_DATA_PORT, DHT11_DATA_PIN) == SET) // 判断高电平持续时间,如果大于等于30us,则该数据位为1,否则为0 { buffer[j] |= (1 << (7 - i)); // 将读取到的数据保存到缓冲区中 } while (GPIO_ReadInputDataBit(DHT11_DATA_PORT, DHT11_DATA_PIN) == SET); // 等待数据位的高电平结束 } } *humi = buffer[0]; // 湿度值 *temp = buffer[2]; // 温度值 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 切换DHT11数据引脚为输出模式 GPIO_Init(DHT11_DATA_PORT, &GPIO_InitStructure); GPIO_SetBits(DHT11_DATA_PORT, DHT11_DATA_PIN); // 将DHT11数据引脚输出高电平 } int main(void) { USART2_Init(); // 初始化USART2 DHT11_Init(); // 初始化DHT11 uint8_t temp, humi; char buffer[50]; while (1) { DHT11_ReadData(&temp, &humi); // 从DHT11读取温湿度数据 sprintf(buffer, "Temperature: %d℃, Humidity: %d%%\r\n", temp, humi); // 将温湿度数据格式化成字符串 for (uint8_t i = 0; i < strlen(buffer); i++) { USART2_SendData(buffer[i]); // 发送温湿度数据串口助手 } delay_ms(1000); // 延时1秒 } } ``` 使用以上代码,您就可以在stm32f103采集dht11温湿度数据并通过usart2发送到串口助手了。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值