2017.11.16 在freertos 上PCF8563驱动程序

2019-04-15 13:11发布

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