#include<STC89C52RC.H>
#include<intrins.h>
#include<nongli.h>
#define uint unsigned int
#define uchar unsigned char
sbit KEY1= P1^0; //调整
sbit KEY2= P1^1; //++
sbit KEY3= P1^2; //--
sbit KEY4= P1^3; //退出
sbit SHCP = P0^1; //11
sbit STCP = P0^2; //12
sbit DS = P0^0; //14
sbit LSA=P0^3;
sbit LSB=P0^4;
sbit LSC=P0^5;
sbit xp=P0^6;
sbit xx=P0^7;
//L数据码 低位A 高位DP //
uchar code duan[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xff,0xc8,0xc7};
// 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 灭 , n , L
uchar disp[8];
uchar disp1[8];
void dis(uchar s1,uchar s2,uchar s3,uchar s4,uchar s5,uchar s6,uchar s7,uchar s8,
uchar s9,uchar s10,uchar s11,uchar s12,uchar s13,uchar s14,uchar s15,uchar s16);
void dis_san(uchar s1,uchar s2,uchar s3,uchar s4,uchar s5,uchar s6,uchar s7,uchar s8,
uchar s9,uchar s10,uchar s11,uchar s12,uchar s13,uchar s14,uchar s15,uchar s16,uchar san);
// ------------------------------------------------------------
// IO口模拟I2C通信
// ------------------------------------------------------------
sbit SCL=P3^6; //串行时钟
sbit SDA=P3^7; //串行数据
uchar a1,a2,a3,a4; //按键消抖用
uchar disflag=0; //时间调整相关
/********************************************************************************************************
** DS3231常数定义
********************************************************************************************************/
#define DS3231_WriteAddress 0xD0 //器件写地址
#define DS3231_ReadAddress 0xD1 //器件读地址
#define DS3231_SECOND 0x00 //秒
#define DS3231_MINUTE 0x01 //分
#define DS3231_HOUR 0x02 //时
#define DS3231_WEEK 0x03 //星期
#define DS3231_DAY 0x04 //日
#define DS3231_MONTH 0x05 //月
#define DS3231_YEAR 0x06 //年
#define DS3231_TEMPERATUREH 0x11 //温度寄存器高字节(8位) 整数部分
uchar shan_count; //:号闪烁计时变量
bit flag; //校时闪烁标志
char hour,minute,second,year,month,day,date,week,Tem_H;
//uint TH3231;
bit ack; //应答标志位
void Delay5US() //@12.000MHz 延时5us
{
_nop_(); _nop_(); _nop_();_nop_(); //1T单片机用4个nop,12T用1个nop
}
//延时0.1ms个单位
void delay1(uint x)
{
while(x--);
}
/**********************************************
//IIC Start
**********************************************/
void IIC_Start()
{
SCL = 1;
SDA = 1;
SDA = 0;
SCL = 0;
}
/**********************************************
//IIC Stop
**********************************************/
void IIC_Stop()
{
SCL = 0;
SDA = 0;
SCL = 1;
SDA = 1;
}
/********************************************************************************************************
3231
********************************************************************************************************/
uchar BCD2HEX(uchar val)
{
return ((val>>4)*10)+(val&0x0f);
}
uchar HEX2BCD(uchar val)
{
return (((val%100)/10)<<4)|(val%10);
}
void SendByte(uchar c)
{
uchar BitCnt;
for(BitCnt=0;BitCnt<8;BitCnt++) //要传送的数据长度为8位
{
if((c<<BitCnt)&0x80)
SDA=1; //判断发送位
else
SDA=0;
SCL=1; //置时钟线为高,通知被控器开始接收数据位
Delay5US(); //保证时钟高电平周期大于4μs
SCL=0;
}
SDA=1; //8位发送完后释放数据线,准备接收应答位
SCL=1;
Delay5US();
if(SDA==1)
ack=0;
else
ack=1; //判断是否接收到应答信号
SCL=0;
Delay5US();
}
uchar RcvByte()
{
uchar retc;
uchar BitCnt;
retc=0;
SDA=1; //置数据线为输入方式
for(BitCnt=0;BitCnt<8;BitCnt++)
{
SCL=0; //置时钟线为低,准备接收数据位
Delay5US(); //时钟低电平周期大于4.7μs
SCL=1; //置时钟线为高使数据线上数据有效
Delay5US();
retc=retc<<1;
if(SDA==1)
retc=retc+1; //读数据位,接收的数据位放入retc中
Delay5US();
}
SCL=0;
return(retc);
}
void Ack_I2C(bit a)
{
SDA = a;
SCL=1;
Delay5US(); //时钟低电平周期大于4us
SCL=0; //清时钟线,钳住I2C总线以便继续接收
Delay5US();
}
uchar write_byte(uchar addr, uchar write_data)
{
IIC_Start();
SendByte(DS3231_WriteAddress);
if (ack == 0)
return 0;
SendByte(addr);
if (ack == 0)
return 0;
SendByte(write_data);
if (ack == 0)
return 0;
IIC_Stop();
Delay5US();
Delay5US();
return 1;
}
uchar read_current()
{
uchar read_data;
IIC_Start();
SendByte(DS3231_ReadAddress);
if(ack==0)
return(0);
read_data = RcvByte();
Ack_I2C(1);
IIC_Stop();
return read_data;
}
uchar read_random(uchar random_addr)
{
uchar Tmp;
IIC_Start();
SendByte(DS3231_WriteAddress);
if(ack==0)
return(0);
SendByte(random_addr);
if(ack==0)
return(0);
Tmp=read_current();
if(random_addr==DS3231_HOUR)
Tmp&=0x3f;
return(BCD2HEX(Tmp));//都转10进制输出
}
/***********************/
uchar read_random1(uchar random_addr) //这个是读温度函数
{
uchar Tmp;
write_byte(0x0e,0x20);//0x0e寄存器的CONV位置1开启温度转换,要这句,温度实时刷新,这句不要,温度要64s才刷新1次
IIC_Start();
SendByte(DS3231_WriteAddress);
if(ack==0)
return(0);
SendByte(random_addr);
if(ack==0)
return(0);
Tmp=read_current();
return Tmp;
}
void ModifyTime(uchar address,uchar num)
{
uchar temp=0;
if(address>6 && address <0) return;
temp=HEX2BCD(num);
write_byte(address,temp);
}
void Set(unsigned char sel,unsigned char selby)
{
unsigned char address;
char item;
unsigned char max,min;
if(sel==5) {address=DS3231_HOUR; max=23;min=0;} //小时
if(sel==6) {address=DS3231_MINUTE; max=59;min=0;} //分钟
// if(sel==3) {address=DS3231_SECOND; max=59;min=0;} //秒
if(sel==1) {address=DS3231_YEAR; max=99;min=0;} //年
if(sel==2) {address=DS3231_MONTH; max=12;min=1;} //月
if(sel==3) //日
{
if(month==2)
{
if(month == 2 && year % 4 != 0)
{
{address=DS3231_DAY; max=29;min=1;}
}
else
{
{address=DS3231_DAY; max=28;min=1;}
}
}
else
{
if(month==1|month==3|month==5|month==7|month==8|month==10|month==12)
{
{address=DS3231_DAY; max=31;min=1;}
}
if(month==4|month==6|month==9|month==11)
{
{address=DS3231_DAY; max=30;min=1;}
}
}
}
if(sel==4) {address=DS3231_WEEK; max=7; min=1;} //星期
item= read_random(address);
if (selby==0) item++; else item--;
if(item>max) item=min;
if(item<min) item=max;
ModifyTime(address, item);
}
void KEY()
{
if(a1==0)
{
if(KEY1==0)
{
Delay5US();
if(KEY1==0)
{
disflag++;
if(disflag>=7)
{
disflag=1;
}
a1=1;
}
}
}
if(KEY1==1)
{
a1=0;
}
/********************************/
if(a4==0)
{
if(KEY4==0)
{
Delay5US();
if(KEY4==0 && disflag!=0 )
{
ModifyTime(DS3231_SECOND, 0);
disflag=0;
}
a4=1;
}
}
if(KEY4==1)
{
a4=0;
}
///////////////////////
if(a2==0)
{
if(KEY2==0)
{
Delay5US();
if(KEY2==0)
{
Set(disflag,0);
a2=1;
}
}
}
if(KEY2==1)
{
a2=0;
}
if(