stc89c52数码管DS1302电子时钟

2023-11-05 19:30

本文主要是介绍stc89c52数码管DS1302电子时钟,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

@stc89c52数码管DS1302电子时钟

刚刚开始学编程,暑假期间闲来无事,用stc89c52通过ds1302做了一个电子时钟。我对ds1302的时钟代码理解也不是太深,自己在网上搜了一下相关代码,以及自己琢磨了一下,做了一个简陋的电子时钟。废话不多直接上代码。

在这里插入代码片
#ifndef __DS1302_H_
#define __DS1302_H_
//---包含头文件---//
#include<reg52.h>
#include<intrins.h>
//---重定义关键词---//
#ifndef uchar
#define uchar unsigned char
#endif#ifndef uint 
#define uint unsigned int
#endif//---定义ds1302使用的IO口---//
sbit DSIO=P3^4;
sbit RST=P3^5;
sbit SCLK=P3^6;//---定义全局函数---//
void Ds1302Write(uchar addr, uchar dat);
uchar Ds1302Read(uchar addr);
void Ds1302Init();
void Ds1302ReadTime();
//---加入全局变量--//
extern uchar TIME[7]; //加入全局变量#endif

接着是ds1302.c

#include"ds1302.h"
char code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d}; 
char code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};
sbit k1=P3^1;
//---DS1302时钟初始化2016年5月7日星期六12点00分00秒。---//
//---存储顺序是秒分时日月周年,存储格式是用BCD码---//
char TIME[7] = {0, 0x12, 0x12, 0x07, 0x05, 0x06, 0x16};
void Ds1302Write(char addr, char dat)
{char n;RST = 0;_nop_();SCLK = 0;//先将SCLK置低电平。_nop_();RST = 1; //然后将RST(CE)置高电平。_nop_();for (n=0; n<8; n++)//开始传送八位地址命令{DSIO = addr & 0x01;//数据从低位开始传送addr >>= 1;SCLK = 1;//数据在上升沿时,DS1302读取数据_nop_();SCLK = 0;_nop_();}for (n=0; n<8; n++)//写入8位数据{DSIO = dat & 0x01;dat >>= 1;SCLK = 1;//数据在上升沿时,DS1302读取数据_nop_();SCLK = 0;_nop_(); } uchar Ds1302Read(uchar addr)
{uchar n,dat,dat1;RST = 0;_nop_();SCLK = 0;//先将SCLK置低电平。_nop_();RST = 1;//然后将RST(CE)置高电平。_nop_();for(n=0; n<8; n++)//开始传送八位地址命令{DSIO = addr & 0x01;//数据从低位开始传送addr >>= 1;SCLK = 1;//数据在上升沿时,DS1302读取数据_nop_();SCLK = 0;//DS1302下降沿时,放置数据_nop_();}_nop_();for(n=0; n<8; n++)//读取8位数据{dat1 = DSIO;//从最低位开始接收dat = (dat>>1) | (dat1<<7);SCLK = 1;_nop_();SCLK = 0;//DS1302下降沿时,放置数据_nop_();}RST = 0;_nop_(); //以下为DS1302复位的稳定时间,必须的。SCLK = 1;_nop_();DSIO = 0;_nop_();DSIO = 1;_nop_();return dat; 
}void Ds1302Init()
{uchar n,temp;Ds1302Write(0x8E,0X00);   //禁止写保护,就是关闭写保护功能for (n=0; n<7; n++)//写入7个字节的时钟信号:分秒时日月周年{Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]); }Ds1302Write(0x8E,0x80);   //打开写保护功能
}void Ds1302ReadTime()
{
uchar n;for (n=0; n<7; n++)//读取7个字节的时钟信号:分秒时日月周年{TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);}
}

ds1302是电子时钟的计时器,是关键。
然后是数码管显示函数smguan.h汉语拼的,勿怪,哈哈哈。很low。

#ifndef _SMGUAN_H_
#define _SMGUAN_H_#include "reg52.h"    //此文件中定义了单片机的一些特殊功能寄存器
#include"ds1302.h"
#include"key.h"
#include"smguan.h"void datapros();
void datayears();
void DigDisplay();
void clockyears();
void clockpros();
unsigned char BCD_shi(unsigned char bcd);
unsigned char shi_BCD(unsigned char shi);#endif

接下来是smguan.c

#include "reg52.h"    //此文件中定义了单片机的一些特殊功能寄存器
#include"ds1302.h"
#include"key.h"
#include"smguan.h"sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;u8 DisplayData[8];
u8 code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};void datapros()   
{ Ds1302ReadTime();DisplayData[0] = smgduan[TIME[2]/16];    //时DisplayData[1] = smgduan[TIME[2]&0x0f];     DisplayData[2] = 0x40;DisplayData[3] = smgduan[TIME[1]/16];    //分DisplayData[4] = smgduan[TIME[1]&0x0f]; DisplayData[5] = 0x40;DisplayData[6] = smgduan[TIME[0]/16];    //秒DisplayData[7] = smgduan[TIME[0]&0x0f];   
}
void datayears()   
{Ds1302ReadTime();DisplayData[0] = smgduan[TIME[6]/16];    //年DisplayData[1] = smgduan[TIME[6]&0x0f];     DisplayData[2] = 0x40;DisplayData[3] = smgduan[TIME[4]/16];    //月DisplayData[4] = smgduan[TIME[4]&0x0f]; DisplayData[5] = 0x40;DisplayData[6] = smgduan[TIME[3]/16];    //日DisplayData[7] = smgduan[TIME[3]&0x0f];
}
void clockpros()
{DisplayData[0] = smgduan[clock_display[2]/16];    //时DisplayData[1] = smgduan[clock_display[2]&0x0f];     DisplayData[2] = 0x40;DisplayData[3] = smgduan[clock_display[1]/16];    //分DisplayData[4] = smgduan[clock_display[1]&0x0f]; DisplayData[5] = 0x40;DisplayData[6] = smgduan[clock_display[0]/16];    //秒DisplayData[7] = smgduan[clock_display[0]&0x0f];}void clockyears()   
{DisplayData[0] = smgduan[clock_display[6]/16];    //年DisplayData[1] = smgduan[clock_display[6]&0x0f];     DisplayData[2] = 0x40;DisplayData[3] = smgduan[clock_display[4]/16];    //月DisplayData[4] = smgduan[clock_display[4]&0x0f]; DisplayData[5] = 0x40;DisplayData[6] = smgduan[clock_display[3]/16];    //日DisplayData[7] = smgduan[clock_display[3]&0x0f];
}
void DigDisplay()
{u8 i;for(i=0;i<8;i++){switch(i)  //位选,选择点亮的数码管,{case(0):LSA=0;LSB=0;LSC=0; break;//显示第0位case(1):LSA=1;LSB=0;LSC=0; break;//显示第1位case(2):LSA=0;LSB=1;LSC=0; break;//显示第2位case(3):LSA=1;LSB=1;LSC=0; break;//显示第3位case(4):LSA=0;LSB=0;LSC=1; break;//显示第4位case(5):LSA=1;LSB=0;LSC=1; break;//显示第5位case(6):LSA=0;LSB=1;LSC=1; break;//显示第6位case(7):LSA=1;LSB=1;LSC=1; break;//显示第7位 }P0=DisplayData[7-i];//发送数据delay(100); //间隔一段时间扫描 P0=0x00;//消隐}  
}unsigned char BCD_shi(unsigned char bcd)  //BCD码转换成十进制
{unsigned char Z;Z=(bcd/16)*10 +bcd%16;return Z;
}
unsigned char shi_BCD(unsigned char shi)  //十进制转换成BCD码
{return ((shi/10)*16+(shi%10));
}

我的所有时钟控制和模式选择都在key.c里面,通过按键进行选择。
接下来是按键函数。key.h

#ifndef _KEY_H_
#define _KEY_H_#include "reg52.h"    //此文件中定义了单片机的一些特殊功能寄存器
#include"ds1302.h"
#include"key.h"
#include"smguan.h"typedef unsigned int u16;   //对数据类型进行声明定义
typedef unsigned char u8;
void delay(u16 i);
void KEY1_time();
void KEY1_date();
void Start();
void key_just();
void song_time();
void key_clock_just();
void clock_just();
void clock_date();
void clock_time();
extern uchar clock_display[7];#endif

然后key.c

#include "reg52.h"    //此文件中定义了单片机的一些特殊功能寄存器
#include"ds1302.h"
#include"key.h"
#include"smguan.h"sbit k1=P3^1;
sbit k2=P3^0;
sbit k3=P3^2;
sbit k4=P3^3;
sbit led1=P2^5;
sbit led2=P2^6;
sbit led3=P2^7;
sbit led4=P2^0;
sbit led5=P2^1;
sbit beep=P1^5;
bit flag,flag1=0,flag2=0;unsigned char last_miao=0;
unsigned char miao;
extern unsigned char last_miao;
extern unsigned char miao;
uchar clock_display[7]={0x10, 0x12, 0x12, 0x07, 0x05, 0x06, 0x16};
void DigDisplay();
void datapros();
void datayears();void delay(u16 i)
{while(i--); 
}
void KEY1_time()
{static u16 count_2=0;static u16 count_3_4=0;static u16 count_4=0;datapros();  DigDisplay();if(k2==0){delay(1000);if(k2==0){count_2++;if(count_2==4)count_2=1;//循环选择while(!k2)//按键检测是否松开{  led1=1;led2=1;led3=1;}}}if(k3==0){delay(1000);if(k3==0){count_3_4++;while(!k3);} }if(k4==0){delay(1000);if(k4==0){count_3_4--;while(!k4);}}if(count_2==3)//修改时{led3=0;TIME[2]+=count_3_4;}if(count_2==2)//修改分{led2=0;TIME[1]+=count_3_4;}if(count_2==1)//修改秒{led1=0;TIME[0]+=count_3_4;}count_3_4=0;if((TIME[0]&0x0f)>9)      //换成BCD码。{TIME[0]=TIME[0]+6;}if((TIME[1]&0x0f)>9)      //换成BCD码。{TIME[1]=TIME[1]+6;}if((TIME[2]&0x0f)>9)      //换成BCD码。{TIME[2]=TIME[2]+6;}if(TIME[0]>=0x60)  //分秒只能到59{TIME[0]=0;}if(TIME[1]>=0x60)  //分秒只能到59{TIME[1]=0;}if(TIME[2]>=0x24)  //小时只能到23{TIME[2]=0;}}void KEY1_date()
{static u16 count_2=0;static u16 count_3_4=0;datayears();  DigDisplay();if(k2==0){delay(1000);if(k2==0){count_2++;if(count_2==4)count_2=1;//循环选择while(!k2)//按键检测是否松开{  led1=1;led2=1;led3=1;}}}if(k3==0){delay(1000);if(k3==0){count_3_4++;while(!k3);} }if(k4==0){delay(1000);if(k4==0){count_3_4--;while(!k4);}}   if(count_2==3)//修改年{led3=0;TIME[6]+=count_3_4;}if(count_2==2)//修改月{led2=0;TIME[4]+=count_3_4;}if(count_2==1)//修改日{led1=0;TIME[3]+=count_3_4;}count_3_4=0;if((TIME[3]&0x0f)>9)      //换成BCD码。{TIME[3]=TIME[3]+6;}if((TIME[4]&0x0f)>9)    {TIME[4]=TIME[4]+6;}if((TIME[6]&0x0f)>9)      {TIME[6]=TIME[6]+6;}if(TIME[3]>=0x32)                   //日只能到31{TIME[3]=0; }if(TIME[4]>=0x13)               //月只能到12{TIME[4]=0;}     
}void Start()
{
miao=BCD_shi(TIME[0]);if(miao-last_miao>=5){flag=~flag;last_miao=miao;  }if(flag!=0){datayears(); }else{datapros();  //数据处理函数    }   
}
void key_just()
{
static u16 count_1=0;if(k2==0){ flag1=~flag1;led4=~led4;}f(flag1==0)Start();     else{if(k1==0){delay(1000);if(k1==0){  count_1++;if(count_1==3)count_1=0;while(!k1);}} if(count_1==1){KEY1_time();     Ds1302Init();}if(count_1==2){KEY1_date();Ds1302Init();}elsedatapros();}
}
void clock_time()
{static u16 count_2=0;static u16 count_3_4=0;static u16 count_4=0;clockpros();;  DigDisplay();if(k2==0){delay(1000);if(k2==0){count_2++;if(count_2==4)count_2=1;//循环选择while(!k2)//按键检测是否松开{  led1=1;led2=1;led3=1;}}}if(k3==0){delay(1000);if(k3==0){count_3_4++;while(!k3);} }if(k4==0){delay(1000);if(k4==0){count_3_4--;while(!k4);}}   if(count_2==3)//修改时{led3=0;clock_display[2]+=count_3_4;}if(count_2==2)//修改分{led2=0;clock_display[1]+=count_3_4;}if(count_2==1)//修改秒{led1=0;clock_display[0]+=count_3_4;}count_3_4=0;if((clock_display[0]&0x0f)>9)      //换成BCD码。{clock_display[0]=clock_display[0]+6;}if((clock_display[1]&0x0f)>9)      //换成BCD码。{clock_display[1]=clock_display[1]+6;}if((clock_display[2]&0x0f)>9)      //换成BCD码。{clock_display[2]=clock_display[2]+6;}if(clock_display[0]>=0x60)  //分秒只能到59{clock_display[0]=0;}if(clock_display[1]>=0x60)  //分秒只能到59{clock_display[1]=0;}if(clock_display[2]>=0x24)  //小时只能到23{clock_display[2]=0;}}
void clock_date()
{static u16 count_2=0;static u16 count_3_4=0;clockyears();  DigDisplay();if(k2==0){delay(1000);if(k2==0){count_2++;if(count_2==4)count_2=1;//循环选择while(!k2)//按键检测是否松开{  led1=1;led2=1;led3=1;}}}if(k3==0){delay(1000);if(k3==0){count_3_4++;while(!k3);} }if(k4==0){delay(1000);if(k4==0){count_3_4--;while(!k4);}}   if(count_2==3)//修改年{led3=0;clock_display[6]+=count_3_4;}if(count_2==2)//修改月{led2=0;clock_display[4]+=count_3_4;}if(count_2==1)//修改日{led1=0;clock_display[3]+=count_3_4;}count_3_4=0;if((clock_display[3]&0x0f)>9)      //换成BCD码。{clock_display[3]=clock_display[3]+6;}if((clock_display[4]&0x0f)>9)    {clock_display[4]=clock_display[4]+6;}if((clock_display[6]&0x0f)>9)      {clock_display[6]=clock_display[6]+6;}if(clock_display[3]>=0x32)                   //日只能到31{clock_display[3]=0; }if(clock_display[4]>=0x13)               //月只能到12{clock_display[4]=0;}     
}
void clock_just()
{static u16 count_1=0;if(k1==0){delay(1000);if(k1==0){  count_1++;if(count_1==3)count_1=0;while(!k1);}} if(count_1==1){clock_time();     
//     Ds1302Init();}if(count_1==2){clock_date();
//     Ds1302Init();}
//  else
//        datapros(); 
}
void key_clock_just()
{if(k4==0){delay(1000);if(k4==0){flag2=~flag2;led5=~led5;while(!k4);}}if(flag2==0)key_just();elseclock_just();
}
void song_time()
{   u16 i;if(TIME[0]==clock_display[0]&&TIME[1]==clock_display[1]&&TIME[2]==clock_display[2]&&TIME[3]==clock_display[3]&&TIME[4]==clock_display[4]&&TIME[6]==clock_display[6]){for(i=0;i<=100;i++)beep=~beep;}
}

主要代码就这些,比较繁琐,下面是主函数main.c

#include "reg52.h"    //此文件中定义了单片机的一些特殊功能寄存器
#include"ds1302.h"
#include"key.h"
#include"smguan.h" 
void main()
{ Ds1302Init();while(1){   key_clock_just();   DigDisplay();//数码管显示函数song_time(); }  
}

代码就这些,很多很繁琐,当时在网上找代码找了好久,也不是特别全,搜了一些代码,从网上借鉴了一些,本文章中是通过按键++直接对TIME数组的控制时分秒进行++;整个代码的功能分三个,按键用来调换模式,第一个是按键不按下时,每五秒切换一次时间和日期,交替来。第二个功能通过按键来对时间,对日期来加减,调时间和日期,第三个是闹铃。

在这里插入图片描述
不足:按键控制的功能太多导致时钟和闹铃转换的时候进行加加或者减减的时候容易跳模式。如果去掉闹钟功能剩下的其他功能都正常的。

因为部分代码是直接复制过来的,第一次写,也不是太懂会不会侵权啥的,哈哈如果有哪里侵权请告诉我。谢谢。

这篇关于stc89c52数码管DS1302电子时钟的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/352015

相关文章

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

Spring Boot集成PDFBox实现电子签章

概述 随着无纸化办公的普及,电子文档的使用越来越广泛。电子签章作为一种有效的身份验证方式,在很多场景下替代了传统的纸质文件签名。Apache PDFBox 是一个开源的Java库,可以用来渲染、生成、填写PDF文档等操作。本文将介绍如何使用Spring Boot框架结合PDFBox来实现电子签章功能。 准备工作 环境搭建:确保你的开发环境中安装了JDK 8或更高版本,并且配置好了Maven或

【电子通识】半导体工艺——保护晶圆表面的氧化工艺

在文章【电子通识】半导体工艺——晶圆制造中我们讲到晶圆的一些基础术语和晶圆制造主要步骤:制造锭(Ingot)、锭切割(Wafer Slicing)、晶圆表面抛光(Lapping&Polishing)。         那么其实当晶圆暴露在大气中或化学物质中的氧气时就会形成氧化膜。这与铁(Fe)暴露在大气时会氧化生锈是一样的道理。 氧化膜的作用         在半导体晶圆

电子电气架构---私有总线通信和诊断规则

电子电气架构—私有总线通信和诊断规则 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节能减排。 无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事.而不是让内心的烦躁、

电子发射与气体导电

物理电磁学练习题:电子发射与气体导电 说明: 以下题目考察对电子发射和气体导电基本概念的理解和应用。 1. 解释以下概念:      (a) 热电子发射      (b) 光电效应      © 逸出功      (d) 等离子体 2. 比较并对比热电子发射和光电效应的异同。 3. 钨的逸出功为 4.5 eV。      (a) 计算能够从钨表面发射电子的最长波长光。      (b) 如

【电子通识】洁净度等级划分及等级标准

洁净度常用于评估半导体、生物制药、医疗、实验室及科研院所、新能源等领域的洁净室、无尘室或者无菌室等环境。         一般来说,晶圆光刻、制造、测试等级为100级或1000级的洁净间,百级洁净间要求空气中0.5微米的尘埃粒子数不得超过每立方米3520个;等级为1000级的洁净间要求0.5微米的尘埃粒子数不得超过每立方米35200个。         晶圆切割或封装工序一

油表加速器时钟屏保 就是这么酷酷的

太酷了!这个时钟屏保太有个性了!油表加速器时钟屏保,模拟汽车加速表盘,非常有质感,用它做屏保,简直就是酷毙了~!今天小编给大家分享一个非常实用好看的时钟屏保(芝麻时钟),官网地址(https://clock.zhimasoft.cn/?bili) 芝麻时钟-油表加速器时钟屏保 我们一起来看下,油表加速器表盘时钟屏保是怎么设置的? 1、打开芝麻时钟软件,找到"时钟屏保"菜单,点击后打开;(

彩虹数字屏保时钟 芝麻时钟开启个性化的时代 屏保怎么能少它

彩虹数字屏保时钟 芝麻时钟开启个性化的时代 屏保怎么能少它?电脑屏保多样化,让大家有了更多的选择,让更多人有机会把自己的电脑打扮得漂漂亮亮,今天小编给大家推荐:芝麻时钟(官网下载地址:http://clock.zhimasoft.cn/?bili),一起看下怎么开启彩虹数字时钟屏保吧! 彩虹数字屏保时钟 1、先下载芝麻时钟到电脑,可以百度,或者微软应用商城搜索“芝麻时钟”下载;

STM32CubeMX 1 创建一个新工程 利用时钟点亮LED KEIL5 Jlink配置

直接上ST的官网下载STM32CubeMX安装 地址: 单片机:STM32F103C8T6 带外部8MHz晶振 目的:利用Timer和使LED按照1Hz的频率闪烁。 在此方面学霸级人物的指引下学习了,并写此文章记录,以防忘记。 新建工程 出现如下界面,中央就是这个封装的引脚图: 接下来开始配置 1. 设置外部晶振接口在PD0和PD1 单机想要配置的引脚,出现选择菜单。

基于MicroPython的ESP8266控制七段数码管的设计方案

以下是一个基于MicroPython的ESP8266控制七段数码管的设计方案: 一、硬件准备 1. ESP8266开发板(如NodeMCU)             2. 七段数码管(共阳或共阴型)                      3. 限流电阻(根据数码管的电流要求选择合适的阻值