毕昇杯之温湿度采集模块

      这一次使用的温湿度传感器也是经历了几次变动,从开始用的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

posted @ 2014-04-03 16:41  跨七海的风  阅读(449)  评论(0编辑  收藏  举报