1 PCF8563芯片
可以看出,PCF8563芯片一共有16个寄存器。也就是该芯片的内部地址最大为0x0f。上述的16个寄存器除了作为普通的存储功能外,还具备授时功能。
2 实现过程
2.1 电路图
2.2 源代码
/*---------------------函数功能:
IIC总线 + PCF8563(内部只有16个地址空间
PCF8563芯片一共有16个寄存器。也就是该芯片的内部地址最大为0x0f。
上述的16个寄存器除了作为普通的存储功能外,还具备授时功能。
-----------------------------------------*/
#include<pic.h>// 调用PIC16f87XA单片机的头文件
#include"delay.h"//调用延时子函数的头文件
__CONFIG(0xFF32);//芯片配置字,看门狗关,上电延时开,掉电检测关,低压编程关
//__CONFIG(HS&WDTDIS&LVPDIS);
/*-----------宏定义--------------*/
#define uint unsigned int
#define uchar unsigned char
#define SDA RC6 // IIC的数据线
#define SCL RC5 // IIC的时钟线
/*-----------子函数声明--------------*/
void IIC_start(void); // IIC启动信号函数
void IIC_end(void); // IIC终止信号函数
void write_1Byte(uchar buf);//向IIC总线写一个字节的函数
char read_1Byte(); //从IIC总线读一个字节的函数
void write_PCF8563(char address,char databuf); //向AT24C02芯片的指定地址写一个字节的数据
char read_PCF8563(char address); //从AT24C02芯片的指定地址读一个字节的数据
/*-----------主函数--------------*/
void main()
{
char bufdata;
// data direction register is TRISA.
// Setting a TRISA bit (= 1) will make the corresponding PORTA pi an input.
// Clearing a TRISA bit (= 0) will make the corresponding PORTA pin an output.
TRISD=0x00; //RD作为输出口,作为LED灯的显示
//TRISC=0B10011111;
PORTD=0x00; //LED的初值为0
//PORTC=0X00;
delay_xms(100);
while(1)
{
bufdata=read_PCF8563(0x00);// 从PCF8563中地址0x00读出数据
PORTD=bufdata;
delay_xms(100);
bufdata=bufdata+1+0xaa;
PORTD=bufdata;
delay_xms(100);
write_PCF8563(0x00,bufdata);//将+1的数据保存在0x00中
}
}
/*************IIC启动信号函数***************/
void IIC_start(void)
{
//为什么这样写,见IIC的时序图
SDA=1;
SCL=1;
asm("NOP");
asm("NOP");
SDA=0;
asm("NOP");
asm("NOP");
SCL=0;
asm("NOP");
asm("NOP");
}
/*************IIC终止信号函数***************/
void IIC_end(void)
{
SDA=0;
SCL=0;
asm("NOP");
asm("NOP");
SCL=1;
asm("NOP");
asm("NOP");
SDA=1;
asm("NOP");
asm("NOP");
SCL=0;//拉低
asm("NOP");
asm("NOP");
}
/*************向IIC总线写一个字节(8 bit)的函数***************/
void write_1Byte(uchar buf)
{
int k=0;
for(k=0;k<8;k++)
{
//将最高位写到SDA总线上去
//SDA=buf&0x80; // 等价于下面的if语句
if(buf&0x80) // 提取buf的最高位数据
SDA=1; //如果buf的最高位为1,就写1
else
SDA=0; //如果buf的最高位为0,就写0
asm("NOP");
asm("NOP");
SCL=1;
asm("NOP");
SCL=0; //时钟信号归零
asm("NOP");
buf=buf<<1; //左移一位,准备提取下一个待写的数据
}
// 每接收到一个字节的数据后,从机必须产生一个应答信号给主机。
// 应答器件在第9个时钟周期将SDA线拉低,表示已经接收了一个八位数据
TRISC4=1; //RC4作为输入,SDA引脚接的是RC4口 开始读数据,读SDA的值
asm("NOP");
SCL=1;
asm("NOP");
asm("NOP");
//if(RC4=0) //说明SDA=0,即成功接收
SCL=0;
TRISC4=0;
}
/*************向IIC总线读一个字节(8 bit)的函数***************/
char read_1Byte()
{
int k=0;
char t_byte=0x00;
TRISC4=1; //RC4作为输入,SDA引脚接的是RC4口 开始读数据,读SDA的值
for(k=0;k<8;k++)
{
t_byte=t_byte<<1; //左移一位
SCL=1;
asm("NOP");
asm("NOP");
//读 SDA的值
if(SDA=1)
t_byte=t_byte|0x01;//写1 只对最低位有影响
else
t_byte=t_byte&0xfe;//写0
SCL=0;
asm("NOP");
asm("NOP");
}
TRISC4=0;
return t_byte; // 返回的是一个字节 eg:0x3f
}
/*************向PCF8563芯片的指定地址写一个字节的数据***************/
void write_PCF8563(char address,char databuf)
{
IIC_start(); //发送起始信号
//PCF8563芯片寄存器: 1010 A2 A1 A0 R/W_n AT24C02芯片的高四位固定为1010
// A2A1A0:从机选择,一共可以接八个AT24C02芯片。 A2A1A0=000,选择第一个芯片。 R/W_n:读/写
// I2C-bus slave address: read A3h and write A2h
write_1Byte(0xa2); //表示写
//指定该器件内部的某一个地址(确定芯片内部地址)
write_1Byte(address); //指定该芯片内部的某一个地址(一共有16个地址)
//向该芯片的指定地址里面写数据
write_1Byte(databuf); //向指定地址发送数据
IIC_end(); //发送结束信号
}
/*************从PCF8563芯片的指定地址读一个字节的数据***************/
char read_PCF8563(char address)
{
char buf;
// PCF8563芯片寄存器: 1010 A2 A1 A0 R/W_n PCF8563芯片的高四位固定为1010
// A2A1A0:从机选择,一共可以接八个PCF8563芯片。 A2A1A0=000,选择第一个芯片。 R/W_n:读/写
IIC_start(); //发送起始信号
// I2C-bus slave address: read A3h and write A2h
write_1Byte(0xa2); //表示写
//指定该器件内部的某一个地址(确定芯片内部地址)
write_1Byte(address); //指定该芯片内部的某一个地址(一共有256个地址)
//在传输过程中,当需要改变传送方向时(写<->读),起始信号IIC_start()和从机地址write_1Byte(0xa1)都被重复产生一次
//由于写变成读,所以需要下面两条指令
IIC_start(); //再次启动
// I2C-bus slave address: read A3h and write A2h
write_1Byte(0xa3); //表示读
//读出该芯片指定地址的数据
buf=read_1Byte();
IIC_end(); //发送结束信号
return buf; // 返回的是一个字节 eg:0x3f
}
|