中科因仑“3+1”工程特种兵精英论坛
标题:
基于AVR16的PCF8563时钟程序-I2C读写
[打印本页]
作者:
lxe
时间:
2014-8-16 12:01
标题:
基于AVR16的PCF8563时钟程序-I2C读写
#include <iom16v.h>
#include <macros.h>
#define uchar unsigned char
#define uint unsigned int
/***********I2C(TWI)基本指令*************/
#define I2C_START() TWCR = BIT(TWINT)|BIT(TWEN)|BIT(TWSTA) //TWI中断标志位,TWI允许位,TWI起始信号状态位
#define I2C_STOP() TWCR = BIT(TWINT)|BIT(TWEN)|BIT(TWSTO) //TWI中断标志位,TWI允许位,TWI停止信号状态位
#define I2C_ACK() TWCR = BIT(TWINT)|BIT(TWEN)|BIT(TWEA) //TWI中断标志位,TWI允许位,TWI应答(ACK)允许位
#define I2C_NAK() TWCR = BIT(TWINT)|BIT(TWEN) //TWI中断标志位,TWI允许位
#define I2C_CHECK_STATUS(X) {while(!(TWCR&BIT(TWINT))); if((TWSR&0xF8)!=(X)) return 0;}
//等待TWI完成当前工作,判断状态寄存器当前状态(即屏蔽低3位)
#define I2C_WRITE(X) TWDR = (X) //I2C写入数据
#define I2C_READ(X) (X) = TWDR //I2C读取数据
/***********TWSR&0xF8 状态码************/
#define START 0x08
#define RE_START 0x10
#define MT_SLA_ACK 0x18
#define MT_SLA_NAK 0x20
#define MT_DATA_ACK 0x28
#define MT_DATA_NAK 0x30 //用于检测I2C当前通信状态
#define SLA_DATA_FAIL 0x38
#define MR_SLA_ACK 0x40
#define MR_SLA_NAK 0x48
#define MR_DATA_ACK 0x50
#define MR_DATA_NAK 0x58
/**********PCF8563器件地址及参数**********/
#define SLA_R_PCF8563 0xA3 //PCF8563时钟芯片读地址
#define SLA_W_PCF8563 0xA2 //PCF8563时钟芯片写地址
#define PAGE_SIZE_PCF8563 16 //PCF8563时钟芯片页容量大小
#define NUM_PAGE_PCF8563 1 //PCF8563时钟芯片页数
uchar seg[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40}; //断码表
uchar table[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //位码表
uchar buf[]={0,0,0,0,0,0,0,0}; //数据缓存区
uchar buffer[]={0,0,0,0,0,0,0,0}; //数据缓存区
/************************************************************************
函数名称:void delay_ms(uint x)
函数功能:1ms延时子程序
输入参数:uint t
返回参数:无
************************************************************************/
void delay_ms(uint t)
{
uint i,j;
for(j=0;j<t;j++)
for(i=0;i<1141;i++);
}
/************************************************************************
函数名称:void delay(uint x)
函数功能:1us延时子程序
输入参数:uint t
返回参数:无
************************************************************************/
void delay(uint t)
{
uint j;
for(j=0;j<t;j++)
;
}
/************************************************************************
函数名称: uchar I2C_Write_n_Bytes(uchar SLA_W, uint ADDR,uint N, uchar *DAT)
函数功能: I2C主机写N字节数据到从器件
输入参数:uchar SLA_W, uint ADDR,uint N, uchar *DAT
返回参数:1
参数说明:
SLA_W: 从器件写地址
ADDR: 从器件内部起始地址写数据
N: 写数据字节数
DAT: 源数据起始地址
************************************************************************/
uchar I2C_Write_n_Bytes(uchar SLA_W, uint ADDR,uint N, uchar *DAT)
{
uint i;
I2C_START(); //启动I2C通信
I2C_CHECK_STATUS(START); //检测I2C状态
I2C_WRITE(SLA_W); //I2C写入地址数据
I2C_NAK();
I2C_CHECK_STATUS(MT_SLA_ACK);
if(SLA_W!=SLA_W_PCF8563)
{
I2C_WRITE((uchar)ADDR>>8);
I2C_NAK();
I2C_CHECK_STATUS(MT_DATA_ACK);
}
I2C_WRITE((uchar)ADDR);
I2C_NAK();
I2C_CHECK_STATUS(MT_DATA_ACK);
/**********写入N个数据***********/
for(i=0;i<N;i++)
{
I2C_WRITE(DAT[i]);
I2C_NAK();
I2C_CHECK_STATUS(MT_DATA_ACK);
}
I2C_STOP(); //I2C通信结束
return 1;
}
/************************************************************************
函数名称: uchar I2C_Read_n_Bytes(uchar SLA_R, uint ADDR,uint N, uchar *DAT)
函数功能: I2C主机读N字节数据到从器件
输入参数:uchar SLA_R, uint ADDR,uint N, uchar *DAT
返回参数:1
参数说明:
SLA_R: 从器件读地址
ADDR: 从器件内部起始地址读数据
N: 读数据字节数
DAT: 源数据起始地址
************************************************************************/
uchar I2C_Read_n_Bytes(uchar SLA_R, uint ADDR,uint N, uchar *DAT)
{
uint i;
I2C_START();
I2C_CHECK_STATUS(START);
I2C_WRITE((SLA_R)-1);
I2C_NAK();
I2C_CHECK_STATUS(MT_SLA_ACK);
if(SLA_R!=SLA_R_PCF8563)
{
I2C_WRITE((uchar)ADDR>>8);
I2C_NAK();
I2C_CHECK_STATUS(MT_DATA_ACK);
}
I2C_WRITE((uchar)ADDR);
I2C_NAK();
I2C_CHECK_STATUS(MT_DATA_ACK);
I2C_START();
I2C_CHECK_STATUS(RE_START);
I2C_WRITE(SLA_R);
I2C_NAK();
I2C_CHECK_STATUS(MR_SLA_ACK);
if(N>1)
{
for(i=0;i<N-1;i++)
{
I2C_ACK();
I2C_CHECK_STATUS(MR_DATA_ACK);
I2C_READ(DAT[i]);
}
}
I2C_NAK();
I2C_CHECK_STATUS(MR_DATA_NAK);
DAT[N-1]=TWDR;
I2C_STOP();
return 1;
}
/************************************************************************
函数名称: void PCF8563_stop(void)
函数功能: 关闭PCF8563
输入参数:无
返回参数:无
************************************************************************/
void PCF8563_stop(void)
{
uchar stopcode=0x20;
I2C_Write_n_Bytes(SLA_W_PCF8563,0,1,&stopcode);
}
/************************************************************************
函数名称: void PCF8563_start(void)
函数功能: 启动PCF8563
输入参数:无
返回参数:无
************************************************************************/
void PCF8563_start(void)
{
uchar startcode=0x00;
I2C_Write_n_Bytes(SLA_W_PCF8563,0,1,&startcode);
}
复制代码
作者:
lxe
时间:
2014-8-16 12:02
本帖最后由 lxe 于 2014-8-16 12:04 编辑
/************************************************************************
函数名称: void PCF8563_set(uchar year,uchar month,uchar day,uchar week,uchar hour,uchar minute,uchar second)
函数功能: PCF8563时钟设置
输入参数:
返回参数:无
参数说明:(BCD码)
year: 年(0x00到0x99)
month: 月(0x01到0x12)
day: 日(0x01到0x31)
hour: 时(0x00到0x23)
minute: 分(0x00到0x59)
second: 秒(0x00到0x59)
week: 星期(0x01到0x07)(非BCD码)
************************************************************************/
void PCF8563_set(uchar year,uchar month,uchar day,uchar week,uchar hour,uchar minute,uchar second)
{
uchar time[7];
time[6] = year; //年
time[5] = month; //月
time[4] = week; //星期
time[3] = day; //日
time[2] = hour; //时
time[1] = minute; //分
time[0] = second; //秒
PCF8563_stop(); //关闭PCF8563
I2C_Write_n_Bytes(SLA_W_PCF8563,2,7,time); //通过I2C向PCF8563写入设定的时间
PCF8563_start(); //启动PCF8563
}
/************************************************************************
函数名称: void PCF8563_read(uchar *time)
函数功能: PCF8563时钟读取
输入参数:uchar *time
返回参数:无
参数说明:
time: 存放读出时间的数组名
time[6]: 年(0x00到0x99)
time[5]: 月(0x01到0x12)
time[3]: 日(0x01到0x31)
time[2]: 时(0x00到0x23)
time[1]: 分(0x00到0x59)
time[0]: 秒(0x00到0x59)
time[4]: 星期(0x01到0x07)
************************************************************************/
void PCF8563_read(uchar *time)
{
uchar second = 0,minute = 0,hour = 0,day = 0,month = 0,year = 0;
I2C_Read_n_Bytes(SLA_R_PCF8563,2,7,time);
time[6] &= 0x7F; //年
time[5] &= 0x1F; //月
time[4] &= 0x07; //星期
time[3] &= 0x3F; //日
time[2] &= 0x3F; //时
time[1] &= 0x7F; //分
time[0] &= 0x7F; //秒
second = (time[0]/16)*10+(time[0]%16); //将BCD码的秒转换成10进制
minute = (time[1]/16)*10+(time[1]%16); //将BCD码的分转换成10进制
hour = (time[2]/16)*10+(time[2]%16); //将BCD码的时转换成10进制
day = (time[3]/16)*10+(time[3]%16); //将BCD码的日转换成10进制
month = (time[5]/16)*10+(time[5]%16); //将BCD码的月转换成10进制
year = (time[6]/16)*10+(time[6]%16); //将BCD码的年转换成10进制
buf[7] = second % 10; //取秒个位
buf[6] = second / 10; //取秒十位
buf[5] = 10; //显示间隔符-
buf[4] = minute%10; //取分个位
buf[3] = minute/10; //取分十位
buf[2] = 10; //显示间隔符-
buf[1] = hour%10; //取时个位
buf[0] = hour/10; //取时十位
buffer[7] = day % 10;
buffer[6] = day / 10;
buffer[5] = month % 10;
buffer[4] = month / 10;
buffer[3] = year % 10;
buffer[2] = year / 10;
buffer[1] = 20 % 10;
buffer[0] = 20 / 10;
}
/************************************************************************
函数名称:void main(void)
函数功能:主函数
输入参数:无
返回参数:无
************************************************************************/
void main(void)
{
uchar dat[132];
uint i=0,k=0;
DDRA = 0xff;
PORTA =0xff;
DDRB = 0xff;
PORTB =0xff;
DDRC &= ~(BIT(PC0) | BIT(PC1)); //初始仳SCL,SDA引脚
PORTC |= BIT(PC0)|BIT(PC1);
TWCR=0; //初始化I2C
TWBR=12; //set bit rate TWBR应大于10
TWSR=0; //set prescale
PCF8563_set(0x14,0x08,0x16,0x01,0x11,0x25,0x45); //写入时间
while(1)
{
PCF8563_read(dat);
if(k<50)
for(i=0;i<8;i++)
{
PORTB=~table[i];
PORTA=seg[buf[i]];
delay(500);
}
if(k>=50)
for(i=0;i<8;i++)
{
PORTB=~table[i];
if(i==3||i==5)
{
PORTA=(seg[buffer[i]] | 0x80);
}
else
{
PORTA=seg[buffer[i]];
}
delay(500);
}
if(++k>70)k=0;
}
}
复制代码
作者:
lucky80204
时间:
2014-8-16 16:54
楼主给力啊,32个赞
作者:
杨玉玺
时间:
2014-8-17 15:19
太牛了,我看移植是太困难了
作者:
lxe
时间:
2014-8-18 11:17
杨玉玺 发表于 2014-8-17 15:19
太牛了,我看移植是太困难了
不用移植的。。51的程序有好多
欢迎光临 中科因仑“3+1”工程特种兵精英论坛 (http://bbs.enlern.com/)
Powered by Discuz! X3.4