2017.11.16 在freertos 上PCF8563驱动程序

版权声明:本文为博主原创文章,未经博主允许不得转载。文章只为项目记录,不能保证观点正确。 https://blog.csdn.net/qq_29486527/article/details/78547518

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

这里写图片描述

这里写图片描述

这里写图片描述

本次开发时基于STM32407上的项目,使用过程如下:
(1)初始化I2C,
在main中加入初始化

/* I2C1 init function */
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)
  {
  /* USER CODE BEGIN I2C1_MspInit 0 */

  /* USER CODE END I2C1_MspInit 0 */

    /**I2C1 GPIO Configuration    
    PA8     ------> I2C2_SCL
    PC9     ------> I2C2_SDA 
    */

//  GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_USART2); //GPIOA2???¡§???aUSART2
//  GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_USART2); //GPIOA3???¡§???aUSART2

    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);

    /* Peripheral clock enable */
    __I2C3_CLK_ENABLE();
  /* Peripheral interrupt init*/
    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);
  /* USER CODE BEGIN I2C1_MspInit 1 */

  /* USER CODE END I2C1_MspInit 1 */
  }

}


与:
 else if(hi2c->Instance==I2C3)             //2117.11013
  {
  /* USER CODE BEGIN I2C1_MspDeInit 0 */

  /* USER CODE END I2C1_MspDeInit 0 */
    /* Peripheral clock disable */
    __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);

    /* Peripheral interrupt DeInit*/
    HAL_NVIC_DisableIRQ(I2C3_EV_IRQn);

    HAL_NVIC_DisableIRQ(I2C3_ER_IRQn);

  }


在stm32f2xx_it.c中添加中断函数


void I2C1_ER_IRQHandler(void)
{
  /* USER CODE BEGIN I2C1_ER_IRQn 0 */

  /* USER CODE END I2C1_ER_IRQn 0 */
  HAL_I2C_ER_IRQHandler(&hi2c1);
  /* USER CODE BEGIN I2C1_ER_IRQn 1 */

  /* USER CODE END I2C1_ER_IRQn 1 */
}

/**
* @brief This function handles I2C3 event interrupt.
*/
void I2C3_EV_IRQHandler(void)
{
  /* USER CODE BEGIN I2C3_EV_IRQn 0 */

  /* USER CODE END I2C3_EV_IRQn 0 */
  HAL_I2C_EV_IRQHandler(&hi2c3);
  /* USER CODE BEGIN I2C3_EV_IRQn 1 */

  /* USER CODE END I2C3_EV_IRQn 1 */
}

/**
* @brief This function handles I2C3 error interrupt.
*/
void I2C3_ER_IRQHandler(void)
{
  /* USER CODE BEGIN I2C3_ER_IRQn 0 */

  /* USER CODE END I2C3_ER_IRQn 0 */
  HAL_I2C_ER_IRQHandler(&hi2c3);
  /* USER CODE BEGIN I2C3_ER_IRQn 1 */

  /* USER CODE END I2C3_ER_IRQn 1 */
}

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  //控制/状态寄存器1  
#define PCF8563_Address_Control_Status_2         (unsigned char)0x01  //控制/状态寄存器2  

#define PCF8563_Address_CLKOUT                   (unsigned char)0x0d  //CLKOUT频率寄存器  
#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  //星期报警  


//PCF8563_TimeTypeDef PCF8563_Time;
extern I2C_HandleTypeDef hi2c3;

/*
//时间:2017.10.26
//作者:tls
//功能:实现向16进制到 bcd码转换
//参数:BINValue    需要转换的 16进制数值
//返回:转换后的 bcd码
*/

unsigned char BinToBcd2(unsigned char BINValue)  
{  
    unsigned char bcdhigh = 0;  

    while (BINValue >= 10)  
    {  
        bcdhigh++;  
        BINValue -= 10;  
    }  

    return ((unsigned char)(bcdhigh << 4) | BINValue);  
}
/*
//时间:2017.10.26
//作者:tls
//功能:实现向BCD码到16进制转换
//参数:BINValue    需要转换的 BCD码
//返回:转换后的 16进制数
*/

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));  
}



/*
//时间:2017.10.26
//作者:tls
//功能:实现向pcf8563中写入一个时间值
//参数:add     写入地址
//      data 写入数据
//      size 数据大小
//返回:0-> 失败          1-> 成功
*/
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;            //发送成功
    }

}   

/*
//时间:2017.10.26
//作者:tls
//功能:实现向pcf8563中写入一个时间值
//参数:add     读取寄存器地址
//      data 读取缓存区
//      size 数据大小
//返回:0-> 失败         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;
    }
}








猜你喜欢

转载自blog.csdn.net/qq_29486527/article/details/78547518