我试图理解此代码(湿度和温度模块)的含义和规则。 我想用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);
}
答案 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位。我想您可能需要一些后备,以防通信丢失。