本帖最后由 xuesong10210 于 2010-10-13 22:15 编辑
自己编写的程序。呵呵!拿出来晒晒。有什么改进的地方大家多提宝贵意见!
程序能够完成时钟显示和日期显示,下载调试一切正常:
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define second 0x80
#define minute 0x82
#define hours 0x84
sbit rs=P3^5;
sbit sclk=P3^6;
sbit sda=P3^4;
sbit ACC7=ACC^7;
sbit ACC0=ACC^0;
uchar time[8],date[15];
uchar Sec,Min,Hour,Week,Day,Month,Year;
ds1302_inputbyte(uchar dat) //写数
{
uchar i;
ACC = dat;
for(i=8; i>0; i--)
{
sclk = 0;
sda = ACC0; //由低位到高位
sclk = 1; //上升沿写入数据
ACC >>= 1;
}
}
ds1302_outputbyte() //读数
{uchar i;
for(i=8; i>0; i--)
{
sclk = 0; //下降沿读出DS1302的数据
ACC >>= 1; //读出由低到高位,只能移7次有效位!!!
ACC7 = sda; //第一个数据
sclk = 1;
}
return (ACC);
}
write_ds1302(uchar address,uchar Data) //一个完整的写操作
{
rs=0;
_nop_();
sclk=0;
rs=1;
ds1302_inputbyte(address);
ds1302_inputbyte(Data);
sclk=1;
rs=0;
}
read_ds1302(uchar address) //一个完整的读操作
{ uchar Data;
rs=0;
sclk=0;
rs=1;
ds1302_inputbyte(address|0x01);
Data=ds1302_outputbyte();
sclk=1;
rs=0;
return(Data);
}
void DS1302_GetTime() //转换时间(BCD码转换成十进制数)
{
uchar ReadValue;
ReadValue = read_ds1302(0x80);
Sec= ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0f); //秒转换
ReadValue =read_ds1302(0x82);
Min = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0f); //分转换
ReadValue = read_ds1302(0x84);
Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0f); //时转换
}
void DS1302_Getday() //转换日期(BCD码转换成十进制数)
{
uchar ReadValue;
ReadValue = read_ds1302(0x8A);
Week= (ReadValue&0x07);
ReadValue =read_ds1302(0x86);
Day = ((ReadValue&0x30)>>4)*10 + (ReadValue&0x0f);
ReadValue = read_ds1302(0x88);
Month = ((ReadValue&0x10)>>4)*10 + (ReadValue&0x0f);
ReadValue = read_ds1302(0x8C);
Year = (ReadValue>>4)*10 + (ReadValue&0x0f);
}
timetostring() //时间显示(十进制数转换成字符)
{
time[0]=Hour/10+'0';
time[1]=Hour%10+'0';
time[2]=':';
time[3]=Min/10+'0';
time[4]=Min%10+'0';
time[5]=':';
time[6]=Sec/10+'0';
time[7]=Sec%10+'0';
time[8]='\0';
}
daytostring() //日期显示(日期转换成相应的字符)
{
DS1302_Getday();
date[0]='2'; //年显示
date[1]='0';
date[2]=Year/10+'0';
date[3]=Year%10+'0';
date[4]='-';
date[5]=Month/10+'0'; //月显示
date[6]=Month%10+'0';
date[7]='-';
date[8]=Day/10+'0'; //日显示
date[9]=Day%10+'0';
date[10]=' ';
switch(Week) //周显示
{
case 1: date[11]='M';
date[12]='o';
date[13]='n';
date[14]=' ';
break;
case 2: date[11]='T';
date[12]='u';
date[13]='e';
date[14]='s';
break;
case 3: date[11]='W';
date[12]='e';
date[13]='d';
date[14]=' ';
break;
case 4: date[11]='T';
date[12]='h';
date[13]='u';
date[14]='r';
break;
case 5: date[11]='F';
date[12]='r';
date[13]='i';
date[14]=' ';
break;
case 6: date[11]='S';
date[12]='a';
date[13]='t';
date[14]=' ';
break;
case 7: date[11]='S';
date[12]='u';
date[13]='n';
date[14]=' ';
break;
}
}
DS1302_Set(uchar address,uchar value) //设定时间及日期写入子函数
{ write_ds1302(0x8e,0x00); //打开DS1302的写允许
write_ds1302(0x80,0x80); //关闭DS1302时钟振荡
write_ds1302(address,(value/10)<<4|(value%10));
//write_ds1302(0x8e,0x80);
}
///////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
sbit LCD_RS = P2^6;
sbit LCD_RW = P2^5;
sbit LCD_EP = P2^7;
delay(int ms)
{ // 延时子程序
int i;
while(ms--)
{
for(i = 0; i< 250; i++)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
}
}
bit lcd_bz()
{ // 测试LCD忙碌状态
bit result;
LCD_RS = 0;
LCD_RW = 1;
LCD_EP = 1;
_nop_();
_nop_();
_nop_();
_nop_();
result = (bit)(P0 & 0x80);
LCD_EP = 0;
return result;
}
lcd_wcmd(uchar cmd)
{ // 写入指令数据到LCD
while(lcd_bz());
LCD_RS = 0;
LCD_RW = 0;
LCD_EP = 0;
_nop_();
_nop_();
P0 = cmd;
_nop_();
_nop_();
_nop_();
_nop_();
LCD_EP = 1;
_nop_();
_nop_();
_nop_();
_nop_();
LCD_EP = 0;
}
lcd_pos(uchar pos)
{ //设定显示位置
lcd_wcmd(pos | 0x80);
}
lcd_wdat(uchar dat1)
{ //写入字符显示数据到LCD
while(lcd_bz());
LCD_RS = 1;
LCD_RW = 0;
LCD_EP = 0;
P0 = dat1;
_nop_();
_nop_();
_nop_();
_nop_();
LCD_EP = 1;
_nop_();
_nop_();
_nop_();
_nop_();
LCD_EP = 0;
}
lcd_init()
{ //LCD初始化设定
lcd_wcmd(0x38); //16*2显示,5*7点阵,8位数据
delay(1);
lcd_wcmd(0x0c); //显示开,关光标
delay(1);
lcd_wcmd(0x06); //移动光标
delay(1);
lcd_wcmd(0x01); //清除LCD的显示内容
delay(1);
}
//////////////////////////////////////////////////////////////////
sbit P1_0=P1^0;
sbit P1_1=P1^1;
uchar Set=0,flag=0,a;
keysan() //时间设置函数
{
while((!P1_1)||(!P1_0)) //判断按键
{ if(P1_0==0) //当P1_0变化时P1_1设置的时间才会有效
{flag++; //(在进入下一个设置时Set清0)
Set=0; }
else
Set++;
while((!P1_1)||(!P1_0)); //松手检测
switch(flag)
{ case 1: //分钟设置
if(Set!=0)
{
if(Set==60)
Set=0;
DS1302_Set(minute,Set&0x3f);}
else
{
write_ds1302(0x8e,0x00);
write_ds1302(0x80,0x80);
}
break;
case 2: //时设置
if(Set!=0)
{
if(Set==24)
Set=0;
DS1302_Set(hours,Set&0x1f);}
else
{
write_ds1302(0x8e,0x00);
write_ds1302(0x80,0x80);
}
break;
case 3: //周设置
if(Set!=0)
{
if(Set==8)
Set=1;
DS1302_Set(0x8A,Set&0x07);}
else
{
write_ds1302(0x8e,0x00);
write_ds1302(0x80,0x80);
}
break;
case 4: //日期设置
if(Set!=0)
{
if(Set==32)
Set=0;
DS1302_Set(0x86,Set&0x3f);}
else
{
write_ds1302(0x8e,0x00);
write_ds1302(0x80,0x80);
}
break;
case 5: //月份设置
if(Set!=0)
{
if(Set==13)
Set=1;
DS1302_Set(0x88,Set&0x1f);}
else
{
write_ds1302(0x8e,0x00);
write_ds1302(0x80,0x80);
}
break;
case 6: //年份显示
if(Set!=0)
{
if(Set==100)
Set=0;
DS1302_Set(0x8c,Set);}
else
{
write_ds1302(0x8e,0x00);
write_ds1302(0x80,0x80);
}
break;
/*if(Set==24) Set=0;
DS1302_Settime(hours,Set&0x1f);
break;*/
default: //跳出时间设置开始走时
if(Set==0)
{write_ds1302(0x8e,0x00);
write_ds1302(0x80,0x00);
flag=0;}
}
}
}
////////////////////////////////////////////////////////////////////
void main()
{
uint i;
lcd_init();
delay(10);
write_ds1302(0x8e,0x00);
write_ds1302(0x80,0x00);
write_ds1302(0x8e,0x80);
while(1)
{
keysan();
DS1302_GetTime();
timetostring();
lcd_pos(0x43); //设置显示位置
for(i=0;i<8;i++) //用1602显示时间
{
lcd_wdat(time);
}
daytostring();
lcd_pos(0x01); //设置显示位置
for(i=0;i<15;i++) //用1602显示时间
{
lcd_wdat(date);
}
}
} |