基于树莓派的空气监测系统(4)DHT11模块程序
硬件模块说明
- 器件(奥松 dht11)
- DC:3.3-5.5v
- 温度:0 - 50°C (±2°C)
- 湿度:20 - 95 %RH(±5%)
工作时序图
初始化时序
读取数据0时序
读取数据1时序
DHT11驱动开发问题
不同频率CPU引起的时序操作问题
1.初始化时序不要加入无关操作,如调试,输出,减少对时序的影响。
2.时序操作连续化,单片机上可多次调用函数读取,但在高主频的CPU上要一次读取全部数据后再进行后期处理。
树莓派GPIO开发简介
树莓派有许多的GPIO(General Purpose Input Output:通用输入/输出),可以用来控制和读取数字电路中TTL电平的逻辑0和逻辑1。首先要知其GPIO的定义,常用的有两种编号定义:WiringPi Pin和BCM GPIO。
GPIO的驱动库这里介绍两种,一种为C语言的WiringPi,另一种为python的RPi.GPIO。
查看当前开发板的gpio接口
$gpio readall
安装wiringPi库
安装git-core
$ sudo apt-get install git-core
载winringPi库
$ git clone git://git.drogon.net/wiringPi
编译和安装库 (在/wiringPi/examples目录中有一些例子可供大家参考)
$ cd wiringPi
$ ./build
编译程序时要链接wiringPi的库,加库选项 -lwiringPi。
$ gcc pi_dht11.c -o pi_dht11 -lwiringPi
wiringPi库相关接口函数
wiringPiSetup();//初始化io
pinMode(GPIO, OUTPUT);//设置输出
digitalWrite(GPIO, LOW); //输出低电平
digitalWrite(GPIO, HIGH); //输出高电平
pinMode(GPIO,INPUT);//设置输入
delay(18);//延时18ms
delayMicroseconds(35);//延时35us
树莓派dht11程序(pi_dht11.c)
树莓派开发GPIO程序,只需要在应用层调用GPIO库的接口。
#include <wiringPi.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
//pi3
unsigned int GPIO = 4;//模块GPIO脚
//#define DPRINTK(x...) printf(x);
#define DPRINTK(x...)
unsigned char U8_data[5];
int get_dht_data(float* temp,float* humi);
int init_dht(void);
int main()
{
float ftemp=0.0,fhumi=0.0;
if(wiringPiSetup()==-1){
printf("pi setup err...\n");
return 1;
}
while(1)
{
if(get_dht_data(&ftemp,&fhumi)==0)
printf("RH=%2f %%,T=%2f oC.\n",fhumi,ftemp);
sleep(3);
}
return 0;
}
int init_dht(void)
{
int l_flag=0,h_flag=0,flag=0;
int i=0,j=0;
int bit_flag[40];
unsigned tmp;
unsigned char U8comdata,U8temp[40];
DPRINTK("DHT11 init...");
//GPIO设置为输出
pinMode(GPIO, OUTPUT);//设置输出
//输出0
digitalWrite(GPIO, LOW); //输出低电平
//延时19ms
delay(18);
//输出1
digitalWrite(GPIO, HIGH); //输出高电平
//延时30us
delayMicroseconds(35);
//设置为输入
pinMode(GPIO,INPUT);//设置输入
//读GPIO
tmp = digitalRead(GPIO) ;
// DPRINTK("gpio=%d\n",tmp);
if(!tmp)
{
while(!(digitalRead(GPIO)) ){
if((l_flag++)>85) break;
delayMicroseconds(1);
}//从机80us低电平
while(digitalRead(GPIO)){
if((h_flag++)>85) break;
delayMicroseconds(1);
}//从机80us高电平
//read 40bit data
for(i=0;i<40;i++){
flag = 0;
while(!(digitalRead(GPIO)) ){
if((flag++)>70) break;
delayMicroseconds(1);
}//从机50us低电平
flag =0;
while(digitalRead(GPIO) ){
if((flag++)>90) break;
delayMicroseconds(1);
}//从机高电平//高电平大于70us为"1",否则26-28us为"0"
if(flag>30){
U8temp[i]=1;
}else{
U8temp[i]=0;
}
bit_flag[i]=flag;
}
for(i=0;i<40;i++){
U8comdata<<=1;
U8comdata|=U8temp[i];
if((i+1)%8 == 0){
U8_data[j]=U8comdata;
j++;
}
// DPRINTK("[%d]flag=%d,val=%d--",i,bit_flag[i],U8temp[i]);
}
DPRINTK("L 80us flag=%d\n",l_flag);
DPRINTK("H 80us flag=%d \n",h_flag);
}else{DPRINTK("L err..\n");}
return 0;
}
int get_dht_data(float* temp,float* humi)
{
char crr=0;
int s=0;
int temp_d=0,humi_d=0;
init_dht();
for(s;s<4;s++){
// printf("data[%d]=%x\n",s,U8_data[s]);
crr+=U8_data[s];
}
// printf("data[4]=%x,crr=%x\n",U8_data[4],crr);
if(crr==U8_data[4]){
humi_d = U8_data[0];
temp_d = U8_data[2];
*humi = humi_d;
*temp = temp_d;
printf("\n+---RH=%d %%,T=%d oC.\n",humi_d,temp_d);
}else{
printf("crr err %X\n",crr);
return -1;
}
return 0;
}