#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我。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)