#define uchar unsigned char #define uint unsigned int #define IIC_READ 0XA1 //内存读指令10100001 #define IIC_WRITE 0XA0 //内存写指令10100000 #define REG_READ 0XD1 //寄存器标志读11010001 #define REG_WRITE 0XD0 //寄存器标志写11010000 #define RUN 1 //运行 #define STOP 0 //停止 #define NOP _nop_() //空指令 #define WD** 0X09 //寄存器09单元的最高位SNL=1串行标识 11-18只读,SNL=0 可读写 #define YEAR 0X08 //YEARS //定义年 寄存器 #define MONTH 0X07 //MONTH //定义月 #define DATE 0X06 //DATE //定义日 //#define DAY 0X05 //DAY //定义天 #define HOURS 0X04 //HOURS //定义时 #define MINUTES 0X03 //MINUTES //定义分 #define SECONDS 0X02 //SECONDS //定义秒 #define CONTROL 0x01 //USER-NV //校准符号 #define FLAGS 0x00 //FLAGS/CONTROL //时间更改标志
#define COMPANION 0X0B //ALARM SECONDS //报警秒//Watchdog Restart&Flags #define WDCON 0X0A //WATCHDOG Control// #define WDFLAG 0X09 //WATCHDOG //看门狗
uchar data addr; sbit SDA=P2^5;//定义数据线 sbit SCL=P2^4;//定义时钟线 bit ack,flag_add; uchar bdata bbyte;//读出或是写入的数据暂存于该数据中 sbit a0=bbyte^0; sbit a1=bbyte^1; sbit a2=bbyte^2; sbit a3=bbyte^3; sbit a4=bbyte^4; sbit a5=bbyte^5; sbit a6=bbyte^6; sbit a7=bbyte^7; //struct str_time//时间结构变量 struct str_time//时间结构变量 { uchar year; uchar month; uchar date; // uchar day; uchar hour; uchar minute; uchar secend; }time; //定义结构体 //====================================== //=============函数列表==================== uchar hex_to_bcd(uchar condata); // uchar bcd_to_hex(uchar condata); void start(void); void stop(void); //void ack(uchar a); //void nack(void); //======================================= //================================================= /*;* Name: hex_to_bcd ;* Description: 十六进制数转换成BCD码格式 ;* Calls: None ;* Input: 需要转换的十六进制数 ;* Outputs: 转换后的BCD码 */ //==================================================== uchar hex_to_bcd(uchar condata) { uchar temp; uchar temp0; uchar temp10; temp10=condata/10; temp0=condata%10; temp=(temp10<<4)|temp0; return(temp); } //====================================================== /*;* Name: bcd_to_hex ;* Description: BCD码格式转换成十六进制数 ;* Calls: None//调用:无 ;* Input: 需要转换的BCD码 ;* Outputs: 转换后的十六进制数 */ //====================================== uchar bcd_to_hex(uchar condata) { uchar temp; uchar temp0; uchar temp10; temp10=(condata&0xF0)>>4; temp0=condata&0x0F; temp=temp10*10+temp0; return(temp); } //========启动I2C总线子程序 SDA由高到低发生在SCL高电平=========
void start(void) { //SCL=0; SDA=1; SCL=1; SDA=0; SCL=0; } //======================================= //FUNCTION:ROUTES TO PROVIDE A STOP SIGNAL //停止I2C总线子程序 SDA由低到高发生时SCL高电平 //======================================= void stop(void) { //SCL=0; SDA=0; SCL=1; SDA=1; SCL=0; } //===================================== //FUNCTION:ROUTES TO PROVIDE ACK SINGAL //从机发送应答位子程序 //入口:a=0应答信号 a=1非应答信号 //======================================= void ack_IIC(bit a) { SDA=1; SCL=1; NOP; NOP; //IFACK=SDA; if(a==0)SDA=0;//应答信号 else SDA=1; //非应答信号 _nop_(); _nop_(); _nop_(); SCL=1; _nop_(); _nop_(); /*时钟低电平周期大于4μs*/ _nop_(); _nop_(); _nop_(); SCL=0; /*清时钟线,钳住I2C总线以便继续接收*/ _nop_(); _nop_(); SCL=0; }
//=====从IIC器件中读出8位数据存到bbyte=========== uchar inbyte(void) {//从IIC器件中读出数据 SDA=1; SCL=1;a7=SDA;SCL=0; SCL=1;a6=SDA;SCL=0; SCL=1;a5=SDA;SCL=0; SCL=1;a4=SDA;SCL=0; SCL=1;a3=SDA;SCL=0; SCL=1;a2=SDA;SCL=0; SCL=1;a1=SDA;SCL=0; SCL=1;a0=SDA;SCL=0; return(bbyte); } //======================================================= //FUNCTION:THE IIC DEVICE SHIFT IN A BYTE FROM THE MASTER void outbyte(uchar c) {//将数据写放IIC器件, uchar BitCnt; for(BitCnt=0;BitCnt<8;BitCnt++) /*要传送的数据长度为8位*/ { if((c<<BitCnt)&0x80)SDA=1; /*判断发送位*/ else SDA=0; _nop_(); SCL=1; /*置时钟线为高,通知被控器开始接收数据位*/ _nop_(); _nop_(); /*保证时钟高电平周期大于4μs*/ _nop_(); _nop_(); _nop_(); SCL=0; _nop_(); _nop_(); SDA=1; /*8位发送完后释放数据线,准备接收应答位*/ _nop_(); _nop_(); SCL=1; _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); if(SDA==1)ack=0; else ack=1; /*判断是否接收到应答信号*/ SCL=0; _nop_(); _nop_(); } } void writebyte(uint add,uchar wbyte)//add为写入地址,wbyte为写入数据 { uchar temph,templ; temph=(uchar)(add/256); templ=(uchar)(add%256); do{ start(); //开始信号 outbyte(IIC_WRITE); //写命令 }while(ack==0); outbyte(temph); while(ack==0); outbyte(templ); while(ack==0); outbyte(wbyte); while(ack==0); ack_IIC(1); //非应答 stop(); } uchar readbyte (uint add)//add为读地址 { uchar temp,temph,templ; temph=(uchar)(add/256); templ=(uchar)(add%256); do{ start(); //开始信号 outbyte(IIC_WRITE); //写命令 }while(ack==0); outbyte(temph); //写地址 while(ack==0); outbyte(templ); //写地址 while(ack==0); do{ start(); //开始信号 outbyte(IIC_READ); //读命令 }while(ack==0); temp=inbyte(); //读数据 ack_IIC(1); //无应答 stop(); //停止信号 return(temp); } //==========连写函数==================================== //add为读起始地址,ptr数据保存指针,writelen为写入数据长度 void writebytelen(uint add,uchar *ptr,uint writelen) { //uchar temp; uchar temph,templ; uint i; temph=(uchar)(add/256);//存高位 templ=(uchar)(add%256);//存低位 do{ start(); outbyte(IIC_WRITE); }while(ack==0);//////////////这样写程序会出现死机现象,应该用do while(++) outbyte(temph); while(ack==0); outbyte(templ); while(ack==0); for(i=0;i<writelen;i++) //连续写地址自动加一 { outbyte(*(ptr+i)); while(ack==0); } stop(); } //========================================================== //连读函数 //add为读起始地址,ptr数据保存指针,writelen为读出数据长度 void readbytelen(uint add,uchar *ptr,uint readlen) { uchar temph,templ; uint i; temph=(uchar)(add/256); templ=(uchar)(add%256); do{ start(); outbyte(IIC_WRITE); }while(ack==0); outbyte(temph); while(ack==0); outbyte(templ); while(ack==0); do{ start(); outbyte(IIC_READ); }while(ack==0); for(i=0;i<readlen-1;i++) { *(ptr+i)=inbyte(); ack_IIC(0); } *(ptr+readlen-1)=inbyte();//最后一个字节数据发无应答信号释放总线 ack_IIC(1); stop(); } //===============写寄存器的内容======================== void write_reg(uchar add,uchar wbyte) { do{ start(); outbyte(REG_WRITE); }while(ack==0); outbyte(add); while(ack==0); outbyte(wbyte); while(ack==0); stop(); } //=================================================
//===========读寄存器的内容到temp============================ uchar read_reg (uchar add) { uchar temp; do{ start(); outbyte(REG_WRITE); }while(ack==0); outbyte(add); while(ack==0); do{ start(); outbyte(REG_READ); }while(ack==0); temp=inbyte(); while(ack==0); stop(); return(temp); }
//=================时间控制函数=========================== void time_control(uchar type) { if(type==RUN) //CONTROL.7位设置为1,晶振停止 write_reg(CONTROL, 0X00); // else write_reg(CONTROL, 0X80); ////CONTROL.7位设置为0,晶振运行 } //============================================ //============================================ /* /* ;* Name: read_time ;* Description: 读取(FM31256-G)内部时钟值并转换成十六进制值 ;* Calls: None ;* Input: None ;* Outputs: None */ //============================================== void read_time(void) { uchar temp[6]; uchar i,flagstempa,flagstempb; flagstempa=read_reg(FLAGS); //00H单元 flagstempb=(flagstempa|0x01)&0xFD;//先将 00单元的最低位写1表示读,在将00单元倒数第二位清零表示不写 //========================= write_reg(FLAGS, flagstempb);//将控制字写时间控制寄存器 do {start(); outbyte(REG_WRITE); }while(ack==0); outbyte(SECONDS);//秒 地址 while(ack==0); do{ start(); outbyte(REG_READ); }while(ack==0); for(i=0;i<6;i++) { temp=inbyte(); ack_IIC(0); }; temp[6]=inbyte(); ack_IIC(1); stop(); //write_reg(FLAGS, flagstempb&0XFE); //========================== time.year=bcd_to_hex(temp[5]); // time.month=bcd_to_hex(temp[4]); // time.date=bcd_to_hex(temp[3]); // // time.day=bcd_to_hex(temp[3]); // time.hour=bcd_to_hex(temp[2]); time.minute=bcd_to_hex(temp[1]); time.secend=bcd_to_hex(temp[0]);
//***************************************
} //====================================== /* ;* Name: write_time ;* Description: 设置(FM31256-G)时钟寄存器,设置内部时钟 ;* Calls: None ;* Input: None ;* Outputs: None */ //=====================================
void write_time(void) { uchar temp[6]; uchar i,flagstempa,flagstempb; flagstempa=read_reg(FLAGS); flagstempb=(flagstempa|0x02)&0xFE; write_reg(FLAGS, flagstempb);
temp[6]=hex_to_bcd(time.year); temp[5]=hex_to_bcd(time.month); temp[4]=hex_to_bcd(time.date); // temp[3]=hex_to_bcd(time.day); temp[2]=hex_to_bcd(time.hour); temp[1]=hex_to_bcd(time.minute); temp[0]=hex_to_bcd(time.secend);
do{ start(); outbyte(REG_WRITE); }while(ack==0); outbyte(SECONDS); while(ack==0); for(i=0;i<6;i++) { outbyte(temp); while(ack==0); } stop(); } //====================================== /* fm_comd1() {uchar SNL,temp**a; temp**a=read_reg(WD**); SNL=(temp**a&&0x80)>>7; if(SNL==1) {flag_add=0;//标识锁存 read_reg(0x11); } else flag_add=1; } */ //=========================================== /* 喂狗程序 */ |