//************************************************************ //实时时钟SD2400读写C51演示程序 // chendw@whwave.com.cn 2008/01/15 //************************************************************ #pragma code #include #include //*********变量及IO口定义********* typedef unsigned char uchar; typedef unsigned int uint; sbit SDA=P3^4; sbit SCL=P3^5; uchar data1,data2,data3,data4; uchar date[7]; //日期数组 /*date[6]=year,date[5]=month,date[4]=day,date[3]=week, date[2]=hour,date[1]=minute,date[0]=second*/ //uchar bdata tempbit; //sbit DI=tempbit^0; //sbit DO=tempbit^1; #define true 1 #define false 0 /********SD2400函数名********/ void I2CWait(void); bit I2CStart(void); void I2CStop(void); void I2CAck(void); void I2CNoAck(void); bit I2CWaitAck(void); void I2CSendByte(uchar demand); uchar I2CReceiveByte(void); void I2CReadDate(void); void I2CWriteStatus(void); void Delay(uint nn); void I2CWriteDate(void); void WriteTimeOn(void); void WriteTimeOff(void); /*********I2C延时***********/ void I2CWait(void) { _nop_();_nop_();_nop_();_nop_(); } /********开启SD2400的I2C总线********/ bit I2CStart(void) { SDA=1; SCL=1; I2CWait(); if(!SDA)return false;//SDA线为低电平则总线忙,退出 SDA=0; I2CWait(); while(SDA)return false;//SDA线为高电平则总线出错,退出 SCL=0; I2CWait(); return true; } /********关闭SD2400的I2C总线*******/ void I2CStop(void) { SDA=0; SCL=0; I2CWait(); SCL=1; I2CWait(); SDA=1; } /*********发送 ACK*********/ void I2CAck(void) { SDA=0; SCL=0; I2CWait(); SCL=1; I2CWait(); SCL=0; } /*********发送NO ACK*********/ void I2CNoAck(void) { SDA=1; SCL=0; I2CWait(); SCL=1; I2CWait(); SCL=0; } /*********读取ACK信号*********/ bit I2CWaitAck(void) //返回为:1=有ACK,0=无ACK { uchar errtime=255; SCL=0; SDA=1; I2CWait(); SCL=1; I2CWait(); while(SDA) { errtime--; if(!errtime) SCL=0; return false; } SCL=0; return true; } /************MCU向SD2400发送一个字节*************/ void I2CSendByte(uchar demand) //数据从高位到低位// { uchar i=8; while(i--) { SCL=0; _nop_(); SDA=(bit)(demand&0x80); demand<<=1; I2CWait(); SCL=1; I2CWait(); } SCL=0; } /*********MCU从SD2400读入一字节*********/ uchar I2CReceiveByte(void) //数据从高位到低位// { uchar i=8; uchar ddata=0; SDA=1; while(i--) { ddata<<=1; //数据从高位开始读取 SCL=0; I2CWait(); SCL=1; I2CWait(); //从高位开始 ddata|=SDA;ddata<<=1 if(SDA) { ddata|=0x01; } } SCL=0; return ddata; } /******读SD2400实时数据寄存器******/ void I2CReadDate(void) { uchar n; I2CStart(); I2CSendByte(0x65); I2CWaitAck(); for(n=0;n<7;n++) { date[n]=I2CReceiveByte(); if (n!=6) //最后一个数据不应答 { I2CAck(); } } I2CNoAck(); I2CStop(); } /******写SD2400实时数据寄存器******/ void I2CWriteDate(void) { WriteTimeOn(); I2CStart(); I2CSendByte(0x64); I2CWaitAck(); I2CSendByte(0x00);//设置写起始地址 I2CWaitAck(); I2CSendByte(0x01);// second I2CWaitAck(); I2CSendByte(0x01);//minute I2CWaitAck(); I2CSendByte(0x88);//hour ,二十四小时制 I2CWaitAck(); I2CSendByte(0x01);//week I2CWaitAck(); I2CSendByte(0x01);//day I2CWaitAck(); I2CSendByte(0x07);//month I2CWaitAck(); I2CSendByte(0x07);//year I2CWaitAck(); I2CStop(); I2CStart(); I2CSendByte(0x64); I2CWaitAck(); I2CSendByte(0x12);//设置写起始地址 I2CWaitAck(); I2CSendByte(0x00);//清零数字调整寄存器 I2CWaitAck(); I2CStop(); WriteTimeOff(); } /******写SD2400允许程序******/ void WriteTimeOn(void) { I2CStart(); I2CSendByte(0x64); I2CWaitAck(); I2CSendByte(0x10);//设置写地址10H I2CWaitAck(); I2CSendByte(0x80);//置WRTC1=1 I2CWaitAck(); I2CStop(); I2CStart(); I2CSendByte(0x64); I2CWaitAck(); I2CSendByte(0x0F);//设置写地址0FH I2CWaitAck(); I2CSendByte(0x84);//置WRTC2,WRTC3=1 I2CWaitAck(); I2CStop(); } /******写SD2400禁止程序******/ void WriteTimeOff(void) { I2CStart(); I2CSendByte(0x64); I2CWaitAck(); I2CSendByte(0x0F);//设置写地址0FH I2CWaitAck(); I2CSendByte(0x0) ;//置WRTC2,WRTC3=0 I2CWaitAck(); I2CSendByte(0x0) ;//置WRTC1=0(10H地址) I2CWaitAck(); I2CStop(); } /*********延时子程序*********/ void Delay(uint nn) { while(nn--); } //////*****主程序*****////// main() { P3=0xFF; I2CWriteDate(); while(1) { I2CReadDate(); Delay(250); Delay(250); } }