这是用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); //打开输出脉冲
}