基于新唐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
}
}
//代码完毕。
离线