C51 (1302时钟案例)

在单片机上没有VCC1(备用电源)
传输数据主要还是CE,I/O,SCLK时钟引脚
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

振荡电路
DS1302 使用一个外部 32.768kHz晶体.振荡电路工作时不需要任何外接的电阻或者电容
表 1 详细指明了几个外部晶体的参数.图 1 显示了震荡电路的功能简图.如果使用指定规格
的晶体,启动时间通常少于 1秒钟.
时钟精确度
时钟的精确度取决于晶振的精确度,以及振荡电路容性负载与晶振校正的容性负载之间匹配
的精确度。另外温度改变引起的晶振频率漂移会使误差增加.外围电路噪音与震荡电路耦合
可能导致时钟运行加快. 图 2 显示了一个典型的隔离晶体与振荡器噪音的印刷电路板布局
详细信息请参考应用笔记 58页: Dallas 实时时钟的晶振注意事项.
在这里插入图片描述
在这里插入图片描述
命令字
图 3显示的是命令字.命令字启动每一次数据传输. MSB (位 7)必须是逻辑 1. 如果是 0,
则禁止对 DS1302写入. 位 6 在逻辑 0时规定为时钟/日历数据,逻辑 1时为 RAM数据.
位 1 至 位 5 表示了输入输出的指定寄存器.LSB (位 0) 在逻辑0时为写操作(输出),逻辑
1时为读操作(输入).命令字以 LSB (位 0)开始总是输入.
图 3. 地址/命令 字
在这里插入图片描述
CE 与时钟控制
所有数据传输开始驱动 CE输入高.CE输入实现两个功能.第一, CE 开启允许对地址/命令序
列的移位寄存器进行读写的控制逻辑. 第二 CE 信号为单字节和多字节 CE数据传输提供了
终止的方法.

一个时钟周期是一系列的上升沿伴随下降沿.要输入数据在时钟的上升沿数据必须有效,而
且在下降沿要输出数据位.如果 CE输入为低电平,则所有数据传输终止,并且 I/O 口成高阻
抗状态.图 4 显示了数据传输. 在上电时, CE必须为逻辑 0直到 VCC 大于 2.0V. 同样,
SCLK 必须为逻辑 0当 CE 变成逻辑 1状态.
数据输入
输入写命令字的 8个 SCLK周期后 ,接下来的 8个 SCLK 周期的上升沿数据字节被输入,如
不慎发生, 多余的 SCLK 周期将被忽略,数据输入以位 0开始.
数据输出
输入读命令字的 8个 SCLK周期后, 随后的 8个 SCLK 周期的下降沿,一个数据字节被输出。
注意第一个数据位的传送发生在命令字节被写完后的第一个下降沿.只要 CE保持高电平,若
不慎发生,多余的 SCLK周期会重新发送数据字节.
此操作允许连续不断的脉冲串模式读取能力.并且,I/O管脚在 SCLK的每个上升沿被置为三
态.数据输出从位 0开始.
脉冲串模式
通过寻址 31(十进制)存储单元(地址/命令位 1到位 5为逻辑 1),脉冲串模式可以指定时
钟/日历或者 RAM寄存器.如前所述,位 6指定时钟或者 RAM,位 0指定读写.时钟/日历寄存
器的存储单元 9至 31和 RAM寄存器的存储单元 31无数据存储能力.脉冲串模式下的读写从
地址 0的位 0开始.

在脉冲串模式下写时钟寄存器时,前 8个寄存器必须按顺序写要发送的数据.然而, 在脉冲
串模式下写 RAM时 ,不必写入要发送数据的所有 31个字节. 不管是否所有 31个字节都被
写入,每个写入字节都会被发送到 RAM.
时钟/日历
读取适当的寄存器字节可以得到时间和日历信息. 表 3 说明了 RTC寄存器. 写入适当的寄
存器字节可以设置或初始化时间和日历. 时间和日历寄存器的内容是二进制编码的十进制
(BCD)格式的.

周中的天寄存器在午夜 12点增加. 周中的天相应的值可以由用户定义,但是必须是连续的
(例如,如果 1代表周日,那么 2代表周一,等等.).非法的时间和日期输入导致未定义操作.

当读写时钟和日期寄存器时,第二(用户)缓存用来防止内部寄存器更新时出错.读时钟和
日期寄存器时, 在 CE上升沿用户缓存与内部寄存器同步.

每当秒寄存器被写入,递减计数电路被复位. 写传输发生在 CE的下降沿.为了避免翻转问题,
一旦递减计数电路复位, 剩下的时间和日期寄存器必须在一秒内被写入.

DS1302可以工作在 12小时制和 24小时制两种模式下.小时寄存器的位 7定义为小时模式选
择位.为高时是 12小时制,12小时制模式下,位 5是上午/下午位且高电平是下午. 24小时
制模式下, 位 5 是第二 10-小时位 (20点–23点).一旦 12/24改变,小时数据必须被重新
初始化.
时钟暂停标志
秒寄存器的位 7被定义为时钟暂停标志. 当此为置 1时,时钟振荡器暂停, DS1302进入漏
电流小于 100nA的低功耗备用模式. 当此为置 0时,时钟开始.初始加电状态未定义.
写保护位
控制寄存器的位 7是写保护位,前 7位(位 0至位 6)被强制为 0且读取时总是读 0. 在任
何对时钟或 RAM的写操作以前,位 7必须为 0.当为高时,写保护位禁止任何寄存器的写操
作. 初始加电状态未定义. 因此,在试图写器件之前应该清除 WP位.
涓流充电寄存器
此寄存器控制DS1302的涓流充电特性.图5的简化结构图显示了涓流充电器的基本元件. 涓
流充电选择(TCS) 位(位 4到 位 7)控制涓流充电器的选择.为了防止意外使能,只有 1010
的模式才能使涓流充电器使能. 所有其他模式都会禁止涓流充电器. DS1302加电时涓流充
电器是禁止的. 二极管选择(DS)位 (位 2和位 3) 选择 VCC2和 VCC1之间连了一个还是两个二
极管. 如果 DS 是 01,一个二极管,10就是 2个二极管. 如果 DS是 00或者 11,不管 TCS,
涓流充电器被禁止. RS 位(位 0 和位 1)选择连在 VCC2 和 VCC1之间的电阻. 表 2显示了 RS
和 DS选择电阻和二极管.
在这里插入图片描述
电阻和二极管的选择是由用户根据电池或超级电容充电所需的最大电流决定的.最大充电电
流可以向下面的例子所示那样计算出来.
假设 5V系统供电电源加在 VCC2,一个超级电容连在 VCC1. 同时假设涓流充电器被使能且 VCC2
与 VCC有一个二极管和电阻 R1.最大电流 IMAX 如下式计算:
IMAX= (5.0V –二极管压降) / R1 ≈ (5.0V – 0.7V) / 2kΩ ≈ 2.2mA
超级电容充电时,VCC2与 VCC1之间压降增加,因此充电电流增加 .

时钟/日历脉冲串模式
时钟/日历命令字节指定脉冲串模式操作. 此模式下, 前八个时钟/日历寄存器必须从地址
0的位 0开始连续读写(见表 3)

如果当指定为写时钟/日历脉冲串模式是、时写保护位置高, 八个时钟/日历寄存器(包括控
制寄存器)都不会发生数据传输. 脉冲串模式下涓流充电器是不可读写的.

在时钟脉冲串读取的开始,当前时间被传送至另外的存储器集合. 当时钟继续运行时,会从
这些第二寄存器读回时间信息.这就消除了万一读取时主寄存器更新重新读取寄存器的必
要.
RAM
静态 RAM在 RAM地址空间内是以 31 x 8字节连续编址的.
RAM脉冲串模式
RAM 命令字节定义了脉冲串模式操作.此模式下, 31 RAM寄存器可以从地址 0的位 0开始连
续读写(见表 3).
寄存器摘要
表 3显示了寄存器数据格式摘要.
晶振选择
一个 32.768kHz 晶振可以通过管脚 2和 3(X1,X2)直接连接到 DS1302. 选择所使用的晶振
需要一个指定的 6pF负载电容. 关于晶振选择和晶振布局注意事项的详细信息请参考应用
笔记 58页: Dallas 实时时钟的晶振注意事项.

图 4 数据传输摘要
这里注意:
写入字节的SCLK需要16个脉冲
读取字节的SCLK需要15个脉冲(有一个高低电平合在了一起)
写程序的时候注意别把程序时序;
在这里插入图片描述

下面是三个引脚工作的时序图:

在这里插入图片描述
在这里插入图片描述

时间读取和写入的寄存器:
在这里插入图片描述

下面是主要代码:(很简单的一个案例)

在这里插入代码片
#include <REGX52.H>
#include "LCD1602.h"
#include "Delay.h"
#include "DS1302.h"


void main()
{
	LCD_Init();   //LCD1602的封装前面的章节有,就不再放出来了
	DS1302_Init();
	
	LCD_ShowString(1,1,"  -  -  ");
	LCD_ShowString(2,1,"  :  :  ");

	DS1302_SetTime();
	
	while(1)	
	{
		DS1302_ReadTime();
 //	LCD_ShowNum(2,1 ,second,3);  //现在是second 为 BCD码值
		LCD_ShowNum(1,1 ,DS1302_Time[0],2);  //现在是十进制为 BCD码值
		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); 
		 
	
	}


}

这里根据时序图敲的代码;

在这里插入代码片:
#include <REGX52.H>
#include "DS1302.h"

sbit DS1302_SCLK = P3^6;
sbit DS1302_IO = P3^4;
sbit DS1302_CE = P3^5;

#define DS1302_SECOND 0x80
#define DS1302_MINUTE 0x82
#define DS1302_HOUR   0x84
#define DS1302_DATE   0x86
#define DS1302_MONTH  0x88
#define DS1302_DAY    0x8a
#define DS1302_YEAR   0x8c
#define DS1302_WP     0x8e

unsigned char DS1302_Time[] = {21 , 18 , 19 ,20, 30 ,10,1}; 

void DS1302_Init()
{
   DS1302_CE = 0;
	 DS1302_SCLK = 0;
}

void DS1302_WriteByte(unsigned char command , database)
{
	  unsigned char i;
    DS1302_CE = 1;
	for(i = 0; i < 8; i++ )  //写指令
	{
	  DS1302_IO = command & (0x01<< i); //将第0位,置一
      DS1302_SCLK = 1;
	  DS1302_SCLK = 0;//在单片机承受晶振内,可以不用延时 
	}
	
  for(i = 0; i < 8; i++ ) //写数据
	{
	  DS1302_IO = command & (0x01<< i); //将第0位,置一
      DS1302_SCLK = 1;
	  DS1302_SCLK = 0;//在单片机承受晶振内,可以不用延时 
	}
	 DS1302_CE = 0;



}


unsigned char DS1302_ReadByte(unsigned char Command)
{
	 unsigned char i;
	 unsigned char Data = 0x00;
	 Command |= 0x01;
	 DS1302_CE = 1;
   for(i = 0; i < 8; i++ )  //写指令
	{
	  DS1302_IO = Command & (0x01<< i); //将第0位,置一
      DS1302_SCLK = 0;//在单片机承受晶振内,可以不用延时 
	  DS1302_SCLK = 1;//在这里特别注意要反过来,否则在这里会直接输出结果值
	} 
	
	for(i = 0; i < 8; i++ )  
	{
	   DS1302_SCLK = 1;
	   DS1302_SCLK = 0;
	   if(DS1302_IO) {Data |= (0x01<< i);}
	
	}
	
	DS1302_CE = 0;
	DS1302_IO = 0;
	return Data;

}


void DS1302_SetTime()  //写入数据
{
    DS1302_WriteByte(DS1302_WP , 0x00);
    DS1302_WriteByte(DS1302_YEAR , DS1302_Time[0]/10*16+DS1302_Time[0]%10);
		DS1302_WriteByte(DS1302_MONTH , DS1302_Time[1]/10*16+DS1302_Time[1]%10);
		DS1302_WriteByte(DS1302_DATE , DS1302_Time[2]/10*16+DS1302_Time[2]%10);
		DS1302_WriteByte(DS1302_HOUR , DS1302_Time[3]/10*16+DS1302_Time[3]%10);
		DS1302_WriteByte(DS1302_MINUTE , DS1302_Time[4]/10*16+DS1302_Time[4]%10);
		DS1302_WriteByte(DS1302_SECOND , DS1302_Time[5]/10*16+DS1302_Time[5]%10);
		DS1302_WriteByte(DS1302_DAY , DS1302_Time[6]/10*16+DS1302_Time[6]%10);
		DS1302_WriteByte(DS1302_WP , 0X80);


}

void DS1302_ReadTime() //读取数据
{
    unsigned char temp;
	  temp = DS1302_ReadByte(DS1302_YEAR);  //读取时钟信息,把BCD码值转换成十进制
    DS1302_Time[0] = temp/16*10+temp%16;
	  temp = DS1302_ReadByte(DS1302_MONTH);
    DS1302_Time[1] = temp/16*10+temp%16;
	  temp = DS1302_ReadByte(DS1302_DATE);
    DS1302_Time[2] = temp/16*10+temp%16;
	  temp = DS1302_ReadByte(DS1302_HOUR);
    DS1302_Time[3] = temp/16*10+temp%16;
	  temp = DS1302_ReadByte(DS1302_MINUTE);
    DS1302_Time[4] = temp/16*10+temp%16;
	  temp = DS1302_ReadByte(DS1302_SECOND);
    DS1302_Time[5] = temp/16*10+temp%16;
	  temp = DS1302_ReadByte(DS1302_DAY);
    DS1302_Time[6] = temp/16*10+temp%16;

}















  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

The endeavor

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值