高级会员 
 
主题
回帖0
积分728
阅读权限30
注册时间2010-9-3
最后登录1970-1-1
在线时间 小时
 
 
 
 
 | 
 
《电子制作》2012年3期《迷你温湿度计》仿制出现问题,通电以后红、绿2个数码管全部8字交替闪烁,查了好多资料不知所因,最后网友提到可能是延时的问题,1T的要快12倍,但怎样修改延时,请大侠帮我。 
 
/* 
迷你温湿度计 
红色显示温度,绿色显示湿度 
温度和湿度能切换显示 
能设置最大值,达到最大值数码管闪烁引起提醒 
*/ 
#include <reg52.h> 
#define uint unsigned int 
#define uchar unsigned char 
#define status1 0 
#define status2 1 
#define status3 2 
 
typedef unsigned char  U8; 
typedef unsigned int   U16; 
typedef unsigned char BYTE; 
unsigned char data dis_buf[4];//用于存数据 
//U8 code table[]={//共阳数码管段码 
// 0xC0,/*0*/ 
// 0xF9,/*1*/ 
// 0xA4,/*2*/ 
// 0xB0,/*3*/ 
// 0x99,/*4*/ 
// 0x92,/*5*/ 
// 0x82,/*6*/ 
// 0xF8,/*7*/ 
// 0x80,/*8*/ 
// 0x90,/*9*/ 
//}; 
U8 code table[]={//共阳数码管段码 (有接错,修改) 
0xC0,/*0*/ 
0xCF,/*1*/ 
0x92,/*2*/ 
0x86,/*3*/ 
0x8D,/*4*/ 
0xA4,/*5*/ 
0xA0,/*6*/ 
0xCE,/*7*/ 
0x80,/*8*/ 
0x84,/*9*/ 
 
0x89,/*H*/ 
0xBF,/*一横*/ 
0x9C,/*度*/ 
0xF0,/*C*/ 
0xFF,/*空*/ 
}; 
sbit  DATA  = P3^7 ;//定义数据接收端口 
sbit P3_2 = P3^2;/*第4个数码管*/ 
sbit P3_3 = P3^3; 
sbit P3_4 = P3^4; 
sbit P3_5 = P3^5; 
//sbit key1 = P3^0;//设置按键 
//sbit key2 = P3^1;//加键 
U8  U8FLAG; 
//U8  U8FLAG,U8temp; 
//U8  shidu_shi,shidu_ge,wendu_shi,wendu_ge; 
//U8  U8T_data_H,U8T_data_L,U8RH_data_H,U8RH_data_L,U8checkdata; 
//U8  U8T_data_H_temp,U8T_data_L_temp,U8RH_data_H_temp,U8RH_data_L_temp,U8checkdata_temp; 
//U8  U8comdata; 
/*******定义变量***********/ 
uchar num,dat0,dat1,dat2,dat3,dat4,flag_dis,returnkey,setnum,displaynum,MaxHum,MaxTem,flashcount,alarmflag1,alarmflag2; 
uint countnum;//int型,用于计算时间到什么时候切换显示 
/********以下两个延时函数是用单片机小精灵计算出来的*****/ 
void delay20ms(void)   //误差 -0.000000000001us 
{ 
    unsigned char a,b,c; 
    for(c=199;c>0;c--) 
        for(b=120;b>0;b--) 
            for(a=1;a>0;a--); 
} 
 
//void delay30us(void)   //误差 0us 
//{ 
//    unsigned char a,b; 
//    for(b=3;b>0;b--) 
//        for(a=28;a>0;a--); 
//} 
void delay40us(void)   //误差 0us 
{ 
    unsigned char a,b; 
    for(b=3;b>0;b--) 
        for(a=38;a>0;a--); 
} 
/**********************************************************/ 
BYTE read_byte(void)/*读取一个字节数据函数*/ 
{ 
        BYTE i,value; 
        for(i = 8; i > 0; i--) 
        { 
                value <<= 1; 
    U8FLAG=2; 
                while((!DATA)&&U8FLAG++);        //等待50us 
                delay40us();/*原本30us*/         
                if(DATA) 
                { 
                        value++; 
                        while((DATA)&&U8FLAG++);        //等待高电平的结束                         
                }                                                                                         
        } 
        return(value);         
} 
 
void dht11_read()/***读取湿度和温度***/ 
{         
        BYTE temp = 0; 
        DATA = 0;                                //主机把总线拉低 
        delay20ms();                        //拉低时间大于18ms,否则DHT11不会响应 
        DATA = 1;                                //主机把总线拉高 
        delay40us();                        //拉高时间为20us-40us                 
//        while(!DATA);                //等待DHT11响应信号(低电平) 
    if(!DATA)//改为if判断 
  { 
   U8FLAG=2;//从2开始计算 
         while((!DATA)&&U8FLAG++);                //等待DHT11拉高总线 
   U8FLAG=2;  
   while((DATA)&&U8FLAG++); 
    
  dat0 = read_byte();//high humidity 
        dat1 = read_byte();//low humidity 
        dat2 = read_byte();//high temp 
        dat3 = read_byte();//low temp 
        dat4 = read_byte();//verification code 
         
        temp = dat0 + dat1 + dat2 + dat3; 
        if(temp == dat4) 
  { 
   if(flag_dis==0)//显示湿度 
   { 
    dis_buf[0]=table[10];//“H” 
    dis_buf[1]=table[11];//一横 
    dis_buf[2]=table[dat0/10];//湿度的十位数 
    dis_buf[3]=table[dat0%10];//湿度的个位数  
   } 
   if(flag_dis==1)//切换时间,不显示 
   { 
    dis_buf[0]=table[14];// 全部为空 
    dis_buf[1]=table[14];// 
    dis_buf[2]=table[14];// 
    dis_buf[3]=table[14];// 
   } 
   if(flag_dis==2)//显示温度 
   { 
    dis_buf[0]=table[dat2/10];//温度的十位数 
    dis_buf[1]=table[dat2%10];//温度的个位数 
    dis_buf[2]=table[12];//度 
    dis_buf[3]=table[13];//C 
   } 
   if(flag_dis==3)//切换时间,不显示 
   { 
    dis_buf[0]=table[14];// 全部为空 
    dis_buf[1]=table[14];// 
    dis_buf[2]=table[14];// 
    dis_buf[3]=table[14];//  
   }   
  } 
    } 
//            return 1; 
//        else  
//                return 0;                 
} 
void inittime()//定时器初始化函数 
{ 
TMOD=0x01;//定时器0工作方式1 
TH0=(65536-5000)/256;//每5毫秒检测一个状态 
TL0=(65536-5000)%256; 
EA=1; 
ET0=1; 
TR0=1; 
} 
/***********************************/ 
void flashalarm()//闪烁提醒函数 
{ 
/**********************************/ 
if(flag_dis==0)//如果现在显示的是湿度 
{ 
if(dat0>=MaxHum)//如果湿度大于等于设定值 
{ 
  if(alarmflag1==1)/*闪烁状态*/ 
  { 
   if(num>=2) num=0;//只显示前两个 
  } 
  else {if(num>=4) num=0;} 
} 
else {if(num>=4) num=0;} 
} 
/************************************/ 
else if(flag_dis==2)//如果显示的是温度 
{ 
if(dat2>=MaxTem)//如果温度大于等于设定值 
{ 
  if(alarmflag2==1) 
  { 
   if(num>=4) num=2;//限制在闪烁前两个 
  } 
  else {if(num>=4) num=0;} 
} 
else {if(num>=4) num=0;} 
} 
else {if(num>=4) num=0;} 
/*******************************/ 
} 
/*************************************/ 
void display()//数码管显示函数 
{ 
P3_2=1; 
P3_3=1; 
P3_4=1; 
P3_5=1;//先关闭所有控制端口 
P1=dis_buf[num]; 
/*******************************/ 
/**********************************/ 
switch(num)//思考:没有对应数值会怎么样? 
{ 
  case 0:P3_2=1;P3_3=1;P3_4=1;P3_5=0;break; 
  case 1:P3_2=1;P3_3=1;P3_4=0;P3_5=1;break; 
  case 2:P3_2=1;P3_3=0;P3_4=1;P3_5=1;break; 
  case 3:P3_2=0;P3_3=1;P3_4=1;P3_5=1;break; 
} 
num++; 
// if(num>=4) num=0; 
flashcount++;//计算标志 
if(flashcount>=100) {alarmflag1=~alarmflag1;alarmflag2=~alarmflag2;flashcount=0;}//0.5秒闪烁一次,然后返回原来的闪烁状态 
if(setnum==1) flashalarm();//加载闪烁函数,区分按键按下 
if(setnum==2)//按键按下时不闪烁  
{ 
if(num>=4) num=0;  
} 
} 
/*****************************************************************/ 
uchar keyread()//读取多个按键,有返回值 
{ 
static uchar KeyStatus=status1,Knum=0;//只声明一次 
uchar keynum; 
//uchar Knum=0; 
uchar i=0; 
keynum=(~P3)&0x03;//低两位 
switch(KeyStatus) 
{ 
  case status1: 
    if(keynum) KeyStatus=status2; 
    return 0; 
    break; 
  case status2: 
    if(!keynum) KeyStatus=status1;//如果是毛刺,就返回第一状态 
    else 
    { 
     for(i=0;i<2;i++)//查询哪个按键按下 
    { 
     if(keynum & 1<<i) 
     { 
      Knum=1+i; 
      break; 
     } 
    } 
     KeyStatus=status3; 
    } 
    return 0; 
    break; 
  case status3: 
    if(!keynum)  
    {KeyStatus=status1;return Knum;} 
    return 0; 
  default : return 0; break; 
} 
} 
/***********************************************************/ 
void set_display()//设置按键按下时的显示项目 
{ 
if(displaynum==1)//设置湿度界面 
{ 
  dis_buf[0]=table[11];//一横 
  dis_buf[1]=table[11];//一横 
  dis_buf[2]=table[MaxHum/10];//湿度的十位数 
  dis_buf[3]=table[MaxHum%10];//湿度的个位数    
} 
/******/ 
if(displaynum==2)//设置温度界面 
{ 
  dis_buf[0]=table[MaxTem/10];//温度的十位数 
  dis_buf[1]=table[MaxTem%10];//温度的个位数 
  dis_buf[2]=table[11];//一横 
  dis_buf[3]=table[11];//一横   
}  
} 
/***********************************/ 
void main() 
{ 
// uchar read_success;//读取成功变量 
inittime();//定时器初始化 
num=0; 
setnum=1;//设置按键的显示项目 
displaynum=0;// 
MaxHum=80;//湿度默认提醒的最大值为80 
MaxTem=40;//温度的默认提醒最大值为40 
flag_dis=0;//初始化显示标志为0,显示湿度 
alarmflag1=1; 
alarmflag2=1; 
while(1) 
{   
//  read_success=dht11_read(); 
//  if(read_success)//是否返回1,读取成功 
//  { 
   /*Hum1=dat0/10;//湿度的十位数 
   Hum2=dat1%10;//湿度的个位数 
   Tem1=dat2/10;//温度的十位数 
   Tem2=dat3%10;//温度的个位数 */ 
   /*添加标志,选择显示不同项目*/ 
   /*添加判断显示项目*/ 
//   dis_buf[0]=table[dat0/10];//湿度的十位数 
//   dis_buf[1]=table[dat0%10];//湿度的个位数 
//   dis_buf[2]=table[dat3/10];//温度的十位数 
//   dis_buf[3]=table[dat3%10];//温度的个位数 
   if(setnum==1)//区分:按键按下后不读取数值 
   { 
   delay20ms(); 
   delay20ms(); 
   delay20ms(); 
   delay20ms(); 
   delay20ms(); 
   delay20ms(); 
   delay20ms(); 
    
   dht11_read();//中断中读取数据 
   } 
//  } 
} 
 
} 
 
void timer0() interrupt 1//中断函数 
{ 
TH0=(65536-5000)/256;//重新赋值 ,5毫秒 
TL0=(65536-5000)%256; 
countnum++;//200次一秒 
if(countnum==1300) flag_dis=1;//6.5秒  
if(countnum==1430) flag_dis=2;//中间切换时间 
if(countnum==2730) flag_dis=3; 
if(countnum==2860) {flag_dis=0;countnum=0;}//标志为0,同时countnum清零 
display();//数码管显示函数 
/*******************************************************/ 
returnkey=keyread(); 
if(returnkey==1)//如果设置按键按下  
{ 
  returnkey=0;//按键值清零 !! 
  setnum++; 
  if(setnum>=3)//按第二下变为1,同时标志变为0,退出设置界面 
  { 
  setnum=1; 
  displaynum=0; 
  flag_dis=0; 
  countnum=0;//计算数值也要为0 
  } 
  if(setnum==2)/*注意!!(经验:标志的冲突问题)*/  
  { 
   if(flag_dis==0){displaynum=1;}//显示模式为设置湿度的界面 
   if(flag_dis==2){displaynum=2;}//显示为设置温度的界面 
   flag_dis=4;//同时使标志设置为4,不进入数据显示项目 
  } 
} 
/*****/ 
if(setnum==2)//按下后才进入 
{ 
  if(displaynum==1)//设置的是湿度 
  { 
   if(returnkey==2)//设置“加”键 
   { 
      returnkey=0;//按键值清零 !! 
      MaxHum=MaxHum+5;//湿度步进值为5 
      if(MaxHum>90) MaxHum=20;//大于90,返回到20 
   }  
  } 
  /*******/ 
  if(displaynum==2)//设置的是温度 
  { 
   if(returnkey==2)//设置加 
   { 
    returnkey=0;//按键值清零 !! 
    MaxTem=MaxTem+2;//温度步进值为2 
    if(MaxTem>50) MaxTem=0;//返回到0 
   } 
  } 
} 
/*********/ 
set_display();//设置按键按下时的显示项目 
 
 
 
DHT11.zip
(3.46 KB, 下载次数: 525)
 |   
 
 
 
 |