** PCF8563 是低功耗的CMOS 实时时钟/日历芯片,它提供一个可编程时钟输出,一个
中断输出和掉电检测器,所有的地址和数据通过I2C 总线接口串行传递。最大总线速度为
400Kbits/s,每次读写数据后,内嵌的字地址寄存器会自动产生增量。**
本次开发时基于STM32407上的项目,使用过程如下:
(1)初始化I2C,
在main中加入初始化
void MX_I2C3_Init(void)
{
hi2c3.Instance = I2C3
hi2c3.Init.ClockSpeed = 100000
hi2c3.Init.DutyCycle = I2C_DUTYCYCLE_2
hi2c3.Init.OwnAddress1 = 0
hi2c3.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT
hi2c3.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE
hi2c3.Init.OwnAddress2 = 0
hi2c3.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE
hi2c3.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE
HAL_I2C_Init(&hi2c3)
// if (HAL_I2C_Init(&hi2c2) != HAL_OK)
// {
// _Error_Handler(__FILE__, __LINE__)
// }
}
在stm32f2xx_hal_msp.c中添加i2c引脚定义
else if(hi2c->Instance==I2C3)
{
/**I2C1 GPIO Configuration
PA8 ------> I2C2_SCL
PC9 ------> I2C2_SDA
*/
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C3;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C3;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
__I2C3_CLK_ENABLE();
HAL_NVIC_SetPriority(I2C3_EV_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(I2C3_EV_IRQn);
HAL_NVIC_SetPriority(I2C3_ER_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(I2C3_ER_IRQn);
}
}
与:
else if(hi2c->Instance==I2C3)
{
__I2C3_CLK_DISABLE();
/**I2C3 GPIO Configuration
PC9 ------> I2C3_SDA
PA8 ------> I2C3_SCL
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_8);
HAL_GPIO_DeInit(GPIOC, GPIO_PIN_9);
HAL_NVIC_DisableIRQ(I2C3_EV_IRQn);
HAL_NVIC_DisableIRQ(I2C3_ER_IRQn);
}
在stm32f2xx_it.c中添加中断函数
void I2C1_ER_IRQHandler(void)
{
HAL_I2C_ER_IRQHandler(&hi2c1);
}
/**
* @brief This function handles I2C3 event interrupt.
*/
void I2C3_EV_IRQHandler(void)
{
HAL_I2C_EV_IRQHandler(&hi2c3);
}
/**
* @brief This function handles I2C3 error interrupt.
*/
void I2C3_ER_IRQHandler(void)
{
HAL_I2C_ER_IRQHandler(&hi2c3);
}
i2C初始化完成后,开始写 pcf8563的驱动程序
(1)
添加结构体,用于存放时间
struct PCF8563_Time
{
unsigned char Year;
unsigned char Month;
unsigned char Day;
unsigned char WeekDay;
unsigned char Hours;
unsigned char Minutes;
unsigned char Seconds;
};
(2)添加 驱动代码
/********************************************************************************
* File Name : PCF8563.c
* Author : TLS
* Date : 2017.11.15
* Description : pcf8563驱动程序,使用硬件I2C3,在mian 中初始化 i2c,
通过I2C 读写PCF8563 相关寄存器地址 完成时间的读写
********************************************************************************/
#include "main.h"
#define PCF8563_Write (unsigned char)0xa2
#define PCF8563_Read (unsigned char)0xa3
#define PCF8563_SUCCESS 0
#define PCF8563_FAIL 1
/******************************************************************************
参数寄存器地址宏定义
******************************************************************************/
#define PCF8563_Address_Control_Status_1 (unsigned char)0x00
#define PCF8563_Address_Control_Status_2 (unsigned char)0x01
#define PCF8563_Address_CLKOUT (unsigned char)0x0d
#define PCF8563_Address_Timer (unsigned char)0x0e
#define PCF8563_Address_Timer_VAL (unsigned char)0x0f
#define PCF8563_Address_Years (unsigned char)0x08
#define PCF8563_Address_Months (unsigned char)0x07
#define PCF8563_Address_Days (unsigned char)0x05
#define PCF8563_Address_WeekDays (unsigned char)0x06
#define PCF8563_Address_Hours (unsigned char)0x04
#define PCF8563_Address_Minutes (unsigned char)0x03
#define PCF8563_Address_Seconds (unsigned char)0x02
#define PCF8563_Alarm_Minutes (unsigned char)0x09
#define PCF8563_Alarm_Hours (unsigned char)0x0a
#define PCF8563_Alarm_Days (unsigned char)0x0b
#define PCF8563_Alarm_WeekDays (unsigned char)0x0c
extern I2C_HandleTypeDef hi2c3;
unsigned char BinToBcd2(unsigned char BINValue)
{
unsigned char bcdhigh = 0;
while (BINValue >= 10)
{
bcdhigh++;
BINValue -= 10;
}
return ((unsigned char)(bcdhigh << 4) | BINValue);
}
unsigned char Bcd2ToBin(unsigned char BCDValue)
{
unsigned char tmp = 0;
tmp = ((unsigned char)(BCDValue & (unsigned char)0xF0) >> (unsigned char)0x04) * 10;
return (tmp + (BCDValue & (unsigned char)0x0F));
}
char PCF8563_Write_Time(unsigned char add,unsigned char data,uint16_t size )
{
HAL_StatusTypeDef sta;
sta=HAL_I2C_Mem_Write_IT(&hi2c3, PCF8563_Write, add,I2C_MEMADD_SIZE_8BIT, &data, size);
osDelay(20);
if(sta!=HAL_OK)
{
return 0;
}
else
{
return 1;
}
}
char PCF8563_Read_Time(unsigned char add,uint8_t * pdata,uint16_t size )
{
HAL_StatusTypeDef sta;
sta=HAL_I2C_Mem_Read_IT(&hi2c3, PCF8563_Read, add,I2C_MEMADD_SIZE_8BIT, pdata, size);
osDelay(10);
if(sta!=HAL_OK)
{
return 0;
}
else
{
return 1;
}
}
/******************************************************************/
char PCF8563_Set_Years(char Years)
{
char Time_data = 0;
if(Years>99)
{
return PCF8563_FAIL ;
}
Time_data = BinToBcd2(Years)&0x7f;
if(PCF8563_Write_Time(PCF8563_Address_Years,Time_data,1 ))
{
return PCF8563_SUCCESS;
}
else
{
return PCF8563_FAIL ;
}
}
char PCF8563_Set_Months(char Months)
{
char Time_data = 0;
if(Months < 1 || Months > 12)
{
return PCF8563_FAIL;
}
Time_data= BinToBcd2(Months);
if( PCF8563_Write_Time(PCF8563_Address_Months,Time_data,1 ) )
{
return PCF8563_SUCCESS;
}
else
{
return PCF8563_FAIL ;
}
}
char PCF8563_Set_Days(char Days)
{
char Time_data = 0;
if( Days > 31)
{
return PCF8563_FAIL;
}
Time_data= BinToBcd2(Days );
if( PCF8563_Write_Time(PCF8563_Address_Days,Time_data,1 ) )
{
return PCF8563_SUCCESS;
}
else
{
return PCF8563_FAIL ;
}
}
char PCF8563_Set_WeekDays(char WeekDays)
{
char Time_data = 0;
if( WeekDays > 6)
{
return PCF8563_FAIL;
}
Time_data= BinToBcd2(WeekDays );
if( PCF8563_Write_Time(PCF8563_Address_WeekDays,Time_data,1 ) )
{
return PCF8563_SUCCESS;
}
else
{
return PCF8563_FAIL ;
}
}
char PCF8563_Set_Hours(char Hours)
{
char Time_data = 0;
if( Hours> 23)
{
return PCF8563_FAIL;
}
Time_data= BinToBcd2(Hours);
if( PCF8563_Write_Time(PCF8563_Address_Hours,Time_data,1 ) )
{
return PCF8563_SUCCESS;
}
else
{
return PCF8563_FAIL ;
}
}
char PCF8563_Set_Minutes(char Minutes)
{
char Time_data = 0;
if( Minutes > 59)
{
return PCF8563_FAIL;
}
Time_data= BinToBcd2(Minutes);
if( PCF8563_Write_Time(PCF8563_Address_Minutes,Time_data,1 ) )
{
return PCF8563_SUCCESS;
}
else
{
return PCF8563_FAIL ;
}
}
char PCF8563_Set_Seconds(char Seconds)
{
char Time_data = 0;
if(Seconds > 59)
{
return PCF8563_FAIL;
}
Time_data= BinToBcd2(Seconds );
if( PCF8563_Write_Time(PCF8563_Address_Seconds,Time_data,1 ) )
{
return PCF8563_SUCCESS;
}
else
{
return PCF8563_FAIL ;
}
}
/**************************************************************************/
char PCF8563_Read_Years(uint8_t *Years)
{
uint8_t tmep_year = 0;
if(PCF8563_Read_Time(PCF8563_Address_Years,&tmep_year,1 ) )
{
tmep_year &= 0x7F;
tmep_year= Bcd2ToBin(tmep_year);
if(tmep_year>99)
{
return PCF8563_FAIL;
}
else
{
*Years = tmep_year;
return PCF8563_SUCCESS;
}
}
else
{
return PCF8563_FAIL ;
}
}
char PCF8563_Read_Months(uint8_t *Months)
{
uint8_t temp_month =0 ;
if(PCF8563_Read_Time(PCF8563_Address_Months,&temp_month,1 ) )
{
temp_month &= 0x1F;
temp_month= Bcd2ToBin(temp_month);
if(temp_month<1||temp_month>12)
{
return PCF8563_FAIL;
}
else
{
*Months = temp_month ;
return PCF8563_SUCCESS;
}
}
else
{
return PCF8563_FAIL ;
}
}
char PCF8563_Read_Days(uint8_t * Days)
{
uint8_t Time_data = 0;
if(PCF8563_Read_Time(PCF8563_Address_Days,&Time_data,1 ) )
{
Time_data&= 0x3F;
Time_data= Bcd2ToBin(Time_data);
if(Time_data<1||Time_data>31)
{
return PCF8563_FAIL;
}
else
{
* Days = Time_data ;
return PCF8563_SUCCESS;
}
}
else
{
return PCF8563_FAIL ;
}
}
char PCF8563_Read_WeekDays(uint8_t * WeekDays)
{
uint8_t Time_data = 0;
if(PCF8563_Read_Time(PCF8563_Address_WeekDays,&Time_data,1 ) )
{
Time_data &= 0x07;
Time_data= Bcd2ToBin(Time_data);
if(Time_data>6)
{
return PCF8563_FAIL;
}
else
{
* WeekDays = Time_data;
return PCF8563_SUCCESS;
}
}
else
{
return PCF8563_FAIL ;
}
}
char PCF8563_Read_Hours(uint8_t * Hours)
{
uint8_t Time_data = 0;
if(PCF8563_Read_Time(PCF8563_Address_Hours,&Time_data,1 ) )
{
Time_data &= 0x3F;
Time_data= Bcd2ToBin(Time_data);
if(Time_data>23)
{
return PCF8563_FAIL;
}
else
{
* Hours = Time_data ;
return PCF8563_SUCCESS;
}
}
else
{
return PCF8563_FAIL ;
}
}
char PCF8563_Read_Minutes(uint8_t * Minutes)
{
uint8_t Time_data = 0;
if(PCF8563_Read_Time(PCF8563_Address_Minutes,&Time_data,1 ) )
{
Time_data &= 0x7F;
Time_data = Bcd2ToBin(Time_data);
if(Time_data>59)
{
return PCF8563_FAIL;
}
else
{
* Minutes = Time_data;
return PCF8563_SUCCESS;
}
}
else
{
return PCF8563_FAIL ;
}
}
char PCF8563_Read_Seconds(uint8_t * Seconds)
{
uint8_t Time_data = 0;
if(PCF8563_Read_Time(PCF8563_Address_Seconds,&Time_data,1 ) )
{
Time_data &= 0x7F;
Time_data= Bcd2ToBin(Time_data);
if(Time_data>59)
{
return PCF8563_FAIL;
}
else
{
* Seconds = Time_data ;
return PCF8563_SUCCESS;
}
}
else
{
return PCF8563_FAIL ;
}
}
char set_err =0 ;
char System_set_times(struct PCF8563_Time *PCF8563_Time)
{
uint8_t Error =0 ;
if(PCF8563_Set_Years(PCF8563_Time->Year))
{
Error++;
}
if(PCF8563_Set_Months(PCF8563_Time->Month))
{
Error++;
}
if(PCF8563_Set_Days(PCF8563_Time->Day))
{
Error++;
}
if(PCF8563_Set_WeekDays(PCF8563_Time->WeekDay))
{
Error++;
}
if(PCF8563_Set_Hours(PCF8563_Time->Hours))
{
Error++;
}
if(PCF8563_Set_Minutes(PCF8563_Time->Minutes))
{
Error++;
}
if(PCF8563_Set_Seconds(PCF8563_Time->Seconds))
{
Error++;
}
set_err = Error ;
if(Error==0)
{
return 1;
}
else
{
return 0;
}
}
char read_err = 0;
uint8_t Seconds,Minutes,Hours,Days,Months,Years,Weekdays;
char System_Read_times(struct PCF8563_Time *PCF8563_Time)
{
uint8_t Error = 0;
if(PCF8563_Read_Years(&Years))
{
Error++;
}
if(PCF8563_Read_Months(&Months))
{
Error++;
}
if(PCF8563_Read_Days(&Days))
{
Error++;
}
if(PCF8563_Read_WeekDays(&Weekdays))
{
Error++;
}
if(PCF8563_Read_Hours(&Hours))
{
Error++;
}
if(PCF8563_Read_Minutes(&Minutes))
{
Error++;
}
if(PCF8563_Read_Seconds(&Seconds))
{
Error++;
}
read_err = Error;
if(Error==0)
{
PCF8563_Time->Year =Years;
PCF8563_Time->Month =Months;
PCF8563_Time->Day =Days;
PCF8563_Time->WeekDay =Weekdays;
PCF8563_Time->Hours =Hours;
PCF8563_Time->Minutes =Minutes;
PCF8563_Time->Seconds =Seconds;
Error = 0;
return 1;
}
else
{
Error = 0;
return 0;
}
}