找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3300|回复: 11
收起左侧

单片机读DHT12只能读出湿度,温度和校验值全是FF?

[复制链接]
ID:5616 发表于 2019-3-13 20:45 | 显示全部楼层 |阅读模式
各位高手,51单片机读DHT12,I2C,只能读出湿度值,温度值和校验值都是FF,换了一个传感器还是这样,已经一周了,折腾的够呛,请高手帮忙分析一下程序,多谢了!

#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint  unsigned int

sbit I2C_SCL = P1^6;                        //DHT12时钟线
sbit I2C_SDA = P1^7;                //DHT12数据线
                                                                        
void delay_ms(uint tim);                                                                          //毫秒级延时函数声明
void delay_n10us(uchar tim);                                                                 //10倍微秒级延时函数声明

void I2C_delay(void);
void I2C_Start(void);
void I2C_Stop(void);
void I2C_Ack(void);
void I2C_NAck(void);
uchar I2C_Wait_Ack(void);
void I2C_WriteByte(uchar txd);
uchar I2C_ReadByte(uchar ack);

void Init_DHT12();                                                                //初始化
void Read_DHT12(uchar *sht);                                               //测量DHT12的温度湿度值,指针
                                                        
void main()
{
        uchar read_dht[5];                                                        //存放从DHT12读取的数据
        float temperature=0.0,humidity=0.0;                               //将温湿度转为小数(保留2位)
               
        Init_DHT12();
        delay_ms(2000);
        
        while(1)
        {
                Read_DHT12(read_dht);                                                    //从DHT12中读数据
                temperature = 1.0 * read_dht[2] + 0.1 * read_dht[3];            
                humidity = 1.0 * read_dht[0] + 0.1 * read_dht[1];               
        }
}

//产生起始信号
void I2C_Start(void)
{
     I2C_SDA = 1;        //注意先拉高SDA,否则可能会误认为是停止信号
    delay_n10us(1);
    I2C_SCL = 1;
    delay_n10us(5);
    I2C_SDA = 0;
    delay_n10us(5);
    I2C_SCL = 0;
    delay_n10us(1);
}
//产生停止信号
void I2C_Stop(void)
{
    I2C_SCL = 0;
    delay_n10us(1);
    I2C_SDA = 0;
    delay_n10us(5);
    I2C_SCL = 1;
    delay_n10us(5);
    I2C_SDA = 1;
    delay_n10us(1);
}
//主机产生应答信号
void I2C_Ack(void)
{
    I2C_SCL = 0;
    delay_n10us(1);
    I2C_SDA = 0;
    delay_n10us(5);
    I2C_SCL = 1;
    delay_n10us(5);
    I2C_SCL = 0;
    delay_n10us(1);
}
//主机产生不应答信号
void I2C_NAck(void)
{
    I2C_SCL = 0;
    delay_n10us(1);
    I2C_SDA = 1;
    delay_n10us(5);
    I2C_SCL = 1;
    delay_n10us(5);
    I2C_SCL = 0;
    delay_n10us(1);
}
//主机等待从机应答信号
//返回值为0,接收应答成功,返回值为1,接收应答失败
uchar I2C_Wait_Ack(void)
{
    uchar tempTime = 0;
    I2C_SCL = 0;
    delay_n10us(1);
    I2C_SDA = 1;
    delay_n10us(5); //增加等待从动件发送应答信号的时间,怕有些器件反应慢
    I2C_SCL = 1;
    delay_n10us(5);
    while(I2C_SDA == 1)//等于1,则无应答
    {
        tempTime++;
        if( tempTime > 250 )//一直无应答
        {
            I2C_Stop();
            return 1;
        }
       delay_n10us(2);
    }
    I2C_SCL = 0;
    delay_n10us(5);
    return 0;
}
//发送一个字节
void I2C_WriteByte(uchar txd)
{
    uchar i = 0;
    I2C_SCL = 0;        //拉低SCL为发送数据准备        
    for(i = 0; i < 8; i++)
    {
        I2C_SCL = 0;
        I2C_SDA = (txd & 0x80) >> 7;
        txd = txd << 1;        //左移1位
        delay_n10us(5);
        I2C_SCL = 1;        //拉高SCL
        delay_n10us(5);
     }
    I2C_SCL = 0;
}
//读取一个字节
uchar I2C_ReadByte(uchar ack)
{
    uchar i = 0;
    uchar rxd = 0;
    I2C_SCL = 0;        
    delay_n10us(1);
    I2C_SDA = 1;
    delay_n10us(5);        //等待从机准备信号
    for(i = 0; i < 8; i++)
    {
        I2C_SCL = 0;
        delay_n10us(10);        //等待从机准备信号
        I2C_SCL = 1;        //拉高SCL
        delay_n10us(10);
        rxd = rxd << 1;        //左移一位,最低位补0
        rxd = rxd | I2C_SDA;        //然后与SDA的状态取或
    }
    I2C_SCL = 0;
    if(ack == 0)
        I2C_NAck();
    else
        I2C_Ack();
    return rxd;
}
void Init_DHT12()
{
    I2C_SDA = 1;        
    delay_n10us(1);
    I2C_SCL = 1;        
    delay_n10us(1);
}
//读取DHT12的温度湿度值
void Read_DHT12(uchar *dht)
{
    I2C_Start();
    I2C_WriteByte(0xB8);        //DHT12写地址0xB8,读地址为0xB9
    I2C_Wait_Ack();
    I2C_WriteByte(0x00);        //写地址
    I2C_Wait_Ack();        //等待从机响应
    I2C_Start();
    I2C_WriteByte(0xB9);        //读指令
    I2C_Wait_Ack();        //等待从机响应
    dht[0] = I2C_ReadByte(1);        //读湿度整数位
    dht[1] = I2C_ReadByte(1);        //读湿度小数位
    dht[2] = I2C_ReadByte(1);        //读温度整数位
    dht[3] = I2C_ReadByte(1);        //读温度小数位
    dht[4] = I2C_ReadByte(0);        //读校验位
    I2C_Stop();
}

回复

使用道具 举报

ID:5616 发表于 2019-3-13 20:48 | 显示全部楼层
显示我是用MAX7219,那部分程序就不发了,否则太长了。湿度值显示正常,手靠近也会变好,但就是温度值的整数部分、小数部分和校验值都是FF,不知道为何?参考恶劣官方的例程(stm32的),和他的程序几乎一模一样,结果仍然是这样。我按照程序一个一个脉冲的分析了,也没有发现时序不对,愁死了。请熟悉I2C的帮忙看一下,多谢了。
回复

使用道具 举报

ID:234075 发表于 2019-3-14 01:08 | 显示全部楼层
没用过这个器件,不过既然湿度能正常读出来,IIC通信应该没问题的。我看你是先读湿度,然后读取温度,试试读取数据时增加延时,部分器件数据转换需要时间~
回复

使用道具 举报

ID:5616 发表于 2019-3-14 08:06 | 显示全部楼层
困扰多天,始终得不到解决,还望熟悉I2C的帮忙解决一下,谢谢!
回复

使用道具 举报

ID:5616 发表于 2019-3-14 20:03 | 显示全部楼层
感谢上面这位朋友,我也很奇怪,湿度能读出,温度读不出,可能还是时序的问题,只有再试试了。
回复

使用道具 举报

ID:502218 发表于 2019-5-11 16:56 | 显示全部楼层
我也遇到这个问题,请问现在有解决方案了吗
回复

使用道具 举报

ID:587604 发表于 2019-7-21 10:06 | 显示全部楼层
请问楼主大哥现在解决了嘛?
回复

使用道具 举报

ID:425246 发表于 2019-8-3 21:14 来自手机 | 显示全部楼层
你好,解决了吗,我也遇到了这个问题
回复

使用道具 举报

ID:116893 发表于 2019-9-11 11:04 | 显示全部楼层
这几天也在玩这传感器,stm32例程转到STC8上来,也是一直不行。后面加好几十毫秒以上的延时可以正确通过校验后获取正常温 湿 度......
回复

使用道具 举报

ID:116893 发表于 2019-9-11 11:12 | 显示全部楼层

如果用函数名字说明一下,就是这个样子:
unsigned char Data;//定义一个缓冲寄存器。
   IIC_Start();//产生起始信号
   IIC_Send_Byte(0xB8);//写入设备地址(写)
   IIC_Wait_Ack();//等待设备的应答
   IIC_Send_Byte(0x00);//写入要操作的单元地址。(0x00~0x04)
   IIC_Wait_Ack();//等待设备的应答。
   IIC_Stop();//产生停止符号。
   IIC_Start();//产生起始信号
   IIC_Send_Byte(0xB9);//写入设备地址(读)
   IIC_Wait_Ack();//等待设备的应答
   Data=IIC_Read_Byte();//读入数据。
   IIC_Stop();//产生停止符号。
( delay(50);//我在每次结束后加了大概50毫秒延时,可以通过校验,不通过校验的概率也很大.......

以上的步骤重复5次,分别输入0x00~0x04这5个地址,就能读出5个字节,
分别是湿度整数位,湿度小数位,温度整数位,温度小数位,校验和。

回复

使用道具 举报

ID:141497 发表于 2019-11-10 23:19 | 显示全部楼层
allen2016 发表于 2019-9-11 11:12
如果用函数名字说明一下,就是这个样子:
unsigned char Data;//定义一个缓冲寄存器。
   IIC_Start(); ...

请教一下,最近也在完这个DHT12,用I2C协议,问题是开机时能够读取一次完整的数据,之后程序读不出数据了,这个I2C用在24C02上正常。请问一下是什么原因造成的?如果方便请回复一下,谢谢!
回复

使用道具 举报

ID:71233 发表于 2022-1-2 14:22 | 显示全部楼层
我的程序从以前读写24C02中搬过来的,现在读出来的都是0xFF,不知道是什么原因。
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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