基于ATMEGA8和PCF8563的多功能数字闹钟,要求显示时分秒(6个数码管),按键可以设置时间,闹钟响10s。。

基于ATMEGA8和PCF8563的多功能数字闹钟,要求显示时分秒(6个数码管),按键可以设置时间,闹钟响10s。。,第1张

#include <avr/io.h>

#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


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/8041148.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-12
下一篇 2023-04-12

发表评论

登录后才能评论

评论列表(0条)

保存