基于51单片机的DS1302实时时钟
本讲内容:
介绍DS1302实时时钟芯片基本知识,演示DS1302例程。
DS1302实时时钟:
DS1302能提供包括秒、分、时、日期、月份和年份信息。闰年可自行调整,可选择12小时制和24小时制,可以设置AM、PM。
只通过三根线进行数据的控制和传递:/RST、I/O、SCLK。
通过备用电源可以让芯片在小于1mw的功率下运作。
DS1302是总线驱动方式,它不仅要向寄存器写入控制字,还需要读取相应寄存器的数据。要想与DS1302通信,首先要先了解DS1302的控制字。DS1302的控制字如图。
位7:必须是逻辑1,如果它为0,则不能把数据写入到DS1302中。
位6:如果为0,则表示存取日历时钟数据,为1表示存取RAM数据。
位5至位1(A4~A0):指示操作单元的地址。
位0:为1表示进行读操作,为0表示要进行写操作,控制字后SCLK下降沿读数据,SCLK上升沿写数据。数据是低位在前,高位在后。
读数据:
读数据时在紧跟8位的控制字指令后的下一个SCLK脉冲的下降沿,读出DS1302的数据,读出的数据是从最低位到最高位。
写数据:
写数据时在紧跟8位的控制字指令后的下一个SCLK脉冲的上升沿,数据被写入DS1302,数据输入也是从最低位(0位)开始。
DS1302的数据读写是通过I/O串行进行的。当进行一次读写操作时最少要读写两个字节。
第一个字节是控制字节,就是一个命令,告诉DS1302是读还是写操作,是对RAM还是对CLOCK寄存器操作,以及操作的地址。
第二个字节就是要读或写的数据了。
单字节写:
在进行操作之前先将CE(也可说是RST)置高电平,然后单片机将控制字的位0放到I/O上,当I/O的数据稳定后,将SCLK置高电平,DS1302检测到SCLK的上升沿后就将I/O上的数据读取,然后单片机将SCLK置为低电平,再将控制字的位1放到I/O上,如此反复,将一个字节控制字的8个位传给DS1302。接下来就是传一个字节的数据给DS1302,当传完数据后,单片机将CE置为低电平,操作结束。
单字节读:
一开始写控制字的过程和上面的单字节写操作是一样,但是单字节读操作在写控制字的最后一个位,SCLK还在高电平时,DS1302就将数据放到I/O上,单片机将SCLK置为低电平后数据锁存,单片机就可以读取I/O上的数据。如此反复,将一个字节的数据读入单片机。
DS1302实时时钟芯片接口电路:
例程:
/**************DS1302_LCD1602显示****************
*单片机型号:STC89C52RC
*开发环境:KEIL
*名称:DS1302_LCD1602显示
********************************************************/
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
uchar a,miao,shi,fen,ri,yue,nian,week,flag,temp,KEYn;
#define yh 0x80 //第一行的初始位置
#define er 0x80+0x40 //第二行初始位置
sbit wr=P1^1;sbit rs=P1^0;sbit en=P2^5;
sbit SCLK=P2^1;sbit IO=P2^0;
sbit RST=P2^4;sbit ACC0=ACC^0;
sbit ACC7=ACC^7;
sbit key=P3^7;
sbit SWITCH_S6=P3^0;
sbit SWITCH_S11=P3^1;
sbit SWITCH_S16=P3^2;
uchar code tab1[]={"2009- - THU"};
uchar code tab2[]={" : : "};
void delay(int In,int Out)
{
int i,j;
for(i=0;i<In;i++)
{for(j=0;j<Out;j++){;}}
}
/******************液晶相关函数********************/
void write_1602com(uchar com) //液晶写入指令函数
{
rs=0; //置为写入命令
P0=com; //送入数据
delay(5,10);
en=1; //拉高使能端
delay(5,10);
en=0; //完成高脉冲
}
void write_1602dat(uchar dat)
{
rs=1; //置为写入数据
P0=dat; //送入数据
delay(5,10);
en=1;
delay(5,10);
en=0;
}
void lcd_init(void)
{
wr=0;
write_1602com(0x38); //设置液晶工作模式
write_1602com(0x0c); //开显示不显示光标
write_1602com(0x06); //整屏不移动,指针加一
write_1602com(0x01);
write_1602com(yh+2); //字符写入的位置
for(a=0;a<14;a++)
{write_1602dat(tab1[a]);}
write_1602com(er+4);
for(a=0;a<8;a++)
{write_1602dat(tab2[a]);}
}
/******************DS1302相关函数********************/
void write_byte(uchar dat)
{
ACC=dat;
RST=1;
for(a=8;a>0;a--)
{
IO=ACC0;
SCLK=0;
SCLK=1;
ACC=ACC>>1;
}
}
uchar read_byte()
{
RST=1;
for(a=8;a>0;a--)
{
ACC7=IO;
SCLK=1;
SCLK=0;
ACC=ACC>>1;
}
return (ACC);
}
void write_1302(uchar add,uchar dat)
{
RST=0;
SCLK=0;
RST=1;
write_byte(add);
write_byte(dat);
SCLK=1;
RST=0;
}
uchar read_1302(uchar add)
{
uchar temp;
RST=0;
SCLK=0;
RST=1;
write_byte(add);
temp=read_byte();
SCLK=1;
RST=0;
return(temp);
}
uchar BCD_Decimal(uchar bcd)
{
uchar Decimal;
Decimal=bcd>>4;
return(Decimal=Decimal*10+(bcd&=0x0F));
}
void ds1302_init()
{
RST=0;
SCLK=0;
write_1302(0x80,miao|0x00);
}
void write_sfm(uchar add,uchar dat)
{
uchar gw,sw;
gw=dat%10;
sw=dat/10;
write_1602com(er+add);
write_1602dat(0x30+sw);
write_1602dat(0x30+gw);
}
void write_nyr(uchar add,uchar dat)
{
uchar gw,sw;
gw=dat%10;
sw=dat/10;
write_1602com(yh+add);
write_1602dat(0x30+sw);
write_1602dat(0x30+gw);
}
void write_week(uchar week) //写星期函数
{
write_1602com(yh+0x0d);
switch(week)
{
case 1:
{
write_1602dat('M');
write_1602dat('O');
write_1602dat('N');
}break;
case 2:
{
write_1602dat('T');
write_1602dat('U');
write_1602dat('E');
}break;
case 3:
{
write_1602dat('W');
write_1602dat('E');
write_1602dat('D');
}break;
case 4:
{
write_1602dat('T');
write_1602dat('H');
write_1602dat('U');
}break;
case 5:
{
write_1602dat('F');
write_1602dat('R');
write_1602dat('I');
}break;
case 6:
{
write_1602dat('S');
write_1602dat('T');
write_1602dat('A');
}break;
case 7:
{
write_1602dat('S');
write_1602dat('U');
write_1602dat('N');
}break;
}
}
/******************按键扫描相关函数*****************/
void keyscan()
{
key=0;
if(SWITCH_S6==0) //SWITCH_S6为功能键
{
delay(5,100);
if(SWITCH_S6==0)
{
while(!SWITCH_S6);
KEYn++;
if(KEYn==9)
KEYn=1;
switch(KEYn)
{
case 1:
{
TR0=0; //关闭定时器
write_1602com(er+0x0b); //写入光标位置
write_1602com(0x0f); //设置光标为闪烁
temp=(miao)/10*16+(miao)%10;
write_1302(0x8e,0x00);
write_1302(0x80,0x80|temp); //miao
write_1302(0x8e,0x80);
}break;
case 2:{write_1602com(er+8);}break; //fen
case 3:{write_1602com(er+5);}break; //shi
case 4:{write_1602com(yh+0x0f);}break; //week
case 5:{write_1602com(yh+0x0b);}break; //ri
case 6:{write_1602com(yh+0x08);}break; //yue
case 7:{write_1602com(yh+0x05);}break; //nian
case 8:
{
write_1602com(0x0c); //设置光标不闪烁
TR0=1; //打开定时器
temp=(miao)/10*16+(miao)%10;
write_1302(0x8e,0x00);
write_1302(0x80,0x00|temp); //miao
write_1302(0x8e,0x80);
}break;
}
}
}
if(KEYn!=0)
//当SWITCH_S6按下以下。再按以下键才有效
{
if(SWITCH_S11==0) //上调键
{
delay(5,10);
if(SWITCH_S11==0)
{
while(!SWITCH_S11);
switch(KEYn)
{
case 1:
{
miao++;
if(miao==60){miao=0;}
write_sfm(0x0a,miao); //写入新的秒数
temp=(miao)/10*16+(miao)%10;
write_1302(0x8e,0x00);
write_1302(0x80,0x80|temp);
write_1302(0x8e,0x80);
write_1602com(er+0x0b);
//因为设置液晶的模式是写入数据后,指针自动加一,在这里是写回原来的位置
}break;
case 2:
{
fen++;
if(fen==60){fen=0;}
write_sfm(0x07,fen);
temp=(fen)/10*16+(fen)%10;
write_1302(0x8e,0x00);
write_1302(0x82,temp);
write_1302(0x8e,0x80);
write_1602com(er+8);
}break;
case 3:
{
shi++;
if(shi==24){shi=0;}
write_sfm(4,shi);
temp=(shi)/10*16+(shi)%10;
write_1302(0x8e,0x00);
write_1302(0x84,temp);
write_1302(0x8e,0x80);
write_1602com(er+5);
}break;
case 4:
{
week++;
if(week==8){week=0;}
write_week(week);
write_1602com(yh+0x0f);
}break;
case 5:
{
ri++;
if(ri==31){ri=0;}
write_nyr(10,ri);
temp=(ri)/10*16+(ri)%10;
write_1302(0x8e,0x00);
write_1302(0x86,temp);
write_1302(0x8e,0x80);
write_1602com(yh+11);
}break;
case 6:
{
yue++;
if(yue==13){yue=0;}
write_nyr(7,yue);
temp=(yue)/10*16+(yue)%10;
write_1302(0x8e,0x00);
write_1302(0x88,temp);
write_1302(0x8e,0x80);
write_1602com(yh+8);
}break;
case 7:
{
nian++;
if(nian==100){nian=0;}
write_nyr(4,nian);
write_1602com(yh+5);
}break;
}
}
}
if(SWITCH_S16==0)
{
delay(5,100);
if(SWITCH_S16==0)
{
while(!SWITCH_S16);
switch(KEYn)
{
case 1:
{
miao--;
if(miao==-1){miao=59;}
write_sfm(0x0a,miao); //写入新的秒数
write_1602com(er+0x0b);
//因为设置液晶的模式是写入数据后,指针自动加一,在这里是写回原来的位置
}break;
case 2:
{
fen--;
if(fen==-1){fen=59;}
write_sfm(7,fen);
temp=(fen)/10*16+(fen)%10;
write_1302(0x8e,0x00);
write_1302(0x82,temp);
write_1302(0x8e,0x80);
write_1602com(er+8);
}break;
case 3:
{
shi--;
if(shi==-1){shi=23;}
write_sfm(4,shi);
temp=(shi)/10*16+(shi)%10;
write_1302(0x8e,0x00);
write_1302(0x84,temp);
write_1302(0x8e,0x80);
write_1602com(er+5);
}break;
case 4:
{
week--;
if(week==-1){week=7;}
write_week(week);
write_1602com(yh+0x0f);
}break;
case 5:
{
ri--;
if(ri==-1){ri=30;}
write_nyr(10,ri);
temp=(ri)/10*16+(ri)%10;
write_1302(0x8e,0x00);
write_1302(0x86,temp);
write_1302(0x8e,0x80);
write_1602com(yh+11);
}break;
case 6:
{
yue--;
if(yue==-1){yue=12;}
write_nyr(7,yue);
temp=(yue)/10*16+(yue)%10;
write_1302(0x8e,0x00);
write_1302(0x88,temp);
write_1302(0x8e,0x80);
write_1602com(yh+8);
}break;
case 7:
{
nian--;
if(nian==-1){nian=99;}
write_nyr(4,nian);
write_1602com(yh+5);
}break;
}
}
}
}
}
void timer_init(){TMOD=0x11;TH0=0;TL0=0;EA=1;ET0=1;TR0=1;}
void sys_init(void)
{
lcd_init();
ds1302_init();
timer_init();
}
void main()
{
sys_init();
while(1){keyscan();}
}
void timer0() interrupt 1
{
miao = BCD_Decimal(read_1302(0x81));
fen = BCD_Decimal(read_1302(0x83));
shi = BCD_Decimal(read_1302(0x85));
ri = BCD_Decimal(read_1302(0x87));
yue = BCD_Decimal(read_1302(0x89));
nian = BCD_Decimal(read_1302(0x8d));
week = BCD_Decimal(read_1302(0x8b));
write_sfm(10,miao);
write_sfm(7,fen);
write_sfm(4,shi);
write_nyr(10,ri);
write_nyr(7,yue);
}
最后,求求看到的此文的小伙伴点赞和关注支持一下下哦。毕竟,码字不容易哦,您的支持是我最大的动力呀!!!呜呜呜~~~
基于51单片机的DS1302实时时钟相关推荐
- 基于51单片机的DS1302实时时钟程序
DS1302概述 DS1302是由美国DALLAS公司推出的具有涓细电流充电能力的低功耗实时时钟芯片.它可以对年.月.日.周.时.分.秒进行计时,且具有闰年补偿等多种功能. 工作原理 DS1302 是 ...
- 基于51单片机、DS1302时钟模块的电子闹钟设计
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 一.设计原理 1.DS1302介绍 2.闹钟音乐播放原理 二.程序设计 1.DS1302.h 2.ds1302.c 3.mu ...
- 基于51单片机1602温度显示时钟
基于51单片机LCD1602温度显示时钟 要在1602上显示时间和温度先要了解1602是如何显示的.详情可以参考我之前的文章基于51单片机1602显示 :时间显示可以用时钟芯片DS1302,但是此次我 ...
- 基于51单片机的手动数字时钟
具体实现功能 实现功能: (1)利用数码管显示时分秒,显示格式为"时-分-秒": (2)利用6个按键控制时.分.秒: (3)设置秒复位按键,可实现秒钟复位. 单片机介绍 51单片是 ...
- 基于51单片机的数字电子时钟
基于51单片机的数字电子时钟 单片机课程设计要求使用51单片机完成一个电子时钟,要求满足基本功能的同时增添丰富的功能参考了很多大佬的方案代码才勉强完成,工程文件下载点击此链接欢迎交流.如遇下载问题可以 ...
- 基于51单片机的DS1302涓流充电计时芯片详细学习(时钟制作)
目录 前言 一.初学者需要了解DS1302的一些基本特性 二.脉冲串模式数据传输 1.单字节写入 2.单字节读取 3.BCD码的转换 三.理论存在实践开始(代码模块) 1.DS1302时钟模块原理图 ...
- 基于51单片机用DS1302和LCD1602设计可调式电子日历与时钟(Proteus仿真)
[嵌入式工程师成长日记] https://mp.weixin.qq.com/s?__biz=Mzg4Mzc3NDUxOQ==&mid=2247484111&idx=1&sn=c ...
- 基于51单片机的多功能时钟温度计proteus仿真原理图
本系统是由AT89S52单片机为控制核心,具有在线编程功能,低功耗,能在3V超低压环境中工作:时钟电路由内部时钟电路外接晶振提供,它是一种高性能.低功耗.带RAM的可随时调整时钟电路,工作电压为3V- ...
- 基于51单片机的可调时钟闹钟全套设计资料
编号:0003 仿真软件:Proteus8.9程序编译软件:keil5编写语言:C语言 功能介绍 时钟设置显示功能 1.这个仿真提供年份日期星期24小时格式时间显示,初始化后可以设置时间,选择模式一后 ...
最新文章
- win2012 R2的ntp时间同步设置解析
- 技术管理中的手段——奖励和惩罚
- Hive 时间戳和日期相互转换
- “命令终端”的实现4-优化之解耦
- 回归(regression)——统计学习方法
- windows7-SQLyog 安装图解
- C语言中结构化数据(变量,指针,数组,字符串,结构体和联合)的内存表示
- Redis 6.0 源码阅读笔记(11) -- 主从复制 Slave 节点流程分析
- 论文笔记_S2D.44_自监督的从稀疏到稠密:用激光雷达和单目摄像机进行自监督深度补全
- ubuntu和ok6410开发板之间架设nfs
- matlab建模仿真教学视频教程,仿真建模与MATLAB
- 51单片机控制步进电机正反转
- 分享180个动态模板PPT模板,总有一款适合你
- php中开通短信验证码,php利用云片网实现短信验证码功能的示例代码
- 高德地图交通态势爬取
- Rancher 中应用、服务、容器的概念
- GBK,UTF8是什么?
- 【Unity开发小技巧】模型单指旋转双指缩放功能代码(多种情况)
- java和python中函数式编程
- 铅酸蓄电池三阶simulink仿真模型,可获得蓄电池充放电特性,并提供数学模型相关文献和多组电池模型参数。
热门文章
- php 获取移动端设备号,getDeviceId()获取设备号IMEI、MEID、ESN
- Java8 Stream 遍历数据效率差?实测结果出乎意料~~
- 【Substance】Substance Painter基本制作流程
- I2C总线3.3V与5V双向电平转换电路
- 技术领导力之路 - 安全感
- python玫瑰花数量的含义_玫瑰花数量的含义?玫瑰花个数的含义?
- java打字游戏和解析_java类与对象案例之打字游戏
- android流量监控软件设计与实现,基于android平台的流量监控系统的设计与实现
- unicode exp学习
- n行Python代码系列:三行程序实现从视频截取子窗内容输出