基本的什么传感器介绍就不多说了
DTH11工作原理和流程:
DHT11共4个引脚,其中一个不用,所以只用3个,VCC、GND、Data。
DHT11为单总线数据格式,数据输入输出都由Data数据线来完成。
DTH11通讯过程如上图所示,先由主机(也就是STM32)发送开始信号(所以在此之前得先将data数据线设置为推挽输出),开始信号是一段超过18ms的低电平,发送完毕后,主机拉高20-40us(程序里拉高30us即可)。然后将data数据线设置为输入模式,DTH11发送响应信号,响应信号是80us的低电平,之后将数据线拉高(DTH11输出高电平)80us。至此,准备工作已做完,开始传输数据。
一次完整的数据传输为40bit,高位先出。
数据格式:8bit湿度整数数据+8bit湿度小数数据
+8bi温度整数数据+8bit温度小数数据
+8bit校验和
数据传送正确时:校验和数据=“8bit湿度整数数据+8bit湿度小数数据
+8bit温度整数数据+8bit温度小数数据”。
上述过程中存在两次判断过程,第一次是检测DTH11是否有响应信号产生,第二次是数据检验和是否等于剩下的四部分之和,注意程序编写过程中的这个问题。
串口部分使用printf函数打印输出,需要在串口程序中对printf 重定向,否则printf不可用。
DTH11.c程序如下
#include "sys.h"
#include "DTH11.h"
#include "delay.h"
// 主机发送起始信号
void DTH11_start(void)
{
DTH11_IO_OUT(); //PG11设置为推挽输出
DTH11_DQ_OUT=0;
delay_ms(20); //大于18ms的低电平
DTH11_DQ_OUT=1;
delay_us(30); //20~40us的高电平
}
//检测DTH11是否存在
//DTh11响应信号低电平80us,高电平80us
//返回值 1:不存在 0:存在
u8 DTH11_check(void)
{
u8 retry=0;
DTH11_IO_IN();
while(DTH11_DQ_IN && retry<100) //等待变为低电平
{
retry++;
delay_us(1);
}
if(retry>=100) return 1;
else retry=0;
while(!DTH11_DQ_IN && retry<100) //等待变为高电平
{
retry++;
delay_us(1);
}
if(retry>=100) return 1;
return 0;
}
//读取一个位的数据
//返回值 1/0
u8 DTH11_Read_Bite(void)
{
u8 retry;
// DTH11_IO_IN();
while(DTH11_DQ_IN && retry<100) //等待变为低电平
{
retry++;
delay_us(1);
}
retry=0;
while(!DTH11_DQ_IN && retry<100); //等待变为高电平
delay_us(40); //等待40us
if(DTH11_DQ_IN)
return 1;
else return 0;
}
//读取一个字节 高位先传
//返回值 读取到的八位字节数据
u8 DTH11_Read_Byte(void)
{
u8 a,dat=0,rec;
for(a=0;a<8;a++)
{
rec=DTH11_Read_Bite();
dat |= rec;
dat=dat<<1;
}
return dat;
}
//读取一次数据
//返回值 1:错误 0:正常
u8 DTH11_Raed_data( u8 *temp, u8 *humi)
{
u8 ReturnBack;
u8 i;
u8 buf[5];
DTH11_start();
ReturnBack=DTH11_check();
if(!ReturnBack)
{
for(i=0;i<5;i++)
{
buf
=DTH11_Read_Byte();
}
if(buf[4]==buf[0]+buf[1]+buf[2]+buf[3])
{
*humi=buf[0];
*temp=buf[2];
}
}
else return 1;
return 0;
}
//初始化DTH11 并检查DTH11是否存在
//返回值 0:存在 1:存在
u8 DTH11_Init(void)
{
RCC->APB2ENR |=1<<8;
GPIOG->CRH &= 0xffff0fff;
GPIOG->CRH |= 0x00003000;
GPIOG->ODR |=1<<11; //输出1
DTH11_start();
return DTH11_check();
}
上述程序中
while(DTH11_DQ_IN && retry<100)
这一句中要注意&&的优先级是低于 < 的,一开始忽略了这一点,怎么看都不对,在此为我不扎实的语法基础默哀。
DTH11_IO_OUT() 和 DTH11_IO_IN()这两个函数放到了DTH11.h文件中(因为很简单,不用单独写一个函数,宏定义一下就可以)
DTH11.h如下
#ifndef __DTH11_H
#define __DTH11_H
#include "sys.h"
#define DTH11_DQ_OUT PGout(11)
#define DTH11_DQ_IN PGin(11)
#define DTH11_IO_OUT() { GPIOG->CRH &= 0xffff0fff; GPIOG->CRH |= 0x00003000;}
#define DTH11_IO_IN() { GPIOG->CRH &= 0xffff0fff; GPIOG->CRH |= 0x00008000;}
void DTH11_start(void);
u8 DTH11_check(void);
u8 DTH11_Read_Bite(void);
u8 DTH11_Read_Byte(void);
u8 DTH11_Raed_data( u8 *temp, u8 *humi);
u8 DTH11_Init(void);
#endif
串口部分我用的正点原子的程序,就用用串口传输下数据的话,感觉都不用改,波特率啥的都默认就行了。因为所给的串口程序里面包含很多别的源文件,这里贴出来就一个文件也用不了,只需要把正点原子的任何一个程序里的串口部分搞过来就行
最后附上主函数
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "dth11.h"
int main(void)
{
u8 t=3;
u8 humi,temp;
Stm32_Clock_Init(9); //系统时钟设置
delay_init(72); //延时初始化
uart_init(72,115200); //串口初始化为115200
printf("ccccccccccc");
while(!DTH11_Init())
{
printf("************");
while(1)
{
// printf("aaaaaaaaaaaaaaaaarn");
if(t%10==0)
{
printf("aaaaaaaaaaaaaaaaarn");
DTH11_Raed_data(&temp, &humi);
printf("humidity:%drn",humi-50);
printf("temperature:%drn",temp-28);
printf("t:%drn",t);
delay_ms(500);
t++;
}
else
t++;
if(t==100) t=0;
}
}
}
里面的那些aaaaaa 和 **************是我调试程序时添加的,不需要的话删除即可,里面的humi-50 和 temp-28 是因为我 测出来的显示值有点大,我估计了一下减了一个值,虽然有投机取巧之嫌,但温湿度的变化总是线性的,这么做在逻辑上是说得通的。
基本的什么传感器介绍就不多说了
DTH11工作原理和流程:
DHT11共4个引脚,其中一个不用,所以只用3个,VCC、GND、Data。
DHT11为单总线数据格式,数据输入输出都由Data数据线来完成。
DTH11通讯过程如上图所示,先由主机(也就是STM32)发送开始信号(所以在此之前得先将data数据线设置为推挽输出),开始信号是一段超过18ms的低电平,发送完毕后,主机拉高20-40us(程序里拉高30us即可)。然后将data数据线设置为输入模式,DTH11发送响应信号,响应信号是80us的低电平,之后将数据线拉高(DTH11输出高电平)80us。至此,准备工作已做完,开始传输数据。
一次完整的数据传输为40bit,高位先出。
数据格式:8bit湿度整数数据+8bit湿度小数数据
+8bi温度整数数据+8bit温度小数数据
+8bit校验和
数据传送正确时:校验和数据=“8bit湿度整数数据+8bit湿度小数数据
+8bit温度整数数据+8bit温度小数数据”。
上述过程中存在两次判断过程,第一次是检测DTH11是否有响应信号产生,第二次是数据检验和是否等于剩下的四部分之和,注意程序编写过程中的这个问题。
串口部分使用printf函数打印输出,需要在串口程序中对printf 重定向,否则printf不可用。
DTH11.c程序如下
#include "sys.h"
#include "DTH11.h"
#include "delay.h"
// 主机发送起始信号
void DTH11_start(void)
{
DTH11_IO_OUT(); //PG11设置为推挽输出
DTH11_DQ_OUT=0;
delay_ms(20); //大于18ms的低电平
DTH11_DQ_OUT=1;
delay_us(30); //20~40us的高电平
}
//检测DTH11是否存在
//DTh11响应信号低电平80us,高电平80us
//返回值 1:不存在 0:存在
u8 DTH11_check(void)
{
u8 retry=0;
DTH11_IO_IN();
while(DTH11_DQ_IN && retry<100) //等待变为低电平
{
retry++;
delay_us(1);
}
if(retry>=100) return 1;
else retry=0;
while(!DTH11_DQ_IN && retry<100) //等待变为高电平
{
retry++;
delay_us(1);
}
if(retry>=100) return 1;
return 0;
}
//读取一个位的数据
//返回值 1/0
u8 DTH11_Read_Bite(void)
{
u8 retry;
// DTH11_IO_IN();
while(DTH11_DQ_IN && retry<100) //等待变为低电平
{
retry++;
delay_us(1);
}
retry=0;
while(!DTH11_DQ_IN && retry<100); //等待变为高电平
delay_us(40); //等待40us
if(DTH11_DQ_IN)
return 1;
else return 0;
}
//读取一个字节 高位先传
//返回值 读取到的八位字节数据
u8 DTH11_Read_Byte(void)
{
u8 a,dat=0,rec;
for(a=0;a<8;a++)
{
rec=DTH11_Read_Bite();
dat |= rec;
dat=dat<<1;
}
return dat;
}
//读取一次数据
//返回值 1:错误 0:正常
u8 DTH11_Raed_data( u8 *temp, u8 *humi)
{
u8 ReturnBack;
u8 i;
u8 buf[5];
DTH11_start();
ReturnBack=DTH11_check();
if(!ReturnBack)
{
for(i=0;i<5;i++)
{
buf
=DTH11_Read_Byte();
}
if(buf[4]==buf[0]+buf[1]+buf[2]+buf[3])
{
*humi=buf[0];
*temp=buf[2];
}
}
else return 1;
return 0;
}
//初始化DTH11 并检查DTH11是否存在
//返回值 0:存在 1:存在
u8 DTH11_Init(void)
{
RCC->APB2ENR |=1<<8;
GPIOG->CRH &= 0xffff0fff;
GPIOG->CRH |= 0x00003000;
GPIOG->ODR |=1<<11; //输出1
DTH11_start();
return DTH11_check();
}
上述程序中
while(DTH11_DQ_IN && retry<100)
这一句中要注意&&的优先级是低于 < 的,一开始忽略了这一点,怎么看都不对,在此为我不扎实的语法基础默哀。
DTH11_IO_OUT() 和 DTH11_IO_IN()这两个函数放到了DTH11.h文件中(因为很简单,不用单独写一个函数,宏定义一下就可以)
DTH11.h如下
#ifndef __DTH11_H
#define __DTH11_H
#include "sys.h"
#define DTH11_DQ_OUT PGout(11)
#define DTH11_DQ_IN PGin(11)
#define DTH11_IO_OUT() { GPIOG->CRH &= 0xffff0fff; GPIOG->CRH |= 0x00003000;}
#define DTH11_IO_IN() { GPIOG->CRH &= 0xffff0fff; GPIOG->CRH |= 0x00008000;}
void DTH11_start(void);
u8 DTH11_check(void);
u8 DTH11_Read_Bite(void);
u8 DTH11_Read_Byte(void);
u8 DTH11_Raed_data( u8 *temp, u8 *humi);
u8 DTH11_Init(void);
#endif
串口部分我用的正点原子的程序,就用用串口传输下数据的话,感觉都不用改,波特率啥的都默认就行了。因为所给的串口程序里面包含很多别的源文件,这里贴出来就一个文件也用不了,只需要把正点原子的任何一个程序里的串口部分搞过来就行
最后附上主函数
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "dth11.h"
int main(void)
{
u8 t=3;
u8 humi,temp;
Stm32_Clock_Init(9); //系统时钟设置
delay_init(72); //延时初始化
uart_init(72,115200); //串口初始化为115200
printf("ccccccccccc");
while(!DTH11_Init())
{
printf("************");
while(1)
{
// printf("aaaaaaaaaaaaaaaaarn");
if(t%10==0)
{
printf("aaaaaaaaaaaaaaaaarn");
DTH11_Raed_data(&temp, &humi);
printf("humidity:%drn",humi-50);
printf("temperature:%drn",temp-28);
printf("t:%drn",t);
delay_ms(500);
t++;
}
else
t++;
if(t==100) t=0;
}
}
}
里面的那些aaaaaa 和 **************是我调试程序时添加的,不需要的话删除即可,里面的humi-50 和 temp-28 是因为我 测出来的显示值有点大,我估计了一下减了一个值,虽然有投机取巧之嫌,但温湿度的变化总是线性的,这么做在逻辑上是说得通的。
举报