找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 3808|回復(fù): 11
收起左側(cè)

單片機(jī)讀DHT12只能讀出濕度,溫度和校驗(yàn)值全是FF?

[復(fù)制鏈接]
ID:5616 發(fā)表于 2019-3-13 20:45 | 顯示全部樓層 |閱讀模式
各位高手,51單片機(jī)讀DHT12,I2C,只能讀出濕度值,溫度值和校驗(yàn)值都是FF,換了一個(gè)傳感器還是這樣,已經(jīng)一周了,折騰的夠嗆,請(qǐng)高手幫忙分析一下程序,多謝了!

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

sbit I2C_SCL = P1^6;                        //DHT12時(shí)鐘線
sbit I2C_SDA = P1^7;                //DHT12數(shù)據(jù)線
                                                                        
void delay_ms(uint tim);                                                                          //毫秒級(jí)延時(shí)函數(shù)聲明
void delay_n10us(uchar tim);                                                                 //10倍微秒級(jí)延時(shí)函數(shù)聲明

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);                                               //測(cè)量DHT12的溫度濕度值,指針
                                                        
void main()
{
        uchar read_dht[5];                                                        //存放從DHT12讀取的數(shù)據(jù)
        float temperature=0.0,humidity=0.0;                               //將溫濕度轉(zhuǎn)為小數(shù)(保留2位)
               
        Init_DHT12();
        delay_ms(2000);
        
        while(1)
        {
                Read_DHT12(read_dht);                                                    //從DHT12中讀數(shù)據(jù)
                temperature = 1.0 * read_dht[2] + 0.1 * read_dht[3];            
                humidity = 1.0 * read_dht[0] + 0.1 * read_dht[1];               
        }
}

//產(chǎn)生起始信號(hào)
void I2C_Start(void)
{
     I2C_SDA = 1;        //注意先拉高SDA,否則可能會(huì)誤認(rèn)為是停止信號(hào)
    delay_n10us(1);
    I2C_SCL = 1;
    delay_n10us(5);
    I2C_SDA = 0;
    delay_n10us(5);
    I2C_SCL = 0;
    delay_n10us(1);
}
//產(chǎn)生停止信號(hào)
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);
}
//主機(jī)產(chǎn)生應(yīng)答信號(hào)
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);
}
//主機(jī)產(chǎn)生不應(yīng)答信號(hào)
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);
}
//主機(jī)等待從機(jī)應(yīng)答信號(hào)
//返回值為0,接收應(yīng)答成功,返回值為1,接收應(yīng)答失敗
uchar I2C_Wait_Ack(void)
{
    uchar tempTime = 0;
    I2C_SCL = 0;
    delay_n10us(1);
    I2C_SDA = 1;
    delay_n10us(5); //增加等待從動(dòng)件發(fā)送應(yīng)答信號(hào)的時(shí)間,怕有些器件反應(yīng)慢
    I2C_SCL = 1;
    delay_n10us(5);
    while(I2C_SDA == 1)//等于1,則無(wú)應(yīng)答
    {
        tempTime++;
        if( tempTime > 250 )//一直無(wú)應(yīng)答
        {
            I2C_Stop();
            return 1;
        }
       delay_n10us(2);
    }
    I2C_SCL = 0;
    delay_n10us(5);
    return 0;
}
//發(fā)送一個(gè)字節(jié)
void I2C_WriteByte(uchar txd)
{
    uchar i = 0;
    I2C_SCL = 0;        //拉低SCL為發(fā)送數(shù)據(jù)準(zhǔn)備        
    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;
}
//讀取一個(gè)字節(jié)
uchar I2C_ReadByte(uchar ack)
{
    uchar i = 0;
    uchar rxd = 0;
    I2C_SCL = 0;        
    delay_n10us(1);
    I2C_SDA = 1;
    delay_n10us(5);        //等待從機(jī)準(zhǔn)備信號(hào)
    for(i = 0; i < 8; i++)
    {
        I2C_SCL = 0;
        delay_n10us(10);        //等待從機(jī)準(zhǔn)備信號(hào)
        I2C_SCL = 1;        //拉高SCL
        delay_n10us(10);
        rxd = rxd << 1;        //左移一位,最低位補(bǔ)0
        rxd = rxd | I2C_SDA;        //然后與SDA的狀態(tài)取或
    }
    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寫(xiě)地址0xB8,讀地址為0xB9
    I2C_Wait_Ack();
    I2C_WriteByte(0x00);        //寫(xiě)地址
    I2C_Wait_Ack();        //等待從機(jī)響應(yīng)
    I2C_Start();
    I2C_WriteByte(0xB9);        //讀指令
    I2C_Wait_Ack();        //等待從機(jī)響應(yīng)
    dht[0] = I2C_ReadByte(1);        //讀濕度整數(shù)位
    dht[1] = I2C_ReadByte(1);        //讀濕度小數(shù)位
    dht[2] = I2C_ReadByte(1);        //讀溫度整數(shù)位
    dht[3] = I2C_ReadByte(1);        //讀溫度小數(shù)位
    dht[4] = I2C_ReadByte(0);        //讀校驗(yàn)位
    I2C_Stop();
}

回復(fù)

使用道具 舉報(bào)

ID:5616 發(fā)表于 2019-3-13 20:48 | 顯示全部樓層
顯示我是用MAX7219,那部分程序就不發(fā)了,否則太長(zhǎng)了。濕度值顯示正常,手靠近也會(huì)變好,但就是溫度值的整數(shù)部分、小數(shù)部分和校驗(yàn)值都是FF,不知道為何?參考惡劣官方的例程(stm32的),和他的程序幾乎一模一樣,結(jié)果仍然是這樣。我按照程序一個(gè)一個(gè)脈沖的分析了,也沒(méi)有發(fā)現(xiàn)時(shí)序不對(duì),愁死了。請(qǐng)熟悉I2C的幫忙看一下,多謝了。
回復(fù)

使用道具 舉報(bào)

ID:234075 發(fā)表于 2019-3-14 01:08 | 顯示全部樓層
沒(méi)用過(guò)這個(gè)器件,不過(guò)既然濕度能正常讀出來(lái),IIC通信應(yīng)該沒(méi)問(wèn)題的。我看你是先讀濕度,然后讀取溫度,試試讀取數(shù)據(jù)時(shí)增加延時(shí),部分器件數(shù)據(jù)轉(zhuǎn)換需要時(shí)間~
回復(fù)

使用道具 舉報(bào)

ID:5616 發(fā)表于 2019-3-14 08:06 | 顯示全部樓層
困擾多天,始終得不到解決,還望熟悉I2C的幫忙解決一下,謝謝!
回復(fù)

使用道具 舉報(bào)

ID:5616 發(fā)表于 2019-3-14 20:03 | 顯示全部樓層
感謝上面這位朋友,我也很奇怪,濕度能讀出,溫度讀不出,可能還是時(shí)序的問(wèn)題,只有再試試了。
回復(fù)

使用道具 舉報(bào)

ID:502218 發(fā)表于 2019-5-11 16:56 | 顯示全部樓層
我也遇到這個(gè)問(wèn)題,請(qǐng)問(wèn)現(xiàn)在有解決方案了嗎
回復(fù)

使用道具 舉報(bào)

ID:587604 發(fā)表于 2019-7-21 10:06 | 顯示全部樓層
請(qǐng)問(wèn)樓主大哥現(xiàn)在解決了嘛?
回復(fù)

使用道具 舉報(bào)

ID:425246 發(fā)表于 2019-8-3 21:14 來(lái)自觸屏版 | 顯示全部樓層
你好,解決了嗎,我也遇到了這個(gè)問(wèn)題
回復(fù)

使用道具 舉報(bào)

ID:116893 發(fā)表于 2019-9-11 11:04 | 顯示全部樓層
這幾天也在玩這傳感器,stm32例程轉(zhuǎn)到STC8上來(lái),也是一直不行。后面加好幾十毫秒以上的延時(shí)可以正確通過(guò)校驗(yàn)后獲取正常溫 濕 度......
回復(fù)

使用道具 舉報(bào)

ID:116893 發(fā)表于 2019-9-11 11:12 | 顯示全部樓層

如果用函數(shù)名字說(shuō)明一下,就是這個(gè)樣子:
unsigned char Data;//定義一個(gè)緩沖寄存器。
   IIC_Start();//產(chǎn)生起始信號(hào)
   IIC_Send_Byte(0xB8);//寫(xiě)入設(shè)備地址(寫(xiě))
   IIC_Wait_Ack();//等待設(shè)備的應(yīng)答
   IIC_Send_Byte(0x00);//寫(xiě)入要操作的單元地址。(0x00~0x04)
   IIC_Wait_Ack();//等待設(shè)備的應(yīng)答。
   IIC_Stop();//產(chǎn)生停止符號(hào)。
   IIC_Start();//產(chǎn)生起始信號(hào)
   IIC_Send_Byte(0xB9);//寫(xiě)入設(shè)備地址(讀)
   IIC_Wait_Ack();//等待設(shè)備的應(yīng)答
   Data=IIC_Read_Byte();//讀入數(shù)據(jù)。
   IIC_Stop();//產(chǎn)生停止符號(hào)。
( delay(50);//我在每次結(jié)束后加了大概50毫秒延時(shí),可以通過(guò)校驗(yàn),不通過(guò)校驗(yàn)的概率也很大.......

以上的步驟重復(fù)5次,分別輸入0x00~0x04這5個(gè)地址,就能讀出5個(gè)字節(jié),
分別是濕度整數(shù)位,濕度小數(shù)位,溫度整數(shù)位,溫度小數(shù)位,校驗(yàn)和。

回復(fù)

使用道具 舉報(bào)

ID:141497 發(fā)表于 2019-11-10 23:19 | 顯示全部樓層
allen2016 發(fā)表于 2019-9-11 11:12
如果用函數(shù)名字說(shuō)明一下,就是這個(gè)樣子:
unsigned char Data;//定義一個(gè)緩沖寄存器。
   IIC_Start(); ...

請(qǐng)教一下,最近也在完這個(gè)DHT12,用I2C協(xié)議,問(wèn)題是開(kāi)機(jī)時(shí)能夠讀取一次完整的數(shù)據(jù),之后程序讀不出數(shù)據(jù)了,這個(gè)I2C用在24C02上正常。請(qǐng)問(wèn)一下是什么原因造成的?如果方便請(qǐng)回復(fù)一下,謝謝!
回復(fù)

使用道具 舉報(bào)

ID:71233 發(fā)表于 2022-1-2 14:22 | 顯示全部樓層
我的程序從以前讀寫(xiě)24C02中搬過(guò)來(lái)的,現(xiàn)在讀出來(lái)的都是0xFF,不知道是什么原因。
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表