ds1302时钟保护程序怎么写,如果能加调时,闹钟功能就更好了

ds1302时钟保护程序怎么写,如果能加调时,闹钟功能就更好了,第1张

#include <reg52.h>

#include <intrins.h>

#define uchar unsigned char

#define uint unsigned int

sbit SCK=P3^6

sbit SDA=P3^4

sbit RST=P3^5// DS1302复位

sbit set=P3^0//定义按键端口

sbit s1=P3^1

sbit s2=P3^2

sbit s3=P3^3

/************液晶口定义*******/

sbit RS=P2^4//RS为数据/指令选择1/0

sbit RW=P2^5//读写

sbit E=P2^6//E为使能信号

bit flag//是否读取时间的标志位

uchar setn=0//复位键、增加键、减少键按下次数

uchar code time0[]="DATE: - - "

uchar code time1[]="TIME: : : "

uchar l_tmpdate[7]={0,55,16,22,8,6,9}//秒分时日月周年// 可随时更改

uchar code write_add[7]={0x80,0x82,0x84,0x86,

0x88,0x8a,0x8c}//秒分时日月周年 写的寄存器地址

uchar code read_add[7]={0x81,0x83,0x85,0x87,

0x89,0x8b,0x8d}//秒分时日月周年 读的寄存器地址

uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d

,0x7d,0x07,0x7f,0x6f,0x40}//共阴数码管 0-9加'-'熄灭表

void delay(uint z)

{

while(--z)

}

void write_com(uchar com)//液晶写命令函数

{

RS=0//写命令使能

RW=0//写

delay(5000)

/****在高脉冲下命令输入*****/

E=0

P0=com

delay(500)

E=1

delay(500)

E=0

}

void write_data(uchar dat)//液晶写数据函数

{

RS=1//写数据使能

RW=0

delay(5000)

/****在高脉冲下数据输入*****/

E=0

P0=dat

delay(500)

E=1

delay(500)

E=0

}

void init()//液晶初始化

{

uchar num

E=0

write_com(0x38)//显示模式设置

delay(500)

write_com(0x38)

delay(500)

write_com(0x38)

write_com(0x08)//显示关闭

delay(500)

write_com(0x01)//显示清屏

write_com(0x06)//光标移动设置整屏不移动

write_com(0x0c)//屏幕开、光标不闪(0)不显示(0)

delay(500)

write_com(0x80)

for(num=0num<16num++)

{

write_data(time0[num])

delay(5)

}

write_com(0x80+0x40)

for(num=0num<13num++)

{

write_data(time1[num])

delay(5)

}

}

void Write_Ds1302_Byte(uchar temp) //写一个字节

{

uchar i

for (i=0i<8i++)//循环8次写入数据

{

SCK=0

SDA=temp&0x01 //每次传输低字节

temp>>=1 //右移一位

SCK=1

}

}

/****************************************************************************/

void Write_Ds1302(uchar add,uchar dat )//向寄存器写数据

{

RST=0

_nop_()

SCK=0

_nop_()

RST=1//启动

_nop_()

Write_Ds1302_Byte(add)//发送地址

Write_Ds1302_Byte(dat)//发送数据

RST=0 //恢复

}

uchar Read_Ds1302_Byte()//读一个字节

{

uchar i,temp=0x00

for (i=0i<8i++) //循环8次 读取数据

{

if(SDA)

temp|=0x80 //每次传输低字节

SCK=0

temp>>=1 //右移一位

SCK=1

}

return(temp)

}

uchar Read_Ds1302(uchar address )//从寄存器读数据

{

uchar date

RST=0

_nop_()

SCK=0

_nop_()

RST=1

_nop_()

Write_Ds1302_Byte(address)

date=Read_Ds1302_Byte()

RST=0

_nop_() //以下为DS1302复位的稳定时间

RST=0

SCK=0

_nop_()

SCK=1

_nop_()

SDA=0

_nop_()

SDA=1

_nop_()

return (date)

}

/*********************************************************/

void Read_RTC(void) //读取日历

{

uchar i,*p

p=read_add //读的地址传递

for(i=0i<7i++) //分7次读取 秒分时日月周年

{

l_tmpdate[i]=Read_Ds1302(*p)

p++

}

}

/******************************************************/

void Set_RTC(void) //设定日历

{

uchar i,*p,tmp

for(i=0i<7i++)

{ //BCD处理,将十六进制转换成十进制

tmp=l_tmpdate[i]/10

l_tmpdate[i]=l_tmpdate[i]%10

l_tmpdate[i]=l_tmpdate[i]+tmp*16

}

Write_Ds1302(0x8E,0X00)//关闭写保护

p=write_add//传要写的寄存器地址

for(i=0i<7i++) //7次写入秒分时日月周年

{

Write_Ds1302(*p,l_tmpdate[i])

p++

}

Write_Ds1302(0x8E,0x80)//打开写保护

}

void write_lcd()

{

static uchar i,temp[2]

switch(i)

{

case 0: write_com(0x80+0x40+0x0b)break//秒

case 1: write_com(0x80+0x40+8)break//分

case 2: write_com(0x80+0x40+5)break//时

case 3: write_com(0x80+0x0b)break//日

case 4: write_com(0x80+8)break//月

case 5: write_com(0x80+0x0e)break//星期

case 6: write_com(0x80+5)break//年

}

temp[0]=l_tmpdate[i]/16//数据的转换

temp[1]=l_tmpdate[i]&0x0f

write_data(0x30+temp[0])

write_data(0x30+temp[1])

i++

if(i==7)

i=0

}

uchar change(uchar x)//十进制转换成十六进制

{

uchar tep,y

y=x

tep=y/16

y=y%16

y=y+tep*10

return y

}

void keyscan()

{

uchar tem[2],tp,Flag//存储要更改的时间数据

if(set==0)

{

flag=1//时间停止

delay(500)//去键盘按下抖动

if(set==0)

{

delay(500)

while(!set)

delay(500)//去键盘抬起时抖动

while(!set)

delay(500)

setn++

if(setn==1)

{

write_com(0x80+0x40+12)//将光标移动到秒个位

write_com(0x0f)//显示光标并且闪烁

}

if(setn==2)

{

write_com(0x80+0x40+9)//将光标移动到分个位

write_com(0x0f)//显示光标并且闪烁

}

if(setn==3)

{

write_com(0x80+0x40+6)//将光标移动到时个位

write_com(0x0f)//显示光标并且闪烁

}

if(setn==4)

{

write_com(0x80+15)

write_com(0x0f)

}

if(setn==5)

{

write_com(0x80+12)

write_com(0x0f)

}

if(setn==6)

{

write_com(0x80+9)

write_com(0x0f)

}

if(setn==7)

{

write_com(0x80+6)

write_com(0x0f)

}

if(setn==8)

{

setn=0

Write_Ds1302(0x8E,0X00)//关闭写保护

Write_Ds1302(write_add[0],l_tmpdate[0])

Write_Ds1302(0x8E,0x80)//打开写保护

flag=0//时钟正常运行

write_com(0x0c)//光标停止闪烁

}

}

}

if(setn!=0)//更改时间

{

if(s1==0)//增加时间

{

delay(5000)

if(s1==0)

{

while(!s1)

delay(5000)//去键盘抬起时抖动

while(!s1)

if(setn==1)

{

l_tmpdate[0]=change(l_tmpdate[0])

l_tmpdate[0]++

if(l_tmpdate[0]>=60)

l_tmpdate[0]=0

{

tp=l_tmpdate[0]/10

l_tmpdate[0]=l_tmpdate[0]%10

l_tmpdate[0]=l_tmpdate[0]+tp*16

Write_Ds1302(0x8E,0X00)//关闭写保护

Write_Ds1302(write_add[0],l_tmpdate[0])

Write_Ds1302(0x8E,0x80)//打开写保护

}

write_com(0x80+0x40+11)

tem[0]=l_tmpdate[0]/16//数据的转换

tem[1]=l_tmpdate[0]&0x0f

write_data(0x30+tem[0])

write_data(0x30+tem[1])

write_com(0x80+0x40+12)

Flag=1

}

if(setn==2)

{ l_tmpdate[1]=change(l_tmpdate[1])

l_tmpdate[1]++

if(l_tmpdate[1]==60)

l_tmpdate[1]=0

{

tp=l_tmpdate[1]/10

l_tmpdate[1]=l_tmpdate[1]%10

l_tmpdate[1]=l_tmpdate[1]+tp*16

Write_Ds1302(0x8E,0X00)//关闭写保护

Write_Ds1302(write_add[1],l_tmpdate[1])

Write_Ds1302(0x8E,0x80)//打开写保护

}

write_com(0x80+0x40+8)

tem[0]=l_tmpdate[1]/16//数据的转换

tem[1]=l_tmpdate[1]&0x0f

write_data(0x30+tem[0])

write_data(0x30+tem[1])

write_com(0x80+0x40+9)

}

if(setn==3)

{ l_tmpdate[2]=change(l_tmpdate[2])

l_tmpdate[2]++

if(l_tmpdate[2]>=24)

l_tmpdate[2]=0

{

tp=l_tmpdate[2]/10

l_tmpdate[2]=l_tmpdate[2]%10

l_tmpdate[2]=l_tmpdate[2]+tp*16

Write_Ds1302(0x8E,0X00)//关闭写保护

Write_Ds1302(write_add[2],l_tmpdate[2])

Write_Ds1302(0x8E,0x80)//打开写保护

}

write_com(0x80+0x40+5)

tem[0]=l_tmpdate[2]/16//数据的转换

tem[1]=l_tmpdate[2]&0x0f

write_data(0x30+tem[0])

write_data(0x30+tem[1])

write_com(0x80+0x40+6)

}

if(setn==4)

{

l_tmpdate[5]=change(l_tmpdate[5])

l_tmpdate[5]++

if(l_tmpdate[5]==8)

l_tmpdate[5]=1

{

tp=l_tmpdate[5]/10

l_tmpdate[5]=l_tmpdate[5]%10

l_tmpdate[5]=l_tmpdate[5]+tp*16

Write_Ds1302(0x8E,0X00)//关闭写保护

Write_Ds1302(write_add[5],l_tmpdate[5])

Write_Ds1302(0x8E,0x80)//打开写保护

}

write_com(0x80+14)

tem[0]=l_tmpdate[5]/16//数据的转换

tem[1]=l_tmpdate[5]&0x0f

write_data(0x30+tem[0])

write_data(0x30+tem[1])

write_com(0x80+15)

}

if(setn==5)

{

l_tmpdate[3]=change(l_tmpdate[3])

l_tmpdate[3]++

if(l_tmpdate[3]==32)

l_tmpdate[3]=0

{

tp=l_tmpdate[3]/10

l_tmpdate[3]=l_tmpdate[3]%10

l_tmpdate[3]=l_tmpdate[3]+tp*16

Write_Ds1302(0x8E,0X00)//关闭写保护

Write_Ds1302(write_add[3],l_tmpdate[3])

Write_Ds1302(0x8E,0x80)//打开写保护

}

write_com(0x80+11)

tem[0]=l_tmpdate[3]/16//数据的转换

tem[1]=l_tmpdate[3]&0x0f

write_data(0x30+tem[0])

write_data(0x30+tem[1])

write_com(0x80+12)

}

if(setn==6)

{

l_tmpdate[4]=change(l_tmpdate[4])

l_tmpdate[4]++

if(l_tmpdate[4]==13)

l_tmpdate[4]=0

write_com(0x80+8)

{

tp=l_tmpdate[4]/10

l_tmpdate[4]=l_tmpdate[4]%10

l_tmpdate[4]=l_tmpdate[4]+tp*16

Write_Ds1302(0x8E,0X00)//关闭写保护

Write_Ds1302(write_add[4],l_tmpdate[4])

Write_Ds1302(0x8E,0x80)//打开写保护

}

tem[0]=l_tmpdate[4]/16//数据的转换

tem[1]=l_tmpdate[4]&0x0f

write_data(0x30+tem[0])

write_data(0x30+tem[1])

write_com(0x80+9)

}

if(setn==7)

{

l_tmpdate[6]=change(l_tmpdate[6])

l_tmpdate[6]++

if(l_tmpdate[6]==100)

l_tmpdate[6]=0

write_com(0x80+5)

{

tp=l_tmpdate[6]/10

l_tmpdate[6]=l_tmpdate[6]%10

l_tmpdate[6]=l_tmpdate[6]+tp*16

Write_Ds1302(0x8E,0X00)//关闭写保护

Write_Ds1302(write_add[6],l_tmpdate[6])

Write_Ds1302(0x8E,0x80)//打开写保护

}

tem[0]=l_tmpdate[6]/16//数据的转换

tem[1]=l_tmpdate[6]&0x0f

write_data(0x30+tem[0])

write_data(0x30+tem[1])

write_com(0x80+6)

}

}

}

if(s2==0)//减少时间

{

delay(5000)

if(s2==0)

{

while(!s2)

delay(5000)//去键盘抬起时抖动

while(!s2)

if(setn==1)

{

l_tmpdate[0]=change(l_tmpdate[0])

if(l_tmpdate[0]!=0)

l_tmpdate[0]--

if(l_tmpdate[0]==0)

l_tmpdate[0]=59

{

tp=l_tmpdate[0]/10

l_tmpdate[0]=l_tmpdate[0]%10

l_tmpdate[0]=l_tmpdate[0]+tp*16

Write_Ds1302(0x8E,0X00)//关闭写保护

Write_Ds1302(write_add[0],l_tmpdate[0])

Write_Ds1302(0x8E,0x80)//打开写保护

}

write_com(0x80+0x40+11)

tem[0]=l_tmpdate[0]/16//数据的转换

tem[1]=l_tmpdate[0]&0x0f

write_data(0x30+tem[0])

write_data(0x30+tem[1])

write_com(0x80+0x40+12)

}

if(setn==2)

{

l_tmpdate[1]=change(l_tmpdate[1])

if(l_tmpdate[1]!=0)

l_tmpdate[1]--

if(l_tmpdate[1]==0)

l_tmpdate[1]=59

{

tp=l_tmpdate[1]/10

l_tmpdate[1]=l_tmpdate[1]%10

l_tmpdate[1]=l_tmpdate[1]+tp*16

Write_Ds1302(0x8E,0X00)//关闭写保护

Write_Ds1302(write_add[1],l_tmpdate[1])

Write_Ds1302(0x8E,0x80)//打开写保护

}

write_com(0x80+0x40+8)

tem[0]=l_tmpdate[1]/16//数据的转换

tem[1]=l_tmpdate[1]&0x0f

write_data(0x30+tem[0])

write_data(0x30+tem[1])

write_com(0x80+0x40+9)

}

if(setn==3)

{ l_tmpdate[2]=change(l_tmpdate[2])

if(l_tmpdate[2]!=0)

l_tmpdate[2]--

if(l_tmpdate[2]==0)

l_tmpdate[2]=23

{

tp=l_tmpdate[2]/10

l_tmpdate[2]=l_tmpdate[2]%10

l_tmpdate[2]=l_tmpdate[2]+tp*16

Write_Ds1302(0x8E,0X00)//关闭写保护

Write_Ds1302(write_add[2],l_tmpdate[2])

Write_Ds1302(0x8E,0x80)//打开写保护

}

write_com(0x80+0x40+5)

tem[0]=l_tmpdate[2]/16//数据的转换

tem[1]=l_tmpdate[2]&0x0f

write_data(0x30+tem[0])

write_data(0x30+tem[1])

write_com(0x80+0x40+6)

}

if(setn==4)

{

l_tmpdate[5]=change(l_tmpdate[5])

if(l_tmpdate[5]!=0)

l_tmpdate[5]--

if(l_tmpdate[5]==0)

l_tmpdate[5]=7

{

tp=l_tmpdate[5]/10

l_tmpdate[5]=l_tmpdate[5]%10

l_tmpdate[5]=l_tmpdate[5]+tp*16

Write_Ds1302(0x8E,0X00)//关闭写保护

Write_Ds1302(write_add[5],l_tmpdate[5])

Write_Ds1302(0x8E,0x80)//打开写保护

}

write_com(0x80+14)

tem[0]=l_tmpdate[5]/16//数据的转换

tem[1]=l_tmpdate[5]&0x0f

write_data(0x30+tem[0])

write_data(0x30+tem[1])

write_com(0x80+15)

}

if(setn==5)

{

l_tmpdate[3]=change(l_tmpdate[3])

if(l_tmpdate[3]!=0)

l_tmpdate[3]--

if(l_tmpdate[3]==0)

l_tmpdate[3]=31

{

tp=l_tmpdate[3]/10

l_tmpdate[3]=l_tmpdate[3]%10

l_tmpdate[3]=l_tmpdate[3]+tp*16

Write_Ds1302(0x8E,0X00)//关闭写保护

Write_Ds1302(write_add[3],l_tmpdate[3])

Write_Ds1302(0x8E,0x80)//打开写保护

}

write_com(0x80+11)

tem[0]=l_tmpdate[3]/16//数据的转换

tem[1]=l_tmpdate[3]&0x0f

write_data(0x30+tem[0])

write_data(0x30+tem[1])

write_com(0x80+12)

}

if(setn==6)

{

l_tmpdate[4]=change(l_tmpdate[4])

if(l_tmpdate[4]!=0)

l_tmpdate[4]--

if(l_tmpdate[4]==0)

l_tmpdate[4]=12

write_com(0x80+8)

{

tp=l_tmpdate[4]/10

l_tmpdate[4]=l_tmpdate[4]%10

l_tmpdate[4]=l_tmpdate[4]+tp*16

Write_Ds1302(0x8E,0X00)//关闭写保护

Write_Ds1302(write_add[4],l_tmpdate[4])

Write_Ds1302(0x8E,0x80)//打开写保护

}

tem[0]=l_tmpdate[4]/16//数据的转换

tem[1]=l_tmpdate[4]&0x0f

write_data(0x30+tem[0])

write_data(0x30+tem[1])

write_com(0x80+9)

}

if(setn==7)

{

l_tmpdate[6]=change(l_tmpdate[6])

if(l_tmpdate[6]!=0)

l_tmpdate[6]--

if(l_tmpdate[6]==0)

l_tmpdate[6]=99

write_com(0x80+5)

{

tp=l_tmpdate[6]/10

l_tmpdate[6]=l_tmpdate[6]%10

l_tmpdate[6]=l_tmpdate[6]+tp*16

Write_Ds1302(0x8E,0X00)//关闭写保护

Write_Ds1302(write_add[6],l_tmpdate[6])

Write_Ds1302(0x8E,0x80)//打开写保护

}

tem[0]=l_tmpdate[6]/16//数据的转换

tem[1]=l_tmpdate[6]&0x0f

write_data(0x30+tem[0])

write_data(0x30+tem[1])

write_com(0x80+6)

}

}

}

}

}

/*******************************************************/

void main(void)

{

//Set_RTC()//在第一次使用时给ds1302赋初值

init()

while(1)

{

if(flag==0)

{

Read_RTC()

write_lcd()

}

keyscan()

}

}

1、存储和读取的时间的内容应为BCD码。write_1302(0x8c,0x11)maioh=(miao&0x7f)>>4……

2、建议上电后,ce=0clk=0延时一会儿再 *** 作1302。或者多写两次撤销写保护命令。

write_1302(0x8e,0x10)笔误,应该是 write_1302(0x8e,0x80)

3、建议读写1302的clk速率降低,如datasheet,2MHz最大。

4、建议首次改写时间时,将秒值最高位置为1,时间设置完毕后,清秒值最高位。

5、建议,刷新LCD速率在100mS~500mS。没有必要不停地读1302,写1602。

6、检查硬件连接,及起振晶体。或更换一片1302再看看。

最后调试成功,请告知原因。谢谢!

AVR MEGE16 DS1302程序,分别保存为DS1302.C DS1302.H

后面是51 DS1302程序,分别保存为DS1302.hmain.c

用哪个下哪个吧。

#include "DS1302.h"

#include "ym12864.h"

#include "delay.h"

/*******************************************

函数名称: DS1302_init

功能: 初始化DS1302的数据接口

参数: 无

返回值 : 无

/********************************************/

void DS1302_portinit(void)

{

DDRB|=BIT(RTC_CLK)|BIT(RTC_DATA)|BIT(RTC_CS)//将时钟端(RTC_CLK)数据端(RTC_DATA)片选端(RTC_CS)设置为输出

}

/*******************************************

函数名称: DS1302_writeB

功能: 向DS1302写入一个字节数据(没有RST *** 作)

参数: byte--要写入的数据

返回值 : 无

/********************************************/

void DS1302_writeB(uchar byte)

{

uchar i

for(i=0i<8i++) //8位数据计数

{

CLR_CLK //拉低时钟端

if(byte&0x01) //当前位是否是1

{

SET_DATA //当前位是1,拉高数据端

}

else

{

CLR_DATA //当前位是0,拉低数据端

}

delay_us(10) //调整时钟和脉冲宽度

SET_CLK //时钟上升沿(DS1302采样数据)

byte>>=1 //数据右移1位,为送出新数据位做准备

}

}

/*******************************************

函数名称: DS1302_readB

功能: 从DS1302读出一个字节数据(没有RST *** 作)

参数: 无

返回值 : byte--读出的数据

/********************************************/

uchar DS1302_readB(void)

{

uchar i,byte=0

DATA_IN //将数据端口设置为输入

CLR_DATA //无上拉电阻

for(i=0i<8i++) //8位数据计数

{

byte>>=1 //保存读入的数据位

SET_CLK //时钟上升沿

delay_us(10) //延时,调整时钟脉冲宽度

CLR_CLK //时钟下降沿,DS1302输出数据位

delay_us(10) //等待数据变化(MEGA16太快,必须等待DS1302的数据位输出,否则不能正确读出)

if(PINB&BIT(RTC_DATA)) //当前位是否是高电平

{

byte|=BIT(PB7) //是高电平就将返回数据的当前位置1

}

else

{

byte&=~BIT(PB7) //是低电平就将返回数据的当前位置0

}

}

DATA_OUT //最后将数据端口设置为输出

return byte //返回读出的数据

}

/*******************************************

函数名称: DS1302_writeD

功能: 向DS1302的某个地址写入一个字节数据

参数: addr--地址值(寄存器或RAM)

data--要写入的地址

返回值 : 无

/********************************************/

void DS1302_writeD(uchar addr,uchar data)

{

CLR_CS //拉低片选端

CLR_CLK //拉低时钟端

delay_us(10)

SET_CS //拉高片选端

delay_us(10) //调整片选脉冲

DS1302_writeB(addr) //写入 *** 作命令(地址)

delay_us(10)

CLR_CLK //拉低时钟端

delay_us(10)

DS1302_writeB(data) //写入数据

CLR_CLK //拉低时钟端

delay_us(10) //调整片选脉冲

CLR_CS //拉低片选端

}

/*******************************************

函数名称: DS1302_readD

功能: 从DS1302的某个地址读出一个字节数据

参数: addr--地址值(寄存器或RAM)

返回值 : data--读出的数据

/********************************************/

uchar DS1302_readD(uchar addr)

{

uchar data

CLR_CS //拉低片选端

CLR_CLK //拉低时钟端

delay_us(10)

SET_CS //拉高片选端

delay_us(10) //调整片选脉冲

DS1302_writeB(addr) //写入 *** 作命令(地址)

delay_us(10)

data=DS1302_readB() //读出数据

delay_us(10)

CLR_CLK //拉低时钟端

CLR_CS //拉低片选端

return data //返回读出的数据

}

/*******************************************

函数名称: DS1302_setT

功能: 设置DS1302的时间

参数: ptTimeD--设置时间数组指针

返回值 : 无

/********************************************/

void DS1302_setT(uchar ptTimeD[])

{

uchar i

uchar addr = 0x80 //写入地址从秒寄存器开始

DS1302_writeD(C_WP|WR,UPROTECT)//控制命令,WP位为0,允许写 *** 作

delay_ms(5)

for(i=0i<7i++)

{

DS1302_writeD(addr|WR,ptTimeD[i]) // 秒 分 时 日 月 星期 年

addr+=2

delay_ms(1)

}

DS1302_writeD(C_WP|WR,PROTECT) //控制命令,WP位为1,不允许写 *** 作

}

/*******************************************

函数名称: DS1302_getT

功能: 读取DS1302的当前时间

参数: time[]--读取的时间数组

返回值 : 无

/********************************************/

void DS1302_getT(uchar time[])

{

uchar i

////////下面的是单次读写//////////////////////////

/* uchar addr = 0x80 //读取地址从秒寄存器开始

for(i=0i<7i++)

{

time[i]=DS1302_readD(addr|RD) // 秒 分 时 日 月 星期 年

addr+=2

}*/

////////////////////////////////////////////////////

/////////下面是多字节读取///////////////

CLR_CS //拉低片选端

delay_us(10)

SET_CS //拉高片选端

delay_us(10) //调整片选脉冲

DS1302_writeB(0xbf) // 0xbf:时钟多字节读取命令

for (i=0i<8i++) //时间数据的存放格式是:

{//秒,分,时,日,月,星期,年,控制

time[i]=DS1302_readB()//【7个数据(BCD格式)+1个控制】

}

CLR_CS //拉低片选端

///////////////////////////////////////////////

CLR_CLK //拉低时钟端(时钟端在不 *** 作时为低)

}

/*******************************************

函数名称: DS1302_check

功能: 检测DS1302是否正常工作

参数: 无

返回值 : exist--为TRUE为检测到DS1302,为FALSE为没检测到

/********************************************/

/*uchar DS1302_check(void)

{

uchar exist

DS1302_writeD(C_WP|WR,UPROTECT) //写入写允许命令

DS1302_writeD(C_RAMBASE|WR,0xA5) //RAM0写入0xA5

exist=DS1302_readD(C_RAMBASE|RD) //读取RAM0

if(exist==0xA5)

{

exist=TRUE //如果读取值与写入值相等,返回TRUE

}

else

{

exist=FALSE //如果读取值与写入值不相等,返回FALSE

}

return exist

}*/

/*******************************************

函数名称: DS1302_init

功能: 初始化DS1302

参数: 无

返回值 : 无

/********************************************/

void DS1302_init(void)

{

DS1302_writeD(C_WP|WR,UPROTECT) //写入写允许命令

DS1302_writeD(C_SEC|WR,CLK_START) //启动振荡器,DS1302开始工作

DS1302_writeD(C_WP|WR,PROTECT) //控制命令,WP位为1,不允许写 *** 作

}

/*******************************************

函数名称: BCD_ASCII

功能: 将压缩BCD码转换成ascii码

参数: BCD--将要转换的压缩BCD码

ptasc--转换后的ASCII码数组指针

返回值 : 无

/********************************************/

void BCD_ASCII(uchar BCD,uchar ptasc[])

{

ptasc[0]=BCD/16|0x30 //0X58 35 38 //转换十位

ptasc[1]=BCD&0x0F|0x30 //转换个位

}

/*******************************************

函数名称: Disp_time

功能: 在1602液晶上显示当前时间(第1行格式:年-月-日 星期;第2行格式:时-分-秒)

参数: time[]--时间数组

返回值 : 无

/********************************************/

void Disp_time(uchar time[])

{

uchar i,asc[2]

uchar line1[11]={0,0,'-',0,0,'-',0,0,' ',0,'\0'}//显示第1行的字符数组

uchar line2[9]={0,0,':',0,0,':',0,0,'\0'} //显示第2行的字符数组

for(i=0i<3i++) //为第2行的字符数组赋值

{

BCD_ASCII(time[2-i],asc)

line2[i*3]=asc[0]

line2[i*3+1]=asc[1]

}

BCD_ASCII(time[6],asc) //为第1行的年赋值

line1[0]=asc[0]

line1[1]=asc[1]

BCD_ASCII(time[4],asc) //为第1行的月赋值

line1[3]=asc[0]

line1[4]=asc[1]

BCD_ASCII(time[3],asc) //为第1行的日赋值

line1[6]=asc[0]

line1[7]=asc[1]

BCD_ASCII(time[5],asc) //为第1行的星期赋值

line1[9]=asc[1]

Disp_String(0,16,"20") //第1行从第3个位置开始显示,将07年显示为2007的形式

Disp_String(0,32,line1)

Disp_String(3,32,line2)//第2行从第5个位置开始显示,/第2行显示

}

#ifndef __DS1302_H

#define __DS1302_H

#include <iom16v.h>

#include <macros.h>

typedef unsigned char uchar

typedef unsigned int uint

typedef unsigned long ulong

/******************RTC常量******************/

#define RTC_CLK PB1

#define RTC_DATA PB0

#define RTC_CS PB4

#define SET_CLKPORTB|=BIT(RTC_CLK)

#define CLR_CLKPORTB&=~BIT(RTC_CLK)

#define SET_DATA PORTB|=BIT(RTC_DATA)

#define CLR_DATA PORTB&=~BIT(RTC_DATA)

#define SET_CS PORTB|=BIT(RTC_CS)

#define CLR_CS PORTB&=~BIT(RTC_CS)

#define DATA_OUT DDRB|=BIT(RTC_DATA)

#define DATA_INDDRB&=~BIT(RTC_DATA)

//命令

#define RD 0x01

#define WR 0x00

#define C_SEC 0x80 //秒

#define C_MIN 0x82 //分

#define C_HR 0x84 //时

#define C_DAY 0x86 //日

#define C_MTH 0x88 //月

#define C_WK 0x8A //星期 DATE

#define C_YR 0x8C //年

#define C_WP 0x8E //控制(写保护)

#define C_CHARGE 0x90 //涓流充电

#define C_BURST 0xBE //时钟多字节

//配置

#define CLK_HALT 0x80 //停止时钟控制位SECOND bit7

#define CLK_START 0x00 //启动时钟

#define M12_24 0x80 //12/24小时值选择位 HOURbit7

#define PROTECT 0x80 //写保护控制位 CONTROL bit7

#define UPROTECT 0x00 //写保护控制位 CONTROL bit7

//涓流充电控制常量

#define TC_D1R2 0xA5 //high 1 Diode +2K Resistors

#define TC_D2R8 0xAB //low 2 Diodes+8K Resistors

#define TC_DISABLED 0x00 //Disabled(TCS<>1010 or DS=00 or RS=00)

//RAM 命令

#define C_RAMBASE 0xC0 //RAM0~RAM30<<1 地址需左移一位

void DS1302_portinit(void)

void DS1302_writeB(unsigned char byte)

unsigned char DS1302_readB(void)

void DS1302_writeD(unsigned char addr,unsigned char data)

unsigned char DS1302_readD(unsigned char addr)

void DS1302_setT(unsigned char ptTimeD[])

void DS1302_getT(unsigned char time[])

void DS1302_init(void)

void BCD_ASCII(unsigned char BCD,unsigned char ptasc[])

void Disp_time(unsigned char time[])

extern void DS1302_portinit(void)

extern void DS1302_setT(unsigned char ptTimeD[])

extern void DS1302_getT(unsigned char time[])

extern void DS1302_init(void)

extern void Disp_time(unsigned char time[])

#endif

#include<reg52.h>

#define uint unsigned int

#define uchar unsigned char

sbit dsrst=P1^4

sbit dssclk=P1^1

sbit dsio=P1^0

uint a[24]={0,0,0,0,0,0,1,0,0,1,9,0,0,0,0,0,0,0,1,0,1,0,9,0}

//分别对应秒秒分分时时日日月月年年

//后12位为闹钟位,用于存储闹钟数据

//1302write DS1302写数据

void dswrite(uchar dswrite)

{

uchar i,temp

delay(1)

temp=dswrite

for(i=0i<8i++)

{

dsio=temp&0x01

delay(1)

dssclk=1

delay(1)

dssclk=0

temp=temp>>1

}

}

//1302read Ds1302读数据

uchar dsread()

{

uchar i,temp

delay(1)

temp=0

for(i=0i<8i++)

{

temp=temp>>1

if(dsio==1)temp=temp+0x80

delay(1)

dssclk=1

delay(1)

dssclk=0

}

return temp

}

//1302addshuju DS1302向某地址写入某数据

void dsaddshuju(uchar add,uchar dsshuju)

{

dsrst=0

dssclk=0

dsrst=1

dswrite(add)// 地址,命令

dswrite(dsshuju)// 写1Byte数据

dssclk=1

dsrst=0

dsio=0

}

//1302on DS1302初始化

void dson()

{

uchar i

dsaddshuju(0x8c,(a[11]<<4)+a[10])

for(i=0i<5i++)

{

dsaddshuju(0x88-i*2,(a[9-i*2]<<4)+a[8-i*2])

}

}

/***********************************************************************/

/***********************************************************************/

/*******************************************************/

/***********************************************************************/

/************************** ***************************/

/************************** ***************************/

/***********************************************************************/

/***********************************************************************/

/************************ ************************/

/******************** 温度时钟显示 C语言程序**********************/

/************************ ************************/

/***********************************************************************/

/***********************************************************************/

/***********************************************************************

硬件连接: DS1302io - P1.0rst - P1.4 clk - P1.1

DS18B20 dq - P1.5

LCD1602 RS- P2.2 RW - P2.3 EN - P2.4 DATAPORT - P0

/***********************************************************************/

#include<reg52.h>

#include"lcd1602.h"

#include"ds1302.h"

#include"ds18b20.h"

#define uint unsigned int

#define uchar unsigned char

uint b[6]

//年月日时分秒

uchar code row1[]={"2009-10-01 "}

uchar code row2[]={"00:00:00"}

uchar year1[12]={31,28,31,30,31,30,31,31,30,31,30,31}//平年

uchar year2[12]={31,29,31,30,31,30,31,31,30,31,30,31}//润年

uchar j[6]={0x85,0x88,0x8b,0x84+0x40,0x87+0x40,0x8a+0x40}//LCD地址

uchar i,k,jj=0,w,clock=0,bigclock=0,c=0,num

//i循环数 k温度缓存 jj地址位

uint temp

sbit b1=P3^0//设置

sbit b2=P3^1//上调

sbit b3=P3^2//下调

sbit b4=P3^3//转换

sbit b5=P3^4//闹钟

sbit speaker=P3^5

lcdscan()

{

for(i=0i<6i++)

{

lcdwrite(j[i])

lcdshuju(a[11-i*2]+0x30)

lcdwrite(j[i]+0x01)

lcdshuju(a[10-i*2]+0x30)

}

}

void key()

{

if(b1==0)

{

dsaddshuju(0x80,(a[1]<<4)+a[0]+0x80)

while(b1==0)

{

for(i=0i<6i++)

{

b[i]=a[11-i*2+clock]*10+a[10-i*2+clock]

}

if(b4==0)

{

delay(3)

jj++

if(jj==6)

{

jj=0

}

}

if(b2==0)

{

delay(3)

b[jj]++

if(b[5]==60)b[5]=0

if(b[4]==60)b[4]=0

if(b[3]==24)b[3]=0

if((b[0]%4==0 &&b[0]%100!=0) || b[0]%400==0){if(b[2]>year2[b[1]-1])b[2]=1}

else {if(b[2]>year1[b[1]-1])b[2]=1}

if(b[1]==13)b[1]=1

if(b[0]==100)b[0]=0

}

if(b3==0)

{

delay(3)

b[jj]--

if(b[5]==-1)b[5]=59

if(b[4]==-1)b[4]=59

if(b[3]==-1)b[3]=23

if((b[0]%4==0 &&b[0]%100!=0) || b[0]%400==0){if(b[2]<=0)b[2]=year2[b[1]-1]}

else {if(b[2]<=0)b[2]=year1[b[1]-1]}

if(b[1]==0)b[1]=12

if(b[0]==-1)b[0]=99

}

for(i=0i<6i++)

{

a[11-i*2+clock]=b[i]/10

a[10-i*2+clock]=b[i]%10

}

lcdwrite(j[jj])

lcdshuju(0)

lcdwrite(j[jj]+1)

lcdshuju(0)

delay(200)

lcdwrite(j[jj])

lcdshuju(a[11-2*jj+clock]+0x30)

lcdwrite(j[jj]+1)

lcdshuju(a[10-2*jj+clock]+0x30)

delay(200)

if(b1==1)

{

dsaddshuju(0x80,(a[1]<<4)+a[0])

dson()

}

if(b5==0)clock=12

}

}

}

void main()

{

speaker=0

lcdrw=0

dson()

lcdon()

lcdwrite(0x83)

for(i=0i<10i++)

{

lcdshuju(row1[i])

delay(1)

}

lcdwrite(0x84+0x40)

for(i=0i<8i++)

{

lcdshuju(row2[i])

delay(1)

}

dsrst=0

dssclk=0

while(1)

{

for(i=0i<5i++)

{

dsrst=1

dswrite(0x81+i*2)

k=dsread()

dsrst=0

a[i*2]=k&0x0f

a[i*2+1]=(k>>4)&0x0f

}

dsrst=1

dswrite(0x8d)

k=dsread()

dsrst=0

a[10]=k&0x0f

a[11]=(k>>4)&0x0f

delay(100)

lcdscan()

key()

if(b5==0)

{

for(i=0i<12i++)

{

if(a[i+12]==a[i])num++

}

if(num==12)bigclock=1

else num=0

lcdwrite(0x8e)

lcdshuju('&')

}

else

{

lcdwrite(0x8e)

lcdshuju(0x00)

}

if(bigclock==1)

{

speaker=1

c++

if(c==100){bigclock=0speaker=0}

}

temp=readtemperature()//temp是uint型的。不然会出现温度到25后回00的现象。可能是由于十六进制与十进制的差异。

lcdwrite(0x8d+0x40)

lcdshuju(temp/100+0x30)

lcdwrite(0x8e+0x40)

lcdshuju(temp/10%10+0x30)

}

}

自己看看,看不明白HI我。


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

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

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

发表评论

登录后才能评论

评论列表(0条)

保存