本帖最后由 tsaiwn 于 2015-4-30 01:28 编辑
再补充说明以下这段:
这时 pin 刚变 LOW 表示 1 bit 正要传送过来
loopCnt = 10000;
while(digitalRead(pin) == LOW)
if (loopCnt-- == 0) return DHTLIB_ERROR_TIMEOUT;
依据图片, dht11 的每个 bit 开始会拉低 50 us
所以, 如果等了 51 us 还没变 HIGH 就可判定 timeout
可是保险起见, 通常我们会多等一下, 例如等 80 us
所以, 其实上述 loopCnt 应该设 300 就够了, 设 10000 是更保守
如果 time out 就 return 返回了,
会到这表示此时 pin 变 HIGH,
立即用 t 记下 micros( )
unsigned long t = micros();
loopCnt = 10000;
while(digitalRead(pin) == HIGH)
if (loopCnt-- == 0) return DHTLIB_ERROR_TIMEOUT;
依据图片, 如果这 bit 是 0,
则 dht11 会在 28 us 后拉低 pin,
如果这 bit 是 1, 则会让 pin 在 HIGH 维持 70 us 才拉低电平;
因此, 只要超过 90 us ( 保守一点啦)没变 LOW 就可判定 timeout
不过这 loopCnt = 10000; 相当于至少 250 us 是超级保守啰!
if ((micros() - t) > 40) bits[idx] |= (1 << cnt);
这句 if 是说如果收到的是 1 就把 1 塞入该 Byte 该有的位置
为何用 micros( ) -t > 40 作条件呢?
因为刚说了, 依据图片如果 bit 是 0, 则 HIGH 应维持约 28us,
如果 bit 是 1, 则 HIGH 应维持 70 us;
假如你用 micros( ) -t > 30 当然也可以,
可是 28 和 30 太近, 万一 dht 自己时序不准确呢 !?
所以保守一点, 用 40 us 当作门坎 !
假如用 70 us 当门坎则也很危险,
因万一 dht11 不准确在 68 us 就拉低, 那 1 就被判为 0 了,
所以, 最好的门坎应该在 40 到 55 之间 !
还有,
从这就可看出万一你在 ISR( ) 内做太多事会影响 dht11 读取!
你看, 假如你刚做了 unsigned long t = micros();
然后就被 ISR( ) 抢走 CPU 执行权,
只要在 ISR( )内做超过 70 us 就铁定出问题 !
Why ?
因为这时 pin 一定已经变 LOW,
然而在 ISR( ) 内因为中断禁止会导致 micros( ) 几乎不变!
(注意, 中断禁止是 millis( ) 不会变, 但 micros( )略为会变!)
这样相当于 Arduino 这边时间静止, 但其实 dht11 已经过了 70us,
于是到底是 0 还是 1 我们会搞错!
如果 ISR( ) 做事超过 78us, 甚至可能影响下一个 bit 的接收!
这里的 78us 是因为万一这 bit 是 0, 会在 28 us 后拉低电平,
表示另一个 bit 即将开始, 依据图片, 开始是拉低持续 50us,
所以, 78 us 之后我们就又拉高, 这样我们没看到拉低,
相当于错过了一个 bit 啰 !
注意喔,
一个 analogRead( ) 就要大约 108us = 大约0.11 ms
所以, 尽量不要在 ISR( ) 内做 analogRead( )
|