最近在学习Linux应用和安卓开发过程中,打算把Linux实现的温湿度显示安卓app上,于是在此之前先基于Orangepi Zero2 全志H616下的wiringPi库对DHT11进行开发,本文主要记录开发过程的一些问题和细节,主要简单通过开启线程来接收温湿度数据,代码还有优化空间,仅供参考。
一、DHT11时序图
数据传送逻辑
模块一次完整的数据传输为40bit,高位在前
数据格式
8bit湿度整数数据+8bit 湿度小数数据 +8bi 温度整数数据 +8bit 温度小数数据 +8bit 校验和
通讯过程时序图
具体DHT11时序分析可以查看主页(4条消息) 51单片机(DHT11温湿度传感器)_51单片机温湿度传感器代码_zoacyf的博客-CSDN博客
二、代码模块
温湿度DHT11初始化
int readSensorData(void) //温湿度初始化
{
char i;
pinMode(dht, OUTPUT); // 将模式设置为输出
digitalWrite(dht, LOW); // 输出高电平
delay(25);
digitalWrite(dht, HIGH); // 输出低电平
pinMode(dht, INPUT); // 将模式设置为输入
pullUpDnControl(dht, PUD_UP);
delayMicroseconds(27);
if (digitalRead(dht) == 0){
while (!digitalRead(dht)); // wait to high
for (i = 0; i < 32; i++)
{
while (digitalRead(dht)); // 数据时钟启动
while (!digitalRead(dht)); //数据开始
delayMicroseconds(40);
databuf *= 2;
if (digitalRead(dht) == 1) // 1
{
databuf++;
}
}
return 1;
}else
{
return 0;
}
}
温湿度读取线程
void *dht11_thread(void *datas) //温湿度线程
{
int W = 0, w = 0;
int S = 0, s = 0;
printf("Use GPIO7 to read data!\n");
pinMode(dht, OUTPUT); // set mode to output
digitalWrite(dht, HIGH); // output a high level
printf("Enter OS-------\n");
while (1)
{
if (readSensorData())
{
W = (databuf >> 8) & 0xff;
w = databuf & 0xff;
S = (databuf >> 24) & 0xff;
s = (databuf >> 16) & 0xff;
}
delay(2000);
if ((W >= 15) && (W <= 35) && (S <= 85) && (S>=15))
{
printf("此时的温湿度为:\n");
printf("温度:%d.%d\n", W, w); //温度
printf( "湿度:%d.%d\n", S, s); //湿度
databuf = 0;
}else{
printf("Sorry! Sensor dosent ans!\n");
databuf = 0;
continue;
}
}
}
三、整体代码
开发过程中遇到的主要问题:
1、温度或湿度数据会出现极端的现象,我们可以做代码优化,丢弃极端数据。2、程序运行卡住,只出现几组数据,这个问题非常头疼。刚开始分析是while里面用sleep造成,经过验证发现并不是,给线程加互斥锁也无法解决问题,最后发现把校验位去掉程序就正常运行,因此盲猜是数据存储的问题导致程序跑飞,大家可以用数组尝试处理,这里我就直接把校验位去掉一直收集温湿度数据了,若需要指令收集温湿度数据可以参考下面博文,本人觉得该大佬写得不错。
(4条消息) 【香橙派+DHT11】香橙派(全志H616)+ DHT11温湿度传感器的驱动教程_RIO小哥的博客-CSDN博客
整体代码
#include <stdio.h>
#include <wiringPi.h>
#include <pthread.h>
#include <unistd.h>
#define dht 7 //引脚接口
unsigned long databuf; //温湿度数据保存区
int readSensorData(void) //温湿度初始化
{
char i;
pinMode(dht, OUTPUT); // 将模式设置为输出
digitalWrite(dht, LOW); // 输出高电平
delay(25);
digitalWrite(dht, HIGH); // 输出低电平
pinMode(dht, INPUT); // 将模式设置为输入
pullUpDnControl(dht, PUD_UP);
delayMicroseconds(27);
if (digitalRead(dht) == 0){
while (!digitalRead(dht)); // wait to high
for (i = 0; i < 32; i++)
{
while (digitalRead(dht)); // 数据时钟启动
while (!digitalRead(dht)); //数据开始
delayMicroseconds(40);
databuf *= 2;
if (digitalRead(dht) == 1) // 1
{
databuf++;
}
}
return 1;
}else
{
return 0;
}
}
void *dht11_thread(void *datas) //温湿度线程
{
int W = 0, w = 0;
int S = 0, s = 0;
printf("Use GPIO7 to read data!\n");
pinMode(dht, OUTPUT); // set mode to output
digitalWrite(dht, HIGH); // output a high level
printf("Enter OS-------\n");
while (1)
{
if (readSensorData())
{
W = (databuf >> 8) & 0xff;
w = databuf & 0xff;
S = (databuf >> 24) & 0xff;
s = (databuf >> 16) & 0xff;
}
delay(2000);
if ((W >= 15) && (W <= 35) && (S <= 85) && (S>=15))
{
printf("此时的温湿度为:\n");
printf("温度:%d.%d\n", W, w); //温度
printf( "湿度:%d.%d\n", S, s); //湿度
databuf = 0;
}else{
printf("Sorry! Sensor dosent ans!\n");
databuf = 0;
continue;
}
}
}
int main()
{
int ret;
pthread_t dht11Thread;
if (-1 == wiringPiSetup())
{
printf("Setup wiringPi failed!");
}
ret = pthread_create(&dht11Thread,NULL,dht11_thread,NULL);//启动线程不断获取温湿度数据
if(ret == 0){
printf("dht11Thread create success!\n");
}
pthread_join(dht11Thread,NULL);//等待线程退出
return 0;
}
运行shell编译
bulid.sh
gcc $1 -lwiringPi -lwiringPiDev -lpthread -lm -lcrypt -lrt
//shell 脚本处理参数,可以通过 $?来处理,这里的$1后面是要编译的文件
//脚本运行没有权限,需加运行权限 (chmod +x build.sh)