#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<reg51.h>#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit pcf8563_scl=P0^4
sbit pcf8563_sda=P0^3
uchar num[10]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39}//数字表
sbit clk=P2^0
sbit dio=P2^1
sbit cfd=P2^2 //充放电开关,
sbit en=P2^3
sbit rw=P2^4
sbit rs=P2^5
sbit deng=P2^6 //测试灯
sbit adcs=P2^7
bit busy=0
uchar sg
uchar sd
uchar fg
uchar fd
uchar mg
uchar md
uchar hou=0
uchar min=0
uchar sec=0
uchar subadd
uchar dat
uchar number
void start_pcf8563()
void send_pcf8563_byte()
void LcdIni(void)
void WrOp(uchar dat)
void WrDat(uchar dat)
void ChkBusy(void)
void display0(void)
void display1(void)
void stop_pcf8563()
void receive_pcf8563_byte()
void spit_time()
void LcdIni()//初始化LCD
{WrOp(0x01)
WrOp(0x38)
WrOp(0x0c)
WrOp(0x06)
}
void WrOp(uchar dat)//写LCD显示地址
{
P1 =dat
rs=0
rw=0
en=0
ChkBusy()
en=1
}
void WrDat(uchar dat)//写LCD显示数据
{ P1=dat
rs=1
rw=0
en=0
ChkBusy()
en=1
}
void ChkBusy() //检查LCD是否忙
{
P1=0xff
rs=0
rw=1
en=0
_nop_()
en=1
while(P1&0x80)
}
void display0() //显示必要的背景
{
WrOp(0x80)
WrDat('T')
WrOp(0x81)
WrDat(':')
WrOp(0x84)
WrDat(':')
WrOp(0x87)
WrDat('卜野罩:')
}
void spit_time()
{
sg=(int)hou/10
sd=(int)hou%10
fg=(int)min/10
fd=(int)min%10
mg=(int)sec/10
md=(int)sec%10
}
void display1()//显示时间型闹六位
{
uchar temp6
uchar temp5
uchar temp4
uchar temp3
uchar temp2
uchar temp1
WrOp(0x82)
temp6=num[sg]
WrDat(temp6)
WrOp(0x83)
temp5=num[sd]
WrDat(temp5)
WrOp(0x85)
temp4=num[fg]
WrDat(temp4)
WrOp(0x86)
temp3=num[fd]
WrDat(temp3)
WrOp(0x88)
temp2=num[mg]
WrDat(temp2)
WrOp(0x89)
temp1=num[md]
WrDat(temp1)
}
void Send_pcf8563_byte(uchar bb) //向PCF8563发送一脊裤个字节
{
uchar aa
pcf8563_scl=0
for(aa=0aa<8aa++)
{
if((bb&0x80)==0x80)
{
pcf8563_sda=1
}
else
{
pcf8563_sda=0
}
pcf8563_scl=1
pcf8563_scl=0
bb=bb<<1
}
_nop_()
_nop_()
pcf8563_sda=1
pcf8563_scl=1
busy=0
if(pcf8563_sda)
{
busy=1
}
else
{
_nop_()
_nop_()
pcf8563_scl=0
busy=0
}
}
void write_pcf8563(uchar subadd,uchar dat)// 向PCF8563对应地址写数据
{
start_pcf8563()
Send_pcf8563_byte(0xa2)
if(!busy)
{
Send_pcf8563_byte(subadd)
if(!busy)
{
Send_pcf8563_byte(dat)
}
}
stop_pcf8563()
}
void read_pcf8563() //读当时的时,分,钞
{
start_pcf8563()
Send_pcf8563_byte(0xa2)
if(!busy)
{
Send_pcf8563_byte(0x02)
if(!busy)
{
start_pcf8563()
Send_pcf8563_byte(0xa3)
receive_pcf8563_byte()
sec=number&0x7f
start_pcf8563()
Send_pcf8563_byte(0xa3)
receive_pcf8563_byte()
min=number&0x7f
start_pcf8563()
Send_pcf8563_byte(0xa3)
receive_pcf8563_byte()
hou=number&0x3f
}
}
stop_pcf8563()
}
void receive_pcf8563_byte() //从PCF8563接受一个字节
{uchar cc
pcf8563_sda=1
number=0
for(cc=0cc<8cc++)
{
number<<=1
pcf8563_scl=0
pcf8563_scl=1
_nop_()
_nop_()
number= number|pcf8563_sda
}
pcf8563_scl=0
_nop_()
_nop_()
}
void start_pcf8563() //开启PCF8563IIC
{
pcf8563_sda=1
pcf8563_scl=1
pcf8563_sda=0//SCL为低,SDA执行一个上跳
pcf8563_scl=0//SCL为低,嵌住数据线
}
void stop_pcf8563() //关闭PCF8563IIC
{
pcf8563_sda=0
pcf8563_scl=1
pcf8563_sda=1//SCL为高,SDA执行一个上跳
pcf8563_scl=0//SCL为低,嵌住数据线
}
void main(void)
{
LcdIni() //初始化屏
display0() //显示必要的背影
write_pcf8563(0x02,sec) //写钞
write_pcf8563(0x03,min) //写分
write_pcf8563(0x04,hou) //写时
while(1)
{
read_pcf8563()//读当前时间
spit_time() //切害时间,为显示做准备
display1()//显示当前时间
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)