依据网上的大佬们的程序,卡在一个小地方,终于搞出来了,特此分享出来哈,希望能帮帮和我一样痛苦的小伙伴:
首先看程序:
main():
#include "stm32f4xx.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "dht22.h"
//ALIENTEK 探索者STM32F407开发板 实验0
//STM32F4工程模板-库函数版本
//技术支持:www.openedv.com
//淘宝店铺:http://eboard.taobao.com
//广州市星翼电子科技有限公司
//作者:正点原子 @ALIENTEK
//float temperature;
float humidity;
int main(void)
{
u8 t=0;
//NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
delay_init(168); //初始化延时函数
uart_init(115200); //初始化串口波特率为115200
Led_Init(); //初始化LED
while(DHT22_Init()) //DHT11初始化
{
printf("DHT22 Error");
delay_ms(200);
}
while(1)
{
if(t%50==0)//每100ms读取一次
{
DHT22_Read_Data(&humidity); //读取温湿度值
//printf("t:%.1f C
",temperature); //显示温度
printf("Hu:%.1f RH
",humidity); //显示湿度
}
delay_ms(10);
t++;
if(t==100)
{
t=0;
LED0=!LED0;
}
}
}
DHT22.c:
#include "dht22.h"
#include "delay.h"
#include "usart.h"
//复位DHT22
void DHT22_Rst(void)
{
DHT22_IO_OUT(); //SET OUTPUT
DHT22_DQ_OUT=0; //拉低DQ
delay_ms(1); //拉低至少18ms
DHT22_DQ_OUT=1; //DQ=1
delay_us(30); //主机拉高20~40us
}
//等待DHT22的回应
//返回1:未检测到DHT22的存在
//返回0:存在
u8 DHT22_Check(void)
{
u8 retry=100;
DHT22_IO_IN();
while (DHT22_DQ_IN&&retry)//DHT22会拉低40~80us
{
retry--;
delay_us(1);
};
if(retry<1) return 1;
else retry=100;
while (!DHT22_DQ_IN&&retry)//DHT22拉低后会再次拉高40~80us
{
retry--;
delay_us(1);
};
if(retry<1)
return 1;
return 0;
}
//从DHT22读取一个位
//返回值:1/0
u8 DHT22_Read_Bit(void)
{
u8 retry=100;
while(DHT22_DQ_IN&&retry)//等待变低电平
{
retry--;
delay_us(1);
}
retry=100;
while(!DHT22_DQ_IN&&retry)//等待变为高电平
{
retry--;
delay_us(1);
}
delay_us(30);//等待30us(此处很重要,等待过长也不可,原因翻到最底下看图吧!)
if(DHT22_DQ_IN)
return 1;
else
return 0;
}
//从DHT22读取一个字节
//返回值:读到的数据
u8 DHT22_Read_Byte(void)
{
u8 i,dat,j;
dat=0;
for (i=0;i<8;i++)
{
// j=DHT22_Read_Bit();
dat<<=1;
dat|=DHT22_Read_Bit();
//printf(&quot;%d
&quot;,j);
// j=DHT22_Read_Bit();
// dat=(j<<7)|(dat>>1);
}
//printf(&quot;
&quot;);
return dat;
}
//从DHT22读取一次数据
//temp:温度值(范围:0~50°)
//humi:湿度值(范围:20%~90%)
//返回值:0,正常;1,读取失败
u8 DHT22_Read_Data(float *humi)
{
u8 buf[5];
u8 i;
//u16 add,he;
DHT22_Rst();
if(DHT22_Check()==0)
{
for(i=0;i<5;i++)//读取40位数据
{
buf=DHT22_Read_Byte();
// printf(&quot;buf[%d]:%d
&quot;,i,buf);
}
//add=buf[0]+buf[1]+buf[2]+buf[3];
//he=buf[4];
//校验和累加时存在相当概率会超出8位(即值大于1个char,故做强制类型转换,只考虑低8位)
*humi=buf[0]*25.6+(float)buf[1]/10;
//*temp=(float)(buf[2]*256+buf[3])/10;
}
else return 1;
return 0;
}
//初始化DHT22的IO口 DQ 同时检测DHT22的存在
//返回1:不存在
//返回0:存在
u8 DHT22_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上la
GPIO_Init(GPIOG, &GPIO_InitStructure);
DHT22_Rst();
return DHT22_Check();
}
DTH22.h:
#ifndef __DHT22_H
#define __DHT22_H
#include &quot;sys.h&quot;
//IO方向设置
#define DHT22_IO_IN() {GPIOG->MODER&=~(3<<(0*2));GPIOG->MODER|=0<<0*2;} //PG9输入模式
#define DHT22_IO_OUT() {GPIOG->MODER&=~(3<<(0*2));GPIOG->MODER|=1<<0*2;} //PG9输出模式
////IO操作函数
#define DHT22_DQ_OUT PGout(0) //数据端口 PG0
#define DHT22_DQ_IN PGin(0) //数据端口 PG0
u8 DHT22_Init(void); //初始化DHT22
u8 DHT22_Read_Data(float *humi); //读取温湿度
u8 DHT22_Read_Byte(void); //读出一个字节
u8 DHT22_Read_Bit(void); //读出一个位
u8 DHT22_Check(void); //检测是否存在DHT22
void DHT22_Rst(void); //复位DHT22
#endif
写在最后:
u8 DHT22_Read_Byte(void)
{
u8 i,dat,j;
dat=0;
for (i=0;i<8;i++)
{
// j=DHT22_Read_Bit();
dat<<=1;
dat|=DHT22_Read_Bit();
//printf(&quot;%d
&quot;,j);
// j=DHT22_Read_Bit();
// dat=(j<<7)|(dat>>1);
}
//printf(&quot;
&quot;);
return dat;
}
此处我为了显示出八位数的具体形式添加了这样的代码,可就是这个坑了我:因为“1”的高电平最长也才70微秒,在调用串口输出的过程中占用了时间第二次读取数据时就不再从第二个数据低电平或第一个数据高电平开始了,可能直接到达第5、6个数据上了。(不知道说的明不明白orz,反正总的来说就是没考虑程序语句运行的时间(就是菜)),祝顺利 |