📄 程序.txt
字号:
#include <REGX51.H>
#include <INTRINS.H>
#include <ABSACC.H >
#define TM_second XBYTE[0x7f00] //秒
#define TM_minute XBYTE[0x7f02] //分
#define TM_hour XBYTE[0x7f04] //时
#define TM_day XBYTE[0x7f07] //日
#define TM_month XBYTE[0x7f08] //月
#define TM_year XBYTE[0x7f09] //年(显示2位)
#define REG_a XBYTE[0x7f0a] //寄存器A
#define REG_b XBYTE[0x7f0b] //寄存器B
#define REG_c XBYTE[0x7f0c] //寄存器C
#define REG_d XBYTE[0x7f0d] //寄存器D
unsigned char clock[8];
unsigned char calendar[8];
unsigned char time_buf[7];
unsigned char time_buf1[7];
unsigned char displaybit[]={0xfe,0xfd,0xfb,0xf7, //位显代码
0xef,0xdf,0xbf,0x7f};
unsigned char code displaycode[]={0xfc,0x60,0xda,0xf2, //数码管显示代码
0x66,0xb6,0xbe,0xe0,
0xfe,0xf6,0x77,0x7c,
0x39,0x5e,0x79,0x71,0x00,0x02};
unsigned char displaycount=0; n=0; ds=0; z=0;
unsigned char displaybuf[8]={16,16,16,16,16,16,16,16};
unsigned int timecount=0, timecount1=0, timecount2=0,c=0;
unsigned char readdata[8];
unsigned long a, aa, bb;
sbit DQ=P3^5; //选P3.5口与DS18B20的数字信号输出端DQ相连
bit sflag;
bit resetpulse(void) //DS18B20初始化实现对DS18B20的复位
{
unsigned char pre;
unsigned char i;
DQ=0; //发出复位脉冲,将数据线下拉480μS-960μS
for(i=255;i>0;i--);
DQ=1; //DS18B20等待15μS-60μS
for(i=60;i>0;i--);
pre=DQ;
for(i=200;i>0;i--);
return(pre); // DS18B20返回60μS-240μS存在低脉冲,判断是否准备好接受或发送数据
}
void writecommandtods18b20(unsigned char command) //写时序
{
unsigned char i,j;
for(i=0;i<8;i++)
{
if((command & 0x01)==0) //写0时序
{
DQ=0; //拉低单总线至少60μS,保证DS18B20在15μS-45μS时可以正确地采样I/O总线上的低电平
for(j=35;j>0;j--);
DQ=1;
}
else //写1时序
{
DQ=0; //拉低单总线后,在15us之内就得释放
for(j=2;j>0;j--);
DQ=1;
for(j=33;j>0;j--);
}
command=_cror_(command,1);
}
}
unsigned char readdatafromds18b20(void) //读时序
{
unsigned char i,j;
unsigned char temp;
temp=0;
for(i=0;i<8;i++)
{
temp=_cror_(temp,1);
DQ=0; //单总线拉低后,读时序开始
_nop_();
_nop_();
DQ=1; //停止将数据线拉低,以读取数据
for(j=10;j>0;j--);
if(DQ==1)
{
temp=temp | 0x80;
}
else
{
temp=temp | 0x00;
}
for(j=200;j>0;j--);
}
return(temp);
}
void settime() //DS12B887设置系统时间
{
REG_b=0xfe; //B寄存器 SET位置1使芯片停止工作,才可以初始化各个时标寄存器;采用二进制码,24小时工作制,不使用夏令时
TM_second =time_buf[0];
TM_minute=time_buf[1];
TM_hour=time_buf[2];
TM_day=time_buf[4];
TM_month=time_buf[5];
TM_year=time_buf[6];
REG_b=0x7e; // SET位清0芯片正常工作,停止初始化
}
void readtime() // DS12B887读取系统时间
{
unsigned char c;
do{ c=REG_a;} while((c&0x80)==0x80); //A寄存器的UIP位为1时,芯片处于或即将开始更新,程序不可读写时标寄存器
time_buf[0]=TM_second;
time_buf[1]=TM_minute;
time_buf[2]=TM_hour;
time_buf[4]=TM_day;
time_buf[5]=TM_month;
time_buf[6]=TM_year;
}
void delay(void) //延时
{
unsigned char a,b;
for(a=0;a<225;a++)
{
for(b=0;b<200;b++);
}
}
void main(void)
{
TMOD=0x01;
TH0=(65536-2000)/256;
TL0=(65536-2000)%256;
ET0=1;
EA=1;
EX1 = 0;
REG_a=0x2f; // A寄存器的DV0-DV2位置为010,启动芯片内部振荡器RTC
readtime();
settime();
TR0=1;
while(1)
{
if(timecount2==c+1) //设置相应变量,有中断程序执行时主程序才读取一次温度值,避免频繁的读取数据对数码管显示造成的影响
{
readtime();c++;
}
clock[7]=time_buf[0]%10; //数字钟赋值
clock[6]=time_buf[0]/10;
clock[5]=17; //显示中间横杆
clock[4]=time_buf[1]%10;
clock[3]=time_buf[1]/10;
clock[2]=17;
clock[1]=time_buf[2]%10;
clock[0]=time_buf[2]/10;
calendar[7]=time_buf[4]%10; //日历赋值
calendar[6]=time_buf[4]/10;
calendar[5]=17;
calendar[4]=time_buf[5]%10;
calendar[3]=time_buf[5]/10;
calendar[2]=17;
calendar[1]=time_buf[6]%10;
calendar[0]=time_buf[6]/10;
if(P3_0==0) // P3.0——显示切换键,ds=0:显示时钟;
ds=1:显示日历;
ds=2:显示温度
{
delay(); while(!P3_0); delay();
ds++;
if(ds==3){ds=0;}
}
if(ds==0) //按键改变时钟时、分、秒值
{
if(P3_1==0) // P3.1——调时调分调秒切换键,z=1:调时;
z=2:调分;
z=3:调秒
{ delay();while(!P3_1);delay();z++;}
switch(z)
{ case 1: if(P3_2==0) // P3.2——时分秒值增加键
{ delay();
while(!P3_2);delay();time_buf[2]++;
if(time_buf[2]==24){time_buf[2]=0;}
settime();
}
if(P3_3==0) // P3.3——时分秒值减小键
{ delay();
while(!P3_3);delay();time_buf[2]--;
if(time_buf[2]==0){time_buf[2]=23;}
settime();
}
break;
case 2: if(P3_2==0)
{ delay();
while(!P3_2);delay();time_buf[1]++;
if(time_buf[1]==60){time_buf[1]=0;}
settime();
}
if(P3_3==0)
{ delay();
while(!P3_3);delay();time_buf[1]--;
if(time_buf[1]==0){time_buf[1]=59;}
settime();
}
break;
case3: if(P3_2==0)
{ delay();
while(!P3_2);delay();time_buf[0]++;
if(time_buf[0]==60){time_buf[0]=0;};
settime();
}
if(P3_3==0)
{ delay();
while(!P3_3);delay();time_buf[0]--;
if(time_buf[0]==0){time_buf[0]=59;}
settime();
}
break;
}
if(z==4){z=0;}
}
if(ds==1) //按键改变日历年、月、日值
{
if(P3_1==0)
{ delay();while(!P3_1);delay();z++;}
switch(z)
{
Case 1: if(P3_2==0)
{ delay();
while(!P3_2);delay();time_buf[6]++;settime();
}
if(P3_3==0)
{ delay();
while(!P3_3);delay();time_buf[6]--;
if(time_buf[6]==0){time_buf[6]=99;}
settime();
}
break;
case 2: if(P3_2==0)
{ delay();
while(!P3_2);delay();time_buf[5]++;
if(time_buf[5]==13){time_buf[5]=0;};
settime();
}
if(P3_3==0)
{ delay();
while(!P3_3);delay();time_buf[5]--;
if(time_buf[5]==0){time_buf[5]=12;}
settime();
}
break;
case 3: if(P3_2==0)
{ delay();
while(!P3_2);delay();time_buf[4]++;
if(time_buf[4]==32){time_buf[4]=0;}
settime();
};
if(P3_3==0)
{ delay();
while(!P3_3);delay();time_buf[4]--;
if(time_buf[4]==0){time_buf[4]=31;}
settime();
}
break;
}
if(z==4){z=0;}
}
}
}
void t0(void) interrupt 1 using 0
{
unsigned char x;
unsigned int result;
TH0=(65536-2000)/256; //定时2ms
TL0=(65536-2000)%256;
c=timecount2; //设置相应变量,有中断程序执行时主程序才读取一次温度值
timecount2++;
if(ds==2) //温度功能设定
{
if(displaycount==2) //温度值个位显示小数点
{
P1=displaycode[displaybuf[displaycount]] | 0x01;
}
else
{
P1=displaycode[displaybuf[displaycount]];
}
}
if(ds==0)
{
P1=displaycode[clock [displaycount]];
}
if(ds==1)
{
P1=displaycode[calendar[displaycount]];
}
P2=displaybit[displaycount];
displaycount++;
if(displaycount==8)
{
displaycount=0;
}
timecount++; timecount1++;
if(timecount1==250) //若P3.1调时调分调秒切换键按下,则每0.5s对应修改位的数值熄灭,实现闪烁显示
{
switch(z)
{ case 1:displaybit[0]=0xff;displaybit[1]=0xff;break;
case 2:displaybit[3]=0xff;displaybit[4]=0xff;break;
case 3:displaybit[6]=0xff;displaybit[7]=0xff;break;
}
}
if(timecount1==500)
{
switch(z)
{ case 0:displaybit[6]=0xbf;displaybit[7]=0x7f;break;
case 1:displaybit[0]=0xfe;displaybit[1]=0xfd;break;
case 2:displaybit[0]=0xfe;displaybit[1]=0xfd;
displaybit[3]=0xf7;displaybit[4]=0xef;break;
case 3:displaybit[0]=0xfe;displaybit[1]=0xfd;
displaybit[3]=0xf7;displaybit[4]=0xef;
displaybit[6]=0xbf;displaybit[7]=0x7f;break;
}
timecount1=0;
}
if(timecount==250) //每0.5s读取一次温度值
{
timecount=0;
if(ds==2)
{
while(resetpulse()); //写前调用初始化程序对DS18B20复位
writecommandtods18b20(0xcc); //单片DS18B20工作,跳过读ROM中64位地址的过程
writecommandtods18b20(0x44); //启动DS18B20进行温度转化,将结果存入内部RAM中
while(resetpulse()); //写前调用初始化程序对DS18B20复位
writecommandtods18b20(0xcc);
writecommandtods18b20(0xbe); // 读DS18B20RAM中温度数据
readdata[0]=readdatafromds18b20(); //温度数据低8位赋值
readdata[1]=readdatafromds18b20(); //温度数据高8位赋值
for(x=0;x<8;x++)
{
displaybuf[x]=16;
}
sflag=0;
if((readdata[1] & 0xf8)==0x80) //温度数据高5位为1时,温度为负值
{
sflag=1;
readdata[1]=~readdata[1]; //对负温度值进行取反加1操作
readdata[0]=~readdata[0];
result=readdata[0]+1;
readdata[0]=result;
if(result>255)
{
readdata[1]++;
}
}
if(sflag==1) //若为负温度,数码管首位显示负号
{
displaybuf[0]=17;
}
readdata[1]=readdata[1]&0x07; //将代表符号的高5位数屏蔽
aa=625;bb=(readdata[1]*256+readdata[0]);
a=bb*aa; //计算实际温度值
displaybuf[1]=a/100000; //给各显示位赋温度值
displaybuf[2]=a%100000/10000;
displaybuf[3]=a%10000/1000;
displaybuf[4]=a%1000/100;
displaybuf[5]=a%100/10;
displaybuf[6]=a%10;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -