📄 ds1302.c
字号:
#include <reg51.h>
sbit CLK= P1^0; //DS1302相关控制信号
sbit DIO= P1^1;
sbit CE= P1^2;
sbit SET= P3^0; //设置键
sbit ADD= P3^1; //加键
sbit DEC= P3^2; //减键
sbit ALAM= P3^6; //闹钟输出
sbit DQ = P3^4; //18B20 I2C通讯口
sbit xsdxs= P0^7;
bit xsd;
bit run_OR_Set=0; //正常走时/设置标志
bit see_Tempreture=0; //查看温度标志位,=1时查看温度
bit see_Timer=0; //查看闹钟
bit zd=0; //整点报时位
bit sd=0; //设置时闪动 =1时开启闪动
unsigned char sd_char=0xFF; //闪动时置数
unsigned char ZDJS=0; //整点计数
unsigned char countt0; //t0中断计数器
unsigned char countt1; //t1中断计数器
unsigned char set_Count=0; //设置计数器,
unsigned char setNZn=0; //设置闹钟计数器
unsigned char NZ_hour=0,NZ_minit=0; //闹钟初值
unsigned char BCD_NZ_hour,BCD_NZ_minit; //
bit NZ=0; //闹钟标志位
unsigned char hour,minit,second,lastsecond;
unsigned char temp_hour,temp_minit,temp_second;
unsigned char code LED_DATA[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; // 共阴
//{0x28,0xEE,0x32,0xA2,0xE4,0xA1,0x21,0xEA,0x20,0xA0}; //共阳
void delay(unsigned int time)
{
while(--time);
}
//==============================================================================
//=============================DS18B20==========================================
//==============================================================================
unsigned char flag_Negative_number = 0;//负数标志
//晶振12MHz
void delay_18B20(unsigned int i)
{
while(i--);
}
//初始化函数
void Init_DS18B20(void)
{
unsigned char x=0;
DQ = 1; //DQ复位
delay_18B20(4); //稍做延时
DQ = 0; //单片机将DQ拉低
delay_18B20(80); //精确延时 大于 480us //100
DQ = 1; //拉高总线
delay_18B20(14);
x = DQ; //稍做延时后,如果x=0则初始化成功,x=1则初始化失败
delay_18B20(20);
}
//读一个字节
unsigned char ReadOneChar(void)
{
unsigned char i=0;
unsigned char dat = 0;
for (i=8;i>0;i--)
{
DQ = 0; // 给脉冲信号
dat>>=1;
DQ = 1; // 给脉冲信号
if(DQ)
dat|=0x80;
delay_18B20(10);
}
return(dat);
}
//写一个字节
void WriteOneChar(unsigned char dat)
{
unsigned char i=0;
for (i=8; i>0; i--)
{
DQ = 0;
DQ = dat&0x01;
delay_18B20(10);
DQ = 1;
dat>>=1;
}
}
//读取温度
unsigned int ReadTemperature(void)
{
unsigned char a=0;
unsigned char b=0;
unsigned int t=0;
float tt=0;
Init_DS18B20();
WriteOneChar(0xCC); //跳过读序号列号的操作
WriteOneChar(0x44); //启动温度转换
Init_DS18B20();
WriteOneChar(0xCC); //跳过读序号列号的操作
WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
a=ReadOneChar();
b=ReadOneChar();
//启动下一次温度转换
//Init_DS18B20();
//WriteOneChar(0xCC); // 跳过读序号列号的操作
//WriteOneChar(0x44); // 启动温度转换
t=b;
t<<=8;
t=t|a;
flag_Negative_number = 0;
if(t>0x0fff)
{
t=~t+1;
flag_Negative_number = 0xff;
}
//18b20:t=d*0.0625
tt=t*0.0625;
t=tt*10+0.5; //有效位到小数点后2位,适用Proteus6.9版本和实物版
//t = t*5; //有效位到小数点后2位,适用Proteus7以上版本
return(t);
}
//==============================================================================
//==============================================================================
//==============================================================================
//==============================================================================
//============================DS1302============================================
//==============================================================================
unsigned char du1302(unsigned char dizhi)
{
unsigned char i,jieguo;
CLK=0;
CE=1;
for(i=0;i<8;i++)
{
DIO=dizhi& 0x01;
CLK=1;CLK=0;
dizhi=dizhi>>1;
}
DIO=1;
jieguo=0;
if(DIO==1){jieguo=jieguo|0x80;}
for(i=0;i<7;i++)
{
CLK=1;CLK=0;
jieguo=jieguo>>1;
if(DIO==1){jieguo=jieguo| 0x80;}
}
CE=0;
return(jieguo);
}
void xie1302(unsigned char dizhi,shuju)
{
unsigned char i;
CE=1;
for(i=0;i<8;i++)
{
DIO=dizhi& 0x01;
CLK=1;CLK=0;
dizhi=dizhi>>1;
}
for(i=0;i<8;i++)
{
DIO=shuju& 0x01;
CLK=1;CLK=0;
shuju=shuju>>1;
}
CE=0;
}
//========================================================================
//========================================================================
//========================================================================
void display(void)
{
unsigned int temp;
if(see_Tempreture==1) //---------------显示温度----------------------
{
temp = ReadTemperature();//*5;
if(flag_Negative_number)
P0 = 0x40;
else
P0 = 0x00;
P2 = 0xBF;
delay(300);
P2 = 0xFF;
P0 = LED_DATA[temp/100%10];
P2 = 0xDF;
delay(300);
P2=0xFF;
//P0 = LED_DATA[temp/10%10+10];
P0 = LED_DATA[temp/10%10];
P2 = 0xEF;
delay(300);
P2=0xFF;
P0 = LED_DATA[temp%10];
P2 = 0xF7;
delay(300);
P2=0xFF;
P0 = 0x58;
P2 = 0xFB;
delay(300);
P2=0xFF;
}
else
{
if(see_Timer==1) //------------显示闹钟--------------------
{
unsigned char D1,D2,D3,D4,D5,D6;
D1=NZ_hour/10; D2=NZ_hour%10;
D3=NZ_minit/10; D4=NZ_minit%10;
D5=0; D6=0;
if(setNZn==1)
P0= (LED_DATA[D1]&sd_char); //display hour
else
P0= LED_DATA[D1];
P2= 0x7F;
delay(300);
P2= 0xFF;
if(setNZn==1)
P0= ((LED_DATA[D2]|0x80)&sd_char);
else
P0= LED_DATA[D2]|0x80;
//xsdxs=xsd;
P2= 0xBF;
delay(300);
P2= 0xff;
if(setNZn==2)
P0= (LED_DATA[D3]&sd_char); //display minit
else
P0= LED_DATA[D3];
P2= 0xDF;
delay(300);
P2=0xff;
if(setNZn==2)
P0= (LED_DATA[D4]&sd_char);
else
P0= LED_DATA[D4];
P2= 0xEF;
delay(300);
P2=0xff;
P0= LED_DATA[D5]; //display second
P2= 0xF7;
delay(300);
P2=0xff;
P0= LED_DATA[D6];
P2= 0xFB;
delay(300);
P2=0xff;
}
else //--------------------显示时间-----------------
{
unsigned char D1,D2,D3,D4,D5,D6;
if(run_OR_Set==1)
second=0x00;
else
second= du1302(0x81);
minit= du1302(0x83);
hour= du1302(0x85);
if(second!=lastsecond){xsd=!xsd;}
lastsecond=second;
D1=hour>>4; D2=hour&0x0f;
D3=minit>>4; D4=minit&0x0f;
D5=second>>4; D6=second&0x0f;
if(set_Count==1)
P0= (LED_DATA[D1]&sd_char); //display hour
else
P0= LED_DATA[D1];
P2= 0x7F;
delay(300);
P2= 0xFF;
if(set_Count==1)
P0= ((LED_DATA[D2]|0x80)&sd_char);
else
P0= LED_DATA[D2]|0x80;
//xsdxs=xsd;
P2= 0xBF;
delay(300);
P2= 0xff;
if(set_Count==2)
P0= (LED_DATA[D3]&sd_char); //display minit
else
P0= LED_DATA[D3];
P2= 0xDF;
delay(300);
P2=0xff;
if(set_Count==2)
P0= (LED_DATA[D4]&sd_char);
else
P0= LED_DATA[D4];
P2= 0xEF;
delay(300);
P2=0xff;
P0= LED_DATA[D5]; //display second
P2= 0xF7;
delay(300);
P2=0xff;
P0= LED_DATA[D6];
P2= 0xFB;
delay(300);
P2=0xff;
}
}
}
void key_Scan(void)
{
if(SET==0) //SET键按下
{
display(); //调用显示,用于延时消抖
if(SET==0)
{
TR1=0; //停止闹钟
NZ=0;
if(see_Tempreture==0)
{
if(see_Timer==0)
{
setNZn=0;
second=0x00;
run_OR_Set=1; //开启设置标志
xie1302( 0x8E, 0x00);
xie1302( 0x80, 0x80); //时钟停止走时
xie1302( 0x8E, 0x80);
set_Count++;
TR0=1; //开启定时器0
if(set_Count==3)
{
run_OR_Set=0; //关闭设置标志位
set_Count=0; //设置计数器清零,
TH0=0x3C;
TL0=0xB0;
TR0=0; //关闭定时器0
sd=0; //关闭闪动
sd_char=0xFF;
xie1302( 0x8E, 0x00);
xie1302( 0x80, 0x00); //时钟启动
xie1302( 0x8E, 0x80);
}
}
else
{
set_Count=0;
setNZn++;
TR0=1;
if(setNZn==3)
{
setNZn=0;
NZ=1; //开启闹钟
BCD_NZ_hour=(((NZ_hour/10)<<4)+(NZ_hour%10)); //将闹钟时间转换为BCD数
BCD_NZ_minit=(((NZ_minit/10)<<4)+(NZ_minit%10));
TH0=0x3C;
TL0=0xB0;
TR0=0;
sd=0;
sd_char=0xFF;
}
}
}
}
do
display();
while(!SET);
}
if(ADD==0)
{
display(); //调用显示,用于延时消抖
if(ADD==0)
{
if(TR1==1)
{
TR1=0;
ALAM=1;
}
else
{
if(see_Tempreture==0)
{
if(set_Count==0)
{
if(setNZn==0)
{
see_Timer=~see_Timer; //开启查看闹钟功能
see_Tempreture=0;
}
if(setNZn==1)
{
NZ_hour++;
if(NZ_hour==24)
NZ_hour=0;
}
if(setNZn==2)
{
NZ_minit++;
if(NZ_minit==60)
NZ_minit=0;
}
}
if(set_Count==1) //调小时
{
hour++;
if((hour&0x0f)>=10) //控制十进制进位
{
hour=hour+0x10;
hour=hour&0xf0;
}
if(hour>=0x24) //1302内部以16进制保存数据
hour=0;
xie1302( 0x8E, 0x00); //将转换后的小时数据写入1302
xie1302( 0x80, 0x80);
xie1302( 0x84,hour);
xie1302( 0x8E, 0x80);
}
if(set_Count==2) //调分钟
{
minit++;
if((minit&0x0f)>=0x0A) //十进制进位
{
minit=minit+0x10;
minit=minit&0xf0;
}
if(minit>=0x60)
minit=0;
xie1302( 0x8E, 0x00);
xie1302( 0x80, 0x80);
xie1302( 0x82,minit);
xie1302( 0x8E, 0x80);
}
}
}
}
do
display();
while(!ADD);
}
if(DEC==0)
{
display(); //调用显示,用于延时消抖
if(DEC==0)
{
if(set_Count==0)
{
if(setNZn==0)
{
see_Tempreture=~see_Tempreture; //当在非设置状态下可以查看温度
see_Timer=0;
}
if(setNZn==1)
{
if(NZ_hour==0)
NZ_hour=24;
NZ_hour--;
}
if(setNZn==2)
{
if(NZ_minit==0)
NZ_minit=60;
NZ_minit--;
}
}
if(set_Count==1) //调小时
{
if((hour&0x0f)>0x00)
hour--;
else
{
if((hour&0xf0)>0x00)
{
hour=hour-0x10;
hour=hour+0x09;
}
else
hour=0x23;
}
xie1302( 0x8E, 0x00);
xie1302( 0x80, 0x80);
xie1302( 0x84,hour);
xie1302( 0x8E, 0x80);
}
if(set_Count==2) //调分钟
{
if((minit&0x0f)>0x00)
minit--;
else
{
if((minit&0xf0)>0x00)
{
minit=minit-0x10;
minit=minit+0x09;
}
else
minit=0x59;
}
xie1302( 0x8E, 0x00);
xie1302( 0x80, 0x80);
xie1302( 0x82,minit);
xie1302( 0x8E, 0x80);
}
}
do
display();
while(!DEC);
}
}
main()
{
unsigned char temp_second;
xie1302( 0x90, 0xa5);
Init_DS18B20();
delay(5000);
TMOD=0x11;
TH0=0x3C;
TL0=0xB0;
TH1=0x3C;
TL1=0xB0;
EA=1;
ET0=1;
ET1=1;
TR0=0;
TR1=0;
while(1)
{
key_Scan();
display();
if(NZ==1)
{
if((hour==BCD_NZ_hour)&&(minit==BCD_NZ_minit)&&(second==0))
TR1=1;
if(minit==(BCD_NZ_minit+1))
{
TR1=0;
ALAM=1;
}
}
if((minit==0x00)&&(second==0x00)) //整点
{
TR1=1;
temp_second=second;
}
if((minit==0x00)&&(second==hour))
{
TR1=0;
ALAM=1;
}
}
}
void Initime0(void) interrupt 1
{
TH0=0x3C;
TL0=0xB0;
TR0=1;
countt0++;
if(countt0==5)
{
countt0=0;
sd=!sd;
if(sd==1)
sd_char=0x00;
else
sd_char=0xFF;
}
}
void Initime1(void) interrupt 3
{
TH1=0x3C;
TL1=0xB0;
countt1++;
TR1=1;
if(countt1==10)
{
countt1=0;
ALAM=~ALAM;
}
key_Scan();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -