嵌入式多路温湿度监控系统(十51单片机温湿度采集模块)

硬件:STC89C52开发板、1602数显、DHT温湿度传感器(利用其I2C数据线)

软件:Keil v4 C语言编译平台,stc-ipc-15xx-v6.85烧录程序

对DHT温度数据的解析有点问题,室温25度左右,温度的高、低位的最高位均为1,这与硬件说明文档不符,我就都屏蔽掉了最高位,得出的温度数据还比较靠谱,也不知怎么回事,各位读者如果知道的话不吝赐教!!!

嵌入式多路温湿度监控系统(十51单片机温湿度采集模块)_第1张图片嵌入式多路温湿度监控系统(十51单片机温湿度采集模块)_第2张图片

DHT12的SDA、SCL分别接P2.0、P2.1,连接好电源、接地后采集结果如下图:

嵌入式多路温湿度监控系统(十51单片机温湿度采集模块)_第3张图片

串口传出的数据分别通过P3.0 、P3.1传送给arm开发板
数据格式是每个数据前后各加一个空格,如:“空格78.5空格空格25.6空格……”,51单片机开发板的miniUSB是一个串口转USB的设备,通过它插入PC,就可以在PC端查看串口传出来的数据了,PC上通过串口助手看到单片机输出的结果,如下图:

嵌入式多路温湿度监控系统(十51单片机温湿度采集模块)_第4张图片


代码:包括了利用I2C时序采集DHT的温湿度数据、1602显示采集到数据、利用串口中断将数据发送出去三大部分

#include 
#include  

#define  AddWr 0xb8    //自己买的温湿度传感器DHT12器件地址

sbit sda=P2^0;
sbit scl=P2^1;

sbit rw = P1^1; 
sbit RS = P1^0;  
sbit LCDEN = P2^5; 

unsigned char bai,shi,ge;
unsigned char table1[]="wendu:";
unsigned char table2[]="shidu:";
unsigned char table3[]="0123456789";
unsigned char table4[]="CRC Error !!!";
unsigned char table5[]="Sensor Error !!";

int Temprature,Humi;


void delayUs()
{
    _nop_();
}

 void delayMs(unsigned int a)
{
    unsigned int i, j;
    for(i = a; i > 0; i--)
        for(j = 100; j > 0; j--);
 }


void delay(unsigned char dat)
{
	unsigned char i;
  for(i=dat;i>0;i--)_nop_();
}
	
/*******************************************************************
                     总线初始化              
函数原型: void  I2c_Init();  
功能:     启动I2C总线,即发送I2C起始条件.  
********************************************************************/
void I2c_Init()
{
  sda=1;         
  _nop_();        /*起始条件建立时间大于4.7us,延时*/
  _nop_();
  _nop_();
  _nop_();
  _nop_();  
  scl=1;
  _nop_();        /*起始条件建立时间大于4.7us,延时*/
  _nop_();
  _nop_();
  _nop_();
  _nop_(); 
}
	
/*******************************************************************
                     起动总线函数               
函数原型: void  IIC_Start();  
功能:     启动I2C总线,即发送I2C起始条件.  
********************************************************************/
void IIC_Start()
{
  sda=1;         /*发送起始条件的数据信号*/
  _nop_();
  scl=1;
  _nop_();        /*起始条件建立时间大于4.7us,延时*/
  _nop_();
  _nop_();
  _nop_();
  _nop_();    
  sda=0;         /*发送起始信号*/
  _nop_();        /* 起始条件锁定时间大于4μs*/
  _nop_();
  _nop_();
  _nop_();
  _nop_();       
  scl=0;       /*钳住I2C总线,准备发送或接收数据 */
  _nop_();
  _nop_();
}

/*******************************************************************
                      结束总线函数               
函数原型: void  IIC_Stop();  
功能:     结束I2C总线,即发送I2C结束条件.  
********************************************************************/
void IIC_Stop()
{
  sda=0;      /*发送结束条件的数据信号*/
  _nop_();       /*发送结束条件的时钟信号*/
  scl=1;      /*结束条件建立时间大于4μs*/
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  sda=1;      /*发送I2C总线结束信号*/
  _nop_();
  _nop_();
  _nop_();
  _nop_();
}

/*******************************************************************
                 字节数据发送函数               
函数原型: void  IIC_Send_Byte(UCHAR c);
功能:     将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
          此状态位进行操作.(不应答或非应答都使ack=0)     
           发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
********************************************************************/
void  IIC_Send_Byte(unsigned char  c)
{
 unsigned char  i;
 
 for(i=0;i<8;i++)  /*要传送的数据长度为8位*/
    {
     if((c<250)
		{
			IIC_Stop();
			return 1;
		}
		delay(1);
	}
	scl=0;//时钟输出0
	delay(50); //这个等待很重要,校验错误的几率小多了
	return 0;  
} 
/*****************************1602*******************************/
 

void writeComm(unsigned char comm)
{
    RS = 0;    
    P0 = comm;
    LCDEN = 1;
    delayUs();
    LCDEN = 0;
    delayMs(1);
}
void init1602()
 {
    rw = 0; 
    writeComm(0x38);
    writeComm(0x0c); 
    writeComm(0x06);
    writeComm(0x01); 
}

//写数据:RS=1, RW=0;
void writeData(unsigned char dat)
{
    RS = 1;
    P0 = dat;
    LCDEN = 1;
    delayUs();
    LCDEN = 0;
    delayMs(1);
}



void writeString(unsigned char * str, unsigned char length)
{
    unsigned char i;
    for(i = 0; i < length; i++)
    {
         writeData(str[i]);
     }
 }



/*------------------------------------------------
把uint 类型的温度、值转化为ascii码字符,
通过串口输出温度采集值
------------------------------------------------*/
void serialOutput(int num)	
{
     SBUF=' ';			   
	 delay(50);
	 SBUF=num/100+'0';		   	   
	 delay(50);		  
	 SBUF=num/10%10+'0';			   
	 delay(50);
	 SBUF='.';			   
	 delay(50);	
	 SBUF=num%10+'0';
	 delay(50);
	 SBUF=' ';			   
	 delay(50);		   
} 
/*------------------------------------------------
串口输出初始化函数
------------------------------------------------*/
void serial_init()
{
   SCON=0x40;//初始化串口方式1,REN=0不允许接受
   PCON=0x80; //SMOD=1 波特率倍增
   TMOD=0x20; //T1初始化为方式2,自动填充
   TL1=0xF4;  //波特率4800b/s
   TH1=0xF4;
   ES=1;	  //不打开串口中断,TI=1时依然可以串口输出,需要在上次输出后加点延时
   EA=1;	  //打开中断总开关
   TR1=1;	  //T1开始运转
}
/*------------------------------------------------
串口输出中断函数
------------------------------------------------*/ 
void SISR() interrupt 4
{
  T1=0;
}

/*********************************************************************************************************
         功能:DHT12读取温湿度函数
变量:Humi_H:湿度高位;Humi_L:湿度低位;Temp_H:温度高位;Temp_L:温度低位;Temp_CAL:校验位
数据格式为:湿度高位(湿度整数)+湿度低位(湿度小数)+温度高位(温度整数)+温度低位(温度小数)+ 校验位
校验:校验位=湿度高位+湿度低位+温度高位+温度低位
*********************************************************************************************************/
void sensor_read(void)
{	
	int i;
	unsigned char Humi_H,Humi_L,Temp_H,Temp_L,Temp_CAL,temp;

	IIC_Start();    //主机发送起始信号
	IIC_Send_Byte(0Xb8);    //发送IIC地址
	if(!IIC_Wait_Ack())  //等待从机应答信号(如无应答:考虑IIC通讯频率是否太快,或者传感器接线错误)
	{
		i=0;
		IIC_Send_Byte(0);
		while(IIC_Wait_Ack())//等待从机应答信号
		{
		 	if(++i>=500)
			{
			 	break;
			}		 
		} 
		i=0;
		IIC_Start();       //主机发送起始信号
		IIC_Send_Byte(0Xb9);     //发送读指令
		while(IIC_Wait_Ack())    //等待从机应答信号
		{
		 	if(++i>=500)
			{
			 	break;
			}			 
		}
	
		Humi_H=IIC_Read_Byte();   //读取湿度高位
		Ack_I2c(0);
		Humi_L=IIC_Read_Byte();   //读取湿度低位
		Ack_I2c(0);
		Temp_H=IIC_Read_Byte();   //读取温度高位
		Ack_I2c(0);
		Temp_L=IIC_Read_Byte();   //读取温度低位
		Ack_I2c(0);
		Temp_CAL=IIC_Read_Byte(); //读取校验位
		Ack_I2c(1);
		IIC_Stop();	   //发送停止信号	
		temp = (unsigned char)(Humi_H+Humi_L+Temp_H+Temp_L);//只取低8位
		if(Temp_CAL==temp)//如果校验成功,往下运行
		{
			Humi=Humi_H*10+Humi_L; //湿度
			//实践得出,在室温约27°时,温度高位Temp_H、温度低位Temp_L的最高位都是1,按照DHT12的技术说明,温度低位Temp_L的最高位是1的话表示是负值,明显不对
			//温度高位Temp_H的数值是10011011(155)也不对啊,那有这高的温度,将最高位去掉为0时,温度高位为27度,这还差不多。
			//温度高位Temp_H的数值是128-137,如果去掉最高位为零的话,那么是0-9,这是对的
			//Temp_H、Temp_L都去掉最高位后合体的温度约为27.5度,且可以环境温度上下浮动变化,感觉这样就对了。
			//那么我的这个传感器的负温度是怎么表示的呢?这个得在温度小于零的环境中试试Temp_H、Temp_L读到的都是什么值就可以了
			Temprature =(Temp_H&0x7F)*10+(Temp_L&0x7F);
	
			/*if(Temp_L&0X80)	//为负温度
			{
				//Temprature =0-(Temp_H*10+((Temp_L&0x7F)));
				// Temprature=Temp_L;
				//Temprature =(int)((char)0-(Temp_L&0x7F));
				//Temprature=Temp_H&0x7F;
				Temprature =(int)((char)0-((Temp_H&0x7F)*10+(Temp_L&0x7F)));
			}
			else   //为正温度
			{
				//Temprature=(Temp_H*10+(Temp_L&0x7F));//为正温度
				 Temprature=Temp_H;
			}*/ 	
			//判断温湿度是否超过测量范围(温度:-20℃~60摄氏度;湿度:20%RH~95%RH)		
			if(Humi>950) 
			{
			  Humi=950;
			}
			if(Humi<200)
			{
				Humi =200;
			}
			if(Temprature>1000)
			{
			  Temprature=1000;
			}
			if(Temprature<-200)
			{
				Temprature = -200;
			}
			
			i=Humi;
			bai=i/100;shi=i%100/10;ge=i%100%10;
			writeComm(0x80);
			writeString(table2,6);
			writeData(table3[bai]);
			writeData(table3[shi]);
			writeData('.');
			writeData(table3[ge]);
			writeData('%');
			writeData('R');
			writeData('H');
			
			i=Temprature;
			if(i<0)
			{
			  i=-i;
			  bai=i/100;shi=i%100/10;ge=i%100%10;
			  writeComm(0x80+0x40);
			  writeString(table1,6);
			  writeData('-');
			  writeData(table3[bai]);
			  writeData(table3[shi]);
			  writeData('.');
			  writeData(table3[ge]);
			  writeData(0xdf);
			  writeData('C');
           }else{ 
			  bai=i/100;shi=i%100/10;ge=i%100%10;
			  writeComm(0x80+0x40);
			  writeString(table1,6);
			  writeData('+');
			  writeData(table3[bai]);
			  writeData(table3[shi]);
			  writeData('.');
			  writeData(table3[ge]);
			  writeData(0xdf);         //"℃中的左上角圆圈的ascii码"
			  writeData('C');
            }
			serialOutput(Humi);
			serialOutput(Temprature);			
			
		}
		else //校验失败
		{
			writeComm(0x80);
			writeString(table4,12);
		}
	}else
	{
	   writeComm(0x80+0x40);
	   writeString(table5,15);
	}	

}

//******************main()主函数********************************
void main()
{
	void I2c_Init();
	init1602();
	serial_init();

	while(1)
	{
		sensor_read();
		delayMs(2000);
  }	
}
 
  
 
 

你可能感兴趣的:(嵌入式多路温湿度监控系统(十51单片机温湿度采集模块))