基于proteus的单片机温湿度测量
0赞Proteus软件是英国Labcenter electronics公司出版的EDA工具软件(该软件中国总代理为广州风标电子技术有限公司)。它不仅具有其它EDA工具软件的仿真功能,还能仿真单片机及外围器件。它是目前最好的仿真单片机及外围器件的工具。虽然目前国内推广刚起步,但已受到单片机爱好者、从事单片机教学的教师、致力于单片机开发应用的科技工作者的青睐。Proteus是世界上著名的EDA工具(仿真软件),从原理图布图、代码调试到单片机与外围电路协同仿真,一键切换到PCB设计,真正实现了从概念到产品的完整设计。是目前世界上唯一将电路仿真软件、PCB设计软件和虚拟模型仿真软件三合一的设计平台,其处理器模型支持8051、HC11、PIC10/12/16/18/24/30/DsPIC33、AVR、ARM、8086和MSP430等,2010年即将增加Cortex和DSP系列处理器,并持续增加其他系列处理器模型。在编译方面,它也支持IAR、Keil和MPLAB等多种编译器。
这个软件的功能还不错,用它做了一个基于at89s52的温湿度测量系统。单片机采用at89s52,外接温度传感器18b20,湿度测量电路hs1101+tl555,4位数码管显示电路,晶振,复位等其他必要外部电路。该系统实现温度,湿度的测量,以及计时功能,能够分时显示当前温度,湿度,时间。因为未设外部按键,还不能实现设置,显示手动切换功能,以后的设计需要继续改进。
程序代码:
#include
#include
#define uchar unsigned char
#define uint unsigned int
sbit DATA = P3^7; //DS18B20接入口
uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e}; //共阳数码管段码
char bai,shi,ge; //定义变量
unsigned int count;//定时器计数值
unsigned int time;//时间变量
/*延时子函数*/
void delay(uint num)
{
while(num--) ;
}
unsigned int frequency,f1,f2;
//void time1(unsigned char x)
//{
//unsigned int i,j;
//for(i=0;i<20*x;i++)
// for(j=0;j<5;j++);
//}
//工作模式配置
void time_init(void){
ES=0;//串行口中断禁止
ET1=0;//T1溢出中断禁止
EX1=0;//外部中断1禁止
ET0=0;//T0溢出中断禁止
EX0=0;//外部中断0禁止
EA=0;//总中断禁止
delay(50) ;
TMOD=0X51; //T1计数,方式1 T0定时,方式1
TH1=TL1=0; //T1计数清零
TH0=0X3c;
TL0=0Xb0; //T0定时10MS(12MHZ)
TF0=0; //T0溢出中断标志清零
ET0=1;
ET1=0; //T0T1溢出中断开
EA=1;
TR0=TR1=1; //开T0 T1
/*
void clean(void)
{
ES=0;//串行口中断禁止
ET1=0;//T1溢出中断禁止
EX1=0;//外部中断1禁止
ET0=1;//T0溢出中断禁止
EX0=0;//外部中断0禁止
EA=1;//总中断禁止
}
unsigned int pinlu()
{ int i;
clean();
TMOD=0X51; //T1计数,方式1 T0定时,方式1
TH1=TL1=0; //T1计数清零
TH0=0Xdb;
TL0=0Xff; //T0定时10MS(11.0592HZ)
TF0=0; //T0溢出中断标志清零
ET0=ET1=1; //T0T1溢出中断开
TR0=TR1=1; //开T0 T1
while(TF0!=1) //定时时间到再往下执行
{;}
TR0=TR1=0; //关T0 T1
TF0=0; //T0溢出中断标志清零
i=TH1*256+TL1;
return(i);
}
*/
//hs1101 测量湿度
unsigned int shidu_mea(void){
unsigned int i,k;
frequency=count*20;
if((frequency>6033)&(frequency<6187)) f1=90;
//将测量数值转换为对应百分比, 1%-100%
if((frequency>6186)&(frequency<6331)) f1=80;
if((frequency>6330)&(frequency<6469)) f1=70;
if((frequency>6468)&(frequency<6601)) f1=60;
if((frequency>6600)&(frequency<6729)) f1=50;
if((frequency>6728)&(frequency<6854)) f1=40;
if((frequency>6853)&(frequency<6977)) f1=30;
if((frequency>6976)&(frequency<7101)) f1=20;
if((frequency>7100)&(frequency<7225)) f1=10;
if(frequency>7224) f1=00;
f2=frequency%100; //对测量数值取低两位
//delay(50); //处理需要等待一段时间,否则f2=0
if((f1==60)||(f1==70)||(f1==90)) f2=f2/13; //对低两位数值取个位,
else if(f1==80) f2=f2/14;
else f2=f2/12;
//delay(50);
f1=f1+f2; //将数据合成一起,送显示
return(f1);
}
/*************DS18b20温度传感器函数*********************/
Init_DS18B20(void) //传感器初始化
{
uchar x=0;
DATA = 1; //DQ复位
delay(10); //稍做延时
DATA = 0; //单片机将DQ拉低
delay(80); //精确延时 大于 480us //450
DATA = 1; //拉高总线
delay(20);
x=DATA; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
delay(30);
}
ReadOneChar(void)
{
uchar i=0;
uchar dat = 0;
for (i=8;i>0;i--)
{
DATA = 0; // 给脉冲信号
dat>>=1;
DATA = 1; // 给脉冲信号
if(DATA)
dat|=0x80;
delay(8);
}
return(dat);
}
WriteOneChar(unsigned char dat)
{
uchar i=0;
for (i=8; i>0; i--)
{
DATA = 0;
DATA = dat&0x01;
delay(10);
DATA = 1;
dat>>=1;
}
delay(8);
}
int ReadTemperature(void)
{
uchar a=0;
uchar b=0;
int t=0;
float tt=0;
Init_DS18B20();
WriteOneChar(0xCC); // 跳过读序号列号的操作
WriteOneChar(0x44); // 启动温度转换
Init_DS18B20();
WriteOneChar(0xCC); //跳过读序号列号的操作
WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
a=ReadOneChar();//低位
b=ReadOneChar();//高位
t=b;
t<<=8;
t=t|a;
tt=t*0.0625;
t= tt*10+0.5;
return(t);
}
void display(int bai,int shi,int ge)
{
P0=0X7f; //显示小数点
P2=0XF2;
delay(50);//显示小数点
P0=table[bai];//显示千位
P2=0xf8;
delay(50);//一小段延时动态显示
P2=0xf0;
P0=table[shi];//显示百位
P2=0xf4;
delay(50);
P2=0xf0;
P0=table[ge];//显示十位
P2=0xf2;
delay(50);
P2=0xf0;
P0=table[0];//显示个位
P2=0xf1;
delay(50);
P2=0XF0;
}
/*显示子函数2*/
//小数点位置在23之间
void display2(int bai,int shi,int ge,int xiao)
{
P0=0X7f; //显示小数点
P2=0XF4;
delay(50);//显示小数点
P0=table[bai];//显示千位
P2=0xf8;
delay(50);//一小段延时动态显示
P2=0xf0;
P0=table[shi];//显示百位
P2=0xf4;
delay(50);
P2=0xf0;
P0=table[ge];//显示十位
P2=0xf2;
delay(50);
P2=0xf0;
P0=table[xiao];//显示个位
P2=0xf1;
delay(50);
P2=0XF0;
}
/*
void main()
{
int temp;
while(1)
{
temp=123;//ReadTemperature()/10;//读温度
bai=temp%1000/100;//显示百位
shi=temp%100/10;//显示十位
ge=temp%10;//显示个位
// display(bai,shi,ge);//显示函数
display(bai,shi,ge);
}
}
*/
//显示函数,分时显示湿度,温度,时间
void xianshi(unsigned int c1,unsigned int c2,unsigned int c3){
unsigned int dis_con;
unsigned char dis1,dis2,dis3,dis4;
dis_con=(time/20)%3;
if(dis_con==0){
dis1=c1%1000/100;//显示百位
dis2=c1%100/10;//显示十位
dis3=c1%10;//显示个位
display(dis1,dis2,dis3);
}
else if(dis_con==1){
dis1=c2%1000/100;//显示百位
dis2=c2%100/10;//显示十位
dis3=c2%10;//显示个位
display(dis1,dis2,dis3);
}
else{
c3=c3/20;
dis1=(c3/60)/10;//分
dis2=(c3/60)%10;//分
dis3=(c3%60)/10;//秒
dis3=(c3%60)%10;//秒
display2(dis1,dis2,dis3);
{
unsigned int temp1,temp2,temp3;
time=0;
//initlcm();
// clear();
//bg=1;
//time1(2);
time_init();
while(1)
{
if(time%20==0){
temp1=ReadTemperature()/10;//读温度
}
temp2=shidu_mea(); //湿度
temp3=time; //时间
//temp2=count*100;
//f1=0x000; //清0,为下次准备
// bai=temp2%1000/100;//显示百位
// shi=temp2%100/10;//显示十位
// ge=temp2%10;//显示个位
// display(bai,shi,ge);//显示函数
xianshi(temp1,temp2,temp3);
}
void time0_isr(void) interrupt 1{
time++;
count=TH1*256+TL1;
TR1=0;
TH1=0;
TL1=0;
TR1=1;
TH0=0X3c;
TL0=0Xb0; //T0定时50MS
}