zoukankan      html  css  js  c++  java
  • 如何为编程爱好者设计一款好玩的智能硬件(六)——初尝试·把温湿度给收集了(下)!

    一、我的构想:如何为编程爱好者设计一款好玩的智能硬件(一)——即插即用、积木化、功能重组的智能硬件模块构想

    二、别人家的孩子:如何为编程爱好者设计一款好玩的智能硬件(二)——别人是如何设计硬件积木的!

    三、MCU选型:如何为编程爱好者设计一款好玩的智能硬件(三)——该选什么样的MCU呢?

    四、温湿度传感器DHT11驱动封装(上):如何为编程爱好者设计一款好玩的智能硬件(四)——初尝试·把温湿度给收集了(上)!

    五、温湿度传感器DHT11驱动封装(中):如何为编程爱好者设计一款好玩的智能硬件(五)——初尝试·把温湿度给收集了(中)!

    六、温湿度传感器DHT11驱动封装(下):

      

      这几天该进程稍微中断,一方面是因为帮助一个好朋友处理保研的事情,另一方面是由于我在思考每天一篇是否会因为过于频繁而缺少干货。于是我决定每个月的模3余0的日子总结一下~特此通告!在四、五两篇中我们详细分析了DHT11的驱动流程,由于我们需要一个便于移植的版本,所以上次挖了个坑说会采用宏定义来尽量方便移植。因此,本节将首先讨论宏定义相关知识,而后封装一个稍微改进的DHT11驱动。

    C Macros

     
    理解宏:
     
      宏是一种预处理指令,它提供了一种机制,可以用来替换源代码中的字符串,宏是用“#define"语句定义的,下面是一个宏定义的例子:
        #define VERSION—STAMP "1.02"
      上例中所定义的这种形式的宏通常被称为标识符。在上例中,标识符VERSION_STAMP即代表字符串"1.02"——在编译预处理时,源代码中的每个VERSION_STAMP标识符都将被字符串“1.02”替换掉。

      以下是另一个宏定义的例子:
          #define CUBE(x)  ((x)*(x)*(x))
      上例中定义了一个名为CUBE的宏,它有一个参数x。CUBE宏有自己的宏体,即((x)*(x)*(x))——在编译预处理时,源代码中的每个CUBE(x)宏都将被((x)*(x)*(x))替换掉。

    使用宏有以下几点好处:

         (1)在输入源代码时,可省去许多键入操作。   
        (2)因为宏只需定义一次,但可以多次使用,所以使用宏能增强程序的易读性和可靠性。
        (3)使用宏不需要额外的开销,因为宏所代表的代码只在宏出现的地方展开,因此不会引起程序中的跳转。
        (4)宏的参数对类型不敏感,因此你不必考虑将何种数据类型传递给宏。
     
    容易出错的地方:

      需要注意的是,在宏名和括起参数的括号之间绝对不能有空格。此外,为了避免在翻译宏时产生歧义,宏体也应该用括号括起来。

    你可能不知道的:

      宏也可使用一些特殊的运算符,例如字符串化运算符“#”和。连接运算符“##”。“#”运算符能将宏的参数转换为带双引号的字符串,请看下例:
          define DEBUG_VALUE(v)  printf(#v"is equal to %d. ",v)
      你可以在程序中用DEBUG_VALUE宏检查变量的值,请看下例:
          int x=20;
          DEBUG_VALUE(x);
      上述语句将在屏幕上打印"x is equal to 20"。这个例子说明,宏所使用的“#”运算符是一种非常方便的调试工具。
      “##”运算符的作用是将两个独立的字符串连接成一个字符串。
     
    这篇文章对宏的种类进行简单的介绍:http://blog.csdn.net/ocean181/article/details/6818687
    这篇文章单独读宏里面的#进行介绍:http://blog.sina.com.cn/s/blog_550405a10100bqar.html
    这篇文章讲了宏中的几个高级的用法:http://www.cnblogs.com/Anker/p/3418792.html (do while)
     
     
    DHT11驱动封装 
     
    DHT11.H
     1 #ifndef __DHT11_H__
     2 #define __DHT11_H__
     3 
     4 #include "delay.h"
     5 
     6 //some typedef need to do
     7 typedef unsigned char    t_uc;
     8 typedef unsigned short     t_us;
     9 typedef unsigned int      t_ui;
    10 typedef char        t_c;
    11 typedef short         t_s;
    12 typedef int          t_i;
    13 
    14 #define DHT11_DELAY_US(x)     Delay_us((x))
    15 #define DHT11_DELAY_MS(x)     Delay_ms((x))
    16 #define DHT11_DATA_PIN        P0_0
    17 #define DHT11_DATA_PIN_READ   DHT11_DATA_PIN          //read the data_pin's data function 
    18 #define DHT11_DATA_PIN_SET    DHT11_DATA_PIN=1        
    19 #define DHT11_DATA_PIN_CLEAR  DHT11_DATA_PIN=0
    20 #define DHT11_DATA_PIN_IN     P0DIR&=~0x01
    21 #define DHT11_DATA_PIN_OUT    P0DIR|=0x01
    22 
    23 
    24 extern    t_i DHT11_GetData(t_us *humidity, t_us *temperature);
    25 
    26 
    27 #endif

    移植的时候只要对.H进行修改就行啦! 

      上面是封装的DHT11的驱动.H文件,可见为了达到方便移植到各个平台的目的,我们在红色部分重定义了数据类型,并且在绿色部分将几个外部依赖全部定义成宏。这样移植到不同平台的时候只需要根据特定的平台,稍微调动下红色部分重定义的数据类型,并且根据宏定义部分相应的功能进行封装和修改(这样.C文件是不需要动的,是不是很方便!)

      这里对部分宏定义进行说明:

      ① DHT11_DATA_PIN 是DHT11通信数据线连在单片机上的引脚  
      ② DHT11_DATA_PIN_READ是读取DHT11_DATA_PIN引脚上的数据函数,返回为该引脚的状态(高电平为1,低电平为0)
      ③ DHT11_DATA_PIN_SET和DHT11_DATA_PIN_CLEAR功能分别是置DHT11_DATA_PIN引脚为高电平和低电平功能函数
      ④ DHT11_DATA_PIN_IN和DHT11_DATA_PIN_OUT功能分别是设置DHT11_DATA_PIN引脚为输入和输出模式

        PS:

      这里第4行引入的外部文件提供delay延时相关函数,同样的第14、15行宏定义也将所要用到的延时微秒和毫秒的函数进行宏定义,总的来说就是方便移植~

    DHT11.C

     1 #include "DHT11.H"
     2 
     3 
     4 t_uc COM(void)//read 8bits data from com
     5 {
     6     t_uc flag, temp; //flag and temp
     7     t_uc comdata;//the 8bits data read from com
     8     t_uc i;
     9     for(i = 0; i < 8; i++)
    10     {
    11         flag = 2;
    12         while((!DHT11_DATA_PIN_READ) && flag++);
    13         DHT11_DELAY_US(30);
    14         temp = 0;
    15         if(DHT11_DATA_PIN_READ)temp = 1;
    16         flag = 2;
    17         while((DHT11_DATA_PIN_READ) && flag++);
    18         if(flag == 1)break;
    19         comdata <<= 1;
    20         comdata |= temp;
    21     }
    22     return comdata;
    23 }
    24 
    25 t_i DHT11_GetData(t_us *humidity, t_us *temperature)//get the hunidity and temperature data
    26 {
    27     t_uc flag, temp; //flag and temp
    28     t_uc ucharT_data_H_temp, ucharT_data_L_temp,
    29          ucharRH_data_H_temp, ucharRH_data_L_temp,
    30          ucharcheckdata_temp;
    31 
    32     //1、start
    33     DHT11_DATA_PIN_OUT; //set the data pin as out mode
    34     DHT11_DATA_PIN_CLEAR;
    35     DHT11_DELAY_MS(19);  //>18MS
    36     DHT11_DATA_PIN_SET;
    37     DHT11_DATA_PIN_IN; //set the data pin as input mode
    38     DHT11_DELAY_US(40);
    39     
    40     if(!DHT11_DATA_PIN_READ)
    41     {
    42         //2、wait
    43         flag = 2;
    44         while((!DHT11_DATA_PIN_READ) && flag++);
    45         flag = 2;
    46         while((DHT11_DATA_PIN_READ) && flag++);
    47 
    48         //3、read data
    49         ucharRH_data_H_temp = COM();
    50         ucharRH_data_L_temp = COM();
    51         ucharT_data_H_temp = COM();
    52         ucharT_data_L_temp = COM();
    53         ucharcheckdata_temp = COM();
    54 
    55         //4、stop
    56         DHT11_DATA_PIN_SET;
    57         
    58         temp = (ucharT_data_H_temp + ucharT_data_L_temp + ucharRH_data_H_temp + ucharRH_data_L_temp);
    59         if(temp == ucharcheckdata_temp) //check the data ,then updata humidity and temperature
    60         {
    61             *humidity = ucharRH_data_H_temp;
    62             *temperature = ucharT_data_H_temp;
    63         }
    64     }
    65     else //fail return -1
    66     {
    67         return -1;
    68     }
    69     
    70     return 0;
    71 }

     .C文件是不用改的~和前两节讲解的相比,这里基本没变,只是将部分函数换成了宏

    得说明的:

      前两节讲过从DHT11中读出来的40bits数据包括温湿度整数和小数部分各8bit表示+一个8bit的校验,上面.C文件第61、62行仅将整数部分提取

    小结&接下来计划:

      至此,我们终于把DHT11给封装好了,接下来不会那么频繁更新(毕竟太快没干货!)。下次我将首先展示该驱动在CC2541(上面的便是基于它的)、STM32、51平台上的移植方法,然后开启一个新的驱动封装——显示器。至于要选择哪一款,暂时还没定,也先留个悬念吧~

     

     

    链接

    基于CC2541平台的实验工程

    >只有DHT11.C和DHT11.H经过整理,其它可能有点乱,见谅<

    http://pan.baidu.com/s/1hq6N168 

     

    DHT11.C和DHT11.H文件

    http://pan.baidu.com/s/1dD0ibDJ

    http://pan.baidu.com/s/1qeHBK

     

     

      

    @beautifulzzzz

      2015-9-17 持续更新中~

     
     
     
  • 相关阅读:
    HDU 2094 产生冠军
    CodeForce 837 A/B/C解题报告
    HDU 4825 Xor Sum 【01字典树】
    Kruskal 最小生成树
    并查集
    ccf 201812-4
    Prim 最小生成树
    ccf 201812-1
    ccf 201812-2
    getline()
  • 原文地址:https://www.cnblogs.com/zjutlitao/p/4814670.html
Copyright © 2011-2022 走看看