#include<reg51.h>//定义函数
#include<intrins.h>
typedef unsigned char uchar;//无符号8位整型变量
typedef unsigned int uint;//无符号16位整型变量
sbit RS=P2^7;//LCD1602数据/命令选择端(H/L)
sbit RW=P2^6;//LCD1602读/写选择端(H/L)
sbit E=P2^5;//LCD1602使能信号端
sbit DATA=P3^6;
sbit SCK=P3^7;
sbit k1=P3^2;//总设置按键
sbit k2=P3^3;//设置按键
sbit k3=P3^4;//+按键
sbit k4=P3^5;//-按键
sbit beep=P2^0;
sbit D1=P1^0;//高温报警指示灯
sbit D2=P1^1;//低温报警指示灯
sbit D3=P1^2;//高湿度报警指示灯
sbit D4=P1^3;//低湿度报警指示灯
sbit ACC0=ACC^0;
sbit ACC7=ACC^7;
sbit IO=P1^5;
sbit SCLK=P1^6;
sbit RST=P1^7;
uchar idata wendu[6];
uchar idata shidu[6];
uchar code table1[]=" 2013-08-30 ";
uchar code table2[]=" QQ:383459194 ";
uchar code table3[]=" gaowenbaojing ";
uchar code table4[]=" diwenbaojing ";
uchar code table5[]="gaoshidubaojing ";
uchar code table6[]=" dishidubaojing ";
uchar code table7[]="gaowen+gaoshidu ";
uchar code table8[]=" gaowen+dishidu ";
uchar code table9[]=" diwen+gaoshidu ";
uchar code table10[]=" diwen+dishidu ";
uchar code table11[]=" this is ok ";
uchar code table12[]=" ";
uchar code table13[]=" : : ";
enum {TEMP,HUMI};
typedef union //定义共用同类型
{
uint i;
float f;
} value;
uchar a,b,c,d,num,flag=0,m=0,num1=0;
char miao,shi,fen;
uchar ccc,ri,yue,nian,zhou,flag1;
//延时子函数
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=120;y>0;y--);
}
//按键提示音子函数
void di()
{
beep=0;
delay(100);
beep=1;
}
//往DS1302时钟芯片写入一字节子函数
void inputbyte(uchar add)
{
uchar i;
ACC=add;
for(i=8;i>0;i--)
{
IO=ACC0;
SCLK=1;
SCLK=0;
ACC=ACC>>1;
}
}
//DS1302时钟芯片输出一字节子函数
uchar outputbyte()
{
uchar i;
for(i=8;i>0;i--)
{
ACC=ACC>>1;
ACC7=IO;
SCLK=1;
SCLK=0;
}
return ACC;
}
//往DS1302时钟芯片写入数据子函数
void write_ds(uchar add,uchar ucda)
{
RST=0;
SCLK=0;
RST=1;
inputbyte(add);
inputbyte(ucda);
SCLK=1;
RST=0;
}
//从DS1302时钟芯片读出数据子函数
uchar read_ds(uchar add)
{
uchar ucda;
RST=0;
SCLK=0;
RST=1;
inputbyte(add);
ucda=outputbyte();
SCLK=1;
RST=0;
return(ucda);
}
//设置DS1302时钟芯片子函数
void write_setds(uchar addr,uchar date)
{
write_ds(0x8e,0x00);
write_ds(addr,date);
write_ds(0x8e,0x80);
}
//检查LCD1602液晶忙位子函数
void LCD1602_busy()
{
uchar i=0;
RS=0;
RW=1;
E=1;
P0=0xff;
i=0;
while(((P0&0x80)==0x80)&&i<150)
i++;
E=0;
}
//LCD1602液晶写指令子函数
void write_com(uchar com)
{
LCD1602_busy();
RS=0;
RW=0;
P0=com;
E=1;
E=0;
}
//LCD1602液晶写数据子函数
void write_date(uchar date)
{
LCD1602_busy();
RS=1;
RW=0;
P0=date;
E=1;
E=0;
}
//LCD1602液晶初始化子函数
void LCD1602_init() //初始化设置
{
//uchar i;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
/*write_com(0x80);
for(i=0;i<16;i++)
{
write_date(table1[i]);
delay(500);
}
write_com(0xc0);
for(i=0;i<16;i++)
{
write_date(table2[i]);
delay(500);
}*/
a=35;
b=10;
c=65;
d=40;
}
//SHT10写字节子函数
char s_write_byte(uchar value)
{
uchar i,error=0;
for(i=0x80;i>0;i>>=1) //高位为1,循环右移
{
if(i&value)
DATA=1;//和要发送的数相与,结果为发送的位
else
DATA=0;
SCK=1;
_nop_();
_nop_();
_nop_();//延时3us
SCK=0;
}
DATA=1; //释放数据线
SCK=1;
error=DATA; //检查应答信号,确认通讯正常
_nop_();
_nop_();
_nop_();
SCK=0;
DATA=1;
return error; //error=1 通讯错误
}
//SHT10读字节子函数
char s_read_byte(uchar ack)
{
uchar i,val=0;
DATA=1; //释放数据线
for(i=0x80;i>0;i>>=1) //高位为1,循环右移
{
SCK=1;
if(DATA)
val=(val|i); //读一位数据线的值
SCK=0;
}
DATA=!ack; //如果是校验,读取完后结束通讯;
SCK=1;
_nop_();
_nop_();
_nop_();//延时3us
SCK=0;
_nop_();
_nop_();
_nop_();
DATA=1; //释放数据线
return val;
}
//SHT10启动传输子函数
void s_transstart()
{
DATA=1;
SCK=0; //准备
_nop_();
SCK=1;
_nop_();
DATA=0;
_nop_();
SCK=0;
_nop_();
_nop_();
_nop_();
SCK=1;
_nop_();
DATA=1;
_nop_();
SCK=0;
}
//SHT10连接复位子函数
void s_connectionreset()
{
uchar i;
DATA=1;
SCK=0;//准备
for(i=0;i<9;i++) //DATA保持高,SCK时钟触发9次,发送启动传输,通迅即复位
{
SCK=1;
SCK=0;
}
s_transstart(); //启动传输
}
//SHT10温湿度检测子函数
char s_measure(uchar *p_value,uchar *p_checksum,uchar mode)
{
unsigned error=0;
uint i;
s_transstart(); //启动传输
switch(mode) //选择发送命令
{
case TEMP: error+=s_write_byte(0x03);
break; //测量温度
case HUMI: error+=s_write_byte(0x05);
break; //测量湿度
default: break;
}
for(i=0;i<65535;i++)
if(DATA==0)
break; //等待测量结束
if(DATA)
error+=1; // 如果长时间数据线没有拉低,说明测量错误
*(p_value)=s_read_byte(1); //读第一个字节,高字节 (MSB)
*(p_value+1)=s_read_byte(1); //读第二个字节,低字节 (LSB)
*p_checksum=s_read_byte(0); //read CRC校验码
return error; // error=1 通讯错误
}
//SHT10温湿度值标度变换及温度补偿子函数
void calc_sth10(float *p_humidity ,float *p_temperature)
{
const float C1=-4.0; // 12位湿度精度 修正公式
const float C2=+0.0405; // 12位湿度精度 修正公式
const float C3=-0.0000028; // 12位湿度精度 修正公式
const float T1=+0.01; // 14位温度精度 5V条件 修正公式
const float T2=+0.00008; // 14位温度精度 5V条件 修正公式
float rh=*p_humidity; // rh: 12位 湿度
float t=*p_temperature; // t: 14位 温度
float rh_lin; // rh_lin: 湿度 linear值
float rh_true; // rh_true: 湿度 ture值
float t_C; // t_C : 温度 ℃
t_C=t*0.01-40; //补偿温度
rh_lin=C3*rh*rh+C2*rh+C1; //相对湿度非线性补偿
rh_true=(t_C-25)*(T1+T2*rh)+rh_lin; //相对湿度对于温度依赖性补偿
if(rh_true>100)
rh_true=100; //湿度最大修正
if(rh_true<0.1)
rh_true=0.1; //湿度最小修正
*p_temperature=t_C; //返回温度结果
*p_humidity=rh_true; //返回湿度结果
}
//往LCD1602液晶写入日期子函数
void write_nyr(uchar add,uchar date)
{
uchar shi,ge ;
shi=date/10;
ge=date%10;
write_com(0x80+0x01+add);
write_date(0x30+shi);
write_date(0x30+ge);
}
//往LCD1602液晶写入时间子函数
void write_sfm1(uchar add,uchar date)
{
uchar shi,ge;
shi=date/10;
ge=date%10;
write_com(0x80+0x42+add);
write_date(0x30+shi);
write_date(0x30+ge);
}
//电子万年历显示子函数
void display1()
{
if(flag1!=1)
{
uchar d;
d=read_ds(0x81);
miao=(d/16)*10+(d%16);
write_sfm1(8,miao);
d=read_ds(0x83);
fen=(d/16)*10+(d%16);
write_sfm1(5,fen);
d=read_ds(0x85);
shi=(d/16)*10+(d%16);
write_sfm1(2,shi);
d=read_ds(0x87);
ri=(d/16)*10+(d%16);
write_nyr(8,ri);
d=read_ds(0x89);
yue=(d/16)*10+(d%16);
write_nyr(5,yue);
d=read_ds(0x8b);
zhou=d%16;
write_nyr(12,zhou);
d=read_ds(0x8d);
nian=(d/16)*10+(d%16);
write_nyr(2,nian);
}
}
//温湿度显示子函数
void display()
{
write_com(0x80+1);
write_date('T');
write_com(0x80+2);
write_date('=');
write_com(0x80+3);
write_date(wendu[0]);
write_com(0x80+4);
write_date(wendu[1]);
write_com(0x80+5);
write_date(wendu[2]);
write_com(0x80+6);
write_date(wendu[3]);
write_com(0x80+7);
write_date(wendu[4]);
write_com(0x80+8);
write_date(' ');
write_com(0x80+9);
write_date('R');
write_com(0x80+10);
write_date('=');
write_com(0x80+11);
write_date(shidu[0]);
write_com(0x80+12);
write_date(shidu[1]);
write_com(0x80+13);
write_date(shidu[2]);
write_com(0x80+14);
write_date(shidu[3]);
write_com(0x80+15);
write_date(shidu[4]);
}
//LCD1602液晶写参数子函数
void write_sfm(uchar aaa,uchar bbb)
{
uchar shi,ge;
shi=bbb/10;
ge=bbb%10;
write_com(0x80+0x40+aaa);
write_date(0x30+shi);
write_date(0x30+ge);
}
//按键扫描子函数
void keyscan()
{
uchar i=100,e;
if(k1==0&&num==0&&num1==0)
{
delay(10);
if(k1==0&&num==0&&num1==0)
{
while(k1==0&&num1==0&&num==0&&i)
{
i--;
delay(10);
}
di();
flag++;
if(flag==1)
{
write_com(0x01);
delay(5);
write_com(0x80+1);
write_date('2');
write_com(0x80+2);
write_date('0');
write_com(0x80+5);
write_date('-');
write_com(0x80+8);
write_date('-');
write_com(0xc0+6);
write_date(':');
write_com(0xc0+9);
write_date(':');
}
if(flag>=2)
{
write_com(0x01);
delay(5);
flag=0;
}
}
}
if(k2==0&&flag==0&&num1==0)
{
delay(10);
if(k2==0&&flag==0&&num1==0)
{
while(k2==0&&num1==0&&flag==0&&i)
{
i--;
delay(10);
}
di();
num++;
if(num==1)
{
write_com(0xc0);
for(e=0;e<16;e++)
write_date(table12[e]);
write_com(0xc0+4);
write_date('T');
write_com(0xc0+5);
write_date('H');
write_com(0xc0+6);
write_date('=');
write_com(0xc0+7);
write_date(a/10+0x30);
write_com(0xc0+8);
write_date(a%10+0x30);
write_com(0xc0+9);
write_date(0xdf);
write_com(0xc0+10);
write_date(0x43);
}
if(num==2)
{
write_com(0xc0+4);
write_date('T');
write_com(0xc0+5);
write_date('L');
write_com(0xc0+6);
write_date('=');
write_com(0xc0+7);
write_date(b/10+0x30);
write_com(0xc0+8);
write_date(b%10+0x30);
write_com(0xc0+9);
write_date(0xdf);
write_com(0xc0+10);
write_date(0x43);
}
if(num==3)
{
write_com(0xc0);
for(e=0;e<16;e++)
write_date(table12[e]);
write_com(0xc0+4);
write_date('R');
write_com(0xc0+5);
write_date('H');
write_com(0xc0+6);
write_date('=');
write_com(0xc0+7);
write_date(c/10+0x30);
write_com(0xc0+8);
write_date(c%10+0x30);
write_com(0xc0+9);
write_date('%');
}
if(num==4)
{
write_com(0xc0+4);
write_date('R');
write_com(0xc0+5);
write_date('L');
write_com(0xc0+6);
write_date('=');
write_com(0xc0+7);
write_date(d/10+0x30);
write_com(0xc0+8);
write_date(d%10+0x30);
write_com(0xc0+9);
write_date('%');
}
if(num>=5)
{
num=0;
}
}
}
if(num!=0&&flag==0&&num1==0)
{
if(k3==0)
{
delay(10);
if(k3==0)
{
while(k3==0&&i)
{
i--;
delay(10);
}
di();
if(num==1)
{
a++;
if(a==50)
a=35;
write_sfm(7,a);
write_com(0xc0+8);
}
if(num==2)
{
b++;
if(b==30)
b=10;
write_sfm(7,b);
write_com(0xc0+8);
}
if(num==3)
{
c++;
if(c==95)
c=65;
write_sfm(7,c);
write_com(0xc0+8);
}
if(num==4)
{
d++;
if(d==60)
d=40;
write_sfm(7,d);
write_com(0xc0+8);
}
}
}
if(k4==0)
{
delay(10);
if(k4==0)
{
while(k4==0&&i)
{
i--;
delay(10);
}
di();
if(num==1)
{
a--;
if(a==15)
a=35;
write_sfm(7,a);
write_com(0xc0+8);
}
if(num==2)
{
b--;
if(b==0)
b=10;
write_sfm(7,b);
write_com(0xc0+8);
}
if(num==3)
{
c--;
if(c==40)
c=65;
write_sfm(7,c);
write_com(0xc0+8);
}
if(num==4)
{
d--;
if(d==0)
d=40;
write_sfm(7,d);
write_com(0xc0+8);
}
}
}
}
if(k2==0&&flag==1&&num==0)
{
delay(10);
if(k2==0&&flag==1&&num==0)
{
while(k2==0&&flag==1&&num==0&&i)
{
i--;
delay(10);
}
di();
num1++;
if(num1==1)
{
flag1=1;
write_ds(0x8e,0x80);
write_com(0x80+0x40+10);
write_com(0x0f);
write_ds(0x8e,0x00);
ccc=read_ds(0x81);
miao=(ccc/16)*10+ccc%16;
ccc=read_ds(0x83);
fen=(ccc/16)*10+ccc%16;
ccc=read_ds(0x85);
shi=(ccc/16)*10+ccc%16;
ccc=read_ds(0x87);
ri=(ccc/16)*10+ccc%16;
ccc=read_ds(0x89);
yue=(ccc/16)*10+ccc%16;
ccc=read_ds(0x8b);
zhou=(ccc/16)*10+ccc%16;
ccc=read_ds(0x8d);
nian=(ccc/16)*10+ccc%16;
}
if(num1==2)
write_com(0x80+0x40+7);
if(num1==3)
write_com(0x80+0x40+4);
if(num1==4)
write_com(0x80+0x0d);
if(num1==5)
write_com(0x80+0x09);
if(num1==6)
write_com(0x80+6);
if(num1==7)
write_com(0x80+3);
if(num1==8)
{
num1=0;
write_com(0x0c);
write_ds(0x8e,0x80);
flag1=0;
}
}
}
if(num1!=0&&flag==1&&num==0)//判断num值
{
if(k3==0&&flag==1&&num==0)//判断k2按键是否按下
{
delay(10);//延时5毫秒
if(k3==0&&flag==1&&num==0)//再次判断k2按键是否按下
{
while(k3==0&&flag==1&&num==0&&i)//判断按键松手检测
{
i--;
delay(10);
}
di();//调用蜂鸣器子函数
if(num1==1)
{
miao++;
if(miao==61)
miao=1 ;
write_sfm1(8,miao);
write_com(0x80+0x4a);
}
if(num1==2)
{
fen++;
if(fen==60)
fen=0;
write_sfm1(5,fen);
write_com(0x80+0x48);
}
if(num1==3)
{
shi++;
if(shi==24)
shi=0;
write_sfm1(2,shi);
write_com(0x80+0x40+5);
}
if(num1==4)
{
zhou++;
if(zhou==8)
zhou=1;
write_nyr(12,zhou);
write_com(0x80+0x0d);
}
if(num1==5)
{
ri++;
if(ri==32)
ri=1;
write_nyr(8,ri);
write_com(0x80+0x0a);
}
if(num1==6)
{
yue++;
if(yue==13)
yue=1;
write_nyr(5,yue);
write_com(0x80+7);
}
if(num1==7)
{
nian++;
write_nyr(2,nian);
write_com(0x80+4);
}
}
}
if(k4==0&&flag==1&&num==0)//判断k3按键是否按下
{
delay(10);//延时10毫秒
if(k4==0&&flag==1&&num==0)//再次判断k3按键是否按下
{
while(k4==0&&flag==1&&num==0&&i)//判断按键松手检测
{
i--;
delay(10);
}
di();//调用蜂鸣器子函数
if(num1==1)
{
miao--;
if(miao==-1)
miao=59;
write_sfm1(8,miao);
write_com(0x80+0x4a);
}
if(num1==2)
{
fen--;
if(fen==-1)
fen=59;
write_sfm1(5,fen);
write_com(0x80+0x48);
}
if(num1==3)
{
shi--;
if(shi==-1)
shi=23;
write_sfm1(2,shi);
write_com(0x80+0x45);
}
if(num1==4)
{
zhou--;
if(zhou==0)
zhou=7;
write_nyr(12,zhou);
write_com(0x80+0x0d);
}
if(num1==5)
{
ri--;
if(ri==-1)
ri=1;
write_nyr(8,ri);
write_com(0x80+0x0a);
}
if(num1==6)
{
yue--;
if(yue==0)
yue=12;
write_nyr(5,yue);
write_com(0x87);
}
if(num1==7)
{
nian--;
write_nyr(2,nian);
write_com(0x84);
}
}
}
write_ds(0x80,(miao/10)*16+miao%10);
write_ds(0x82,(fen/10)*16+fen%10);
write_ds(0x84,(shi/10)*16+shi%10);
write_ds(0x86,(ri/10)*16+ri%10);
write_ds(0x88,(yue/10)*16+yue%10);
write_ds(0x8a,(zhou/10)*16+zhou%10);
write_ds(0x8c,(nian/10)*16+nian%10);
}
}
//主函数
void main()
{
uint temp,humi,i;
uint aa,bb,cc,dd;
value humi_val,temp_val; //定义两个共同体,一个用于湿度,一个用于温度
uchar error; //用于检验是否出现错误
uchar checksum;
LCD1602_init();//调用LCD1602液晶初始化子函数
//delay(5000);//延时
//write_com(0x01);
write_setds(0x80,0x50);
write_setds(0x82,0x59);
write_setds(0x84,0x10);
write_setds(0x86,0x17);
write_setds(0x88,0x03);
write_setds(0x8a,0x03);
write_setds(0x8c,0x10);
write_setds(0x90,0xa4);
s_connectionreset();
while(1)//大循环
{
keyscan();
if(flag==1)
{
display1();
}
if(flag==0&&num==0&&error==0&&num1==0)
{
aa=a*10;
bb=b*10;
cc=c*10;
dd=d*10;
if(temp>aa&&temp>bb&&humi<cc&&humi>dd)
{
D1=0;
D2=1;
D3=1;
D4=1;
write_com(0xc0);
for(i=0;i<16;i++)
{
write_date(table3[i]);
}
}
if(temp<aa&&temp<bb&&humi<cc&&humi>dd)
{
D1=1;
D2=0;
D3=1;
D4=1;
write_com(0xc0);
for(i=0;i<16;i++)
{
write_date(table4[i]);
}
}
if(temp<aa&&temp>bb&&humi>cc&&humi>dd)
{
D1=1;
D2=1;
D3=0;
D4=1;
write_com(0xc0);
for(i=0;i<16;i++)
{
write_date(table5[i]);
}
}
if(temp<aa&&temp>bb&&humi<cc&&humi<dd)
{
D1=1;
D2=1;
D3=1;
D4=0;
write_com(0xc0);
for(i=0;i<16;i++)
{
write_date(table6[i]);
}
}
if(temp>aa&&temp>bb&&humi>cc&&humi>dd)
{
D1=0;
D2=1;
D3=0;
D4=1;
write_com(0xc0);
for(i=0;i<16;i++)
{
write_date(table7[i]);
}
}
if(temp>aa&&temp>bb&&humi<cc&&humi<dd)
{
D1=0;
D2=1;
D3=1;
D4=0;
write_com(0xc0);
for(i=0;i<16;i++)
{
write_date(table8[i]);
}
}
if(temp<aa&&temp<bb&&humi>cc&&humi>dd)
{
D1=1;
D2=0;
D3=0;
D4=1;
write_com(0xc0);
for(i=0;i<16;i++)
{
write_date(table9[i]);
}
}
if(temp<aa&&temp<bb&&humi<cc&&humi<dd)
{
D1=0;
D2=0;
D3=1;
D4=0;
write_com(0xc0);
for(i=0;i<16;i++)
{
write_date(table10[i]);
}
}
if(temp<aa&&temp>bb&&humi<cc&&humi>dd)
{
D1=1;
D2=1;
D3=1;
D4=1;
write_com(0xc0);
for(i=0;i<16;i++)
{
write_date(table11[i]);
}
}
}
if(flag==0)
{
error=0; //初始化error=0,即没有错误
error+=s_measure((uchar*)&temp_val.i,&checksum,TEMP); //温度测量
error+=s_measure((uchar*)&humi_val.i,&checksum,HUMI); //湿度测量
if(error!=0)
s_connectionreset();//如果发生错误,系统复位
else
{
humi_val.f=(float)humi_val.i; //转换为浮点数
temp_val.f=(float)temp_val.i; //转换为浮点数
calc_sth10(&humi_val.f,&temp_val.f); //修正相对湿度及温度
temp=temp_val.f*10;
humi=humi_val.f*10;
wendu[0]=temp/1000+'0'; //温度百位
wendu[1]=temp%1000/100+'0'; //温度十位
wendu[2]=temp%100/10+'0'; //温度个位
wendu[3]=0x2E; //小数点
wendu[4]=temp%10+'0'; //温度小数点后第一位
shidu[0]=humi/1000+'0'; //湿度百位
shidu[1]=humi%1000/100+'0'; //湿度十位
shidu[2]=humi%100/10+'0'; //湿度个位
shidu[3]=0x2E; //小数点
shidu[4]=humi%10+'0'; //湿度小数点后第一位
display();
}
delay(800);
}
}
}
|