#include #include "clock.h" #include "lcd.h"//加载延时函数 //IO模拟IIC, 器件:dsPIC33FJ64GP706, 编译器:C30 #define Clock_SCL LATGbits.LATG12 #define Clock_SDA LATGbits.LATG13 // 地址 R/W // EEPROM->1010 | | // 111 0 // RTC ->1101 #define RTC_White_Addr 0xde #define RTC_Read_Addr 0xdf #define EEPROM_White_Addr 0xae #define EEPROM_Read_Addr 0xaf void read_time(); unsigned char BCDINT(unsigned char x); unsigned char INTBCD(unsigned char x); void I2C_Start(void);//IIC开始 void I2C_Stop(void);//IIC结束 void Send_Data (unsigned char Data);//发送一个字节数据 unsigned char Receive_Data(void);//接收一个字节数据 void Clock_I2C_RTC_ByteWrite(unsigned char Data, unsigned char WriteAddr);//时钟数据字节写 void Clock_I2C_RTC_PageWrite(unsigned char WriteAddr, unsigned char NumByteToWrite) ;//时钟数据页写 unsigned char Clock_I2C_RTC_RandomRead(unsigned char ReadAddr);//时钟数据随机读 unsigned char Hour=0,Min=0,Year=0,Date=0,Month=0;// 年,月,日,时,分 unsigned char Timer_Change;//时间改变,刷新标志 unsigned char ASK=0; unsigned int jishu0,jishu1,jishuqi;//测试用 unsigned char Clock_SR;//时钟状态位,测试用 unsigned char Clock_PWR;//测试用 /////////////////////////////////////////////////////////////////////// // 读时间 // 在待机界面每分钟刷新一次时间,Timer_Change=1 //////////////////////////////////////////////////////////////////////// void read_time()//-------------------------------读DS1302的日期和时间 {unsigned char Timer_Min;//分的中间变量,比较分钟有无变化 Clock_SR = Clock_I2C_RTC_RandomRead(0x3f); //读ISL12026状态位 Clock_PWR = Clock_I2C_RTC_RandomRead(0x14); Timer_Min = BCDINT(Clock_I2C_RTC_RandomRead(0x30)); if(Min != Timer_Min)//分钟变化 {Min = Timer_Min;//赋值分 Timer_Change=1;//时间变化置位,供Menu_Main_Loop()函数判断 Year = BCDINT(Clock_I2C_RTC_RandomRead(0x34));//年 Month = BCDINT(Clock_I2C_RTC_RandomRead(0x33));//月 Date = BCDINT(Clock_I2C_RTC_RandomRead(0x32)& 0x3f);//日 Hour = BCDINT(Clock_I2C_RTC_RandomRead(0x31)) ;//时 } } ///////////////////////////////////////////////////// //开始IIC ///////////////////////////////////////////////////////// void I2C_Start (void) { Clock_SDA=0; Clock_SCL=0; TRISGbits.TRISG12=0; //SCL置输出 TRISGbits.TRISG13=0; //SDA置输出 Clock_SDA=1; asm("nop"); Clock_SCL=1; Delay(8); Clock_SDA=0; Delay(8); Clock_SCL=0; Delay(8); } /////////////////////////////////////////////// //停止IIC //////////////////////////////////////////////// void I2C_Stop(void) { Clock_SCL=0; Clock_SDA=0; asm("nop");// Delay(8); Clock_SCL=1; Delay(8); Clock_SDA=1; Delay(8); TRISGbits.TRISG12=1; //释放IIC线 TRISGbits.TRISG13=1; } ////////////////////////////////////////////////////// // 发送一个字节 8位 //////////////////////////////////////////////////////// void Send_Data (unsigned char Data) { unsigned char loop; Clock_SDA=0;Clock_SCL=0; TRISGbits.TRISG12=0; //SCL置输入 TRISGbits.TRISG13=0; //SDA do { for(loop=8;loop>0;loop--)//送8位目标数据 { if(Data & 0x80)Clock_SDA = 1; else Clock_SDA = 0; asm("nop");// Delay(8); Clock_SCL = 1; Delay(8); Clock_SCL = 0; asm("nop"); // Delay(8); Data = Data << 1; } TRISGbits.TRISG13 = 1; //SDA脚置为输入 asm("nop");//Delay(8); Clock_SCL = 1; Delay(8); if(PORTGbits.RG13==1){ASK = 1;} else {ASK = 0;}//SDA为0,即ACK为0,成功 } while(ASK);//ASK==1,数据未发送成功,再循环重发 TRISGbits.TRISG13 = 0; //SDA脚置为输出 asm("nop"); } unsigned char Receive_Data(void) { unsigned char loop,Data; for(loop=8;loop>0;loop--) { Clock_SCL = 1;//SCL==1 if(PORTGbits.RG13){Data = Data | 0x1;} Data<<=1; Clock_SCL = 0;//SCL==0 } return Data; } ////////////////////////////////////////////////////////////////////////////// // 时钟字节写 // RTC地址0x0030. //CCR地址在0x0000-0x003f,故地址可用8位地址代替,高位00去掉能省点存储空间吗? //////////////////////////////////////////////////////////////////////////// void Clock_I2C_RTC_ByteWrite(unsigned char Data, unsigned char WriteAddr) { unsigned char Addr_H, Addr_L; Addr_L = WriteAddr;// & 0x00ff; //低8位地址 Addr_H = 0x00;//WriteAddr >> 8; //高8位地址 I2C_Start();// IIC开始 Send_Data(RTC_White_Addr);//送器件寻址地址 Send_Data(Addr_H);//送目标地址H Send_Data(Addr_L);//送目标地址L Send_Data(Data);//送数据 I2C_Stop(); //IIC结束 } ////////////////////////////////////////////////////////////////////////////////////////// // 时钟页写 //写入字节数 8个字节 //CCR地址在0x0000-0x003f,故地址可用8位地址代替,高位00去掉能省点存储空间吗? //////////////////////////////////////////////////////////////////////////////////////// void Clock_I2C_RTC_PageWrite(unsigned char WriteAddr, unsigned char NumByteToWrite) { unsigned char Addr_H,Addr_L,i; /*unsigned char RTC_Data[8]={10,10,10,10,10,10,0,0x20}; */unsigned char RTC_Data[8]; RTC_Data[0] = INTBCD(10);//秒 RTC_Data[1] = INTBCD(14);//Min;//分 RTC_Data[2] = INTBCD(11)|0x80;//Hou;//时 RTC_Data[3] = INTBCD(22);//Date;//日 RTC_Data[4] = INTBCD(12);//Motch;//月 RTC_Data[5] = INTBCD(11);//Year;//年 RTC_Data[6] = INTBCD(2);//周 RTC_Data[7] = 32;//0x20;//Y2K.默认为20H Addr_L = WriteAddr;// & 0x00ff; //低8位地址 Addr_H = 0x00;//WriteAddr >> 8; //高8位地址 Clock_I2C_RTC_ByteWrite(0x02,0x3f); //进入时钟 这两个指令必须加,不然时钟始终读写不成功 Clock_I2C_RTC_ByteWrite(0x06,0x3f); I2C_Start();// IIC开始 Send_Data(RTC_White_Addr);//送RTC写寻址地址 Send_Data(Addr_H);//送目标地址H Send_Data(Addr_L);//送目标地址L while(NumByteToWrite--) {Send_Data(RTC_Data[i++]); } I2C_Stop(); //IIC结束 Clock_I2C_RTC_ByteWrite(0x00,0x3f); //sr } ///////////////////////////////////////////////////////////////////////////////// // 时钟随机读 CCR地址在0x0000-0x003f,故地址可用8位地址代替,高位00去掉能省点存储空间吗? //////////////////////////////////////////////////////////////////////////////////// unsigned char Clock_I2C_RTC_RandomRead(unsigned char ReadAddr) { unsigned char Addr_H,Addr_L,Data; Addr_L = ReadAddr;// & 0x00ff; //低8位地址 Addr_H = 0x00;//ReadAddr>> 8; //高8位地址 I2C_Start();// IIC开始 Send_Data(RTC_White_Addr);//送RTC写寻址地址 Send_Data(Addr_H);//送目标地址H Send_Data(Addr_L);//送目标地址L I2C_Start();// IIC再开始 Send_Data(RTC_Read_Addr);//送RTC读寻址地址 Data = Receive_Data();//读数据 I2C_Stop(); //IIC结束 return Data; } ///////////////////////////////////////////////////////////////////////////////// // EEPROM页写 16个字节 16位地址 ///////////////////////////////////////////////////////////////////////////// void Clock_I2C_EEPROM_PageWrite(unsigned int WriteAddr, unsigned char NumByteToWrite) { unsigned char Addr_H,Addr_L; Addr_L = WriteAddr&0x00ff; //低8位地址 Addr_H = WriteAddr>>8; //高8位地址 I2C_Start();// IIC开始 Send_Data(EEPROM_White_Addr);//送EEPROM写寻址地址 Send_Data(Addr_H);//送目标地址H Send_Data(Addr_L);//送目标地址L while(NumByteToWrite--) {Send_Data(9); } I2C_Stop(); //IIC结束 } ///////////////////////////////////////////////////////////////////////////////// // EEPROM随机读 16位地址 ///////////////////////////////////////////////////////////////////////////// unsigned char Clock_I2C_EEPROM_RandomRead(unsigned int ReadAddr) { unsigned char Addr_H,Addr_L,Data; Addr_L = ReadAddr&0x00ff; //低8位地址 Addr_H = ReadAddr>> 8; //高8位地址 I2C_Start();// IIC开始 Send_Data(EEPROM_White_Addr);//送RTC写寻址地址 Send_Data(Addr_H);//送目标地址H Send_Data(Addr_L);//送目标地址L I2C_Start();// IIC再开始 Send_Data(EEPROM_Read_Addr);//送RTC读寻址地址 Data = Receive_Data();//读数据 I2C_Stop(); //IIC结束 return Data; } unsigned char BCDINT(unsigned char x)//BCD码转换为十进制 {return((0x0f&x)+((x>>4)*10));} unsigned char INTBCD(unsigned char x)//十进制转换为BCD码 {return((x%100)/10*16+(x%10));}