raspberrypi/gpio/dht11.c

121 lines
2.7 KiB
C

/*
* DTH11 温度湿度传感器
*
*/
#include <wiringPi.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#define MAX_TIME 85
#define MAX_TRIES 100
int dht11_val[5] = { 0, 0, 0, 0, 0 };
int dht11_read_val(int *h, int *t, int pin)
{
uint8_t lststate = HIGH;
uint8_t counter = 0;
uint8_t j = 0, i;
for (i = 0; i < 5; i++) {
dht11_val[i] = 0;
}
pinMode(pin, OUTPUT);
digitalWrite(pin, LOW);
delay(18);
digitalWrite(pin, HIGH);
delayMicroseconds(40);
pinMode(pin, INPUT);
for (i = 0; i < MAX_TIME; i++) {
counter = 0;
while (digitalRead(pin) == lststate) {
counter++;
delayMicroseconds(1);
if (counter == 255)
break;
}
lststate = digitalRead(pin);
if (counter == 255)
break;
// top 3 transitions are ignored
if ((i >= 4) && (i % 2 == 0)) {
dht11_val[j / 8] <<= 1;
if (counter > 16)
dht11_val[j / 8] |= 1;
j++;
}
}
// verify cheksum and print the verified data
if ((j >= 40)
&& (dht11_val[4] ==
((dht11_val[0] + dht11_val[1] + dht11_val[2] +
dht11_val[3]) & 0xFF))) {
// Only return the integer part of humidity and temperature. The sensor
// is not accurate enough for decimals anyway
*h = dht11_val[0];
*t = dht11_val[2];
return 0;
} else {
// invalid data
return 1;
}
}
static int is_num(char *str)
{
int i, len;
for (i = 0, len = strlen(str); i < len; i++) {
if (isdigit(str[i]) == 0) {
printf("不是数字\n");
return 1;
}
}
return 0;
}
int main(int argc, char *argv[])
{
if (argc != 2) {
printf("Parameter error.\n");
exit(1);
}
if (is_num(argv[1]) == 1) {
printf("Parameter error, parameter 1 is PIN pin value\n");
exit(1);
}
int pin = atol(argv[1]);
int h; //humidity
int t; //temperature in degrees Celsius
wiringPiSetup();
// read the sensor until we get a pair of valid measurements
// but bail out if we tried too many times
int retval = 1;
int tries = 0;
while (retval != 0 && tries < MAX_TRIES) {
retval = dht11_read_val(&h, &t, pin);
if (retval == 0) {
//printf("%d %d\n", h, t);
printf("Humidity = %d Temperature = %d ℃ ( %f ℉ )\n", h, t, ((t*1.8)+32));
} else {
delay(3000);
}
tries += 1;
}
if (tries < MAX_TRIES)
return 0;
else
return 1;
}