爱玩科技网
您的当前位置:首页STM32对时钟芯片PCF8563的编程

STM32对时钟芯片PCF8563的编程

来源:爱玩科技网


这是用STM32对PCF8563编程的程序、模拟IIC,经验证可用~

移植用到的文件:IIC.h IIC.c PCF8563.h PCF8563.c ,我把它们全都复制到了这个Word文档里。

使用要初始化的函数:void PCF8563_Init(void). 就唯一这个。

全局变量: u8 PCF8563_Time[7]; 程序初始的值是给PCF8563设置的时间,程序中读取返回的值是PCF8563当时的时间。

我这里使用的IIC的 SCL,SDA的引脚分别为PA.0 PA.1, 具体看IIC.h 和 IIC.C。 只要修改好两个引脚的初始化配套你手上的板子这,就能成功移植~

Delay_nus(20):这是一个延迟20us的函数。

IIC.h:

#ifndef _IIC_H_

#define _IIC_H_

#include \"stm32f10x.h\"

/* Private typedef -----------------------------------------------------------*/

/* Private define ------------------------------------------------------------*/

/*#define I2C_Speed 100000

#define I2C1_SLAVE_ADDRESS7 0xA0

#define I2C_PageSize 256 */

//SCL PA0

//SDA PA1

#define SCL_H() GPIO_SetBits(GPIOA, GPIO_Pin_0)

#define SCL_L() GPIO_ResetBits(GPIOA, GPIO_Pin_0)

#define SDA_H() GPIO_SetBits(GPIOA, GPIO_Pin_1)

#define SDA_L() GPIO_ResetBits(GPIOA, GPIO_Pin_1)

//返回0,和1

#define Read_SDA() GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1)

u8 IIC_ReadByte(void);

void IIC_WriteByte(u8 byte);

void IIC_WaitAck(void);

void IIC_Stop(void);

void IIC_Start(void);

void IIC_Init(void);

void I2C_Ack(void);

void I2C_NoAck(void);

//取回八个字节的数据:秒,分,时,天,星期,月份,年份。

#endif

IIC.c:

#include \"IIC.h\"

#include \"delay.h\"

/**/

void IIC_Init(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

/* Configure I2C1 pins: SCL and SDA */

RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOA, ENABLE);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; //开漏输出,可以在不用改变成输入的情况下读取IO的电平

GPIO_Init(GPIOA, &GPIO_InitStructure);

SCL_H(); //拉高

SDA_H();

}

void IIC_Start(void)

{

/* SDA_H();

SCL_H();

delay_nus(20);

SDA_L();

delay_nus(20);

*/

SDA_H();

SCL_H();

delay_nus(20);

SDA_L();

delay_nus(20);

SDA_L();

delay_nus(20);

}

void IIC_Stop(void)

{

SCL_L(); //1

delay_nus(20); // 2

SDA_L(); // 3. 1,2,3这三行不可缺少

delay_nus(20);

SCL_H();

delay_nus(20);

SDA_H();

delay_nus(20);

}

void IIC_WaitAck(void)

{

u16 k;

SCL_L();

SDA_H();

delay_nus(20);

SCL_H();

k = 0;

while((Read_SDA()!= 0) && (k < 60000))k++;

delay_nus(20);

SCL_L();

delay_nus(20);

}

void IIC_WriteByte(u8 byte)

{

u8 i = 0;

for(i = 0; i < 8; i++)

{

SCL_L();

delay_nus(20);

if(byte & 0x80)

{

SDA_H();

}

else

{

SDA_L();

}

delay_nus(20);

SCL_H();

delay_nus(20);

byte<<=1;

}

SCL_L();

delay_nus(20);

}

u8 IIC_ReadByte(void)

{

u8 i,ReadByte;

SDA_H();

for(i = 0; i < 8; i++)

{

ReadByte <<= 1;

SCL_L();

delay_nus(20);

SCL_H();

delay_nus(20);

if(Read_SDA())

{

ReadByte |= 0x01;

}

else

{

ReadByte &= ~(0x01);

}

}

return ReadByte;

}

void I2C_Ack(void)

{

SCL_L();

delay_nus(20);

SDA_L();

delay_nus(20);

SCL_H();

delay_nus(20);

SCL_L();

delay_nus(20);

}

void I2C_NoAck(void)

{

SCL_L();

delay_nus(20);

SDA_H();

delay_nus(20);

SCL_H();

delay_nus(20);

SCL_L();

delay_nus(20);

}

PCF8563.h:

#ifndef _PCF8563_H_

#define _PCF8563_H_

#include \"IIC.h\"

#define ReadCode 0xa3

#define WriteCode 0xa2

void PCF8563_Init(void);

u8 PCF8563_ReaDAdress(u8 Adress);

void PCF8563_WriteAdress(u8 Adress, u8 DataTX);

//取回7个字节的数据:秒,分,时,天,星期,月份,年份。

//全局变量

extern u8 PCF8563_Time[7];

void PCF8563_ReadTimes(void);

//在CLKOUT上定时1S输出一个下降沿脉冲

void PCF8563_CLKOUT_1s(void);

#endif

PCF8563.c:

#include \"PCF8563.h\"

//全局变量,程序初始的值就是要初始化的时间,

//用途:1:初始化时间。2:读取返回时间

// 秒,分,时,天,星期,月份,年份。

u8 PCF8563_Time[7] = {50, 59, 23, 31, 6, 12, 12};

void PCF8563_Init(void)

{

IIC_Init();

//十进制码转换成BCD码

PCF8563_Time[0] = ((PCF8563_Time[0]/10) << 4) | (PCF8563_Time[0]%10);

PCF8563_Time[1] = ((PCF8563_Time[1]/10) << 4) | (PCF8563_Time[1]%10);

PCF8563_Time[2] = ((PCF8563_Time[2]/10) << 4) | (PCF8563_Time[2]%10);

PCF8563_Time[3] = ((PCF8563_Time[3]/10) << 4) | (PCF8563_Time[3]%10);

// PCF8563_Time[4] = ((PCF8563_Time[4]/10 << 4)) | (PCF8563_Time[4]%10);

//星期不用转换

PCF8563_Time[5] = ((PCF8563_Time[5]/10 << 4)) | (PCF8563_Time[5]%10);

PCF8563_Time[6] = ((PCF8563_Time[6]/10 << 4)) | (PCF8563_Time[6]%10);

PCF8563_CLKOUT_1s();

PCF8563_WriteAdress(0x00, 0x20); //禁止RTC source clock

//初始化PCF8563的时间

PCF8563_WriteAdress(0x02, PCF8563_Time[0]);

PCF8563_WriteAdress(0x03, PCF8563_Time[1]);

PCF8563_WriteAdress(0x04, PCF8563_Time[2]);

PCF8563_WriteAdress(0x05, PCF8563_Time[3]);

PCF8563_WriteAdress(0x06, PCF8563_Time[4]);

PCF8563_WriteAdress(0x07, PCF8563_Time[5]);

PCF8563_WriteAdress(0x08, PCF8563_Time[6]);

PCF8563_WriteAdress(0x00, 0x00); //Enable RTC sorce clock

}

u8 PCF8563_ReaDAdress(u8 Adress)

{

u8 ReadData;

IIC_Start();

IIC_WriteByte(0xa2);

IIC_WaitAck();

IIC_WriteByte(Adress);

IIC_WaitAck();

IIC_Start();

IIC_WriteByte(0xa3);

IIC_WaitAck();

ReadData = IIC_ReadByte();

IIC_Stop();

return ReadData;

}

void PCF8563_WriteAdress(u8 Adress,u8 DataTX)

{

IIC_Start();

IIC_WriteByte(0xa2);

IIC_WaitAck();

IIC_WriteByte(Adress);

IIC_WaitAck();

IIC_WriteByte(DataTX);

IIC_WaitAck();

IIC_Stop();

}

//取回八个字节的数据:秒,分,时,天,星期,月份,年份。

void PCF8563_ReadTimes(void)

{

IIC_Start();

IIC_WriteByte(0xa2);

IIC_WaitAck();

IIC_WriteByte(0x02);

IIC_WaitAck();

IIC_Start();

IIC_WriteByte(0xa3);

IIC_WaitAck();

PCF8563_Time[0] = IIC_ReadByte()&0x7f;

I2C_Ack();

PCF8563_Time[1] = IIC_ReadByte()&0x7f;

I2C_Ack();

PCF8563_Time[2] = IIC_ReadByte()&0x3f;

I2C_Ack();

PCF8563_Time[3] = IIC_ReadByte()&0x3f;

I2C_Ack();

PCF8563_Time[4] = IIC_ReadByte()&0x07;

I2C_Ack();

PCF8563_Time[5] = IIC_ReadByte()&0x1f;

I2C_Ack();

PCF8563_Time[6] = IIC_ReadByte();

I2C_NoAck();

IIC_Stop();

PCF8563_Time[0] (PCF8563_Time[0]&0x0f);

PCF8563_Time[1] (PCF8563_Time[1]&0x0f);

PCF8563_Time[2] (PCF8563_Time[2]&0x0f);

PCF8563_Time[3] (PCF8563_Time[3]&0x0f);

PCF8563_Time[4] (PCF8563_Time[4]&0x0f);

PCF8563_Time[5] (PCF8563_Time[5]&0x0f);

PCF8563_Time[6] (PCF8563_Time[6]&0x0f);

}

= ((PCF8563_Time[0]&0xf0)>>4)*10 = ((PCF8563_Time[1]&0xf0)>>4)*10 = ((PCF8563_Time[2]&0xf0)>>4)*10 = ((PCF8563_Time[3]&0xf0)>>4)*10 = ((PCF8563_Time[4]&0xf0)>>4)*10 = ((PCF8563_Time[5]&0xf0)>>4)*10 = ((PCF8563_Time[6]&0xf0)>>4)*10 +

+

+

+

+

+

+

//在CLKOUT上定时1S输出一个下降沿脉冲,经过验证,可以设置STM32的GPIO上拉输入,设置成下降沿中断,单片机每过1S产生一次中断

void PCF8563_CLKOUT_1s(void)

{

PCF8563_WriteAdress(0x01, 0); //禁止定时器输出,闹铃输出

PCF8563_WriteAdress(0x0e, 0); //关闭定时器等等

// PCF8563_WriteAdress(0x0e, 0); //写入1

PCF8563_WriteAdress(0x0d, 0x83); //打开输出脉冲

}

因篇幅问题不能全部显示,请点此查看更多更全内容