搜索
bottom↓
回复: 9

PCF8563 能读时间,不能设置时间

[复制链接]

出0入0汤圆

发表于 2012-2-22 15:13:54 | 显示全部楼层 |阅读模式
PCF8563 是用在手持设备中,
有时候会出现能读时间,但是不能设置时间,
只有复位PCF8563后(切断后备电池)才能再次设置时间。
迷惑中,不知道有谁碰到过。
还请多指教。

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2012-2-22 15:16:33 | 显示全部楼层
// ===============================================================================================                                                 
// 文件名称:PCF8563.c
// 芯片类型: MSP430F149                                                                                                                 
// 开发软件: IAR Embedded Workbench V3.2 , Windows XP                                                                                    
// 开发时间:2007年07月08日 ---  2007年07月10日                                                               
// 程序功能:使用M430的P4.6、P4.7对外部的IIC时钟进行读写操作
// 编写人员:吕云曾                                                                       
// 联系方式:13845052176  lvyunzeng@163.com  
//=================================================================================================                                             
//==连接芯片的管脚连接==
//                         --- --- --- VCC
//               PCF8563    |  10k 10k   MSP430               
//              |--------|  |   |   | |----------|   
//  32.768KHz---|OSI  VDD|---   |   | |          |
//       |------|OSO  CLK|      |   | |          |
// P1.7-+-------|INT  SCL|<-----+---|-|P4.7      |   
//      |    |--|VSS  SDA|<---------+>|P4.6      |
//     10K   |  |--------|            |----------|
//  VCC---  \|/ GND                  
//========================================= 头文件 ================================================
#include  <msp430x14x.h>

//========================================== 宏定义 ===============================================
//========================== 宏定义 =================================
#define Uchar unsigned char
#define uchar unsigned char
#define Uint  unsigned int
#define Ulong unsigned long
//==  PCF8563 定义 ==   
#define SCL0 ClrP2(2)
#define SCL1 SetP2(2)
#define SDA0 ClrP2(1)
#define SDA1 SetP2(1)
#define DIR_IN      P2DIR &=~ BIT1             //I/O口为输入
#define DIR_OUT     P2DIR |=  BIT1              //I/0口为输出
#define SDA_IN      ((P2IN >> 1) & 0x01)        //Read SDA

#define ClrP2(n) P2OUT&=(~(1<<n))
#define SetP2(n) P2OUT|=(1<<n)


//======================================= 变量定义 =================================================
uchar g8563_Store[4];    //== 时间交换区,全局变量声明 ==
/*
PCF8563_time[0] --- 秒   ;  
PCF8563_time[1] --- 分   ;
PCF8563_time[2] --- 小时 ;  
PCF8563_time[3] --- 日   ;
PCF8563_time[4] --- 星期 ;  
PCF8563_time[5] --- 月   ;
PCF8563_time[6] --- 年   ;
*/
uchar PCF8563_time[7];   
//uchar c8563_Store[4]={0x00,0x59,0x07,0x01};  //== 写入时间初值:星期一  07:59:00 ==
uchar Set8563_time[7]={0x00,0x59,0x07,0x0A,0x02,0x07,0x07}; //==写入时间初值:2007年07月星期二 10日 07:59:00 ==
//======================================== 函数声明 ================================================
void InitMain (void);         //=== 系统初始化函数  ===
void delayX10ms(int count);   //===延迟===     
void Delay();
void Start();
void Stop();
void WriteACK();
void writenoack();
void WaitACK();
void writebyte(uchar wdata);
uchar Readbyte();
void writeData(uchar address,uchar mdata);
uchar ReadData(uchar address)  ;             /*单字节*/
void ReadData1(uchar address,uchar count,uchar * buff);   /*多字节*/
void P8563_Read();
void P8563_gettime();
void P8563_settime();
void P8563_init();                 //== 初始化时间 ==
//=================================================================================================
//========================================== 主函数  ==============================================
//=================================================================================================
void main(void)
{
  WDTCTL  = WDTPW + WDTHOLD;   //=== Stop watchdog timer  ===
  InitMain ();                 //=== 系统初始化函数  ===
  P8563_init();                //== 初始化时间 ==  
   _EINT();                     //== Enable interrupts ===   
while (1)
  {

       P8563_gettime();
       P1OUT ^= BIT6;         //===P4.0取反输出===
       delayX10ms(50);
       P1OUT ^= BIT7;         //===P4.0取反输出===
       delayX10ms(50);
        
     
  }

}

//=============================================================================
//函 数 名: void InitMain (void)
//功 能:系统初始化
//入口参数:NO
//返 回 值:NO
//=============================================================================
//----------------------- 系统初始化函数 ----------------------------
void InitMain (void)
{
    unsigned int i;
    WDTCTL=WDTPW+WDTHOLD; //停止看门狗
    //--- 系统时钟配置 ---
    BCSCTL2 |= SELS;  //SMCLK = XT2 -----
                      //MCLK = DCOCLK
    do
    {
      IFG1 &= ~OFIFG;                           // Clear OSCFault flag
      for (i = 0xFF; i > 0; i--);               // Time for flag to set
    }
    while ((IFG1 & OFIFG));                   // OSCFault flag still set?
    BCSCTL2 |= SELM_2 + SELS;                 // MCLK = SMCLK = XT2 (safe)
    BCSCTL2 |= DIVM1 + DIVM0;                 // MCLK = XT2/8
    //-----PCF8563 INT中断 ----
    P2DIR &= ~BIT0;
    P2DIR &= ~BIT3;
   
    P2DIR |= BIT1;
    P2DIR |= BIT2;
     
    P1DIR = 0xff;
  /*
    //--- 4X4按键I/O配置 ---
    P2DIR = 0;        //== 将P2口所有的管脚在初始化的时候设置为输入方式 ==
    P2SEL = 0;        //== 将P2口所有的管脚设置为一般I/O口 ==
    P2DIR |= BIT4;    //== 将P2.4 P2.5 P2.6 P2.7设置为输出方向 ==
    P2DIR |= BIT5;
    P2DIR |= BIT6;
    P2DIR |= BIT7;
    P2OUT = 0xF0;     //== 先输出低电平 ==
    //-----PCF8563 INT中断 ----
    P1DIR = 0x00;
    P1IES = 0Xff;
    P1IE  = 0x80;    //列线上升沿允许P1中断
    //--- LED 测试端口 ---
    //P4DIR  |= 0x01;             //== Set P4.0 to output direction ==
     //--- 液晶数据线接口 ---
    P5DIR=0xff;           //== 设置IO口的方向为输出 ==
    P4DIR=0xff;           //== 设置IO口的方向为输出 ==
*/
}

//=============================================================================
//函 数 名: delayX10ms(int count)
//功 能:延时子函数
//入口参数:int count
//返 回 值:NO
//=============================================================================
void delayX10ms(int count)   //===延迟===
{
unsigned int i,j,k;
for (i=0; i<count; i++)
  for(j=0; j<10; j++)
    for(k=0; k<120; k++);
}      

//===================================================================
//=============  内部函数,延时1 ====================================
//===================================================================
void Delay()
{
   int i ;                        //== IIC的读写速度小于400KHz ==
    for(i=0;i<20;i++);            //== 根据晶振频率制定延时时间 ==
}                                 //== 此程序采用 8MHz 系统时钟 ==
//===================================================================
//=============  内部函数,I2C开始  =================================
//===================================================================
void Start()
{   
     SDA1 ;
     SCL1 ;
     Delay();
     SDA0 ;
     Delay();
     SCL0 ;
}

//===================================================================
//=============   内部函数,I2C结束   ===============================
//===================================================================
void Stop()
{
    SDA0 ;
    SCL0 ;
    Delay();
    SCL1 ;
    Delay();
    SDA1 ;
    Delay();
     
}

//===================================================================
//=============   内部函数,输出ACK=0    ============================
//===================================================================
void WriteACK()
{
    SDA0 ;
    Delay();
    SCL1 ;
    Delay();
    SCL0 ;
}

//===================================================================
//=============   内部函数,输出ACK=1    ============================
//===================================================================
void writenoack()
{
    SDA1 ;
    Delay();
    SCL1 ;
    Delay();
    SCL0 ;
}

//===================================================================
//=============   内部函数,等待ACK  ================================
//===================================================================
void WaitACK()
{  
   uchar errtime = 0 ;
    SDA1 ;
    Delay();               //== 读ACK ==
    SCL1 ;
    Delay();
    DIR_IN;
    while((SDA_IN == 0x01)&(errtime<=50))  //== 防止读取信号出现死循环==
    {
     errtime++;
       if(errtime==50)
       {
      Stop();
        }
    }
    errtime = 0 ;
    DIR_OUT;
    SCL0 ;
    Delay();
   
}
//===================================================================
//=============  内部函数.输出数据字节 ==============================
//===================================================================
void writebyte(uchar wdata)
{
    uchar i;
    for(i=0;i<8;i++)
    {
        if(wdata&0x80) SDA1 ;
          else SDA0 ;
          wdata<<=1;
          SCL1 ;
          Delay();
          SCL0 ;
    }
    WaitACK();
}

//===================================================================
//=============   内部函数.输入数据  ================================
//===================================================================
uchar Readbyte()
{
    uchar i,bytedata;
    SDA1 ;
    DIR_IN ;
    for(i=0;i<8;i++)
    {
        SCL1 ;
        bytedata<<=1;
        bytedata|=SDA_IN;
        SCL0 ;
        Delay();
    }
    DIR_OUT ;
    return(bytedata);
}

//===================================================================
//=============   输出数据->pcf8563  ================================
//===================================================================
void writeData(uchar address,uchar mdata)
{
    Start();
    writebyte(0xa2);          //== 写命令 ==
    writebyte(address);       //== 写地址 ==
    writebyte(mdata);         //== 写数据 ==
    Stop();
}

//===================================================================
//=============   输入数据<-pcf8563   ===============================
//===================================================================
uchar ReadData(uchar address)    //== 单字节 ==
{   uchar rdata;
    Start();
    writebyte(0xa2);             //== 写命令 ==
    writebyte(address);          //== 写地址 ==
    Start();
    writebyte(0xa3);             //== 读命令 ==
    rdata=Readbyte();
    writenoack();
    Stop();
    return(rdata);
}
void ReadData1(uchar address,uchar count,uchar * buff) //== 多字节 ==
{   uchar i;
    Start();
    writebyte(0xa2);             //== 写命令 ==
    writebyte(address);          //== 写地址 ==
    Start();
    writebyte(0xa3);             //== 读命令 ==
    for(i=0;i<count;i++)
    {
        buff=Readbyte();
        if(i<count-1) WriteACK();
    }
    writenoack();
    Stop();
}

//===================================================================
//=============   内部函数,读入时间到内部缓冲区  ====================
//===================================================================
void P8563_Read()
{   uchar  time[7];
    ReadData1(0x02,0x07,time);
    //g8563_Store[0]=time[0]&0x7f;        //== 秒 ==
    //g8563_Store[1]=time[1]&0x7f;        //== 分 ==
    //g8563_Store[2]=time[2]&0x3f;        //== 小时 ==
    //g8563_Store[3]=time[4]&0x07;        //== 星期 ==
   
    PCF8563_time[0]=time[0]&0x7f;        //== 秒 ==
    PCF8563_time[1]=time[1]&0x7f;        //== 分 ==
    PCF8563_time[2]=time[2]&0x3f;        //== 小时 ==
    PCF8563_time[3]=time[3]&0x7f;        //== 日 ==
    PCF8563_time[4]=time[4]&0x07;        //== 星期 ==
    PCF8563_time[5]=time[5]&0x7f;        //== 月 ==
    PCF8563_time[6]=time[6]&0x7f;        //== 年 ==
   
   
}

//===================================================================
//=============   读入时间到内部缓冲区----外部调用   ================
//===================================================================
void P8563_gettime()
{
    P8563_Read();
    if(g8563_Store[0]==0)
      P8563_Read();      //== 如果为秒=0,为防止时间变化,再读一次 ==
}

//===================================================================
//=============   写时间修改值  =====================================
//===================================================================
void P8563_settime()
{
   uchar i;
   //for(i=2;i<=4;i++) {  writeData(i,g8563_Store[i-2]); }
   //writeData(6,g8563_Store[3]);
   for(i=2;i<=8;i++)
   writeData(i, PCF8563_time[i-2]);
}
//===================================================================
//==================== 初始化时间 ===================================
//===================================================================
void P8563_init()
{
  uchar i;
// if((ReadData(0xa)&0x3f)!=0x8)                          
//== 检查是否第一次启动,是则初始化时间 ==
  //  {
      for(i=0;i<=6;i++)  PCF8563_time=Set8563_time; //== 初始化时间 ==
      P8563_settime();
      writeData(0x0,0x00);                               //== control1=0x00 ==
      writeData(0x9,0x00);                              //== 0分 报警 ==
      //writeData(0xa,0x8);                             //== 8:00报警 ==
      writeData(0x1,0x12);                              //== control2 报警有效 ==
      //writeData(0xd,0xf0);                            //== 频率输出 ==
   //  }
}

//=============================================================================
//端口1中断函数
//多中断中断源:P1IFG.0~P1IFG7
//进入中断后应首先判断中断源,退出中断前应清除中断标志,否则将再次引发中断
//=============================================================================
#pragma vector=PORT1_VECTOR
__interrupt void Port1()
{
//== 以下为参考处理程序,不使用的端口应当删除其对于中断源的判断 ==
  if((P1IFG&BIT7) ==BIT7)//== 处理P1IN.7中断 ==
{
    P1IFG &= ~BIT7; //== 清除中断标志 ==
    //以下填充用户代码
    writeData(0x1,0x12);      //== 清除分中断标志位 令AF=0  ==
    P4OUT ^= 0x01;         //== P4.0取反输出===
   
   
}
}

出0入0汤圆

发表于 2012-2-22 15:17:32 | 显示全部楼层
看看吧,我自己改的程序。项目中使用的,当时独立调试的程序段,完全可以用。希望对你有帮助!

出0入0汤圆

 楼主| 发表于 2012-2-22 15:35:09 | 显示全部楼层
谢谢,时间是可以读出来的,就是有时会不能设置时间,
对了下你的程序,跟你的差不多。
因为产品已经投产了,不方便再全部跟换驱动程序了。

要是能大概知道哪些情况会引起这种现象,就能更方便找出问题。

出0入0汤圆

发表于 2012-2-22 15:38:28 | 显示全部楼层
没用过这个片子,但是用过很多RTC片子。

一般寄存器会有个有个WP的位,写保护的。

软件上一般会这么处理:

初次上电时候,关闭写保护,然后写正确时间,然后往芯片自带的RAM里面写一个值。然后打开写保护。

以后上电时,会读这个RAM的值,如果是以前写进去的,说明没有掉电,时间也没有丢。就不会打开写保护,所以不能写。
如果掉电了,RAM的值被清零,所以软件判断掉电了,会关闭写保护,就可以写时间了。

所以你说拔掉电池,就可以写,应该就这样的。



估计是写保护被打开了。

出0入0汤圆

 楼主| 发表于 2012-2-22 17:13:27 | 显示全部楼层
回复【4楼】womenhome
-----------------------------------------------------------------------

谢谢,我又翻了一遍PCF8563的芯片手册,里面没有提到也没有跟写保护相关的寄存器。

出0入0汤圆

发表于 2012-2-22 18:27:09 | 显示全部楼层
我记得似乎电压低的时候是只读的

出0入0汤圆

 楼主| 发表于 2012-2-22 18:40:17 | 显示全部楼层
回复【6楼】chenlong0108
-----------------------------------------------------------------------

不是电压低的问题,
因为PCF8563的供电电压是由7V+降压下来的,也量过PCF8563的供电脚(3V),
另外,同一块电池,假如出现不能设置时间的问题,就一直是这样子,
除非复位PCF8563(切断后备电池)才能再次设置时间。
假如是电压低,那么同一块电池,也应该是一直不能设置才对。

出0入0汤圆

发表于 2012-2-22 18:49:05 | 显示全部楼层
IIC 的速度问题,一楼那里有注明,小于400k,楼主看看你的程序延时吧,我估计又是延时时间不够,超过了400k

出0入0汤圆

 楼主| 发表于 2012-2-23 08:53:29 | 显示全部楼层
回复【8楼】xiaojian
-----------------------------------------------------------------------

谢谢,我会检查通信速率是否小于400。
只是 不能设置时间的情况 也是偶尔出来,
可能需要几天的测试,才能确认。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-6-19 05:59

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表