garfield

基于proteus的单片机温湿度测量

0
阅读(4316)

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<reg52.h>
#include <intrins.h>
#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--) ;
}

///hs1101////////////
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)
{
 P2=0XF0; //显示小数点
 P0=0X7f; //显示小数点
 P2=0XF2;
 delay(50);//显示小数点
 P2=0xf0;
 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)
{
 P2=0XF0; //显示小数点
 P0=0X7f; //显示小数点
 P2=0XF4;
 delay(50);//显示小数点
 P2=0xf0;
 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);
 }
 }
void main()
{
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
 
}