//实时时钟SD2200读写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*/ #define true 1 #define false 0 /********SD2200函数名********/ 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(bit order); void I2CReadDate(void); void I2CWriteStatus(void); void Delay(uint nn); uchar I2CReadEEram(uchar sramadd_lo); void I2CWriteEEram(uchar sramadd_lo,uchar sramdata); /*********I2C延时***********/ void I2CWait(void) { _nop_();_nop_();_nop_();_nop_(); } /********开启SD2200的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; } /********关闭SD2200的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; } /************从SD2200发送一个字节*************/ 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从SD2200读入一字节*********/ uchar I2CReceiveByte(bit order)//order=1,H_L;order=0,L_H { uchar i=8; uchar ddata=0; SDA=1; if(order) { while(i--) { ddata<<=1; //数据从高位开始读取 SCL=0; I2CWait(); SCL=1; I2CWait(); //从高位开始 ddata|=SDA;ddata<<=1 if(SDA) { ddata|=0x01; } } } else { while(i--) { ddata>>=1; //数据从低位开始读取 SCL=0; I2CWait(); SCL=1; I2CWait(); //从低位开始 ddata|=SDA;ddata>>=1 if(SDA) { ddata|=0x80; } } } SCL=0; return ddata; } /******读SD2200实时数据寄存器******/ void I2CReadDate(void) { uchar n; if(!I2CStart())return; I2CSendByte(0x65,1);//从年开始读取数据 if(!I2CWaitAck()){I2CStop();return;} for(n=0;n<7;n++) { date[n]=I2CReceiveByte(0); if (n!=6) //最后一个数据不应答 { I2CAck(); } } I2CNoAck(); I2CStop(); } /*写SD2200状态寄存器命令*/ void I2CWriteStatus(void) { if(!I2CStart())return; I2CSendByte(0x60,1); //发送SD2200状态寄存器_1命令 if(!I2CWaitAck()){I2CStop();return;} I2CSendByte(0x03,0); //IC进行复位初始化,24小时制 I2CWaitAck(); I2CStop(); I2CStart(); I2CSendByte(0x62,1); //发送SD2200状态寄存器_2命令 I2CWaitAck(); I2CSendByte(0x00,0); //清TEST位,禁止中断输出 I2CWaitAck(); I2CStop(); } /*写SD2200时间寄存器命令*/ void I2CWriteTime(void) { uchar n; date[0]=0x06;//year;2006/03/03/05/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); //发送SD2200写时间寄存器命令, I2CWaitAck(); for(n=0;n<7;n++) { I2CSendByte(date[n],0); I2CWaitAck(); } I2CStop(); } /******读SD2200EEsram数据寄存器-单字节******/ uchar I2CReadEEram(uchar sramadd_lo) { uchar ddata=0xFF; I2CStart(); I2CSendByte(0x0A0,1); I2CWaitAck(); I2CSendByte(sramadd_lo,1); I2CWaitAck(); I2CStart(); I2CSendByte(0x0A1,1); I2CWaitAck(); ddata=I2CReceiveByte(1); I2CNoAck(); I2CStop(); return ddata; } /******写SD2200EEsram数据寄存器-单字节******/ void I2CWriteEEram(uchar sramadd_lo,uchar sramdata) { I2CStart(); I2CSendByte(0x0A0,1); I2CWaitAck(); I2CSendByte(sramadd_lo,1); I2CWaitAck(); I2CSendByte(sramdata,1); I2CWaitAck(); I2CStop(); Delay(250); Delay(250); Delay(250); Delay(250); Delay(250); Delay(250); Delay(250); Delay(250); Delay(250); Delay(250);/*总延时10ms,SRAM中不用此延时*/ } /*********延时子程序*********/ void Delay(uint nn) { while(nn--); } //////*****主程序*****////// main() { P3=0xFF; I2CWriteEEram(0,0x38);/*在地址0写入数据0x38作为例子*/ data1=0; data1=I2CReadEEram(0); _nop_(); _nop_(); I2CWriteStatus(); I2CWriteTime(); while(1) { I2CReadDate(); _nop_(); Delay(250); Delay(250); } }