#include <util/delay.h>
#include <stdio.h>
#include <avr/interrupt.h>//ISR(BADISR_vect){ //服务程序}
#include<1602_PADATA_PB13CON.h>//LCD1602驱动
//#include<ws_iic_port.h>//IIC的驱动
#include<ws_iic.h>
/////////////////////sssssssssssssssssssssssssssssssssssssss///////////////////////////////////////////////////////////////////////////
//若有 这样的错误 c:/avr/winavr/lib/gcc/../../avr/include/util/delay.h:85:3: warning: #warning "F_CPU not defined for <util/delay.h>"
//一定要定义:在PROJECT===》CONFIGURATION OPTIONS===>GENNRAL===》Frequency===》填写你晶体的频率,就这样,你的问题就可以解决掉了。
//#define _pcf8563_ 4
#define uchar unsigned char
#define uint unsigned int
uchar line1[11]={0,0,'-',0,0,'-',0,0,'w','0'}//显示年月日和星期;放一个空字符。可能是lcd写字符串函数存在问题
uchar line2[9]={0,0,'-',0,0,'-',0,0}//小时,分,秒
//PCF8563的时间存储为 秒-分-小时-日-星期-月/世纪-年7个字节
uchar set_time[7]={56,59,9,27,4,128+7,11}//这些是十进制,使用时要转为bcd码
uchar get_time[7]//读出为bcd码,使用时转为十进制
volatile uchar int_time//设置报警中断的次数
//PCF 8563 iic总线,INTA低电平有效,32.768KHz 的振荡
//16 个寄存器设计成可寻址的8 位并行寄存器但不是所有位都有用前两个寄存器内存地址00H 01H 用于控制寄存器和状态寄存器内存地址02H 08H 用于时钟计数器秒~年计数器地址
//09H 0CH 用于报警寄存器定义报警条件地址0DH 控制CLKOUT 管脚的输出频率地址0EH 和0FH分别用于定时器控制寄存器和定时器寄存器秒分钟小时日月年分钟报警小时报警日报
//警寄存器编码格式为BCD 星期和星期报警寄存器不以BCD 格式编码
/*
400kHz I2C 总线(VDD=1.8 5.5V) 其从地址读0A3H写0A2H
//地址 寄存器名称 Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
00H 控制/状态寄存器1 TEST1 0 STOP 0 TESTC 0 0 0 .1)TEST1=0 普通模式TEST1=1 EXT_CLK 测试模式2)STOP=0 芯片时钟运行STOP=1 所有芯片分频器异步置逻辑
0 芯片时钟停止运行CLKOUT 在32.768kHz 时可用3)TESTC=0 电源复位功能失效普通模式时置逻辑0
TESTC=1 电源复位功能有效4)位6,4,2,1,0 缺省值置逻辑0
01H 控制/状态寄存器2 0 0 0 TI/TP AF TF AIE TIE
AF 和AIE 都有效时则INT 一直有效;
当报警发生时AF 被置逻辑1 在定时器倒计数结束时TF 被置逻辑1
AIE=0 报警中断无效AIE=1 报警中断有效
TIE=0 定时器中断无效TIE=1 定时器中断有效
0DH CLKOUT 输出寄存器 FE ·····FD1 FD0
0EH 定时器控制寄存器 TE ·····TD1 TD0
0FH 定时器倒计数数值寄存器 定时器倒计数数值(二进制)
02h 秒 VL 00 -59 BCD 码格式数 VL=0 保证准确的时钟/日历数据VL=1 不保证准确的时钟/日历数据
03h 分钟 00 -59 BCD 码格式数
04h 小时 00 -59 BCD 码格式数
05h 日 01- 31 BCD 码格式数
06h 星期 0- 6
07h 月/世纪 C 01 -12 BCD 码格式数
08h 年 00- 99 BCD 码格式数
09h 分钟报警 AE 00 -59 BCD 码格式数
0Ah 小时报警 AE 00 -23 BCD 码格式数
0BH 日报警 AE 01- 31 BCD 码格式数
0CH 星期报警 AE 0- 6
*/
/*
atmega16中,IIC 的SCL, SDA端口可以设置上拉电阻,这样可节约外部上拉电阻。
SCL frequency= CPU Clock frequency/(16 + 2(TWBR) . 4^TWPS)
TWI 工作在主机模式时,TWBR 值应该不小于10。否则主机会在SDA 与 SCL 产生错误输出作为提示信号。问题出现于TWI 工作在主机模式下,向从机发送Start + SLA + R/W 的
时候( 不需要真的有从机与总线连接)。
*/
//器件地址:A0 A1 A2 = 0 0 0
#define WR_SLA8563_ADDR 0xA2 //write device-address
#define RD_SLA8563_ADDR 0xA3 //read device-address
//以下为控制器寄存器地址
//以下为二进制存储
#define CTRL_BUF1 0x00
#define CTRL_BUF2 0x01
//以下为BCD 存储
#define SECOND_DATA_BUF 0x02
#define MINUTE_DATA_BUF 0x03
#define HOUR_DATA_BUF 0x04
#define DAY_DATA_BUF 0x05
#define WEEK_DATA_BUF 0x06
#define MONTH_DATA_BUF 0x07
#define YEAR_DATA_BUF 0x08
#define MINUTE_AE_BUF 0x09
#define HOUR_AE_BUF 0x0A
#define DAY_AE_BUF 0x0B
#define WEEK_AE_BUF 0x0C
//以下为二进制存储
#define CLK_FRQ_BUF 0x0D //80-37.768kHz81--1024Hz82--32Hz83--1Hz
#define TIMER_CTRL_BUF 0x0E
#define COUNT_VAL_BUF 0x0F
#define PCF8563_ERR 0
#define PCF8563_CRR 1
//十进制转BCD码,即高位取出来后左移4位,低位取出不变
//BCD码这种编码形式利用了四个位元来储存一个十进制的数码
#define Int_To_BCD(dec) (((dec/10)<<4)+dec%10) //PCF8563的时间以及报警设置都是BCDB码 32(DEC)-->32(BCD)
#define BCD_To_Int(bcd) ((bcd>>4)*10+(bcd&0x0f)) //高位乘10,低位不变
//写一个数据
uchar Write_Abyte(uchar Addr,uchar data)
{
//判断写地址是否成功,成功返回1,否者范围0
if ((I2C_Write(WR_SLA8563_ADDR,Addr,data))==PCF8563_ERR)
return PCF8563_ERR
return PCF8563_CRR
}
//设置小时,分,秒
void Set_time_HSS(uchar hour,uchar minute,uchar second)
{
hour=Int_To_BCD(hour)
minute=Int_To_BCD(minute)
second=Int_To_BCD(second)
Write_Abyte(HOUR_DATA_BUF,hour)
Write_Abyte(MINUTE_DATA_BUF,minute)
Write_Abyte(SECOND_DATA_BUF,second)
}
//设置年月日
void Set_time_YMD(uchar year,uchar month,uchar day)
{
year=Int_To_BCD(year)
month=Int_To_BCD(month)
day=Int_To_BCD(day)
Write_Abyte(YEAR_DATA_BUF,year)
Write_Abyte(MONTH_DATA_BUF,month)//包含世纪
Write_Abyte(DAY_DATA_BUF,day)
}
void Set_Time_Week(uchar week)
{
week=Int_To_BCD(week)
Write_Abyte(WEEK_DATA_BUF,week )
}
//一次将数组中时间写入芯片,n应<=7.
void Set_Time_All(uchar start_adr,uchar *ptdata,uchar n)
{
uchar i,temp
for(i=0i<ni++)
{
temp=Int_To_BCD(ptdata[i])//化为bcd码
Write_Abyte(start_adr+i,temp)
}
}
//读N个数据
uchar Read_Nbyte(uchar start_addr,uchar *pRdDat,uchar num)//使用 uint8_t I2C_Read_(uint16_t wrDAdr,uint8_t wordAdr,uint8_t rdDAdr,uint8_t *pRdDat,uint8_t num)
{
if( I2C_Read_(WR_SLA8563_ADDR,start_addr,RD_SLA8563_ADDR,pRdDat,num)==I2C_ERR )
return PCF8563_ERR
return PCF8563_CRR
}
//uchar get_time(uchar start_adr,uchar *ptdata,uchar n)
//{
//}
//初始化8563的工作方式
void PCF8563_Init(void)
{
//报警设置
//CTRL_BUF1=0x00 //TEST1 0 STOP 0 TESTC 0 0 0 普通模式都置0
//CTRL_BUF2= 0x00010010 //0 0 0 TI/TP AF TF AIE TIE 报警中断有效
//这里需要将控制字内容写入,需要调用IIC的写数据 *** 作 uint8_t I2C_Write(uint16_t wrDAdr,uint8_t wordAdr,uint8_t dat) wrDAdr-->器件写地址
Write_Abyte(CTRL_BUF1,0x00)
Write_Abyte(HOUR_AE_BUF,Int_To_BCD(10) )
Write_Abyte(MINUTE_AE_BUF,Int_To_BCD(20) )
Write_Abyte(CTRL_BUF2,0x13)
}
void Disp_Time_In_LCD1602( )
{
uchar i
//第一行 年月日 周次;第二行 小时 分 秒
Read_Nbyte(SECOND_DATA_BUF, get_time,7)//一次获得所有数据
get_time[0]= get_time[0]&0x7f//秒
get_time[1]= get_time[1]&0x7f//分
get_time[2]= get_time[2]&0x3f//小时
get_time[3]= get_time[3]&0x3f//日
get_time[4]= get_time[4]&0x0f//星期
get_time[5]= get_time[5]&0x1f//月再下一个为年
for(i=0i<7i++)
{
get_time[i]=BCD_To_Int(get_time[i])//将BCD转为十进制后处理
}
//uchar line1[11]={0,0,'-',0,0,'-',0,0,'w','0'}//显示年月日和星期
line1[0]=(get_time[6]/10)|0x30//取十位数
line1[1]=(get_time[6]%10)|0x30//取个位数,其它同
line1[3]=(get_time[5]/10)|0x30//取十位数
line1[4]=(get_time[5]%10)|0x30//取个位数,其它同
line1[6]=(get_time[3]/10)|0x30//取十位数
line1[7]=(get_time[3]%10)|0x30//取个位数,其它同
line1[9]=get_time[4]|0x30//取个位数,其它同,week
//uchar line2[8]={0,0,'-',0,0,'-',0,0}//小时,分,秒
line2[0]=(get_time[2]/10)|0x30//取十位数
line2[1]=(get_time[2]%10)|0x30//取个位数,其它同
line2[3]=(get_time[1]/10)|0x30//取十位数
line2[4]=(get_time[1]%10)|0x30//取个位数,其它同
line2[6]=(get_time[0]/10)|0x30//取十位数
line2[7]= get_time[0] |0x30 //取个位数,其它同
i=LCD_Show_Num_New(0,0,20)//在年份前加入20
LCD_Str_Write(i,0,line1)
LCD_Str_Write(0,1,line2)
}
//增加中断1来设置初始时间;低电平有效
ISR(INT1_vect)
{
Set_Time_All(SECOND_DATA_BUF,set_time,7)
// Write_Abyte(CTRL_BUF2,0x1f)
}
//增加中断0来记录报警次数;低电平有效
ISR(INT0_vect)
{
int_time++
// Write_Abyte(CTRL_BUF2,0x0A)//清除中断
//Write_Abyte(HOUR_AE_BUF,Int_To_BCD(11))
}
void Interrupt_init()
{
DDRD&=~(_BV(PD2)|_BV(PD3))//2个中断口为输入口
GICR|=_BV(7)|_BV(6)//开启中断0,1
MCUCR|=_BV(3)|_BV(1) //INT1下降沿触发,INT0下降沿中断
GIFR|=_BV(7)|_BV(6)//清除中断标志
SREG|=_BV(7)//开启中断
}
int main(void)
{uchar i
TWBR = 0X0F //设置TWI波特率
TWSR &= 0XFC //设置TWI预分频 为 1
LCD_Init()
PCF8563_Init()
_delay_ms(100)
///中断设置
Interrupt_init()
// Write_Abyte(CLK_FRQ_BUF,0x81)//1024Hz的频率发生
i=LCD_Str_Write(8,1,"times")
while(1)
{
_delay_ms(100)
Disp_Time_In_LCD1602()
LCD_Show_Num_New(13,1,int_time)//显示中断次数
}
}
#include <reg52.h>#include <stdio.h>
#include <absacc.h>
#include <intrins.h>
typedef unsigned char uchar
uchar g8563_Store[4]/*时间交换区,全局变量声明*/
uchar code c8563_Store[4]={0x50,0x59,0x07,0x01}/*写入时间初值:星期一 07:59:40*/
sbit CS=P1^4
sbit CLK=P1^7
sbit DIO=P1^6
sbit KEY=P3^2
sbit SDA=P1^1 // pcf8563时钟
sbit SCL=P1^0 // pcf8563时钟
bdata uchar com_data
sbit mos_bit=com_data^7
sbit low_bit=com_data^0
void delay_50us()
{
uchar i
for (i=0i<6i++){}
}
void delay_8us()
{
uchar i
for (i=0i<1i++){}
}
void delay_50ms()
{
uchar i,j
for(j=0j<50j++)
for(i=0i<125i++){}
}
void send(uchar sebuf)
{
uchar i
com_data=sebuf
CLK=0
CS=0
delay_50us()
for(i=0i<8i++)
{
delay_8us()
DIO=mos_bit
CLK=1
delay_8us()
com_data=com_data<<1
CLK=0
}
DIO=0
}
uchar receive(void)
{
uchar i,rebuf
CLK=1
delay_50us()
for(i=0i<8i++)
{
com_data=com_data<<1
low_bit=DIO
CLK=1
delay_8us()
CLK=0
delay_8us()
}
rebuf=com_data
DIO =1
CS=1
return rebuf
}
void reset(void)
{
DIO=1
delay_50ms()
send(0xa4)
CS=1
}
/* 7289显示程序 */
/* addr为显示位置 范围0~7*/
/* dat为现实内容 */
void display(uchar addr,uchar dat)
{
if(addr<0 || addr >7)
return
send(0xc8 + addr)
delay_50us()
send(dat)
CS=1
}
/* 发送双字节命令*/
void sendcommand(uchar addr,uchar dat)
{
send(addr)
delay_50us()
send(dat)
CS=1
}
/********************************************
内部函数,延时1
********************************************/
void Delay()
{
// {P10=1_nop_()P10=0}
_nop_()
_nop_()/*根据晶振频率制定延时时间*/
}
/********************************************
内部函数,I2C开始
********************************************/
void Start()
{
EA=0
SDA=1
SCL=1
Delay()
SDA=0
Delay()
SCL=0
}
/********************************************
内部函数,I2C结束
********************************************/
void Stop()
{
SDA=0
SCL=0
Delay()
SCL=1
Delay()
SDA=1
Delay()
EA=1
}
/********************************************
内部函数,输出ACK ,每个字节传输完成,输出ack=0,结束读书据,ack=1
********************************************/
void WriteACK(uchar ack)
{
SDA=ack
Delay()
SCL=1
Delay()
SCL=0
}
/********************************************
内部函数,等待ACK
********************************************/
void WaitACK()
{
uchar errtime=20
SDA=1
Delay()/*读ACK*/
SCL=1
Delay()
while(SDA)
{ errtime--}
SCL=0
Delay()
}
/********************************************
内部函数.输出数据字节
入口:B=数据
********************************************/
void writebyte(uchar wdata)
{
uchar i
for(i=0i<8i++)
{
if(wdata&0x80) SDA=1
else SDA=0
wdata<<=1
SCL=1
Delay()
SCL=0
}
WaitACK()//I2C器件或通讯出错,将会退出I2C通讯
}
/********************************************
内部函数.输入数据
出口:B
********************************************/
uchar Readbyte()
{
uchar i,bytedata
SDA=1
for(i=0i<8i++)
{
SCL=1
bytedata<<=1
bytedata|=SDA
SCL=0
Delay()
}
return(bytedata)
}
/********************************************
输出数据->pcf8563
********************************************/
void writeData(uchar address,uchar mdata)
{
Start()
writebyte(0xa2)/*写命令*/
writebyte(address)/*写地址*/
writebyte(mdata)/*写数据*/
Stop()
}
/********************************************
输入数据<-pcf8563
********************************************/
uchar ReadData(uchar address) /*单字节*/
{
uchar rdata
Start()
writebyte(0xa2)/*写命令*/
writebyte(address)/*写地址*/
Start()
writebyte(0xa3)/*读命令*/
rdata=Readbyte()
WriteACK(1)
Stop()
return(rdata)
}
void ReadData1(uchar address,uchar count,uchar * buff) /*多字节*/
{
uchar i
Start()
writebyte(0xa2)/*写命令*/
writebyte(address)/*写地址*/
Start()
writebyte(0xa3)/*读命令*/
for(i=0i<counti++)
{
buff[i]=Readbyte()
if(i<count-1) WriteACK(0)
}
WriteACK(1)
Stop()
}
/********************************************
内部函数,读入时间到内部缓冲区
********************************************/
void P8563_Read()
{
uchar time[7]
ReadData1(0x02,0x07,time)
g8563_Store[0]=time[0]&0x7f/*秒*/
g8563_Store[1]=time[1]&0x7f/*分*/
g8563_Store[2]=time[2]&0x3f/*小时*/
g8563_Store[3]=time[4]&0x07/*星期*/
}
/********************************************
读入时间到内部缓冲区----外部调用
********************************************/
void P8563_gettime()
{
P8563_Read()
if(g8563_Store[0]==0)
P8563_Read()/*如果为秒=0,为防止时间变化,再读一次*/
}
/********************************************
写时间修改值
********************************************/
void P8563_settime()
{
uchar i
for(i=2i<=4i++) { writeData(i,g8563_Store[i-2])}
writeData(6,g8563_Store[3])
}
/********************************************
P8563的初始化-----外部调用
********************************************/
void P8563_init()
{
uchar i
for(i=0i<=3i++) g8563_Store[i]=c8563_Store[i]/*初始化时间*/
P8563_settime()
writeData(0x0,0x00)
writeData(0xa,0x8)/*8:00报警*/
writeData(0x1,0x12)/*报警有效*/
writeData(0xd,0xf0)
}
main()
{
reset()
P8563_init()
while(1)
{
P8563_Read()
display(0,g8563_Store[2] >>4)
display(1,g8563_Store[2] & 0x0f)
sendcommand(0x82,0x0a)
display(3,g8563_Store[1] >>4)
display(4,g8563_Store[1] & 0x0f)
sendcommand(0x85,0x0a)
display(6,g8563_Store[0] >>4)
display(7,g8563_Store[0] & 0x0f)
}
}
前段时间用pcf8563芯片做了个电子时钟,这个芯片自动走时间,我只用去读和写就行了,pcf8563要加一个后备电池,这样就不怕单片机掉电了。这个不太符合你的要求,不过这是我现成的,我可不想在这里重新写代码。代码不是很规范,但是能正常运行。
你在Keil里建个工程,下面一段是display.c的代码:
#include "at89x51.h"
#include "PCF8563.h"
//#include "TG12232.h"
#define Key_Set P2_2
#define Key_Add P2_1
#define Key_Sub P2_0
//#define LCD_CS P2_5
//#define LCD_DATA P2_6
//#define LCD_CLK P2_7
void Key_down()
void Displaybuffer(char Location)
//void LCD_Display()
unsigned char LedTable[10]={0x3f,0x03,0x6d,0x67,0x53,0x76,0x7e,0x23,0x7f,0x77}
bit state=0
char set=0
void main()
{
unsigned char i,j,n=2
P1=0
TMOD=0x01
TH0=0x4c
TL0=0x00
ET0=1
EA=1
// P8563_init()
P2=0xff
P3=0x02
P1=LedTable[8]
// while(n--)
for(i=0i<250i++)
for(j=0j<6j++)
{
delay(10)
P3<<=1
if(P3==0x80)
P3=0x02
delay(10)
}
delay(5000)
// lcd_init()
// set_lcd_position(0,1) //汉字定位到上行左端
// lcd_display(0,0,"Welcome to use!")
// lcd_display(1,0," Leo.Zheng ")
// delay(1000)
// lcd_send_com(0x01)//清除
// lcd_display(0,0,"20 / /")
while(1)
{
Key_down()
Displaybuffer(set)
// LCD_Display()
}
}
void Time0_H() interrupt 1
{
static unsigned char i=0
TH0=0x4c
TL0=0x00
i++
if(i==8)
{
i=0
state=~state
}
}
/*
void LCD_Display()
{
lcd_display_char(0,2,((g8563_Store[6]&0xf0)>>4)+0x30)//年
lcd_display_char(0,3,(g8563_Store[6]&0x0f)+0x30)//
}*/
void Key_down()
{
// static char set=0
unsigned char buffer
if(!Key_Set)
for(buffer=0buffer<250buffer++)
_nop_()
if(!Key_Set)
{
if(set==0)
{
writeData(0x0,0x20)//使时间停止
TR0=1
}
set++
if(set==4)
{
set=0
TR0=0
writeData(0x0,0x00)
}
while(!Key_Set)
Displaybuffer(set)
}
if(!Key_Add)
for(buffer=0buffer<250buffer++)
_nop_()
if(!Key_Add)
{
if(set==0)
return
P8563_gettime()
buffer= g8563_Store[set-1]
buffer=((buffer&0xf0)>>4)*10+(buffer&0x0f)
if(buffer>=59)
buffer=0
else if(buffer>=23 && set==3)
buffer=0
else
buffer++
buffer=(buffer/10<<4)+(buffer%10)
writeData(set+1,buffer)
while(!Key_Add)
Displaybuffer(set)
}
if(!Key_Sub)
for(buffer=0buffer<250buffer++)
_nop_()
if(!Key_Sub)
{
if(set==0)
return
P8563_gettime()
buffer= g8563_Store[set-1]
buffer=((buffer&0xf0)>>4)*10+(buffer&0x0f)
if(buffer == 0)
{
if(set==3)
buffer=23
else
buffer=59
}
else
buffer--
buffer=(buffer/10<<4)+(buffer%10)
writeData(set+1,buffer)
while(!Key_Sub)
Displaybuffer(set)
}
}
void Displaybuffer(char Location)
{
unsigned char i
P8563_gettime()
/*****************************************/
if(Location==1 && state==0)
{
P1=0
P3=0
goto sec_bit1
}
P3=0x02
P1=LedTable[g8563_Store[0]&0x0f] //sec
sec_bit1:
for(i=0i<250i++)
P1=0
if(Location==1 && state==0)
{
P1=0
P3=0
goto sec_bit2
}
P3=0x04
P1=LedTable[(g8563_Store[0]&0xf0)>>4]
sec_bit2:
for(i=0i<250i++)
P1=0
/*****************************************/
if(Location==2 && state==0)
{
P1=0
P3=0
goto min_bit1
}
P3=0x08
P1=LedTable[g8563_Store[1]&0x0f] //min
min_bit1:
for(i=0i<250i++)
P1=0
if(Location==2 && state==0)
{
P1=0
P3=0
goto min_bit2
}
P3=0x10
P1=LedTable[(g8563_Store[1]&0xf0)>>4]
min_bit2:
for(i=0i<250i++)
P1=0
/*****************************************/
if(Location==3 && state==0)
{
P1=0
P3=0
goto hour_bit1
}
P3=0x20
P1=LedTable[g8563_Store[2]&0x0f] //hour
hour_bit1:
for(i=0i<250i++)
P1=0
if(Location==3 && state==0)
{
P1=0
P3=0
goto hour_bit2
}
P3=0x40
P1=LedTable[(g8563_Store[2]&0xf0)>>4]
hour_bit2:
for(i=0i<250i++)
P1=0
P3=0x02
/*****************************************/
}
这下面一段是pcf8563.h的代码:
#ifndef __PFC8563_H__
#define __PFC8563_H__
#include <intrins.h>
#define uchar unsigned char
sbit SDA=P2^4
sbit SCL=P2^3
//extern void _nop_ (void)
//extern void delay(unsigned int ms)
uchar g8563_Store[7] /*时间交换区,全局变量声明*/
uchar code c8563_Store[7]={0x01,0x02,0x07,0x09,0x04,0x02,0x12} /*写入时间初值:秒,分,时,日,周,月,年(BCD码)
07:59:00*/
void delay(long time)
{while(time--)
}
/********************************************
内部函数,延时1
********************************************/
void DD()
{
//delay(1)
// uchar i
// for(i=0i<250i++)
_nop_()
_nop_() /*根据晶振频率制定延时时间*/
}
/********************************************
内部函数,I2C开始
********************************************/
void Start()
{ EA=0
SDA=1
SCL=1
DD()
SDA=0
DD()
SCL=0
}
/********************************************
内部函数,I2C结束
********************************************/
void Stop()
{
SDA=0
SCL=0
DD()
SCL=1
DD()
SDA=1
DD()
EA=1
}
/********************************************
内部函数,输出ACK ,每个字节传输完成,输出ack=0,结束读数据,ack=1
********************************************/
void WriteACK(uchar ack)
{
SDA=ack
DD()
SCL=1
DD()
SCL=0
}
/********************************************
内部函数,等待ACK
********************************************/
void WaitACK()
{ uchar errtime=20
SDA=1
DD() /*读ACK*/
SCL=1
DD()
while(SDA)
{ errtime--
if(!errtime)
{
Stop()
SDA=0 //自己加的******
}
}
SDA=1 //自己加的******
SCL=0
DD()
}
/********************************************
内部函数.输出数据字节
入口:B=数据
********************************************/
void writebyte(uchar wdata)
{
uchar i
for(i=0i<8i++)
{
if(wdata&0x80) SDA=1
else SDA=0
wdata<<=1
SCL=1
DD()
SCL=0
}
WaitACK() //I2C器件或通讯出错,将会退出I2C通讯
}
/********************************************
内部函数.输入数据
出口:B
********************************************/
uchar Readbyte()
{
uchar i,bytedata
SDA=1
for(i=0i<8i++)
{
SCL=1
bytedata<<=1
bytedata|=SDA
SCL=0
DD()
}
return(bytedata)
}
/********************************************
输出数据->pcf8563
********************************************/
void writeData(uchar address,uchar mdata)
{
Start()
writebyte(0xa2) /*写命令*/
writebyte(address) /*写地址*/
writebyte(mdata) /*写数据*/
Stop()
}
/********************************************
输入数据<-pcf8563
********************************************/
uchar ReadData(uchar address) /*单字节*/
{ uchar rdata
Start()
writebyte(0xa2) /*写命令*/
writebyte(address) /*写地址*/
Start()
writebyte(0xa3) /*读命令*/
rdata=Readbyte()
WriteACK(1)
Stop()
return(rdata)
}
void ReadData1(uchar address,uchar count,uchar * buff) /*多字节*/
{ uchar i
Start()
writebyte(0xa2) /*写命令*/
writebyte(address) /*写地址*/
Start()
writebyte(0xa3) /*读命令*/
for(i=0i<counti++)
{
buff[i]=Readbyte()
if(i<count-1) WriteACK(0)
}
WriteACK(1)
Stop()
}
/********************************************
内部函数,读入时间到内部缓冲区
********************************************/
void P8563_Read()
{ uchar time[7]
ReadData1(0x02,0x07,time)
g8563_Store[0]=time[0]&0x7f /*秒*/
g8563_Store[1]=time[1]&0x7f /*分*/
g8563_Store[2]=time[2]&0x3f /*小时*/
g8563_Store[3]=time[4]&0x07 /*星期*/
g8563_Store[4]=time[3]&0x3f /*日*/
g8563_Store[5]=time[5]&0x1f /*月*/
g8563_Store[6]=time[6] /*年*/
}
/********************************************
读入时间到内部缓冲区----外部调用
********************************************/
void P8563_gettime()
{
P8563_Read()
if(g8563_Store[0]==0)
P8563_Read() /*如果为秒=0,为防止时间变化,再读一次*/
}
/********************************************
写时间修改值
********************************************/
//void P8563_settime()
//{
// uchar i
// for(i=2i<=8i++) { writeData(i,g8563_Store[i-2]) }
// writeData(6,g8563_Store[3])
//}
/********************************************
P8563的初始化-----外部调用
********************************************/
/*
void P8563_init()
{
uchar i
if((ReadData(0xa)&0x3f)!=0x8) //检查是否第一次启动,是则初始化时间
{
// for(i=0i<=6i++) g8563_Store[i]=c8563_Store[i] //初始化时间
// P8563_settime()
writeData(0x0,0x00)
writeData(0xa,0x8) //8:00报警
writeData(0x1,0x12) //报警有效
writeData(0xd,0xf0)
}
}
*/
#endif
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)