• 毕昇杯之温湿度采集模块


          这一次使用的温湿度传感器也是经历了几次变动,从开始用的DHT11模块,到接下来的AMD2302,再到最后使用的AMD2302可用版本,不得不说,模块的价位真的决定了她的性能,很大程度上,开始的DHT11这个模块,真心尼玛坑爹啊,调试程序调试了好久,突然间发现他是坏的,AMD2302好好地,就是因为短了一下路,结果就烧了,又白等了几天,他们的性能都差不多,AMD2302的价位是20多块钱,我在想这个是不是在抢钱,好的传感器都比较贵,,,,,但是买东西的一条法则,尤其是元器件,那就是便宜没好货

      总结几条买传感器的法则:1,由于传感器容易坏,所以项目的时候,一定要买两个,也就是所用项目传感器的2倍,

                  2:尽量挑好的传感器用于比赛,嘻嘻,因为学校有报销嘛

    好了现在总结一下AMD2302传感器是怎么样工作的调试程序过程中又能学到什么!!!

    这个是模块资料下载地址:http://download.csdn.net/detail/generoius/7142111

    //****************************************************************//
    //           AM系列读单总线使用范例 
    //单片机 :AT89S52 或 STC89C52RC 
    // 功能  :串口发送温湿度数据  波特率 9600 
    // 晶振  :12M (用户系统时钟如不是12M 请更改相关宏定义及注释的延时时间)
    // 编译环境:  Keil3
    // 公司  :奥松电子    
    //****************************************************************//
    
    #include "reg52.h"
    #include <intrins.h>
    
    //用户根据自己的晶振修改相应值
    #define FOSC  12000000
    #define BAUD  9600 
    
    //读传感器 端口位定义,可修改
    sbit Sensor_SDA = P0^0;
    sbit Sensor_SCL = P0^1;
    
    // 变量定义
    unsigned char Sensor_Data[5]={0x00,0x00,0x00,0x00,0x00};
    unsigned char Sensor_Check;          //校验和
    
    unsigned char Sensor_AnswerFlag;  //收到起始标志位
    unsigned char Sensor_ErrorFlag;   //读取传感器错误标志
    unsigned int  Sys_CNT;
    unsigned int  Tmp;
    
    unsigned char *String;
    
    //字符串定义
    #define S_Temp "Temp:"
    #define S_RH   "RH:"
    #define S_CRCT "Check: True"
    #define S_CRCF "Check: Wrong"
    #define S_Data "Data: "
    #define S_NotS "Sensor Not Connected"
    
    /********************************************
    |* 功能: 延时    晶振为12M时                    *|
    |*  t = 1 为 20us  然后成倍增加10us左右        *|
    ********************************************/
    void Delay_N10us(unsigned char t)
    {
        while(t--)
       {
            _nop_();
       }
    }
    /********************************************
    |* 功能: 延时    晶振为12M时                    *|
    |* 延时大约 1ms                                *|
    ********************************************/ 
    void Delay_N1ms(unsigned int t)
    {
      unsigned int i;
      unsigned int j;
      for(j=t;j>0;j--)
         for(i=124;i>0;i--);  //延时大约 1ms
    }
    /********************************************
    |* 功能: 初始化串口                        *|
    ********************************************/
    void InitUART(void)
      {
        unsigned int iTmpBaud;
        unsigned long lTmpBaud;
        iTmpBaud = 0;
        //首先选定定时器2作为波特率发生器,16位定时器,自动装载
        SCON = 0x50;    //SM0 SM1 SM2 REN TB8 RB8 TI RI        //0   1   0   1   0   0   0  0    
          PCON = 0x00;    //PCON的地址是87H,这里SMOD =0
    
          T2CON = 0x30;    //TF2 EXF2 RCLK TCLK EXEN2 TR2 C(/T2) CP(/RL2) //0 0 1 1 0 0 0 0 
          T2MOD = 0x00;    // /    /    /    /        /    /    T2OE    DCEN   //0 0 0 0 0 0 0 0
    
          lTmpBaud = FOSC/BAUD;
          lTmpBaud /= 32;                        //12T-mode
          iTmpBaud = lTmpBaud & 0xFFFF;        
          iTmpBaud = 65536 - iTmpBaud;
          RCAP2H = (iTmpBaud>>8) & 0x0FF;
          RCAP2L = iTmpBaud & 0x0FF;
    
          RI = 0;            //清除接收中断标志
          REN = 1;        //允许串行接收
          ES = 1;            //允许串行中断
          TR2 = 1;        //启动定时器1
    
          EA=1;//开总中断
      }  
    
    /********************************************
    |* 功能: 串口发送函数                         *|
    ********************************************/
    void UARTSend(char UCHAR)
      {
        SBUF=UCHAR;
        while(TI==0);
        TI=0;
      }
    /********************************************
    |* 功能: 串口中断函数                         *|
    ********************************************/
    void UARTRead(void) interrupt 4
      {
        char temp; 
        if(RI)
        {
          RI=0;
          temp = SBUF;
        }
      }
     /********************************************
    |* 功能: 串口发送子函数                     *|
    ********************************************/
    void UART_PutString(unsigned char *buf)
      {
        while(*buf)
          UARTSend(*buf++);
      }
    void UART_PutStringAndNum(unsigned char *buf ,unsigned int num)
      {
        unsigned char a[3],i;
        a[3] = '0'+num%10;
        a[2] = '.';
        a[1] = '0'+num/10%10;
        a[0] = '0'+num/100%10;
        while(*buf)
          UARTSend(*buf++);
        UARTSend(' ');
         for(i=0;i<4;i++)
        {
            UARTSend(a[i]);
        } 
      }
    void UART_PutStringAnd_Data(unsigned char *buf ,unsigned char *bufdata)
      {
        unsigned char a[2],i,j;
        while(*buf)
          UARTSend(*buf++);
        UARTSend(' ');
        for(i=0;i<5;i++)
        {
            a[0] = bufdata[i]/16; 
            a[1] = bufdata[i]%16;
            for(j=0;j<2;j++)
            {
              if(a[j]>9)
              {
                a[j] = (a[j]-10)+'A';
              }
              else
              {
                a[j] = a[j]+'0';
              }
              UARTSend(a[j]);
            }
            UARTSend(' ');
        } 
      }
    /********************************************
    |* 功能: 串口发送传感器数据函数             *|
    ********************************************/
    void UARTSend_Nbyte(void)
      {
           if(Sensor_AnswerFlag == 1)
           {
              Sensor_Check = Sensor_Data[0]+Sensor_Data[1]+Sensor_Data[2]+Sensor_Data[3];
              //校验成功
              if(Sensor_Check ==Sensor_Data[4])    
              {
                 String = S_RH;//"RH:";       
                 Tmp = Sensor_Data[0]*256+Sensor_Data[1];       
                 UART_PutStringAndNum(String,Tmp); 
                    UARTSend(' ');
                 UARTSend(' ');
                 
                 String = S_Temp;// "Temp:";       
                    Tmp = Sensor_Data[2]*256+Sensor_Data[3];       
                 UART_PutStringAndNum(String,Tmp);
                    UARTSend(' ');
                 UARTSend(' ');
    
                 String = S_CRCT;//"Check: True";
                 UART_PutString(String);
              }else    //校验失败 送上读到数据
              {
                 String = S_Data;//"Data: ";
                 UART_PutStringAnd_Data(String,Sensor_Data);
                 UARTSend(' ');    
                 UARTSend(' ');
                 String = S_CRCF;//"Check: Wrong";
                 UART_PutString(String); 
              }
            }// 传感器未连接
            else
            {
               String = S_NotS; //"Sensor Not Connected";
                UART_PutString(String);
            }        
            UARTSend(0x0A); 
    
      }  
    void Clear_Data (void)
      {
        int i;
        for(i=0;i<5;i++)
        {
           Sensor_Data[i] = 0x00;
         }//接收数据清零
      }
    
    
    /********************************************
    |* 功能: 读传感器发送的单个字节            *|
    ********************************************/
    unsigned char Read_SensorData(void)
      {
        unsigned char i,cnt;
        unsigned char buffer,tmp;
        buffer = 0;
        for(i=0;i<8;i++)
        {
            cnt=0;
            while(!Sensor_SDA)    //检测上次低电平是否结束
            {
              if(++cnt >= 300)
               {
                  break;
               }
            }
            //延时Min=26us Max50us 跳过数据"0" 的高电平
            Delay_N10us(2);     //延时30us   
            
            //判断传感器发送数据位
            tmp =0;
            if(Sensor_SDA)     
            {
              tmp = 1;
            }  
            cnt =0;
            while(Sensor_SDA)        //等待高电平 结束
            {
                   if(++cnt >= 200)
                {
                  break;
                }
            }
            buffer <<=1;
            buffer |= tmp;    
        }
        return buffer;
      }
    
    /********************************************
    |* 功能: 读传感器                          *|
    ********************************************/
    unsigned char Read_Sensor(void)
      {
        unsigned char i;
        //主机拉低(Min=800US Max=20Ms) 
        Sensor_SDA = 0;
        Delay_N1ms(2);  //延时2Ms
          
        //释放总线 延时(Min=30us Max=50us)
        Sensor_SDA = 1;     
        Delay_N10us(1);//延时30us
        //主机设为输入 判断传感器响应信号 
        Sensor_SDA = 1; 
               
        Sensor_AnswerFlag = 0;  // 传感器响应标志     
    
        //判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行      
        if(Sensor_SDA ==0)
        {
           Sensor_AnswerFlag = 1;//收到起始信号
           Sys_CNT = 0;
           //判断从机是否发出 80us 的低电平响应信号是否结束     
           while((!Sensor_SDA))
           {
             if(++Sys_CNT>300) //防止进入死循环
             {
               Sensor_ErrorFlag = 1;
               return 0;
              } 
            }
            Sys_CNT = 0;
            //判断从机是否发出 80us 的高电平,如发出则进入数据接收状态
            while((Sensor_SDA))
            {
               if(++Sys_CNT>300) //防止进入死循环
               {
                 Sensor_ErrorFlag = 1;
                 return 0;
               } 
            }          
            // 数据接收    传感器共发送40位数据 
            // 即5个字节 高位先送  5个字节分别为湿度高位 湿度低位 温度高位 温度低位 校验和
            // 校验和为:湿度高位+湿度低位+温度高位+温度低位
            for(i=0;i<5;i++)
            {
              Sensor_Data[i] = Read_SensorData();
            }
          }
          else
          {
            Sensor_AnswerFlag = 0;      // 未收到传感器响应    
          }
          return 1;
      }    
    
    void main(void)
    {
      Sensor_SCL = 0;
      InitUART();  //初始串口发送函数
      while(1)
      {
        Clear_Data();         // 清除收到数据
        Read_Sensor();          // 读取传感器数据
        UARTSend_Nbyte();      // 串口发送读到传感器数据
        Delay_N1ms(2000);      // 延时 2S(两次读取间隔至少2S) 
      }
    }
    View Code

    这个是模块提供的程序,有代码可以知道这个模块工作是用来I2C协议,并且提供的例程比较好,用串口可以进行调试,这个文件是一个单文件的程序,如何给他整理一个单独的模块,让他融进大程序中去,才是玩模块的人的核心工作,这也是为什么玩模块的人出去工作不怎么高的原因

    这个是我的程序中的一段话:

    //这个程序调试也调试了好久现在总结一下单文件变多文件的步骤
    //第一:将要拆封的源文件 新建一个新的头文件
    //第二:填入三句话:#ifndef *****#define******#endif
    //第三在.h文件中包含原来文件中所有的函数声明
    //第四:将源文件的变量名复制,记得是复制,因为放在头文件中只是声明,声明不等于定义
    //第五:由于是声明:所以变量不需要赋值,所以将头文件中变量的赋值删除
    //第六,在源文件中包含该头文件

    注意以后修改程序,都要在先复制程序,然后在进行更改,并且对程序的修改作进一步的说明,以及程序哪些地方需要共同注意,这是程序员最基本的一种素质

    此外还需要注意变量的定义,有些变量,在同一个文件中有别名,所以需要自己动手,修改他们

    这是我修改的程序:我也把他晒出来

    wendu.c

    //****************************************************************//
    //           AM系列读单总线使用范例 
    //单片机 :AT89S52 或 STC89C52RC 
    // 功能  :串口发送温湿度数据  波特率 9600 
    // 晶振  :12M (用户系统时钟如不是12M 请更改相关宏定义及注释的延时时间)
    // 编译环境:  Keil3
    // 公司  :奥松电子    
    //****************************************************************//
    
    #include "reg52.h"
    #include <intrins.h>
    #include"wendu.h"
    
    // 变量定义
    
    unsigned char Sensor_Check;          //校验和
    unsigned char Sensor_AnswerFlag;  //收到起始标志位
    unsigned char Sensor_ErrorFlag;   //读取传感器错误标志
    unsigned int  Sys_CNT;
    
    
    
    
    /********************************************
    |* 功能: 延时    晶振为12M时                    *|
    |*  t = 1 为 20us  然后成倍增加10us左右        *|
    ********************************************/
    void Delay_N10us(unsigned char t)
    {
        while(t--)
       {
            _nop_();
       }
    }
    /********************************************
    |* 功能: 延时    晶振为12M时                    *|
    |* 延时大约 1ms                                *|
    ********************************************/ 
    void Delay_N1ms(unsigned int t)
    {
      unsigned int i;
      unsigned int j;
      for(j=t;j>0;j--)
         for(i=124;i>0;i--);  //延时大约 1ms
    }
     
    void Clear_Data (void)
      {
        int i;
        for(i=0;i<5;i++)
        {
           Sensor_Data[i] = 0x00;
         }//接收数据清零
      }
    
    
    /********************************************
    |* 功能: 读传感器发送的单个字节            *|
    ********************************************/
    unsigned char Read_SensorData(void)
      {
        unsigned char i,cnt;
        unsigned char buffer,tmp;
        buffer = 0;
        for(i=0;i<8;i++)
        {
            cnt=0;
            while(!Sensor_SDA)    //检测上次低电平是否结束
            {
              if(++cnt >= 300)
               {
                  break;
               }
            }
            //延时Min=26us Max50us 跳过数据"0" 的高电平
            Delay_N10us(2);     //延时30us   
            
            //判断传感器发送数据位
            tmp =0;
            if(Sensor_SDA)     
            {
              tmp = 1;
            }  
            cnt =0;
            while(Sensor_SDA)        //等待高电平 结束
            {
                   if(++cnt >= 200)
                {
                  break;
                }
            }
            buffer <<=1;
            buffer |= tmp;    
        }
        return buffer;
      }
    
    /********************************************
    |* 功能: 读传感器                          *|
    ********************************************/
    unsigned char Read_Sensor(void)
      {
        unsigned char i;
        //主机拉低(Min=800US Max=20Ms) 
        Sensor_SDA = 0;
        Delay_N1ms(2);  //延时2Ms
          
        //释放总线 延时(Min=30us Max=50us)
        Sensor_SDA = 1;     
        Delay_N10us(1);//延时30us
        //主机设为输入 判断传感器响应信号 
        Sensor_SDA = 1; 
               
        Sensor_AnswerFlag = 0;  // 传感器响应标志     
    
        //判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行      
        if(Sensor_SDA ==0)
        {
           Sensor_AnswerFlag = 1;//收到起始信号
           Sys_CNT = 0;
           //判断从机是否发出 80us 的低电平响应信号是否结束     
           while((!Sensor_SDA))
           {
             if(++Sys_CNT>300) //防止进入死循环
             {
               Sensor_ErrorFlag = 1;
               return 0;
              } 
            }
            Sys_CNT = 0;
            //判断从机是否发出 80us 的高电平,如发出则进入数据接收状态
            while((Sensor_SDA))
            {
               if(++Sys_CNT>300) //防止进入死循环
               {
                 Sensor_ErrorFlag = 1;
                 return 0;
               } 
            }          
            // 数据接收    传感器共发送40位数据 
            // 即5个字节 高位先送  5个字节分别为湿度高位 湿度低位 温度高位 温度低位 校验和
            // 校验和为:湿度高位+湿度低位+温度高位+温度低位
            for(i=0;i<5;i++)
            {
              Sensor_Data[i] = Read_SensorData();
            }
          }
          else
          {
            Sensor_AnswerFlag = 0;      // 未收到传感器响应    
          }
          return 1;
      }    
    
    /*void main(void)
    {
      Sensor_SCL = 0;
      while(1)
      {
        Clear_Data();         // 清除收到数据
        Read_Sensor();          // 读取传感器数据
        Delay_N1ms(2000);      // 延时 2S(两次读取间隔至少2S) 
      }
    }*/
    View Code

    wendu.h

    #ifndef __WENDU_H__
    #define __WENDU_H__
    #include <reg52.h>
    sbit Sensor_SDA = P3^3;
    sbit Sensor_SCL = P3^4;
    
    
    extern unsigned char Sensor_Data[5];
    extern unsigned char Sensor_Check;          //校验和
    
    extern unsigned char Sensor_AnswerFlag;  //收到起始标志位
    extern unsigned char Sensor_ErrorFlag;   //读取传感器错误标志
    extern unsigned int  Sys_CNT;
    extern unsigned int  Tmp;
    
    
    void Clear_Data (void);
    void Delay_N10us(unsigned char t);
    void Delay_N1ms(unsigned int t);
    unsigned char Read_SensorData(void);
    unsigned char Read_Sensor(void);
    
    #endif
    View Code

    但是不要以为这样就可以得到正确的温湿度,因为这样得到的数字么有进行校正,需要在主程序中进行校正,这个校正也矫正了我好久

    这个是主程序中的一段话:

            Read_Sensor();          // 读取传感器数据
        
            L1:
                //计算传感器数据
            Sensor_Check = Sensor_Data[0]+Sensor_Data[1]+Sensor_Data[2]+Sensor_Data[3];
              //校验成功
        
            if(Sensor_Check ==Sensor_Data[4])    
            {     
        //    String = S_RH;//"RH:";       
            wetness = Sensor_Data[0]*256+Sensor_Data[1];
            shidu[3] = '0'+wetness%10;
            shidu[2] = '.';
            shidu[1] = '0'+wetness/10%10;
            shidu[0] = '0'+wetness/100%10;       
          // String = S_Temp;// "Temp:";       
            temperature = Sensor_Data[2]*256+Sensor_Data[3];       
            wendu[3] = '0'+temperature%10;
            wendu[2] = '.';
            wendu[1] = '0'+temperature/10%10;
            wendu[0] = '0'+temperature/100%10;    
            } 
            else
            {
                goto L1;
            }

    经过上面的程序的修改,就可以得到精度为0.1的温湿度了

    好了这个温湿度传感器模块就总结到这里!!!

    版权所有,转载请注明链接地址:http://www.cnblogs.com/fengdashen/p/3643303.html

    技术交流QQ:1070937053

  • 相关阅读:
    结构和联合
    字符串、字符和字节
    数组
    函数
    指针
    操作符和表达式
    语句
    数据
    TinyXML2 使用
    是否忘记了向源中添加“#include "StdAfx.h"”?
  • 原文地址:https://www.cnblogs.com/fengdashen/p/3643303.html
Copyright © 2020-2023  润新知