【香橙派+DHT11】香橙派(全志H616)+ DHT11温湿度传感器的驱动教程

这篇具有很好参考价值的文章主要介绍了【香橙派+DHT11】香橙派(全志H616)+ DHT11温湿度传感器的驱动教程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、前言

最近写DHT11的代码到香橙派(全志H616)上,发现网上案例基本上都是树莓派+DHT11的居多,香橙派的少,少数找得到的代码跑起来也是不稳定或者数据相对不太准确,于是这里自己写了一篇,供大家参考和批评指正

产品概述


DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器,应用领域:暖通 空调;汽车;消费品;气象站;湿度调节器;除湿器;家电;医疗;自动控制
dht11驱动,单片机,单片机,stm32,嵌入式硬件

特点
  • 相对湿度和温度测量
  • 全部校准,数字输出
  • 长期稳定性
  • 超长的信号传输距离:20米
  • 超低能耗:休眠
  • 4 引脚安装:可以买封装好的
  • 完全互换 : 直接出结果,不用转化
数据传送逻辑

只有一根数据线DATA,主控MCU发送序列指令给DHT11模块,模块一次完整的数据传输为40bit,高位先出

数据格式

8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据+8bit校验和

关于校验:假设接收到的40位数据为:
dht11驱动,单片机,单片机,stm32,嵌入式硬件

计算:
0011 0101 + 0000 0000 + 0001 1000 + 0000 0100 = 0101 0001(校验位)


DHT11通信时序

dht11驱动,单片机,单片机,stm32,嵌入式硬件

(1)主机发送起始信号
首先单片机将连接DHT11 DATA引脚的GPIO口输出低电平,且低电平保持时间不能小于18ms (t1)最大不能超多30ms,然后拉高数据线20~40us (t2) ,等待读取DHT11的响应信号。

(2)检测从机应答信号
DHT11的DATA引脚检测到外部信号有低电平(t1),并等待外部低电平信号结束(t2),延迟后DHT11的DATA引脚处于输出状态,之后DHT11开始输出80 us (t3)的低电平作为应答信号,紧接着输出80us(t4)的高电平通知主机准备接收数据。
主机的I/O此时处于输入状态,检测I/O有低电平(DHT11应答信号)后,等待80us的高电平后接受数据。

(3)数据传输
由DHT11的DATA引脚输出40位数据,采用高位优先方式(MSB),微处理器根据I/0电平的变化接收40位数据。
位数据“0”的格式为:50微秒的低电平和26-28us的高电平。
位数据“1”的格式为:50微秒的低电平加70us的高电平。


二、代码


主体代码主要是利用多线程,用户每发送一次数据读取请求,创建一个线程用于读取数据;利于提高代码的健壮性和扩展性;

同时引入一个blockFlag的标志位,避免子线程代码跑飞无法退出的问题;

并且在测试过程中发现有偶尔测试出温度明显错误的数据;考虑到可能是由于环境、传感器、延时误差等原因导致的数据不准确问题,所以程序中会将超过50°C的数据视为无效数据,自行重新测试,最多自行重试5次

GPIO初始化

因为发送给DHT11的起始信号是先拉低电平,所以拉低电平前先维持一个稳定的高电平状态

void GPIO_init(int gpio_pin)
{
    pinMode(gpio_pin, OUTPUT); // set mode to output
    digitalWrite(gpio_pin, 1); // output a high level
    delay(1000);
}
起始信号

因为DHT11的触发是单次的,即每发送一次起始信号,才会检查一次温湿度,所以发送起始信号的代码必然是要多次复用,所以这里也封装成一个函数

void DHT11_Start_Sig()
{
	pinMode(pinNumber,OUTPUT);	//让GPIO为输出模式
	digitalWrite(pinNumber,HIGH);
	digitalWrite(pinNumber,LOW);
	delay(25);	//维持25ms的低电平
	digitalWrite(pinNumber,HIGH);	//转化为高电平,等待DHT11的响应信号
	
	pinMode(pinNumber,INPUT);
	//响应信号为80us电平与80us的准备信号
	
	pullUpDnControl(pinNumber,PUD_UP);	//进行上拉,增加稳定性,非必选
	delayMicroseconds(35);	//维持35微秒
}
读取数据
void* readSensorData(void *arg)
{
    uint8 crc; 	
    uint8 i;	
	int attempt = 5;	//调用一次最多尝试测5次
	
	while(attempt)
	{
		databuf = 0;	//清空数据存储buf
		crc = 0;		//清空校验位数据存储buf
		DHT11_Start_Sig();	
        
	    if(digitalRead(pinNumber)==0) //检测DHT11是否应答,应答则继续下一步
	    {
	      while(!digitalRead(pinNumber)); //wait to high
          
          //读取4个数据,合计32位
	      for(i=0;i<32;i++)
	      {
		       while(digitalRead(pinNumber)); //data clock start
		       while(!digitalRead(pinNumber)); //data start
	           delayMicroseconds(HIGH_TIME);	//如果32微秒后,仍然检测到是高电平,则该数据位为1
	           databuf*=2;		//移位到buf的更高位
	           if(digitalRead(pinNumber)==1) //1
	            {
	                databuf++;
	            }
	      }
          //读取校验位
	      for(i=0;i<8;i++)
	      {
			  	while(digitalRead(pinNumber)); //data clock start
			    while(!digitalRead(pinNumber)); //data start
		        delayMicroseconds(HIGH_TIME);
		        crc*=2;  
		        if(digitalRead(pinNumber)==1) //1
		        {
		           crc++;
		        }
	      }
          
		  //用于校验数据的准确性,当温度大于50时,视为无效数据
	  	  if(((databuf>>8)&0xff) > 50)
		  {
			 attempt--;
			 delay(500);	//不加这段延迟,下一次传感器来不及响应
			 continue;
		  }	
		  else
		  {
            //打印数据
		  	printf("Congratulations ! Sensor data read ok!\n");
	       	printf("RH:%lu.%lu\n",(databuf>>24)&0xff,(databuf>>16)&0xff); 
	       	printf("TMP:%lu.%lu\n",(databuf>>8)&0xff,databuf&0xff);
			blockFlag = 0;	//用来避免程序有时候跑飞,卡在此函数中,无法跳出
			return (void*)1;
		  }
	   }
	   else		//dht not answer
	   {
	   		blockFlag = 0;
	   		printf("Sorry! Sensor dosent ans!\n");
	        return (void*)0;
	   }
	}
    
    //如果代码执行到这里,则证明尝试读取了5次数据,都是不准确的数据
	blockFlag = 0;
	printf("get data fail\n");
	return (void*)2;
}
整体代码
#include <wiringPi.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include "contrlDevices.h"

typedef unsigned char uint8;
typedef unsigned int  uint16;
typedef unsigned long uint32;
 
#define HIGH_TIME 32
 
int pinNumber = 6;  //use gpio1 to read data
uint32 databuf;
int blockFlag;


void GPIO_init(int gpio_pin)
{
    pinMode(gpio_pin, OUTPUT); // set mode to output
    digitalWrite(gpio_pin, 1); // output a high level
    delay(1000);
    //return;
}


void DHT11_Start_Sig()
{
	pinMode(pinNumber,OUTPUT);
	digitalWrite(pinNumber,HIGH);
	digitalWrite(pinNumber,LOW);
	delay(25);
	digitalWrite(pinNumber,HIGH);
	
	pinMode(pinNumber,INPUT);
	//响应信号为80us电平与80us的准备信号
	
	pullUpDnControl(pinNumber,PUD_UP);
	delayMicroseconds(35);
}
 
 
void* readSensorData(void *arg)
{
    uint8 crc; 	
    uint8 i;	
	int attempt = 5;	//调用一次最多尝试测5次
	
	while(attempt)
	{
		databuf = 0;	//清空数据存储buf
		crc = 0;		//清空校验位数据存储buf
		DHT11_Start_Sig();	
        
	    if(digitalRead(pinNumber)==0) //检测DHT11是否应答,应答则继续下一步
	    {
	      while(!digitalRead(pinNumber)); //wait to high
          
          //读取4个数据,合计32位
	      for(i=0;i<32;i++)
	      {
		       while(digitalRead(pinNumber)); //data clock start
		       while(!digitalRead(pinNumber)); //data start
	           delayMicroseconds(HIGH_TIME);	//如果32微秒后,仍然检测到是高电平,则该数据位为1
	           databuf*=2;		//移位到buf的更高位
	           if(digitalRead(pinNumber)==1) //1
	            {
	                databuf++;
	            }
	      }
          //读取校验位
	      for(i=0;i<8;i++)
	      {
			  	while(digitalRead(pinNumber)); //data clock start
			    while(!digitalRead(pinNumber)); //data start
		        delayMicroseconds(HIGH_TIME);
		        crc*=2;  
		        if(digitalRead(pinNumber)==1) //1
		        {
		           crc++;
		        }
	      }
          
		  //用于校验数据的准确性,当温度大于50时,视为无效数据
	  	  if(((databuf>>8)&0xff) > 50)
		  {
			 attempt--;
			 delay(500);	//不加这段延迟,下一次传感器来不及响应
			 continue;
		  }	
		  else
		  {
            //打印数据
		  	printf("Congratulations ! Sensor data read ok!\n");
	       	printf("RH:%lu.%lu\n",(databuf>>24)&0xff,(databuf>>16)&0xff); 
	       	printf("TMP:%lu.%lu\n",(databuf>>8)&0xff,databuf&0xff);
			blockFlag = 0;	//用来避免程序有时候跑飞,卡在此函数中,无法跳出
			return (void*)1;
		  }
	   }
	   else		//dht not answer
	   {
	   		blockFlag = 0;
	   		printf("Sorry! Sensor dosent ans!\n");
	        return (void*)0;
	   }
	}
    
    //如果代码执行到这里,则证明尝试读取了5次数据,都是不准确的数据
	blockFlag = 0;
	printf("get data fail\n");
	return (void*)2;
}
 
int main ()
{

	pthread_t tid;
	int waitTimes = 10;
	char cmd[5] = {'\0'};
	
    if (wiringPiSetup() == -1) 
    {
    	printf("Setup wiringPi failed!");
    	return 1;
  	}
  	printf("Enter OS-------\n");
  
    while(1)
    {
     	waitTimes = 10;		
        blockFlag = 1;
        delay(1000);
        printf("input y\n");
        scanf("%s",cmd);
        getchar();
        if(strcmp(cmd,"y") == 0)
        {
            //创建一个线程用于读取传感器数据;
            //严谨来说此处的tid并发时有bug;读者可以自行优化,可以用互斥锁或者tid设为数组等都行
            //就当作留给读者的一个小作业吧
            if (pthread_create(&tid, NULL, readSensorData, NULL) != 0)
            {
                printf("thread create fail!\n");
                return -1;
            }
            
            //等待数据读取线程10s钟,如果10后blockFlag未置0,则说明读数据时跑飞卡住了
            while(waitTimes && blockFlag)
            {
                delay(1000);
                waitTimes--;
            }
            //强行结束跑飞的线程
            if(blockFlag == 1)
            {
                pthread_cancel(tid);
                printf("线程超时退出.....\n");
            }
        }
        else
        {
            printf("go on\n");
            continue;
        }
    }
    return 0;
}


执行结果

dht11驱动,单片机,单片机,stm32,嵌入式硬件


参考文章:
STM32一线协议-DHT11温湿度传感器采样实现文章来源地址https://www.toymoban.com/news/detail-668280.html

到了这里,关于【香橙派+DHT11】香橙派(全志H616)+ DHT11温湿度传感器的驱动教程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • STM32+DHT11温湿度传感器

    STM32+DHT11温湿度传感器

    DATA 用于微处理器与 DHT11之间的通讯和同步,采用单总线数据格式,一次 通讯时间4ms左右,数据分小数部分和整数部分,具体格式在下面说明,当前小数 部分用于以后扩展,现读出为零.操作流程如下: 一次完整的数据传输为40bit,高位先出。 数据格式:8bit湿度整数数据+8bit湿度小数数据

    2023年04月13日
    浏览(45)
  • STM32--DHT11温湿度传感器

    STM32--DHT11温湿度传感器

    本文介绍基于STM32F103实现的DHT11温湿度传感器数据采集及显示,完整代码见文末链接 一、DHT11传感器简介 DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期

    2024年02月16日
    浏览(47)
  • STM32—DHT11温湿度传感器

    STM32—DHT11温湿度传感器

    (1).下图一是DHT11总的时序图。 (2).图二对应图一的左边黑色部分,图三对应图一的绿色部分,图四的左部分图对应图一的红色部分,图四的右部分对应图一的黄色部分。 (3).首先图二部分是单片机向DHT11发送我要开始的信号,此时单片机IO口处于输出模式,输出低电平至少18MS,

    2024年02月19日
    浏览(47)
  • FPGA—DHT11数字温湿度传感器

    FPGA—DHT11数字温湿度传感器

    目录 1. 理论学习 2.实操 2.1 顶层模块 2.1.1 整体模块框图 2.1.2 顶层代码 2.2 DHT11 控制模块 2.2.1 模块框图 2.2.2 状态转换图绘制 2.2.3 波形图绘制 2.2.4 RTL代码 2.3 上板验证 3. 总结 DHT11简介        DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应

    2024年02月06日
    浏览(242)
  • stm32读取DHT11温湿度传感器

    stm32读取DHT11温湿度传感器

    我们知道DHT11是单总线协议,只有一根数据线。 且内部有个上拉电路(下图)。那么数据线默认就是高电平那接下来就可以讲解主机如何和DHT11通讯的 读取DHT11的芯片手册,可以知道,DHT11一次完成的数据输出是40bit,高位先出。 格式:8bit湿度整数数据+8bit湿度小数数据 +8bi温

    2024年02月09日
    浏览(45)
  • FPGA读取DHT11数字温湿度传感器

    FPGA读取DHT11数字温湿度传感器

    最近在做一个DHT11相关的东西,写了一个DHT11控制模块。参考了正点原子和野火电子的文档资料后总觉得又乱又杂,所以自己跟着数据手册写了一遍,当然了也很感谢正点原子和野火文档的帮助。 DHT11是一种数字温湿度传感器,有4个引脚但只有三个有效引脚,分别是VDD,DATA和

    2024年02月05日
    浏览(47)
  • 51单片机(DHT11温湿度传感器)

    51单片机(DHT11温湿度传感器)

    DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器,应用领域:暖通 空调;汽车;消费品;气象站;湿度调节器;除湿器;家电;医疗;自动控制 相对湿度和温度测量 全部校准,数字输出 长期稳定性 超长的信号传输距离:20米 超低能耗:休眠 4 引脚

    2024年02月02日
    浏览(45)
  • stm32连接DHT11温湿度传感器

    stm32连接DHT11温湿度传感器

    目录 1. DHT11简介 1.1. 连接电路  1.2. 串行接口 (单线双向)  2. cubeMX设置 3. 代码开发  3.1. 实现定时函数 3.2. 打开串口调试 3.4. 测试代码实现 4. 运行效果 信息如下: 建议连接线长度短于20米时用5K上拉电阻,大于20米时根据实际情况使 用合适的上拉电阻  DHT11的供电电压为 3-5

    2023年04月16日
    浏览(47)
  • FPGA project : dht11 温湿度传感器

    FPGA project : dht11 温湿度传感器

    没有硬件,过几天上板测试。        其他模块都是之前的,就不发了。    

    2024年02月08日
    浏览(49)
  • DHT11温湿度传感器(配合树莓派使用)

    DHT11温湿度传感器(配合树莓派使用)

    DHT11是一种数字温湿度传感器,可以测量周围环境的温度和相对湿度。该传感器使用单个数字信号线与微控制器通信,具有较高的可靠性和稳定性。它适用于许多应用领域,如气象观测、室内环境监测、工业控制等。 DHT11传感器使用的基本原理是通过感应元件测量周围环境的

    2024年02月06日
    浏览(14)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包