找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1076|回复: 12
收起左侧

基于STC89C56单片机的DS1302可调时钟(不按照我设置的时间显示)

[复制链接]
ID:970151 发表于 2023-10-25 21:22 | 显示全部楼层 |阅读模式
450黑币
为什么我的按键可调时钟不按照我的设置的显示呢 我可以按键改变设置的时间LCD也会对应显示我设置过的时间,但是我只要一按键推出TimeSet模式,它就又显示之前的时间了。我明明声明了全局数组。但是我在每个时间改变之后的语句后面加了DS1302_SetTime(),就解决这个问题了。有大佬知道为什么么? 为什么不可以等所有东西设置完在退出的最后加一句DS1302_SetTime()实现呢?

51hei图片_20231025210350.png
51hei图片_20231025210856.png
51hei图片_20231025210922.png
51hei图片_20231025210956.png
51hei图片_20231025212150.jpg

10-2DS1302可调时钟.zip

69.15 KB, 下载次数: 25

普中-6开发板原理图.pdf

205.83 KB, 下载次数: 13

回复

使用道具 举报

ID:970151 发表于 2023-10-25 21:23 | 显示全部楼层
全部的源代码和开发板原理图已上传
回复

使用道具 举报

ID:69038 发表于 2023-10-26 07:14 | 显示全部楼层
没有细看你的代码图片,能读写,说明时序正常,显示不对可能是你的数据转换没做好:
1302读写的是十进制BCD码,你该不会是当做16进制来处理了吧?
回复

使用道具 举报

ID:332444 发表于 2023-10-26 07:32 | 显示全部楼层
那就改为修改立即生效,不能成功的原因极大可能是读取,或在调节时停止读取并在更新后恢复读取.
回复

使用道具 举报

ID:213173 发表于 2023-10-26 10:36 | 显示全部楼层
Diameter 发表于 2023-10-25 21:23
全部的源代码和开发板原理图已上传

把这个示例的端口定义按你的实际电路重新定义即可运行。
无标题.jpg


万年历汉字1602 1302 1820 仿真范例程序.rar (141.83 KB, 下载次数: 14)
回复

使用道具 举报

ID:1064915 发表于 2023-10-26 11:51 | 显示全部楼层
把单片机STC89C56换成89C52,单片机性能不完全一致
回复

使用道具 举报

ID:584814 发表于 2023-10-26 18:18 | 显示全部楼层
本帖最后由 man1234567 于 2023-10-27 09:59 编辑

主要看主程序里的注释自己调整就好,总体感觉有些啰嗦有点乱
#include <REGX51.H>
#include "LCD1602.h"
#include "DS1302.h"
#include "Timer0.h"
#include "Key.h"

unsigned char KeyNum,MODE,TimeSetSelect,TimeSetFlashFlag;

void TimeShow(void)//读时间并按指定位置显示
{
                DS1302_ReadTime();//读时间               
                LCD_ShowNum(1,1,DS1302_Time[0],2);//按指定位置显示年
                LCD_ShowNum(1,4,DS1302_Time[1],2);//按指定位置显示月
                LCD_ShowNum(1,7,DS1302_Time[2],2);//按指定位置显示日
                LCD_ShowNum(2,1,DS1302_Time[3],2);//按指定位置显示时
                LCD_ShowNum(2,4,DS1302_Time[4],2);//按指定位置显示分
                LCD_ShowNum(2,7,DS1302_Time[5],2);//按指定位置显示秒
          
}
void TimeSet(void)//修改时间并实时显示
{
        if(KeyNum==2)//按下2号键
        {
                TimeSetSelect++;//年月日时分秒循环跳转
                if(TimeSetSelect>5)//单向跳转的防溢出
                {
                        TimeSetSelect=0;
                }
        }
        if(KeyNum==3)//按下3号键
        {
                DS1302_Time[TimeSetSelect]++;//时间内容循环跳转,上行,+
                if(DS1302_Time[0]>99){DS1302_Time[0]=0;}//年
                if(DS1302_Time[1]>12){DS1302_Time[1]=1;}//月
                if(DS1302_Time[1]==1||DS1302_Time[1]==3||DS1302_Time[1]==5||DS1302_Time[1]==7||DS1302_Time[1]==8||DS1302_Time[1]==10||DS1302_Time[1]==12)//适应月大小等
                {               
                        if(DS1302_Time[2]>31)//双月大防溢出
                        {
                        DS1302_Time[2]=1;
                        }
                }
                else if(DS1302_Time[1]==4||DS1302_Time[1]==6||DS1302_Time[1]==9||DS1302_Time[1]==11)//单月小防溢出
                {
                        if(DS1302_Time[2]>30)
                {
                        DS1302_Time[2]=1;
                }
                }
                else if(DS1302_Time[1]==2)//2月平润防溢出
                {
                        if(DS1302_Time[0]%4==0)
                        {
                                        if(DS1302_Time[2]>29){DS1302_Time[2]=1;}
                        }
                        else
                        {
                                if(DS1302_Time[2]>28){DS1302_Time[2]=1;}
                        }
                       
                }
                if(DS1302_Time[3]>23){DS1302_Time[3]=0;}//时防溢出
                if(DS1302_Time[4]>59){DS1302_Time[4]=0;}//分防溢出
                if(DS1302_Time[5]>59){DS1302_Time[5]=0;}//秒防溢出
                //                DS1302_SetTime();//不奇怪,原因看看主程序注释。
        }
        if(KeyNum==4)////时间内容循环跳转,下行,-
        {
                DS1302_Time[TimeSetSelect]--;
                if(DS1302_Time[0]<0){DS1302_Time[0]=99;}//同+相关原理,有些啰嗦可以合写
                if(DS1302_Time[1]<1){DS1302_Time[1]=12;}
                if(DS1302_Time[1]==1||DS1302_Time[1]==3||DS1302_Time[1]==5||DS1302_Time[1]==7||DS1302_Time[1]==8||DS1302_Time[1]==10||DS1302_Time[1]==12)
                {               
                        if(DS1302_Time[2]<1)
                        {
                        DS1302_Time[2]=31;
                        }
                        if(DS1302_Time[2]>31)
                        {
                        DS1302_Time[2]=1;
                        }
                }
                else if(DS1302_Time[1]==4||DS1302_Time[1]==6||DS1302_Time[1]==9||DS1302_Time[1]==11)
                {
                if(DS1302_Time[2]<1)
                {
                DS1302_Time[2]=30;
                }
                        if(DS1302_Time[2]>30)
                {
                        DS1302_Time[2]=1;
                }       
                }
                else if(DS1302_Time[1]==2)
                {
                        if(DS1302_Time[0]%4==0)
                        {
                                if(DS1302_Time[2]<1){DS1302_Time[2]=29;}
                                if(DS1302_Time[2]>29){DS1302_Time[2]=1;}
                        }
                        else
                        {
                                if(DS1302_Time[2]<1){DS1302_Time[2]=28;}
                                if(DS1302_Time[2]>28){DS1302_Time[2]=1;}
                        }
                                DS1302_SetTime();
                }
                if(DS1302_Time[3]<0){DS1302_Time[3]=23;}
                if(DS1302_Time[4]<0){DS1302_Time[4]=59;}
                if(DS1302_Time[5]<0){DS1302_Time[5]=59;}
        }
        if(TimeSetSelect==0&&TimeSetFlashFlag==1){LCD_ShowString(1,1,"  ");}//依选择调整类别的显示定位,同样感觉啰嗦
        else{        LCD_ShowNum(1,1,DS1302_Time[0],2);}
        if(TimeSetSelect==1&&TimeSetFlashFlag==1){LCD_ShowString(1,4,"  ");}
        else{        LCD_ShowNum(1,4,DS1302_Time[1],2);}
        if(TimeSetSelect==2&&TimeSetFlashFlag==1){LCD_ShowString(1,7,"  ");}
        else{        LCD_ShowNum(1,7,DS1302_Time[2],2);}
        if(TimeSetSelect==3&&TimeSetFlashFlag==1){LCD_ShowString(2,1,"  ");}
        else{        LCD_ShowNum(2,1,DS1302_Time[3],2);}
        if(TimeSetSelect==4&&TimeSetFlashFlag==1){LCD_ShowString(2,4,"  ");}
        else{        LCD_ShowNum(2,4,DS1302_Time[4],2);}
        if(TimeSetSelect==5&&TimeSetFlashFlag==1){LCD_ShowString(2,7,"  ");}
        else{        LCD_ShowNum(2,7,DS1302_Time[5],2);}
//        DS1302_SetTime();//写时间,可以退出调整后写,否则过于频繁
}
void main()
{
        LCD_Init();//1602初始化,图片中正常显示就没看了
        DS1302_Init();//1302初始化,图片中正常显示就没看了
        Timer0_Init();//定时器初始化,建议在调整时间开始时执行,停留在调时状态过长时自动返回显示
        LCD_ShowString(1,1,"  -  -  ");//美化上行
        LCD_ShowString(2,1,"  :  :  ");//美化下行

        while(1)//主循环,先读按键,有1按下时反转状态关并执行相关语句,然后有无按1键都选择状态执行显示/写时。
        {

                KeyNum=Key();//读按键,1为调时/显时切换,2为调时时选择调整类别,3、4分别是调整的+和-。
                if(KeyNum==1)//按下1号键后切换调时/显示
                {
                        if(MODE==0)//如果正常显示时
                        {
                          MODE=1;//立即先切换到调时模式
                                TimeSetSelect=0;//然后选择从年开始调整,然后并不立即调时,而是随后写入时间
                        }
                        else if(MODE==1)//如果调时模式时
                  {
                                MODE=0;//立即先切换到正常显示模式,然后执行调时
                                DS1302_SetTime();//开始调时,随后不执行写时(TimeSet();),往下执行就是显示新读取1302的时间
                  }
                }
               
                switch(MODE)//选择显时(模式0)和调时(模式1),顺序执行不受按键影响:
                {
                        case 0:TimeShow();break;//显时(因为在按下键后已反转模式,因此显示的以是重新读1302的时间而不是调整后的时间,此时显示的时间不是以前的而是以前的时间加上你在调时中停留的时间,理论有一定概率显示是和以前一样的)
                        case 1:TimeSet();break;//写时间(因为在按下键后已反转模式所以不在调时后执行,此时并写入时间上次读出的时间,不按键就一直这样写且理论上极小概率可能回退一秒,再按1键就进入调时再反转进入显示模式)
                }
        }
}

void Timer0_Routine() interrupt 1//每隔一秒执行一次中断
{
        static unsigned int T0Count;
        TH0=64535/256;
        TL0=64535%256;
        T0Count++;
        if(T0Count>=500)
        {
                T0Count=0;
                TimeSetFlashFlag=!TimeSetFlashFlag;
        }
}
回复

使用道具 举报

ID:970151 发表于 2023-10-27 11:55 | 显示全部楼层
man1234567 发表于 2023-10-26 18:18
主要看主程序里的注释自己调整就好,总体感觉有些啰嗦有点乱
#include
#include "LCD1602.h"

  “switch(MODE)//选择显时(模式0)和调时(模式1),顺序执行不受按键影响:
                {
                        case 0:TimeShow();break;//显时(因为在按下键后已反转模式,因此显示的以是重新读1302的时间而不是调整后的时间,此时显示的时间不是以前的而是以前的时间加上你在调时中停留的时间,理论有一定概率显示是和以前一样的)” 为啥我的DS1302_SetTime只要调用过不就会把我全局数组里改变的时间写到DS1302里面 我DS1302不应该存在以前的时间的啊
回复

使用道具 举报

ID:584814 发表于 2023-10-27 14:59 | 显示全部楼层
Diameter 发表于 2023-10-27 11:55
“switch(MODE)//选择显时(模式0)和调时(模式1),顺序执行不受按键影响:
                {
    ...

细读我的注释就知道了。
改的方式很多,比如模式的切换可以在相应模式工作完成后进行。
你的程序现在是显示模式时写时间到1302而修改后不保存只是重读1302再显示。
回复

使用道具 举报

ID:970151 发表于 2023-10-27 16:56 | 显示全部楼层
man1234567 发表于 2023-10-27 14:59
细读我的注释就知道了。
改的方式很多,比如模式的切换可以在相应模式工作完成后进行。
你的程序现在是 ...

逆天我跟着视频教程做的 DS1302写完还要加保存程序么 不是写入 就自动覆盖DS1302芯片原来的数据啊
回复

使用道具 举报

ID:965189 发表于 2023-10-28 08:56 来自手机 | 显示全部楼层
我之前试过修改不成功,后来每次修改之后重新初始化DS1302就可以了。
回复

使用道具 举报

ID:584814 发表于 2023-10-28 17:15 | 显示全部楼层
Diameter 发表于 2023-10-27 16:56
逆天我跟着视频教程做的 DS1302写完还要加保存程序么 不是写入 就自动覆盖DS1302芯片原来的数据啊

你画个框图就知道逻辑错在哪里了
回复

使用道具 举报

ID:476415 发表于 2024-1-7 10:27 | 显示全部楼层
是时序上出问题了,写入操作没有完成时序?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表