标题: DS1302实时时钟的问题,如何用4个按键调时呢? [打印本页]
作者: 迈特拉布 时间: 2018-5-29 11:27
标题: DS1302实时时钟的问题,如何用4个按键调时呢?
不好意思,我又来了,我用4个按键调节时钟(考虑手上没有与门器件没用中断,时间不够了),代码如下,可是LCD不显示,请各位帮俺看看如何修改,问题应该出在主函数和主函数上面的子函数上了,请各位帮帮忙
#include <reg52.h>
#include <string.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit SDA=P1^0; // DS1302数据线
sbit CLK=P1^1; //DS1302时钟线
sbit RST=P1^2; //DS1302复位线
sbit RS=P2^0;
sbit RW=P2^1;
sbit EN=P2^2;
sbit K1=P3^4; // 选择
sbit K2=P3^5; // 加
sbit K3=P3^6; // 减
sbit K4=P3^7; // 确定
uchar tCount=0;
//一年中每个月的天数,2月的天数由年份决定
uchar MonthsDays[]={31,31,30,31,30,31,31,30,31,30,31};
uchar *WEEK[]={"SAT","SUN","MON","TUS","WEN","THU","FRI"};
uchar LCD_DSY_BUFFER1[]={"Date 00-00-00 "}; //LCD显示缓冲
uchar LCD_DSY_BUFFER2[]={"Time 00:00:00 "};
uchar DateTime[7]; //所读取的日期时间
char Adjust_Index=-1;
uchar Change_Flag[]="-MHDM-Y"; //当前调节的标志:分钟,小时,天,月,年
void DelayMS(uint x)
{
uchar i;
while(x--) for(i=0;i<120;i++);
}
void DS1302_Write_Byte(uchar x) //发送一个字节到DS1302通信线上
{
uchar i;
for(i=0;i<8;i++) //低位在前,移位输出
{
SDA=x&1; //输出该位数据
CLK=1; //拉高时钟
CLK=0; //拉低时钟,完成一个位的操作
x>>=1;
}
}
uchar DS1302_Read_Byte()
{
uchar i,b,t;
for(i=0;i<8;i++)
{
b>>=1;
t=SDA;
b|=t<<7;
CLK=1;
CLK=0;
}
return b/16*10+b%16;
}
uchar Read_Data(uchar addr)
{
uchar dat;
RST=0;
CLK=0;
RST=1;
DS1302_Write_Byte(addr);
dat=DS1302_Read_Byte();
CLK=1;
RST=0;
_nop_(); //以下为DS1302复位的稳定时间,必须的。
CLK = 1;
_nop_();
SDA = 0;
_nop_();
SDA = 1;
_nop_();
return dat;
}
void Write_DS1302(uchar addr,uchar dat)
{
CLK=0;
RST=1;
DS1302_Write_Byte(addr);
DS1302_Write_Byte(dat);
CLK=0;
RST=0;
}
void SET_DS1302()
{
uchar i;
Write_DS1302(0x8e,0x00);
for(i=0;i<7;i++)
{
Write_DS1302(0x80+2*i,(DateTime[i]/10<<4|(DateTime[i]%10)));
}
Write_DS1302(0x8e,0x80);
}
void GetTime()
{
uchar i;
for(i=0;i<7;i++)
{
DateTime[i]=Read_Data(0x81+2*i);
}
}
uchar Read_LCD_State()
{
uchar state;
RS=0; //命令
RW=1; //读
EN=1; //读为高电平
DelayMS(1);
state=P0;
EN=0;
DelayMS(1);
return state; //要输出
}
void LCD_Busy_Wait() //LCD1602响应速度相对于单片机来说是偏慢的
{
while((Read_LCD_State()&0x08)==0x80);
DelayMS(5);
}
void Write_LCD_Data(uchar dat) //写数据
{
LCD_Busy_Wait(); //忙检测
RS=1; //数据
RW=0; //写为低电平
EN=0; //写操作时为低电平
P0=dat;
EN=1;
DelayMS(1);
EN=0;
}
void Write_LCD_Command(uchar cmd)//写命令
{
LCD_Busy_Wait();
RS=0; //命令
RW=0; //写为低电平
EN=0; //写操作时为低电平
P0=cmd;
EN=1;
DelayMS(1);
EN=0;
}
void Init_LCD() //LCD初始化
{
Write_LCD_Command(0x38); DelayMS(1);
Write_LCD_Command(0x01); DelayMS(1);
Write_LCD_Command(0x06); DelayMS(1);
Write_LCD_Command(0x0C); DelayMS(1);
}
void Set_LCD_POS(uchar p)
{
Write_LCD_Command(p+0x80);
}
void Display_LCD_String(uchar p,uchar *s)
{
uchar i;
Set_LCD_POS(p);
for(i=0;i<16;i++)
{
Write_LCD_Data(s[i]);
DelayMS(1);
}
}
void Format_DateTime(uchar d,uchar *a)
{
a[0]=d/10+'0';a[1]=d%10+'0';
}
uchar isLeapYear(uint y)
{
return (y%4==0&&y%100!=0)||(y%400==0);
}
void DateTime_Adjust(char x)
{
switch (Adjust_Index)
{
case 6: //年
if(x== 1&&DateTime[6]<99) DateTime[6]++;
if(x==-1&&DateTime[6]>0) DateTime[6]--;
MonthsDays[2]=isLeapYear(2000+DateTime[6])? 29:28;
if(DateTime[3]>MonthsDays[DateTime[4]])
DateTime[3]=MonthsDays[DateTime[4]];
//RefreshWeekDay();
break;
case 4: //月
if(x== 1&&DateTime[4]<12) DateTime[4]++;
if(x==-1&&DateTime[4]>1) DateTime[4]--;
MonthsDays[2]=isLeapYear(2000+DateTime[6])? 29:28;
if(DateTime[3]>MonthsDays[DateTime[4]])
DateTime[3]=MonthsDays[DateTime[4]];
//RefreshWeekDay();
break;
case 3: //日
MonthsDays[2]=isLeapYear(2000+DateTime[6])? 29:28;
if(x== 1&&DateTime[3]<MonthsDays[DateTime[4]]) DateTime[3]++;
if(x==-1&&DateTime[3]>0) DateTime[3]--;
//RefreshWeekDay();
break;
case 2: //时
if(x== 1&&DateTime[2]<23) DateTime[2]++;
if(x==-1&&DateTime[2]>0) DateTime[2]--;
break;
case 1: //秒
if(x== 1&&DateTime[1]<59) DateTime[1]++;
if(x==-1&&DateTime[1]>0) DateTime[1]--;
break;
}
}
void main()
{
Init_LCD();
while(1)
{
GetTime();
if(K1==0)
{
DelayMS(10); //按键消抖
while(K1==0);
if(Adjust_Index==-1||Adjust_Index==1) {Adjust_Index=7;}//uchar Change_Flag[]="-MHDM-Y";
Adjust_Index--;
if(Adjust_Index==5) Adjust_Index=4;
LCD_DSY_BUFFER2[13]='[';
LCD_DSY_BUFFER2[14]=Change_Flag[Adjust_Index];
LCD_DSY_BUFFER2[15]=']';
if(K2==0) // 加
{
DelayMS(10); //按键消抖
while (K2==0); DateTime_Adjust(1);
}
else if(K3==0) // 减
{
DelayMS(10); //按键消抖
while (K3==0); DateTime_Adjust(-1);
}
else if(K4==0) // 确定
{
DelayMS(10); //按键消抖
while(K4==0);
SET_DS1302(); //调整后的时间写入DS1302
LCD_DSY_BUFFER2[13]=' ';
LCD_DSY_BUFFER2[14]=' ';
LCD_DSY_BUFFER2[15]=' ';
Adjust_Index=-1;
}
}
}
Format_DateTime(DateTime[6],LCD_DSY_BUFFER1+5); //年
Format_DateTime(DateTime[4],LCD_DSY_BUFFER1+8); //月
Format_DateTime(DateTime[3],LCD_DSY_BUFFER1+11); //日
strcpy(LCD_DSY_BUFFER1+13,WEEK[DateTime[5]]); //week
Format_DateTime(DateTime[2],LCD_DSY_BUFFER2+5); //时
Format_DateTime(DateTime[1],LCD_DSY_BUFFER2+8); //分
Format_DateTime(DateTime[0],LCD_DSY_BUFFER2+11); //秒
Display_LCD_String(0x00,LCD_DSY_BUFFER1);
Display_LCD_String(0x40,LCD_DSY_BUFFER2);
}
作者: zl2168 时间: 2018-5-29 22:31
本帖最后由 zl2168 于 2018-5-29 22:33 编辑
下功夫阅读别人成功有效的程序,认真体会理解,仔细对照查错。而不是发出大段无里头程序,让别人帮你查错。
作者: az2232549 时间: 2018-5-29 22:37
仔细看,可以的
作者: 王企鹅 时间: 2018-5-29 22:46
肯定是需要中断的,毕竟单片机是怎么都跑步过来
作者: 王企鹅 时间: 2018-5-29 22:49
你这样处理,按键调节分开。按键处理的时候。停止时间显示,然后按键处理完了再回去处理显示
作者: benng1996 时间: 2018-5-29 22:57
你把LCD的函数写在死循环外面当然LCD不显示啦,在编写程序时要有个程序流程的概念,楼上说得对,要自己仔细查,不然永远都是发帖问
作者: 迈特拉布 时间: 2018-5-29 23:39
苦口良药,感谢指点
作者: 迈特拉布 时间: 2018-5-29 23:40
明白,已经解决
作者: 迈特拉布 时间: 2018-5-29 23:41
以后会注意,感谢提醒
作者: zl2168 时间: 2018-5-30 06:20
本帖最后由 zl2168 于 2018-5-30 06:22 编辑
我这里有3个不同方式的按键调时案例,你可参考一下。
实例91 具有校正功能的时钟1302(LCD1602显示)
先Proteus仿真,确认有效。
实例91 带校正时钟1302(LCD1602显示).rar
(52.68 KB, 下载次数: 79)
以上摘自张志良编著《
80C51单片机仿真设计实例教程——基于Keil C和Proteus》清华大学出版社ISBN 978-7-302-41682-1,书中电路和程序设计有详细说明,程序语句条条有注解。
作者: zl2168 时间: 2018-5-30 06:23
实例93 具有校正功能的时钟1302(LED数码管显示)
先Proteus仿真一下,确认有效。
以上摘自张志良编著《80C51单片机仿真设计实例教程——基于Keil C和Proteus》清华大学出版社ISBN 978-7-302-41682-1,内有常用的单片机应用100案例,用于仿真实验操作,电路与程序真实可靠可信可行。
作者: zl2168 时间: 2018-5-30 06:25
本帖最后由 zl2168 于 2018-5-30 06:27 编辑
实例94 模拟电子钟(由80C51定时器产生秒时基)
先Proteus仿真一下,确认有效。
实例94 模拟电子钟(由80C51定时器产生秒时基).rar
(43.05 KB, 下载次数: 15)
以上摘自张志良编著《80C51单片机仿真设计实例教程——基于Keil C和Proteus》清华大学出版社ISBN 978-7-302-41682-1,内有常用的单片机应用100案例,用于仿真实验操作,电路与程序真实可靠可信可行。书中电路和程序设计有详细说明,程序语句条条有注解。
作者: 安笙mie 时间: 2019-4-21 20:05
迈特拉布 发表于 2018-5-29 23:41
以后会注意,感谢提醒
楼主可以发个联系方式吗,想搬运一下程序,谢谢
欢迎光临 (http://www.51hei.com/bbs/) |
Powered by Discuz! X3.1 |