http://hi.baidu.com/mpc2010/blog/item/bbfd3423e7d738278644f916.html

tinyArm调试————PCF8563

2011-02-23 20:52

对于tinyARm介绍及我们的工程详见前面的日志(浅谈TinyARm调试——MOdbus协议栈调试经验)。现在我来总结这段时间我所做的工作,在调试好的485通讯基础上调试实时时钟PCF8563.

一、简介PCF8563

      PCF8563 是低功耗的 CMOS 实时时钟/日历芯片,它提供一个可编程时钟输出,一个中断输出和掉电检测器,所有的地址和数据通过 I2C 总线接口串行传递。最大总线速度为400Kbits/s,每次读写数据后,内嵌的字地址寄存器会自动产生增量。具体说明可详见此芯片的datasheet。

      值得注意的是内存地址02H~08H 用于时钟计数器(秒~年计数器)编码格式为 BCD,所以我们如果想要显示时间格式必须要进行BCD_TO_HEC的转换。

二、硬件连接图

    通用的硬件连接图如下所示。 在我们的硬件中pcf8563的SCL与SDA脚分别于TinyArm的P0.19与P0.20脚相连。所以在软件中引脚设置也要将LPC2300PinCfg.h中的两个引脚的功能选择为I2c1.即

#define    P0_19_FNUC        P0_19_SDA1

#define    P0_20_FNUC        P0_20_SCL1

具体引脚的设置根据自己的设计可以采用I2c0或I2c1。

t1

三、调试程序(主要工作)

     由于这是一款时钟芯片,初始化当前时间之后,芯片会自动跟踪当地实际时间。我们调试的目的是对芯片进行初始化,然后把时间读出来,再发送到上位机通过串口调试助手判断结果。

    首先,我们可以明确的知道,这2个功能分别是通过I2c的读写来实现。于是我们通过I2c的读写功能写了2个函数分别用于设置和读取PCF内部寄存器。具体程序段如下:

#define PCF8563  0xA2       /*I2C 总线从地址:读,0A3H;写,0A2H*/    
#define BCD_to_HEC(b)    ((INT8U)(((b>>4)*10)+(b&0x0fu)))
#define HEC_to_BCD(h)    ((INT8U)(((h/10)<<4)|(h%10)))

#define I2C_INTERFACE  1                                             /*  0: PCF8563接在I2C0上       */
                                                                                 /*  1: PCF8563接在I2C1上       */
extern int32 I2CWrite(uint8 , uint8* ,uint16 ,uint8 *,uint32 ,void  (*)(INT8U));
extern int32 I2CRead(uint8, uint8* , uint16 ,uint8 *,uint32 ,void(*)(INT8U));
extern int32 I2CGetFlag(void);

/*********************************************************************************************************
** Function name:           pcf8563SetTime
** Descriptions:            设置PCF8563的时间
** input parameters:        pTime -日期时间
************************************************************************/

INT32S pcf8563SetTime (PCF8563_Time *pTime)
{
    INT8U ucTimeBuff[10];

    if (pTime == NULL) {
        return -1;
    }
    ucTimeBuff[0] = 0x00;            /*从机子地址设置*/
    ucTimeBuff[1] = 0x00;          /*控制/状态寄存器1设置*/
    ucTimeBuff[2] = 0x12;         /*控制/状态寄存器2设置*/
    ucTimeBuff[3] = HEC_to_BCD(pTime->Second); 
    ucTimeBuff[4] = HEC_to_BCD(pTime->Minute);
    ucTimeBuff[5] = HEC_to_BCD(pTime->Hour); 
    ucTimeBuff[6] = HEC_to_BCD(pTime->Day);
    ucTimeBuff[7] = HEC_to_BCD(pTime->Week);
    ucTimeBuff[8] = HEC_to_BCD(pTime->Month);
    if (pTime->Year >= 2000){
        ucTimeBuff[8] |= 0x80;
        ucTimeBuff[9] = HEC_to_BCD((INT8U)(pTime->Year - 2000));
    }else{
        ucTimeBuff[9] = HEC_to_BCD((INT8U)(pTime->Year - 1900));
    }
    /*
     *  通过I2C写PCF8563
     */
#if I2C_INTERFACE == 0
    I2CWrite(I2C0,PCF8563, ucTimeBuff, ONE_BYTE_SADDR, (ucTimeBuff+1), 9,NULL);
    while(1) {
        if(I2CGetFlag()==I2C_WRITE_END)   {
            break;
        }
        OSTimeDly(1);
    }    
#endif
#if I2C_INTERFACE == 1 
I2cWrite(I2C1, PCF8563, ucTimeBuff, ONE_BYTE_SADDR, ucTimeBuff+1, 9,NULL); 
while(1) {
  if(I2cGetFlag(I2C1) == I2C_WRITE_END) {
      break;
  }
  OSTimeDly(1);
}
#endif
    return 0;
}

*********************************************************************************************************
** Function name:           pcf8563GetTime
** Descriptions:            设置PCF8563的时间
** input parameters:        pTime -日期时间
************************************************************************/

INT32S pcf8563GetTime (PCF8563_Time *pTime)
{
    INT8U ucTimeBuff[10];

    if (pTime == NULL) {
        return -1;
    }
    /*
     *  通过I2C读PCF8563
     */
#if I2C_INTERFACE == 0
    memset(ucTimeBuff, 0, 10);
    ucTimeBuff[0]=0x02;
I2CRead(PCF8563+1, ucTimeBuff, 1, ucTimeBuff, 7,NULL); */             /* 读取外部PCF8563时钟          */

   while(1) {
        if(I2CGetFlag() == I2C_READ_END) {
            break;
        }
        OSTimeDly(1);
    }
#endif
#if I2C_INTERFACE == 1
    memset(ucTimeBuff, 0, 10);
    ucTimeBuff[0]=0x02;
I2cRead(I2C1, PCF8563 + 1, ucTimeBuff, ONE_BYTE_SADDR, ucTimeBuff, 7,NULL);

while(1) {
  if(I2cGetFlag(I2C1) ==I2C_READ_END) {
      break;
  }
  OSTimeDly(1);
}
#endif
    pTime->Second = BCD_to_HEC((ucTimeBuff[0] &0x7f));                 /* 秒             */
    pTime->Minute = BCD_to_HEC((ucTimeBuff[1] & 0x7f));                 /*分              */
    pTime->Hour   = BCD_to_HEC((ucTimeBuff[2] & 0x3f));                 /*  小时         */
    pTime->Day    = BCD_to_HEC((ucTimeBuff[3] & 0x3f));                 /*  日             */
    pTime->Week   = BCD_to_HEC((ucTimeBuff[4] & 0x07));                 /*  星期        */
    if (ucTimeBuff[5]&0x80){
        pTime->Month = BCD_to_HEC((ucTimeBuff[5] & 0x1f));              /*  月                  */
        pTime->Year  = (INT16U)(BCD_to_HEC(ucTimeBuff[6]) + 2000);      /*  年为20XX    */
    }else{
        pTime->Month = BCD_to_HEC((ucTimeBuff[5]&0x1f));
        pTime->Year  = (INT16U)(BCD_to_HEC(ucTimeBuff[6]) + 1900);      /*  年为19XX       */
    }
    return 0;
}

    这2个函数写好之后后面就可以进行我们的任务调度了,该任务会将读出的实时时钟以固定日期的格式通过RS485通讯到上位机显示出来。任务程序如下:

void TASK0 (void *pdata)
{
    #define I2C_INTERFACE   1 
    PCF8563_Time time;
    char         cStrTmp[32];
    char         uartInitArg[] = "RxBufSize=8 TxBufSize=64 BaudRate=9600";
    char      rs485Arg[32];                                             /* RS-485参数缓存               */
    /*
     *  初始化UART0
     */
    UartInit(UART0, uartInitArg, NULL);                                 /* 初始化UART0                  */
    sprintf(rs485Arg, "RS485Dir=%u", P0_04);                       /* 获取RS-485方向控制引脚    */
                                                                                   /* P0.4的编号值                 */
    UartSetMode(UART0, SET_RS485, rs485Arg);          /* 使能RS-485设置其方向控制引脚 */
  SetVICIRQ(UART0_IRQ_CHN, 8, (uint32)UART0_ISR);                     /* 设置UART0中断   */   
    /*
     *   初始化I2C
     */  
    while(I2cInit(I2C1, "Speed=400000", NULL) == OPERATE_FAIL) {       
        OSTimeDly(1);
    }
    SetVICIRQ(I2C1_IRQ_CHN, 2, (uint32)I2C1_ISR);                       /*  设置I2C中断         */
    /*
     *  通过I2C写PCF8563  设置PCF8563的时间
     */
    time.Year   = 2011;
    time.Month  = 2;
    time.Day    = 16;
    time.Week   = 3;
    time.Hour   = 10;
    time.Minute = 10;
    time.Second = 10; 

    pcf8563SetTime (&time);
    while (1) {
        /*
         *  读PCF8563的时间,并通过串口发送
         */         
         if(pcf8563GetTime(&time)==0)
         { 
            /*
             *  格式化要显示的字符串
             */
           sprintf(cStrTmp, "%04d-%02d-%02d %01d %02d:%02d:%02d",
                time.Year, time.Month,  time.Day, time.Week,
                time.Hour, time.Minute, time.Second);
            cStrTmp[21] = '\r';
            cStrTmp[22] = '\n';
            UartWrite(UART0, (uint8 *)cStrTmp, 23, NULL);             /* 通过UART0发送日期时间  */
        OSTimeDly(OS_TICKS_PER_SEC);
        }
    }
}

  如果硬件连接么有问题的话,到此就OK了。

四、调试结果

如图所示:

t2

工程完整文件我会传到csdn上,以后有需要的同学可以去下载~~~

posted on 2011-08-29 10:51  xilentz  阅读(1122)  评论(0编辑  收藏  举报