DS3231高精度时钟程序代码(单片机STC89c52RC与1602显示)
- 格式:docx
- 大小:132.29 KB
- 文档页数:31
//DS3231,经测试,日期,时间,星期,温度可以用1602显示#in elude <reg51.h>#in elude vintrin s.h>#defi ne uchar un sig ned char#defi ne uint un sig ned int#define yh 0x80 //第一行的初始位置#defi ne er 0x80+0x40 // 第二行初始位置sbit wr=P1A1;sbit rs=P1A。
;sbit en=卩2人5;sbit SDA=P3A6; //模拟I2C数据传送位 SDAsbit SCL=P3A7; //模拟I2C时钟控制位 SCL sbit INT=P3A2;sbit key1=P1A7; // 功能键,修改键sbitkey2=P3A4;// 上调键sbitkey3=P3A5;// 下调键sbit RESET=P3A3;bit ack;// 应答标志位#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 // 年// 闹铃 1#define DS3231 _SALARM1ECOND 0x07 // 秒#define DS3231 _ALARM1MINUTE 0x08 // 分#define DS3231 _ALARM1HOUR 0x09 // 时#define DS3231 _ALARM1WEEK 0x0A// 星期 / 日// 闹铃 2#define DS3231 _ALARM2MINUTE 0x0b // 分#define DS3231 _ALARM2HOUR0x0c // 时可编辑#define DS3231_TEMPERATUREH 0x11#define DS3231_TEMPERATUREL 0x12 uchara,miao,shi,fen,ri,yue,nian,week,temp1,temp2,key1n,temp; uchar code tab1[]={"2017- - FRI"}; uchar code tab2[]={" : : ."};uchar HEX2BCD(uchar val) //B 码转换为 BCD 码{uchar k;k=(val)/10*16+(val)%10; return k;}uchar BCD_Decimal(uchar bcd){uchar Decimal; Decimal=bcd>>4;return(Decimal=Decimal*10+(bcd&=0x0F));#define DS3231_ALARM2WEEK #define DS3231_CONTROL #define DS3231_STATUS #define BSY #define OSF0x0d // 星期 / 日0x0e // 控制寄存器 0x0f // 状态寄存器2 // 忙7// 振荡器停止标志#define DS3231_XTAL0x10 // 晶体老化寄存器// 温度寄存器高字节 // 温度寄存器低字节 (8 位 ) (高 2 位 )}void delayus(uint us){while (us--);}void Start_I2C(){SDA=1; // 发送起始条件的数据信号 delayus(1);SCL=1;delayus(5); // 起始条件建立时间大于 4.7us, 延时SDA=0; // 发送起始信号delayus(5); //起始条件锁定时间大于4阳SCL=0; //钳住 I2C 总线,准备发送或接收数据delayus(2);}void Stop_I2C(){SDA=0; // 发送结束条件的数据信号delayus(1); // 发送结束条件的时钟信号SCL=1; // 结束条件建立时间大于 4us delayus(5);SDA=1; // 发送 I2C 总线结束信号delayus(4);}void SendByte(uchar c){uchar BitCnt;for(BitCnt=0;BitCnt<8;BitCnt ++){if((c<<BitCnt)&0x80)SDA=1;elseSDA=0;delayus(1);SCL=1;数据位delayus(5);SCL=0;// 要传送的数据长度为 8 位// 判断发送位// 置时钟线为高,通知被控器开始接收//保证时钟咼电平周期大于 4阳delayus(2);SDA=1; //8 位发送完后释放数据线,准备接收应答位delayus(2);SCL=1;delayus(3);if(SDA==1)ack=0;elseack=1; // 判断是否接收到应答信号SCL=0;delayus(2);}uchar RcvByte(){uchar retc;uchar BitCnt;retc=0;SDA=1; // 置数据线为输入方式for(BitCnt=0;BitCnt<8;BitCnt++)SCL=0;delayus(5);SCL=1;delayus(3);retc=retc<<1;if(SDA==1)retc=retc+1;delayus(2);}SCL=0;delayus(2);return(retc);}// 置时钟线为低,准备接收数据位//时钟低电平周期大于 4.7 Q//置时钟线为高使数据线上数据有效// 读数据位 ,接收的数据位放入 retc 中void Ack_I2C(bit a){if(a==0)SDA=0; else // 在此发出应答或非应答信号SDA=1;SCL=1;delayus(5); //时钟低电平周期大于4阴SCL=0; // 清时钟线,钳住 I2C 总线以便继续接收delayus(2);}uchar write_byte(uchar addr, uchar write_data) {Start_I2C();SendByte(DS3231_WriteAddress);if (ack == 0)return 0;SendByte(addr);if (ack == 0)return 0;SendByte(write_data);if (ack == 0)return 0;Stop_I2C();return 1;}uchar read_current(){uchar read_data;Start_I2C();SendByte(DS3231_ReadAddress);if(ack==0)return(0);read_data = RcvByte();Ack_I2C(1);Stop_I2C();return read_data;}uchar read_random(uchar random_addr) {Start_I2C();SendByte(DS3231_WriteAddress);if(ack==0)SendByte(random_addr);if(ack==0)return(0);return(read_current()); }void ModifyTime(uchar yea,uchar sec,uchar week){uchar temp=0;temp=HEX2BCD(yea);write_byte(DS3231_YEAR,temp);temp=HEX2BCD(mon);write_byte(DS3231_MONTH,temp);temp=HEX2BCD(da);write_byte(DS3231_DAY,temp);temp=HEX2BCD(hou);write_byte(DS3231_HOUR,temp); mon,uchar da,uchar hou,uchar// 修改年// 修改月// 修改日// 修改时min,uchartemp=HEX2BCD(min);write_byte(DS3231_MINUTE,temp); // 修改分temp=HEX2BCD(sec);write_byte(DS3231_SECOND,temp); // 修改秒temp=HEX2BCD(week);write_byte(DS3231_WEEK,temp); // 修改星期}**************** 液晶写入********************** write_1602com(uchar com)// 液晶写入指令函数{ rs=0;// 置为写入命令P0=com;// 送入数据delayus(1000);en=1;// 拉高使能端delayus(1000);en=0;// 完成高脉冲}write_1602dat(uchar dat){rs=1;// 置为写入数据P0=dat;// 送入数据delayus(1000);en=1;delayus(1000);en=0;}*******************over*********************lcd_init()// 液晶初始化函数{ wr=0;write_1602com(0x38);// 设置液晶工作模式write_1602com(0x0c);// 开显示不显示光标write_1602com(0x06);// 整屏不移动,指针加一write_1602com(0x01);write_1602com(yh+1);// 字符写入的位置for(a=0;a<14;a++){write_1602dat(tab1[a]);//delay(3);}write_1602com(er);for(a=0;a<12;a++){//delay(3);}write_1602com(er+14); // 写温度符号write_1602dat(0xdf);write_1602dat(0x43);void write_sfm(uchar add,uchar dat)// 写时分秒及温度{ uchar gw,sw;gw=dat%10;sw=dat/10;write_1602com(er+add);write_1602dat(0x30+sw);write_1602dat(0x30+gw);}void write_nyr(uchar add,uchar dat) // 写日期{ uchar gw,sw;gw=dat%10;sw=dat/10;write_1602com(yh+add);write_1602dat(0x30+sw);write_1602dat(0x30+gw);}void write_week(uchar week)// 写星期函数{write_1602com(yh+0x0c);switch(week){case 1:write_1602dat('M');//delay(5);write_1602dat('O');//delay(5);write_1602dat('N');break;case 2:write_1602dat('T');//delay(5);write_1602dat('U');//delay(5);write_1602dat('E');break;case 3:write_1602dat('W');//delay(5);break;case 4:write_1602dat('T');//delay(5);write_1602dat('H');//delay(5);write_1602dat('U');break;case 5:write_1602dat('F');//delay(5);write_1602dat('R');//delay(5);write_1602dat('I');break;case 6:write_1602dat('S');//delay(5);write_1602dat('T');//delay(5);write_1602dat('A');break;case 7:write_1602dat('S');//delay(5);write_1602dat('U');//delay(5);write_1602dat('N');break;}void keyscan(){if(key1==0)//key1 为功能键{delayus(5000);if(key1==0){while(!key1);key1n++;if(key1n==9)key1n=1;switch(key1n){case 1: TR0=0;// 关闭定时器//TR1=0;write_1602com(er+0x06);// 写入光标位置write_1602com(0x0f);// 设置光标为闪烁break;//write_1602com(0x0f);break;case 3: write_1602com(er+0);//shi//write_1602com(0x0f);break;case 4: write_1602com(yh+0x0d);//week//write_1602com(0x0f);break;case 5: write_1602com(yh+0x09);//ri//write_1602com(0x0f);break;case 6: write_1602com(yh+0x06);//yue//write_1602com(0x0f);break;case 7: write_1602com(yh+0x03);//nian//write_1602com(0x0f);break;case 8: write_1602com(0x0c);// 设置光标不闪烁write_sfm(6,miao);// 写入新的秒数temp=(miao)/10*16+(miao)%10;write_byte(DS3231_SECOND,temp); // 退出时修改秒write_1602com(er+6);temp=(fen)/10*16+(fen)%10;write_byte(DS3231_MINUTE,temp); // 修改分write_1602com(er+3);TR0=1;// 打开定时器break;}}}if(key1n!=0)// 当 key1 按下以下。