专注电子技术学习与研究
当前位置:单片机教程网 >> MCU设计实例 >> 浏览文章

51单片机做的温湿度测量仪

作者:佚名   来源:本站原创   点击数:  更新时间:2012年07月07日   【字体:

本人去年用51单片机做的温湿度传感器模块,有实物,有程序,供大家分享。
该1602液晶的D0~D7数据口连接单片机的P17~P10口,所以程序里的指令和数据都是逆向输入的。
程序和电路图下载: http://www.51hei.com/f/温湿度传感器+1602原理图.rar


#include<reg52.h> 
#include<intrins.h> 
#include<math.h> 
#define uchar unsigned char 
#define uint unsigned int 

#define noACK 0 
#define ACK 1
#define STATUS_REG_W 0x06
#define STATUS_REG_R 0x07
#define MEASURE_TEMP 0x03 
#define MEASURE_HUMI 0x05 
#define RESET 0x1e

sbit SCK =P1^0;
sbit DATA=P1^1;
sbit led1=P1^7; 

sbit  rs=P2^3; //H数据,L命令
sbit  en=P2^5; //高脉冲使能,使能脉宽最小150ns
sbit  rw=P2^4;
uchar code table_temp[]=" TEMP: ";
uchar code table_humi[]=" HUMI: ";
uchar code table_c[]=" C  ";
uchar code table_p[]=" %  ";
uchar error=0; 

void delayms(uint z) 
{ 
	uint i,j; 
	for(i=z;i>0;i--) 
	for( j=110;j>0;j--); 
} 

//启动时序 
void transstart() 
{ 
	SCK=1;
	_nop_(); 
	DATA=0;
	_nop_(); 
	SCK=0;
	_nop_();
	_nop_();
	_nop_(); 
	SCK=1;
	_nop_(); 
	DATA=1;
	_nop_(); 
	SCK=0; 
} 

//写入命令子函数 
uchar write_byte(uchar value) 
{ 
	uchar i; 
	for(i=0x80;i>0;i=i/2) 
	{ 
		if(i&value) 
			DATA=1; 
		else 
			DATA=0; 
		SCK=1; 
		_nop_();
		_nop_();
		_nop_(); 
		SCK=0; 
	} 
	DATA=1; 
	SCK=1; 
	error=DATA; 
	SCK=0; 
	return error; 
} 

//从传感器读数据 
uchar read_byte(bit ack) 
{ 
	uchar i,val=0; 
	DATA=1; 
	for(i=0x80;i>0;i=i/2) 
	{ 
		SCK=1; 
		if(DATA) 
		val=val|i; 
		SCK=0; 
	} 
	DATA=!ack; 
	SCK=1; 
	_nop_();
	_nop_();
	_nop_(); 
	SCK=0; 
	DATA=1; 
	return val; 
} 

//
void connectionreset() 
{ 
	uchar i; 
	DATA=1; 
	SCK=0; 
	for(i=0;i<9;i++) 
	{ 
		SCK=1; 
		SCK=0; 
	} 
	transstart(); 
} 

uint measure1() //测量温度函数
{ 
	uchar value_1,value_2;
	uint tempvalue;
	transstart();
	error+=write_byte(MEASURE_TEMP);
	if(error!=0)
	{
		connectionreset();
	}
	else 
	{ 
		while(DATA==1)
		{
			_nop_();
		}
		if(DATA==0)
		{ 
			value_1=read_byte(ACK);
			value_2=read_byte(noACK);
			tempvalue=value_2+value_1*256; //转换成 16 位的 int 型
		}
		else error=1; 
	} 
	return tempvalue; 
}
 
uint measure2() //测量湿度函数
{ 
	uchar value_1,value_2; 
	uint tempvalue; 
	transstart(); 
	error+=write_byte(MEASURE_HUMI); 
	if(error!=0) 
	connectionreset(); 
	else 
	{ 
		while(DATA==1) 
		_nop_(); 
		if(DATA==0) 
		{ 
			value_1=read_byte(ACK);
			value_2=read_byte(noACK); 
			tempvalue=value_2+value_1*256; 
		} 
		else error=1; 
	} 
	return tempvalue; 
} 

void lcdwrdata(uchar dat)
{
	dat = ((dat&0x01)<<7)|((dat&0x02)<<5)|((dat&0x04)<<3)|((dat&0x08)<<1)|((dat&0x10)>>1)|((dat&0x20)>>3)|((dat&0x40)>>5)|((dat&0x80)>>7);
	rs=1;//写数据时RS拉高
	en=1;
	P0=dat;
	delayms(6);
	en=0;
	delayms(6);
}

void lcdwrcom(uchar cdat)//写指令数据到LCD  
{	
	cdat = ((cdat&0x01)<<7)|((cdat&0x02)<<5)|((cdat&0x04)<<3)|((cdat&0x08)<<1)|((cdat&0x10)>>1)|((cdat&0x20)>>3)|((cdat&0x40)>>5)|((cdat&0x80)>>7);
	rs=0;//写指令时RS拉低
	en=1;
	P0=cdat;//
	delayms(6);//不加此延时将导致不能写入指令,但能写入显示数据
	en=0;
	delayms(6);
}

void lcd_init()
{
	lcdwrcom(0x38); //0x38设置显示模式为:16X2显示,5X7点阵,8位数据接口
	lcdwrcom(0x0c); //打开显示光标闪烁
	lcdwrcom(0x06); //
	lcdwrcom(0x01); //
}

void display(float temp,float humi) //1602显示函数(温度,湿度)
{
	uint a,b,c,d,e,f,g,h;

	a=(temp/1000);
	b=((temp-a*1000)/100);
	c=((temp-a*1000-b*100)/10);
	d=(temp-a*1000-b*100-c*10);
	e=(humi/1000);
	f=((humi-e*1000)/100);
	g=((humi-e*1000-f*100)/10);
	h=(humi-e*1000-f*100-g*10);

	lcdwrcom(0x80+0x07);lcdwrdata('0'+a);
	lcdwrcom(0x80+0x08);lcdwrdata('0'+b);
	lcdwrcom(0x80+0x09);lcdwrdata('.')  ;
	lcdwrcom(0x80+0x0A);lcdwrdata('0'+c);
	lcdwrcom(0x80+0x0B);lcdwrdata('0'+d);
	lcdwrcom(0x80+0x47);lcdwrdata('0'+e);
	lcdwrcom(0x80+0x48);lcdwrdata('0'+f);
	lcdwrcom(0x80+0x49);lcdwrdata('.')  ;
	lcdwrcom(0x80+0x4A);lcdwrdata('0'+g);
	lcdwrcom(0x80+0x4B);lcdwrdata('0'+h);
	
}

float calc_temp(uint tempvalue) //计算温度值子函数 
{ 
	const float d1=-39.9;
	const float d2=+0.01;
	float temp_final;
	tempvalue=tempvalue&0x3fff; //取出低 14 位
	temp_final=d1+d2*((float)tempvalue);
	return temp_final; //返回温度值
}

//计算湿度值子函数 
float calc_humi(float humivalue) 
{ 
	const float c1=-4.0,c2=0.0405,c3=-0.0000028,t1=0.01,t2=0.00008; 
	float rh=humivalue; 
	float rhlin; 
	float rhtrue; 
	rhlin=c1+c2*rh+c3*rh*rh; 
	rhtrue=(27.87-25)*(t1+t2*rh)+rhlin; 
	if(rhtrue>100) 
		rhtrue=100; 
	if(rhtrue<0.1) 
		rhtrue=0.1; 
	humivalue=rhtrue; 
	return humivalue;
}
 
void main() 
{ 
	uint i; //定义计数器
	uint value1; //定义传感器传出来的数值(16位)
	uint value2; //定义传感器传出来的数值(16位)
	float dis_tempvalue; //定义温度变量
	float dis_humivalue; //定义湿度变量
	//以下是初始化液晶操作
	rw=0;
	delayms(200);
	en=0;
	lcd_init();
	//以下是液晶固定显示
	lcdwrcom(0x80+0x00); //第1行00位置
	for(i=0;i<7;i++)
	{
		lcdwrdata(table_temp[i]);
	}
	lcdwrcom(0x80+0x0C); //第1行0C位置
	for(i=0;i<4;i++)
	{
		lcdwrdata(table_c[i]);
	}
	lcdwrcom(0x80+0x40); //第2行40位置
	for(i=0;i<7;i++)
	{
		lcdwrdata(table_humi[i]);
	}
	lcdwrcom(0x80+0x4C); //第2行4C位置
	for(i=0;i<4;i++)
	{
		lcdwrdata(table_p[i]);
	}
	//
	while(1) 
	{ 
		connectionreset(); 
		error=0; 
		value1=measure1(); 
		value2=measure2(); 
		if(error==0) 
		{ 
			led1=0; 
			delayms(200); 
			led1=1; 
			delayms(200);
			dis_tempvalue=calc_temp(value1);   //计算温度值
			dis_humivalue=calc_humi(value2);   //计算湿度值
			display(dis_tempvalue*100,dis_humivalue*100); //LCD1602显示温湿度
		} 
		else 
		{ 
			continue; 
		} 
	} 
} 
关闭窗口

相关文章