我无法使用RaspberryPi理解湿度和温度传感器的源代码

时间:2020-09-11 12:30:58

标签: c raspberry-pi

我试图理解此代码(湿度和温度模块)的含义和规则。 我想用C和RaspberryPi运行它。 但是,即使我试图弄清楚这一点,我也不明白*****部分在做什么。

为什么MAXTIMINGS是85? 为什么句子等于255? 你能告诉我****部分的含义是什么吗?

这是时序图和数据表链接。

https://www.mouser.com/datasheet/2/758/DHT11-Technical-Data-Sheet-Translated-Version-1143054.pdf#search='DHT11+datasheet'enter image description here

#include <stdio.h>
#include <wiringPi.h>

#define MAXTIMINGS  85
#define DHTPIN      15  //DHT connect to TxD
int dht11_dat[5] ={0,0,0,0,0};//store DHT11 data

void read_dht11_dat()
{
    uint8_t laststate = HIGH;
    uint8_t counter = 0;
    uint8_t j = 0,i;
    float f;//fahrenheit

    dht11_dat[0] = dht11_dat[1] = dht11_dat[2] = dht11_dat[3] = dht11_dat[4] = 0;

    //pull pin down to send start signal
    pinMode( DHTPIN, OUTPUT );
    digitalWrite( DHTPIN, LOW );
    delay( 18 );
    //pull pin up and wait for sensor response
    digitalWrite( DHTPIN, HIGH );
    delayMicroseconds( 40 );
    //prepare to read the pin
    pinMode( DHTPIN, INPUT );
    ***************************************************************
    //detect change and read data
    for ( i = 0; i < MAXTIMINGS; i++ ) { 
        counter = 0; 
        while ( digitalRead( DHTPIN ) == laststate ) { 
            counter++; 
            delayMicroseconds( 1 ); 
            if ( counter == 255 ) { break; }
        }

        laststate = digitalRead( DHTPIN ); 
        if ( counter == 255 ) break; 
         //ignore first 3 transitions if ( (i >= 4) && (i % 2 == 0) )
        {
            //shove each bit into the storage bytes
            dht11_dat[j / 8] <<= 1; 
            if ( counter > 16 )dht11_dat[j / 8] |= 1;
            j++;
        }
    }
    **************************************************************************
    //check we read 40 bits(8bit x 5) +verify checksum in the last byte
    //print it out if data is good
    if ( (j >= 40) &&
         (dht11_dat[4] == ( (dht11_dat[0] + dht11_dat[1] + dht11_dat[2] + dht11_dat[3]) & 0xFF) ) )
    {
        f = dht11_dat[2] * 9. / 5. + 32;
        printf( "Humidity = %d.%d %% Temperature = %d.%d C (%.1f F)\n",
            dht11_dat[0], dht11_dat[1], dht11_dat[2], dht11_dat[3], f );
    }
    else
    {
        printf( "Data not good, skip\n" );
    }
}

int main( void )
{
    if ( wiringPiSetup() == -1 )
    {
        fprintf(stderr,"Can't init wiringPi: %s\n",strerror(errno));
        exit(EXIT_FAILURE);
    }
    print_info();
    while ( 1 )
    {
        read_dht11_dat();
        delay(1000);//wait ls to refresh
    }

    return(0);
}

2 个答案:

答案 0 :(得分:0)

while ( digitalRead( DHTPIN ) == laststate )会检查引脚的数字状态(最多255us),然后在找不到变化的情况下跳出外部for循环。我认为数字255并不重要,这只是一些超时上限。这是一个粗略的技巧,而不是正确使用带有输入捕获功能的片上硬件计时器。

显然,计数器对于算法也很有意义,因此它似乎正在测量PWM脉冲等的占空比。再次,以非常粗糙的方式。

我想在Rasp PI“变相PC”上可能不容易访问硬件计时器-使用裸机微控制器,这整个过程会更容易且更漂亮。

//ignore first 3 transitions if ( (i >= 4) && (i % 2 == 0) )行是代码气味。这是故意注释掉的,还是只是某人调试尝试的一部分?

线条

dht11_dat[j / 8] <<= 1; 
if ( counter > 16 )dht11_dat[j / 8] |= 1;

仅用一个或零填充一个位域/字节数组,具体取决于计数器是否大于16us。移位将上一个数据向上移动,然后LSB设置为1或保持为0。

答案 1 :(得分:0)

程序将引脚设置为高电平一段时间,以向设备发送信号。器件发送40位数据,并在引脚保持高电平的时间长度内发出“ 1”和“ 0”信号。该程序只是对引脚状态进行采样,直到检测到85个边沿转换(实际应该多一些),或者直到没有边沿经过255微秒。边沿之间的循环周期数用于确定是否要在数据数组中移位“ 1”或“ 0”。

数据分为五个字节,最后一个字节是前四个字节的校验和。

对于这样的循环采样,通信速度可能太快了,我的印象是程序中的某些参数可能是通过反复试验得出的。至少对于特定型号的Pi,这是一件相当安全的事情,因为它们之间的差异很小。

尽管如此,我不禁想到一个更好的方法是捕获GPIO固件中提供的上升沿中断,然后在固定的延迟后进行单个采样。只需执行40次,直到读取完所有40位。我想您可能需要一些后备,以防通信丢失。