OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3958|回复: 7

用stm32f407采集AM2302的温湿度数据,但是采集到的数据是错误的,请看看哪里错了。

[复制链接]

42

主题

153

帖子

0

精华

初级会员

Rank: 2

积分
141
金钱
141
注册时间
2017-10-30
在线时间
51 小时
发表于 2018-6-6 17:02:29 | 显示全部楼层 |阅读模式
10金钱
自己按照时序写的程序,自己没有找到问题的所在,认为没有什么问题,但是就是读出来的温湿度数据是错误的。希望做过这个实验的同学们能给点帮助,谢谢了。首先感谢大家能耐心的看完,希望能提出宝贵的建议。谢谢、

附上AM2302.C程序
#include "dht22.h"
#include "delay.h"
#include "lcd.h"
#include "sys.h"
#include "stdlib.h"

int    Humi_H=0,Humi_L=0,Temp_H=0,Temp_L=0,Check_data=0,Hum,Temp;

//复位DHT22,2S的启动延时
void DHT22_Rst(void)          
{  
        delay_ms(2000);
        DHT22_IO_OUT() ;
        DHT22_DQ_OUT =1;
       
}

u8 DHT22_Read_Bit(void) //读一位                         
{
       
        while(DHT22_DQ_IN == 0);
        delay_us(50);
        if(DHT22_DQ_IN == 1)
        {
                return 1;
        }
        else
                return 0;
}

u8 DHT22_Read_Byte(void) //读一个字节   
{        
    u8 i,dat;
    dat=0;
        for (i=0;i<8;i++)
        {
                  
            dat|=DHT22_Read_Bit();
                        dat<<=1;
    }                                                    
    return dat;
}


void Read_DHT22(void)//读数据
{
        u8 t = 0;
        DHT22_IO_OUT();         //SET OUTPUT,设置为输出模式
        DHT22_DQ_OUT=0;         //拉低DQ
        delay_us(1500);            //拉低至少1ms
        DHT22_DQ_OUT=1;               
        DHT22_IO_IN();       
        delay_us(30);             //主机拉高20~40us,至此是单片机的起始信息。
       
        if(DHT22_DQ_IN == 0)//判断DHT22是否返回响应
        {
                while (DHT22_DQ_IN == 0)//轮询为80us的低电平后跳出循环,时序图上说明会输出80us的低电平作为应答信号。
                {
                        t++;
                        delay_us(1);
               
                }//响应80us的低电平
                t = 0;
                while (DHT22_DQ_IN == 1)//轮询80us后跳出来,输出80us的高电平通知外设准备接受数据。
                {
                        t++;
                        delay_us(1);
               
                }//响应80us的高电平
               
        //响应结束,开始读取数据。       
       
           Humi_H=DHT22_Read_Byte();          //湿度的高8位数据
           Humi_L=DHT22_Read_Byte();          //湿度的低8位数据
           Temp_H=DHT22_Read_Byte();          //温度的高8位数据
           Temp_L=DHT22_Read_Byte();          //温度的低8位数据
           Check_data=DHT22_Read_Byte();                //校验字节数据
                                                          //这里没有写校验程序。不影响。

               //40位数据传输完之后的状态。
                DHT22_IO_IN();
                delay_us(50);
                DHT22_IO_OUT();         //SET OUTPUT,设置为输出模式
                DHT22_DQ_OUT=1;
               
        }

}
void AM2302(void)
{
         Hum=(Humi_H*256+Humi_L);//此处的湿度为实际湿度的10倍
         Temp=Temp_H*256+Temp_L;//此处的湿度为实际温度的10倍
}

void DHT22_Init(void)//初始化
{
        GPIO_InitTypeDef  GPIO_InitStructure;

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);//使能GPIOG时钟

  //GPIOF9,F10初始化设置
  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;//50MHz
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
  GPIO_Init(GPIOG, &GPIO_InitStructure);//初始化

       
}























QQ截图20180606164915.png
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

2

主题

168

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
336
金钱
336
注册时间
2018-5-14
在线时间
69 小时
发表于 2018-6-6 17:19:07 | 显示全部楼层
u8 DHT22_Read_Bit(void) //读一位                        
{
         
        while(DHT22_DQ_IN == 0);
         delay_us(50);
         if(DHT22_DQ_IN == 1)
         {
                 return 1;
         }
         else
                 return 0;
}

只用过DHT11,想来时序应该差不多,所以感觉你上面那段程序不很靠谱,可以分析如下:
假设DHT22输出数据为11001100,引脚变高电平时,跳出“while(DHT22_DQ_IN == 0);”循环,开始计时50us(假设你的计时很精确,否则问题更大了),然后判断引脚电平,此时DHT输出位为1,则引脚高电平,位置1,跳出函数,然后函数再一次被调用,重新执行“while(DHT22_DQ_IN == 0);”由于之前输出没有完成(70us高电平),此时引脚仍然为高电平,循环直接跳过,然后……时序不对了!剩余10多us的高电平加上数据开始的50us的低电平,足以使你第2次调用函数的50us延时耗尽,而延时耗尽时,引脚正处于50us低电平,你得到了位0……剩下的自己分析吧
回复

使用道具 举报

109

主题

5564

帖子

0

精华

资深版主

Rank: 8Rank: 8

积分
10570
金钱
10570
注册时间
2017-2-18
在线时间
1913 小时
发表于 2018-6-6 18:10:54 | 显示全部楼层
帮顶!
回复

使用道具 举报

42

主题

153

帖子

0

精华

初级会员

Rank: 2

积分
141
金钱
141
注册时间
2017-10-30
在线时间
51 小时
 楼主| 发表于 2018-6-8 08:57:44 | 显示全部楼层
kvdong 发表于 2018-6-6 17:19
u8 DHT22_Read_Bit(void) //读一位                        
{
         

谢谢您,这确实是我没有考虑到的,谢谢。
还想问一下您, 就是我的  读函数  里面最前面的等待从机响应的程序有没有错误呢?我的引脚电平在那一步一直是高电平。不知是这么回事。
回复

使用道具 举报

2

主题

168

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
336
金钱
336
注册时间
2018-5-14
在线时间
69 小时
发表于 2018-6-8 09:21:16 | 显示全部楼层
bufangqi 发表于 2018-6-8 08:57
谢谢您,这确实是我没有考虑到的,谢谢。
还想问一下您, 就是我的  读函数  里面最前面的等待从机响应 ...

看上去似乎没什么大问题,那个if()判断感觉意义不大,甚至不知道会不会起反作用。如果一直是高电平的话,可以考虑看看延时是否正确,器件、单片机引脚、电气连接有没有问题
回复

使用道具 举报

2

主题

168

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
336
金钱
336
注册时间
2018-5-14
在线时间
69 小时
发表于 2018-6-8 09:22:46 | 显示全部楼层
另外,你的截图上好像说上电2S以后再开始读传感器,是否做到了。
回复

使用道具 举报

42

主题

153

帖子

0

精华

初级会员

Rank: 2

积分
141
金钱
141
注册时间
2017-10-30
在线时间
51 小时
 楼主| 发表于 2018-6-8 10:33:31 | 显示全部楼层
kvdong 发表于 2018-6-8 09:22
另外,你的截图上好像说上电2S以后再开始读传感器,是否做到了。

您好,这个已经上电实现了,
//复位DHT22,2S的启动延时
void DHT22_Rst(void)           
{  
        delay_ms(2000);
        DHT22_IO_OUT() ;
        DHT22_DQ_OUT =1;
        
}
这个实现了两秒的延时。并且 在主函数了调用了这个函数。
回复

使用道具 举报

42

主题

153

帖子

0

精华

初级会员

Rank: 2

积分
141
金钱
141
注册时间
2017-10-30
在线时间
51 小时
 楼主| 发表于 2018-6-8 10:35:13 | 显示全部楼层
kvdong 发表于 2018-6-8 09:21
看上去似乎没什么大问题,那个if()判断感觉意义不大,甚至不知道会不会起反作用。如果一直是高电平的话, ...

嗯恩,在时序上也没有找到哪里有错误,可能是那些细节上自己还没有发现。谢谢你。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-29 06:27

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表