您尚未登录。

楼主 #1 2020-05-09 18:32:40

缥缈九哥
会员
注册时间: 2020-05-09
已发帖子: 76
积分: 92

基于新唐NUC123的3.0的BSP包的PCF8563驱动程序--缥缈九哥

基于新唐NUC123的3.0的BSP包的PCF8563驱动程序

源码如下:

/******************************************************************************
 * @file     pcf8563.c
 * @brief    The Driver code for PCF8563 with NUC123ZD4AN0
 * @version  1.0.0
 * @date     22, June, 2018
 *
 * @note
 * Copyright (C) 2000-2016 PM9GZY by yuanxihua@21cn.com. All rights reserved.
 ******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/*
_________________________________________________
| NUC123ZD4AN0     PCF8563  |
|            |
| SDA1 - PA10  <--->  SDA   |
| SCL1 - PA11   --->  SCL   |
| INT0 -  PB14  <---  INT   |
|_______________________________________________|
*/
/* Private typedef -----------------------------------------------------------*/
typedef enum {START=0,STOP,ACK,NAK}i2c_status_t;
typedef struct
{
 uint8_t CTL_status[2];
 uint8_t VL_second;
 uint8_t TM_minute;
 uint8_t TM_hour;
 uint8_t TM_day;
 uint8_t TM_weekday;
 uint8_t CTY_month;
 uint8_t TM_year;
 uint8_t AL_minute;
 uint8_t AL_hour;
 uint8_t AL_day;
 uint8_t AL_weekday;
 uint8_t CTL_clkout;
 uint8_t CTL_timer;
 uint8_t TM_timer;
}pcf8563_t;

//#define pbcd_to_byte(x)  (((((x)>>4)&0x0f)*10)+((x)&0x0f))
//#define byte_to_pbcd(x)  (((((x)/10)&0x0f)<<4)+(((x)%10)&0x0f))
/* Private define ------------------------------------------------------------*/
#define PCF8563_SLAVEADDR          0xA2    /* Clock i2c slave address */
#define PCF8563_CLK_HZ           100000    /* Clock i2c speed */
#define PCF8563_I2C_WAIT_US      100000    /* Clock wait time */
/* Private macro -------------------------------------------------------------*/
void PCF8563_Get_Time(struct tm *Time);
void PCF8563_Set_Time(struct tm Time);
/* Private variables ---------------------------------------------------------*/
uint8_t pbcd_to_byte(uint8_t pbcd)
{
 uint8_t msb,lsb;
 msb = (pbcd >> 4);
 lsb = pbcd & 0xf;
 if((msb>9)||(lsb>9)){return(99);}
 else{return((10*msb)+lsb);}
}  
uint8_t byte_to_pbcd(uint8_t bin)
{
 if(bin>=99){return(0x99);}/* overflow? */
 else{return(((bin/10)<<4)|(bin%10));}
}
 
static void CLK_SysTickDelayMs(uint32_t ms)
{
 for(uint32_t i=0;i<ms;i++){CLK_SysTickDelay(1000);}
}
void I2C1_Configuration(void)
{
 /* Unlock protected registers */
    SYS_UnlockReg();
 
    /* Set GPA multi-function pins for I2C1 SDA and SCL */
 SYS->GPA_MFP &= ~(SYS_GPA_MFP_PA10_Msk | SYS_GPA_MFP_PA11_Msk);
    SYS->GPA_MFP |= (SYS_GPA_MFP_PA10_I2C1_SDA | SYS_GPA_MFP_PA11_I2C1_SCL);
    SYS->ALT_MFP &= ~(SYS_ALT_MFP_PA10_Msk | SYS_ALT_MFP_PA11_Msk);
    SYS->ALT_MFP |= (SYS_ALT_MFP_PA10_I2C1_SDA | SYS_ALT_MFP_PA11_I2C1_SCL);
 
 /* Enable I2C1 module clock */
    CLK_EnableModuleClock(I2C1_MODULE);

 /* reset I2C1 modules */
 SYS_ResetModule(I2C1_RST);
  
 /* Get I2C1 clock */
// DBG_PRINTF("I2C1 clock %d Hz\n", I2C_GetClockFreq(I2C1));
 /* Lock protected registers */
    SYS_LockReg();
}

static void I2C_SEND_STATUS(I2C_T *i2c,i2c_status_t status)  
{
 uint32_t i=PCF8563_I2C_WAIT_US;
 if(status==START){I2C_SET_CONTROL_REG(i2c, I2C_I2CON_STA_SI); }else   //set start
 if(status==STOP ){I2C_SET_CONTROL_REG(i2c, I2C_I2CON_STO_SI); }else  //set stop
 if(status==ACK  ){I2C_SET_CONTROL_REG(i2c, I2C_I2CON_SI_AA); }else  //set ack
 if(status==NAK  ){I2C_SET_CONTROL_REG(i2c, I2C_I2CON_SI);  }else{;} //set nack
 while((I2C_GetIntFlag(i2c)==0)&&(i--)){CLK_SysTickDelay(1);};
// DBG_PRINTF("I2C_SS STATUS=0x%02x\n\r",I2C_GET_STATUS(i2c));
}

static void I2C_SEND_DATA(I2C_T *i2c,uint8_t data,i2c_status_t ack)  
{
 uint32_t i=PCF8563_I2C_WAIT_US;
 I2C_SET_DATA(i2c, data);
 if(ack==ACK){I2C_SET_CONTROL_REG(i2c, I2C_I2CON_SI_AA);  }else  //ACK
 if(ack==NAK){I2C_SET_CONTROL_REG(i2c, I2C_I2CON_SI);  }else{;} //NACK
 while((I2C_GetIntFlag(i2c)==0)&&(i--)){CLK_SysTickDelay(1);};
// DBG_PRINTF("I2C_SD=0x%02x STATUS=0x%02x\n\r",data,I2C_GET_STATUS(i2c));
}

static uint8_t I2C_READ_DATA(I2C_T *i2c,i2c_status_t ack)  
{
 uint32_t i=PCF8563_I2C_WAIT_US;
 while((I2C_GetIntFlag(i2c)==0)&&(i--)){CLK_SysTickDelay(1);};
 uint8_t data=I2C_GET_DATA(i2c);
 if(ack==ACK){I2C_SET_CONTROL_REG(i2c, I2C_I2CON_SI_AA);  }else  //ACK
 if(ack==NAK){I2C_SET_CONTROL_REG(i2c, I2C_I2CON_SI);  }else{;} //NACK
// DBG_PRINTF("I2C_RD STATUS=0x%02x\n\r",I2C_GET_STATUS(i2c));
 return data;
}

void PCF8563_Get_Time(struct tm *Time)
{
 uint8_t buf[16],i;
 
 I2C1_Configuration();
 //i2c bus open 
 I2C_Open(I2C1, PCF8563_CLK_HZ);
 
 //send i2c start
 I2C_SEND_STATUS(I2C1,START);
    //send slave address & writer command
 I2C_SEND_DATA(I2C1,0xa2,ACK);
 //send register address
 I2C_SEND_DATA(I2C1,0x00,ACK);
   
 //send i2c start
 I2C_SEND_STATUS(I2C1,START);
 //send slave address & read command
 I2C_SEND_DATA(I2C1,0xa3,ACK);

 uint8_t tmp=I2C_READ_DATA(I2C1,ACK);
 for(i=0;i<15;i++)
 {
  //receive data with ack
  buf[i]= I2C_READ_DATA(I2C1,ACK);
  CLK_SysTickDelay(100);
 }
 //receive data with nak
 buf[i]= I2C_READ_DATA(I2C1,NAK);

 //send i2c stop
 I2C_SEND_STATUS(I2C1,STOP);
 
 CLK_SysTickDelay(100);    
 I2C_Close(I2C1);
// DBG_PRINTF("\n\rGETBUF:");for(i=0;i<16;i++){printf("%02x ",buf[i]);}

// memset(Time,0,sizeof(struct tm));
 Time->tm_sec  = pbcd_to_byte(buf[2]&0x7f);
 Time->tm_min  = pbcd_to_byte(buf[3]&0x7f);
 Time->tm_hour  = pbcd_to_byte(buf[4]&0x3f);
 Time->tm_mday  = pbcd_to_byte(buf[5]&0x3f);
 Time->tm_mon  = pbcd_to_byte(buf[7]&0x1f)-1; 
 Time->tm_year  = pbcd_to_byte(buf[8])+100;
}
void PCF8563_Set_Time(struct tm Time)
{
 uint8_t buf[16],i;
 
 buf[0]=0;
 buf[1]=0;
 buf[2]=byte_to_pbcd(Time.tm_sec);
 buf[3]=byte_to_pbcd(Time.tm_min);
 buf[4]=byte_to_pbcd(Time.tm_hour);
 buf[5]=byte_to_pbcd(Time.tm_mday);
 buf[7]=byte_to_pbcd(Time.tm_mon)+1;
 buf[8]=byte_to_pbcd(Time.tm_year%100);
 
// DBG_PRINTF("\n\rSETBUF:");for(i=0;i<16;i++){printf("%02x ",buf[i]);}
 I2C1_Configuration(); 
 //i2c bus open 
 I2C_Open(I2C1, PCF8563_CLK_HZ);
 
 //send i2c start
 I2C_SEND_STATUS(I2C1,START);
    //send slave address & writer command
 I2C_SEND_DATA(I2C1,0xa2,ACK);
 //send register address
 I2C_SEND_DATA(I2C1,0x00,ACK);
 
 for(i=0;i<15;i++)
 {
  //send data with ack
  I2C_SEND_DATA(I2C1,buf[i],ACK);
  CLK_SysTickDelay(100);
 }
 //send data with nak
 I2C_SEND_DATA(I2C1,buf[i],NAK);
    
    //send i2c stop
 I2C_SEND_STATUS(I2C1,STOP);
  
 CLK_SysTickDelay(100);
 I2C_Close(I2C1);
}
uint8_t PCF8563_Chk_Time(struct tm *t)
{
 uint32_t year=t->tm_year, month=t->tm_mon, day=t->tm_mday;   //防止修改指针
 uint32_t hour=t->tm_hour, minute=t->tm_min, second=t->tm_sec;  //防止修改指针
 if((year<2010)||(year>2030)){return 0;}
 if((month<1)||(month>12)){return 0;}
 if((day<1)||(day>31)){return 0;}
 if((month==4||month==6||month==9||month==11)&&(day>30)){return 0;}
 if(month==2){if(year%4){if(day>28){return 0;}}else{if(day>29){return 0;}}}
 if((hour>23)||(minute>59)||(second>60)){return 0;}
 return 1;
}

void PCF8563_test(void)
{
 __align(4) struct tm Time;
  
#if 0
 const char Month[12][4]= {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};char sMonth[4]= {0};
 const char *DataStr = __DATE__; //Aug 20 2016
 const char *TimeStr = __TIME__; //20:12:38
    sscanf(DataStr, "%s %d %d", sMonth, &Time.tm_mday, &Time.tm_year);
    sscanf(TimeStr, "%d:%d:%d", &Time.tm_hour, &Time.tm_min, &Time.tm_sec);
 for(int i=0;i<12;i++){if(strncmp(sMonth, Month[i],3)==0){Time.tm_mon=i;break;}}

 Time.tm_year  -= 1900;  /* years since 1900 */
// Time.tm_mon  = 8-1;   /* months since January, 0 to 11 */
// Time.tm_mday  = 20;   /* day of the month, 1 to 31 */
// Time.tm_hour  = 18;   /* hours since midnight, 0 to 23 */
// Time.tm_min  = 43;   /* minutes after the hour, 0 to 59 */
 Time.tm_sec  +=10;   /* seconds after the minute, 0 to 60
         (0 - 60 allows for the occasional leap second) */
 PCF8563_Set_Time(Time);

 while(1)
#endif
 {
  PCF8563_Get_Time(&Time);
  time_t t=mktime(&Time); // printf("t=%d %s",t, ctime(&t));
  printf("%s", asctime(&Time));

  char str[80]; strftime(str,100,"GET Time:%F %H:%M:%S\n\r",&Time); printf("%s", str);     
  CLK_SysTickDelayMs(1000);
  
  struct tm a;
  a.tm_year  = 100;  /* years since 1900 */
  a.tm_mon  = 0;  /* months since January, 0 to 11 */
  a.tm_mday  = 1;  /* day of the month, 1 to 31 */
  a.tm_hour  = 0;  /* hours since midnight, 0 to 23 */
  a.tm_min  = 0;  /* minutes after the hour, 0 to 59 */
  a.tm_sec  = 0;  /* seconds after the minute, 0 to 60 */
  
  time_t p=mktime(&a);
  printf("p=0x%08x = %d , %s",p,p,ctime(&p));
  //p=0x386d4380 = 946684800 , Sat Jan  1 00:00:00 2000
  t=0x1F4DC49F+p;//1986-08-23 14:11:43
  printf("t=0x%08x = %d , %s",t,t,ctime(&t));
  //t=1471875103 Mon Aug 22 14:11:43 2016
 }
 
}

//代码完毕。

离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn