//实时时钟SD2000读写C51演示程序 //本程序在王思焰,闫亨的程序基础上修改,在此一并致谢! // chendw@whwave.com.cn 2006/03/03 #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[0]=year,date[1]=month,date[2]=day,date[3]=week, date[4]=hour,date[5]=minute,date[6]=second*/ //uchar bdata tempbit; //sbit DI=tempbit^0; //sbit DO=tempbit^1; #define true 1 #define false 0 /********SD2000函数名********/ void I2CWait(void); bit I2CStart(void); void I2CStop(void); void I2CAck(void); void I2CNoAck(void); bit I2CWaitAck(void); void I2CSendByte(uchar demand,bit order); uchar I2CReceiveByte(void); void I2CReadDate(void); void I2CWriteStatus(void); void Delay(uint nn); /*********I2C延时***********/ void I2CWait(void) { _nop_();_nop_();_nop_();_nop_(); } /********开启SD2000的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; } /********关闭SD2000的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; } /************从SD2000发送一个字节*************/ void I2CSendByte(uchar demand,bit order) //order=1,H_L;order=0,L_H { uchar i=8; //order=1,从HI-->LO发送8bit数据 //order=0,从LO-->HI发送8bit数据 if(order) { while(i--) { SCL=0; _nop_(); SDA=(bit)(demand&0x80); demand<<=1; I2CWait(); SCL=1; I2CWait(); } SCL=0; } else { while(i--) { SCL=0; _nop_(); SDA=(bit)(demand&0x01); demand>>=1; I2CWait(); SCL=1; I2CWait(); } SCL=0; } } /*********MCU从SD2000读入一字节*********/ 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|=0x80; } } SCL=0; return ddata; } /******读SD2000实时数据寄存器******/ void I2CReadDate(void) { uchar n; I2CStart(); I2CSendByte(0x65,1); //从年开始读取数据 I2CWaitAck(); for(n=0;n<7;n++) { date[n]=I2CReceiveByte(); if (n!=6) //最后一个数据不应答 { I2CAck(); } } I2CNoAck(); I2CStop(); } /*写SD2000状态寄存器命令*/ void I2CWriteStatus(void) { I2CStart(); I2CSendByte(0x62,1); //发送SD2000状态寄存器命令, I2CWaitAck(); I2CSendByte(0x40,0); //24小时制,关所有中断 I2CWaitAck(); I2CStop(); } /*写SD2000时间寄存器命令*/ void I2CWriteTime(void) { uchar n; date[0]=0x06;//year;2006/03/03/13/14/50 date[1]=0x03;//month date[2]=0x03;//day date[3]=0x05;//week date[4]=0x13;//hour date[5]=0x14;//minute date[6]=0x50;//second I2CStart(); I2CSendByte(0x64,1); //发送SD2000写时间寄存器命令, I2CWaitAck(); for(n=0;n<7;n++) { I2CSendByte(date[n],0); I2CWaitAck(); } I2CStop(); } /*********延时子程序*********/ void Delay(uint nn) { while(nn--); } //////*****主程序*****////// main() { P3=0xFF; I2CWriteStatus(); I2CWriteTime(); while(1) { I2CReadDate(); Delay(250); Delay(250); } }