zoukankan      html  css  js  c++  java
  • 【STM32 .Net MF开发板学习19】DHT11温湿度传感器通信(上)

    前段时间开发远程医疗系统(Dr.Cloud)就曾用到过温湿度传感器,不过当时考虑到集成难度,选了一个RS485接口的传感器,该传感器实现了Modbus Rtu Slave的功能,只要客户程序实现Modbus Rtu Client即可读出温湿度数据。是方便了开发,不过价格不菲,要价要150元左右。

    网友fangyuan推荐了一款仅7元的DHT11温湿度传感器,刚开始以为是TTL电平的串口通信,后来一研究,原来通过一根数据线的双向通信,并且对时序要求很严格,这东西也许用单片做更容易,用STM32来做,反而有老虎吃天,无从下口之感。想来想去,最理想的方式也许需要深入研究时钟的输入捕获相关知识了。

    不过直到三个多月之后的今天,才有时间和精力去研究相关内容。闲言少叙,先看一下DHT11的典型应用电路(见下图)。

    通信接口为串行接口(单线双向),通信过程如下:

    数字0和数字1的信号表示方法如下(有点类似红外遥控器的编码了):

    一次完整的数据传输为40bit,高位先出。

    数据格式:8bit湿度整数数据+8bit湿度小数数据

    +8bi温度整数数据+8bit温度小数数据

             +8bit校验和

    其工作模式为:用户MCU发送一次开始信号后,DHT11从低功耗模式转换到高速模式,等待主机开始信号结束后,DHT11发送响应信号,送出40bit的数据,并触发一次信号采集,用户可选择读取部分数据.从模式下,DHT11接收到开始信号触发一次温湿度采集,如果没有接收到主机发送开始信号,DHT11不会主动进行温湿度采集.采集数据后转换到低速模式。

    详细资料请从如下地址下载:http://download.csdn.net/source/2535109

    单片机读取数据的一般思路就是,延时一定的时间,去读Data数据线的电平是高是低,从而判断数据是0还是1。不过这样做,对延时精度要求很高,否则很容易把起始位当成数据位来判断了。

    但是在STM32系统,由于存在多任务和中断程序,如果用传统的延时方法,是很难满足多任务下数据读取需求的,所以我最直接的思路还是,通过时钟的输入捕获功能,获取Data数据线上所有上升沿和下降沿的精确时间,有了这个数据,就可以非常精确的判断出数字0和数字1了。

    设置时钟的代码如下:

    //72M/(71+1)=1M   1us一次滴答     

    CPU_TIMER_Initialize(timer,0xFFFF,71,TIMER_ISR,NULL);

    STM32F10x_TIMER &tim=STM32F10x::TIMER(timer);

    //TIM3_CH3

    tim.CCMR[1] = 0x01 | 0x30;      //输入模式,滤波为映射到TI3

    tim.CCER = 0x0200;              //下降沿有效

    tim.DIER = 0x0008;               //中断

    //tim.CCER |= 0x0100;           //捕获使能

    //TIM3_CH4

    tim.CCMR[1] |= 0x0200 | 0x3000; //输入模式,滤波为8   映射到TI3

    tim.CCER |= 0x0000;             //上升沿有效

    tim.DIER |= 0x0010;

    //tim.CCER |= 0x1000;           //捕获使能

     

    中断TIMER_ISR函数里,记下中断发生时刻的计数器的值,根据这些值,就可以换算为实际的温湿度数据了,相关代码如下:

    STM32F10x_TIMER &tim=STM32F10x::TIMER(timer);       

     time_index = 0;

     HT_Flag = FALSE;

     tim.CCER |= 0x0100;        //捕获使能

     tim.CCER |= 0x1000;        //捕获使能

     Sleep(10000);              //延时 10ms 最长 80+80+40*(50+70) = 4960us = 4.96ms

     tim.CCER &= ~0x0100;       //捕获禁止

     tim.CCER &= ~0x1000;       //捕获禁止

     tim.CR1 = 0x0;              //禁止计数 

     if(time_index>8)

     {

         UINT32 index=0;

              UINT32 data[128];

              

         for(int i=4;i<time_index;i+=2)

         {

            time_data[index++]=time_data[i];

         }

        

         if(index==40)

         {

            for(int i=0;i<5;i++)

            {

               HT_data[i]=0;

               for(int j=0;j<8;j++)

               {

                  HT_data[i]|= time_data[i*8+j] > 40 ? (1 <<(7-j)) :0;

               }

            }

                      HT_Flag = (((HT_data[0]+HT_data[1]+HT_data[2]+HT_data[3]) & 0xFF) == HT_data[4]);

         }    

    }

    接线图和运行后的结果如下图所示,可以看出温湿度已经源源不断的被读出来了。

    以上程序还是底层C/C++的代码,需要封装成托管类库才能供上层应用程序调用,不过这次我的思路和以前不同,不是简单的封装成一个读取接口就成了,我想这部分应用,更具有通用性,在《红外遥控器编码识别》中我们用到方式,其实很笨,并且很容易受到干扰,完全可以采用这种方式,这样做甚至直接就可以识别出相应的编码信息来。

    所以,我打算专门写一篇这种接口封装的博文,以期应用开发的朋友,也可以开发出这种对时序要求严格的应用来。

     

    MF快速参考: .NET Micro Framework 快速入门

    MF中文讨论组:http://space.cnblogs.com/group/MFSoft/

    微软官方论坛:MSDN微软中文技术论坛(.NET Micro Framework)

    开发板简明手册:http://blog.sina.com.cn/s/blog_6b938f630100kh0k.html

    【低价开发板】http://item.taobao.com/item.htm?id=7117999726

  • 相关阅读:
    前沿技术解密——VirtualDOM
    Ques核心思想——CSS Namespace
    Unix Pipes to Javascript Pipes
    Road to the future——伪MVVM库Q.js
    聊聊CSS postproccessors
    【译】十款性能最佳的压缩算法
    Kafka Streams开发入门(9)
    Kafka Streams开发入门(8)
    【译】Kafka Producer Sticky Partitioner
    【译】99th Percentile Latency at Scale with Apache Kafka
  • 原文地址:https://www.cnblogs.com/yefanqiu/p/1872246.html
Copyright © 2011-2022 走看看