高级会员
主题
回帖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)
|
|