打印

如何读写FM31256时间

[复制链接]
3647|4
手机看帖
扫描二维码
随时随地手机跟帖
沙发
asiasun21|  楼主 | 2007-8-30 09:59 | 只看该作者

程序如下

#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;
}
*/
//===========================================
/*
喂狗程序
*/

使用特权

评论回复
板凳
littlerong| | 2019-12-17 11:08 | 只看该作者
你好,我的读写都可以,但是秒从0-32,之后又变成0;秒经历过两次0-32后,分才+1.
这可能是什么原因造成的

使用特权

评论回复
地板
我只想学习啊| | 2020-6-24 15:35 | 只看该作者
littlerong 发表于 2019-12-17 11:08
你好,我的读写都可以,但是秒从0-32,之后又变成0;秒经历过两次0-32后,分才+1.
这可能是什么原因造成的 ...

你好,请问你的问题解决了吗?

使用特权

评论回复
5
airwill| | 2020-6-27 08:36 | 只看该作者
是不是读时序里的延迟太短了?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

2

帖子

0

粉丝