一、PCF2129介绍
PCF2129主要特性
内部集成温度补偿功能的振荡器电容;
精度:±3ppm(-20℃~+70℃);
内置32.768 kHz晶振;
可提供年、月、日、星期、时、分和秒等信息;
时间印输入管脚,可中断的时间印功能;
1MHz的双线I2C总线接口;
6.5Mbit/s的三线SPI总线接口;
备用电池输入和转换电路;
备用电池电压输出;
电池电量低报警;
监控晶振停止工作功能;
开漏中断引脚;
1秒或1分钟中断输出;
具有中断和复位功能的可编程的看门狗定时器;
具有中断能力的可编程闹钟功能;
可编程的方波输出;
工作电压:1.2V~4.2V;
低后备电流:典型值为0.65μA(VDD=3.0V,Tamb=25℃时)。
二、PCF2129驱动程序
spi.c
#include "spi.h"
SPI_HandleTypeDef SPI3_Handler; //SPI2句柄
//以下是SPI模块的初始化代码,配置成主机模式
//SPI口初始化
//这里针是对SPI2的初始化
void SPI3_Init(void)
{
SPI3_Handler.Instance=SPI3; //SP2
SPI3_Handler.Init.Mode=SPI_MODE_MASTER; //设置SPI工作模式,设置为主模式
SPI3_Handler.Init.Direction=SPI_DIRECTION_2LINES;//设置SPI单向或者双向的数据模式:SPI设置为双线模式
SPI3_Handler.Init.DataSize=SPI_DATASIZE_8BIT; //设置SPI的数据大小:SPI发送接收8位帧结构
SPI3_Handler.Init.CLKPolarity=SPI_POLARITY_LOW; //串行同步时钟的空闲状态为高电平
SPI3_Handler.Init.CLKPhase=SPI_PHASE_1EDGE; //串行同步时钟的第二个跳变沿(上升或下降)数据被采样
SPI3_Handler.Init.NSS=SPI_NSS_SOFT; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
SPI3_Handler.Init.NSSPMode=SPI_NSS_PULSE_DISABLE;//NSS信号脉冲失能
SPI3_Handler.Init.MasterKeepIOState=SPI_MASTER_KEEP_IO_STATE_ENABLE; //SPI主模式IO状态保持使能
SPI3_Handler.Init.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_128;//定义波特率预分频的值:波特率预分频值为256
SPI3_Handler.Init.FirstBit=SPI_FIRSTBIT_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
SPI3_Handler.Init.TIMode=SPI_TIMODE_DISABLE; //关闭TI模式
SPI3_Handler.Init.CRCCalculation=SPI_CRCCALCULATION_DISABLE;//关闭硬件CRC校验
SPI3_Handler.Init.CRCPolynomial=7; //CRC值计算的多项式
HAL_SPI_Init(&SPI3_Handler);
__HAL_SPI_ENABLE(&SPI3_Handler); //使能SPI2
// SPI3_ReadWriteByte(0Xff); //启动传输
}
//SPI2底层驱动,时钟使能,引脚配置
//此函数会被HAL_SPI_Init()调用
//hspi:SPI句柄
void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)
{
GPIO_InitTypeDef GPIO_Initure;
RCC_PeriphCLKInitTypeDef SPI2ClkInit;
__HAL_RCC_GPIOB_CLK_ENABLE(); //使能GPIOF时钟
__HAL_RCC_SPI3_CLK_ENABLE(); //使能SPI2时钟
//设置SPI2的时钟源
SPI2ClkInit.PeriphClockSelection=RCC_PERIPHCLK_SPI2; //设置SPI2时钟源
SPI2ClkInit.Spi123ClockSelection=RCC_SPI123CLKSOURCE_PLL; //SPI2时钟源使用PLL1Q
HAL_RCCEx_PeriphCLKConfig(&SPI2ClkInit);
//PB10,14,15
GPIO_Initure.Pin=GPIO_PIN_3|GPIO_PIN_4;
GPIO_Initure.Mode=GPIO_MODE_AF_PP; //复用推挽输出
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH; //快速
GPIO_Initure.Alternate=GPIO_AF6_SPI3; //复用为SPI2
HAL_GPIO_Init(GPIOB,&GPIO_Initure); //初始化
//PB10,14,15
GPIO_Initure.Pin=GPIO_PIN_5;
GPIO_Initure.Mode=GPIO_MODE_AF_PP; //复用推挽输出
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH; //快速
GPIO_Initure.Alternate=GPIO_AF7_SPI3; //复用为SPI2
HAL_GPIO_Init(GPIOB,&GPIO_Initure); //初始化
}
//SPI速度设置函数
//SPI速度=PLL1Q/分频系数
//@ref SPI_BaudRate_Prescaler:SPI_BAUDRATEPRESCALER_2~SPI_BAUDRATEPRESCALER_256
//PLL1Q时钟一般为200Mhz:
void SPI3_SetSpeed(u32 SPI_BaudRatePrescaler)
{
assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));//判断有效性
__HAL_SPI_DISABLE(&SPI3_Handler); //关闭SPI
SPI3_Handler.Instance->CFG1&=~(0X7<<28); //位30-28清零,用来设置波特率
SPI3_Handler.Instance->CFG1|=SPI_BaudRatePrescaler;//设置SPI速度
__HAL_SPI_ENABLE(&SPI3_Handler); //使能SPI
}
//SPI2 读写一个字节
//TxData:要写入的字节
//返回值:读取到的字节
u8 SPI3_ReadWriteByte(u8 TxData)
{
u8 Rxdata;
HAL_SPI_TransmitReceive(&SPI3_Handler,&TxData,&Rxdata,1, 1000);
return Rxdata; //返回收到的数据
}
pcf2129.c
#include "pcf2129.h"
#include "spi.h"
void pcf2129_init()
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_GPIOB_CLK_ENABLE(); //开启GPIOB时钟
GPIO_Initure.Pin=GPIO_PIN_8; //PB0,1
GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //推挽输出
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH; //高速
HAL_GPIO_Init(GPIOB,&GPIO_Initure); //初始化GPIOB.0和GPIOB.1
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET); //PB0置0
SPI3_Init();
}
void pcf2126_write_read(u8 rw,u8 addr,u8 *buf,u8 len)
{
u8 temp=rw,i;
temp<<=7;
temp|=(1<<5);
temp|=addr;
pcf2129_cs_clr();
SPI3_ReadWriteByte(temp);
for(i=0;i<len;i++)
{
buf[i] = SPI3_ReadWriteByte(buf[i]);
}
pcf2129_cs_set();
}
void pcf2129_set_time(CalendarObj *calendar)
{
u8 tempBuf[7];
tempBuf[0]=HEX_TO_BCD(calendar->second);
tempBuf[1]=HEX_TO_BCD(calendar->minute);
tempBuf[2]=HEX_TO_BCD(calendar->hour);
tempBuf[3]=HEX_TO_BCD(calendar->day);
tempBuf[4]=HEX_TO_BCD(calendar->week);
tempBuf[5]=HEX_TO_BCD(calendar->month);
tempBuf[6]=HEX_TO_BCD(calendar->year-BASE_YAER);
pcf2126_write_read(PCF2129_W,PCF2129_SECOND,tempBuf,sizeof(tempBuf));
}
void pcf2129_get_time(CalendarObj *calendar)
{
u8 tempBuf[7];
pcf2126_write_read(PCF2129_R,PCF2129_SECOND,tempBuf,sizeof(tempBuf));
calendar->year=BASE_YAER+BCD_TO_HEX(tempBuf[6]);
calendar->month=BCD_TO_HEX(tempBuf[5]);
calendar->week=BCD_TO_HEX(tempBuf[4]);
calendar->day=BCD_TO_HEX(tempBuf[3]);
calendar->hour=BCD_TO_HEX(tempBuf[2]);
calendar->minute=BCD_TO_HEX(tempBuf[1]);
calendar->second=BCD_TO_HEX(tempBuf[0]);
}
main.c
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "mpu.h"
#include "pcf2129.h"
int main(void)
{
CalendarObj calendar;
Cache_Enable(); //打开L1-Cache
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(160,5,2,4); //设置时钟,400Mhz
delay_init(400); //延时初始化
uart_init(115200); //串口初始化
led_init(); //初始化LED时钟
MPU_Memory_Protection(); //保护相关存储区域
pcf2129_init();
// calendar.year=2021;
// calendar.month=6;
// calendar.week=5;
// calendar.day=18;
//
// calendar.hour=15;
// calendar.minute=22;
// calendar.second=0;
//
// pcf2129_set_time(&calendar);
while(1)
{
pcf2129_get_time(&calendar);
printf("%d-%d-%d %d:%d:%d %d\r\n",calendar.year,calendar.month,calendar.day,calendar.hour,calendar.minute,calendar.second,calendar.week);
turn_g_led();
delay_ms(1000);
}
}
三、完整工程下载