【51单片机】程序实验16.DS1302时钟

主要参考学习资料:B站【普中官方】51单片机手把手教学视频

开发资料下载链接:http://www.prechin.cn/gongsixinwen/208.html

单片机套装:普中STC51单片机开发板A4标准版套餐7

目录

DS1302时钟芯片介绍

DS1302简介

DS1302是达拉斯公司生产的时钟芯片,其具体特点如下:

①具有涓流充电的充电方式,涓流充电通过小电流持续充电来补偿电池的自放电损失,可以有效延长电池使用寿命,保持高饱和度的电量状态。且有主电源和备用电源双电源管脚,避免断电后时钟数据损失。

②具有时钟、日历功能,可以计算2100年之前的时间信息,有闰年调整功能。

③工作电压为3.0~5.5V,在2.0V时电流为300nA,功耗极低。

④具有单字节传送和多字节传送字符组两种读写方式。

⑤具有DIP和SIOC两种封装方式,本实验板载为SIOC封装,体积非常小。

⑥通过三线制SPI串行接口与单片机通信,分别为复位信号线(使能线)、I/O数据线和时钟线,而标准的SPI分别由MISO和MOSI来实现数据的输出和输入。

⑦兼容TTL电平,可以直接跟单片机IO口连接。

⑧工作温度范围为-40℃~85℃。

DS1302八个管脚的功能如下:

名称 功能
VCC2/VCC1 主电源/备用电源
X1/X2 外部晶振管脚,提供晶振源
CE 使能管脚,高电平时芯片工作
I/O 串行数据输入输出引脚
SCLK 时钟引脚

DS1302使用

DS1302的使用分为两步:①从中读取时间②将读取到的时间转换到数码管或液晶显示

控制寄存器

控制寄存器用于存放DS1302的控制命令,对DS1302的读写进行控制。

7 6 5 4 3 2 1 0
1 RAM/CK A4 A3 A2 A1 A0 RD/WR
  • RAM/CK:设置操作对象,1为RAM,0为内部寄存器。
  • A0~A4:操作对象的操作地址位。
  • RD/WR:设置读写方向,1为读操作,2为写操作。

以下是内部寄存器和RAM的地址表:

日历/时钟寄存器

DS1302共有12个寄存器,其中7个与日历/时钟功能相关,它们的数据以BCD码格式存入。

BCD码用4位二进制位来表示1位十进制位中的0~9,表示两位数时高八位表示十位,低八位表示个位,在处理二进制数据时通过整除16提取十位,对16取余提取个位。

各个寄存器各个位的功能如下表所示:

特别说明:

  • 秒寄存器D7为DS1302运行标志位,0为工作状态,1为停止工作。
  • 小时寄存器D7为时间格式位,1为12小时制,0为24小时制,。D5和D6在12小时制下,D5区分AM/PM,D6存储小时的十位0/1;在24小时制下,D5和D6共同存储小时的十位0/1/2。
  • 写保护寄存器D7为写保护位,1开启写保护,0关闭写保护。
  • 慢充电寄存器控制涓流充电方式,很少用到,不作深入介绍。

读写时序

DS1302的数据传输方式和DS18B20相同,先传低位后传高位。

在读写操作过程中,CE必须保持高电平。读写操作完成后设置CE为低电平,等待下一次操作。

在时钟产生上升沿时数据一位一位由低到高进行写入,先写入控制命令,随后读字节在控制命令发送完成后的第一个下降沿开始读取,而写字节在控制命令发送完成后的第一个上升沿继续写入数据。

在进行写操作前,需先将写保护寄存器的WP位设置为0,写完后再设置为1。写和读的时候数据都以BCD码格式传输。

硬件设计

实验16 DS1302时钟

实现功能:数码管显示电子时钟时分秒,格式为"XX-XX-XX"。

数码管驱动沿用自实验14

DS1302驱动

ds1302.h

c 复制代码
#ifndef _ds1302_H
#define _ds1302_H

#include "public.h"

//定义复位线、时钟线和数据线管脚
sbit DS1302_RST = P3^5;
sbit DS1302_CLK = P3^6;
sbit DS1302_IO = P3^4;

//定义存储秒分时日月周年的数组
extern u8 gDS1302_TIME[7];

void ds1302_init(void);
void ds1302_read_time(void);

#endif

ds1302.c

c 复制代码
#include "ds1302.h"
#include "intrins.h"

//存储秒分时日月周年地址读写的命令
u8 gWRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};
u8 gREAD_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};

//存储秒分时日月周年的数组
//赋值作为初始化的时间,以2025年星期二3月11日11点45分14秒为例
u8 gDS1302_TIME[7] = {0x14, 0x45, 0x11, 0x11, 0x03, 0x02, 0x25};

//写字节函数
void ds1302_write_byte(u8 addr, u8 dat)
{
	//循环控制变量
	u8 i = 0;
	//复位并将时钟设为低电平
	DS1302_RST = 0;
	_nop_();
	DS1302_CLK = 0;
	_nop_();
	DS1302_RST = 1;
	//由低到高写入地址
	for(i=0;i<8;i++)
	{
		//IO管脚准备好最低位信号
		DS1302_IO = addr & 0x01;
		//次低位移至最低位
		addr >>= 1;
		//产生上升沿使信号写入
		DS1302_CLK = 1;
		_nop_();
		DS1302_CLK = 0;
		_nop_();
	}
	//由低到高写入数据
	for(i=0;i<8;i++)
	{
		DS1302_IO = dat & 0x01;
		dat >>= 1;
		DS1302_CLK = 1;
		_nop_();
		DS1302_CLK = 0;
		_nop_();
	}
	//拉低复位线等待下次操作
	DS1302_RST = 0;
}

//读字节函数
u8 ds1302_read_byte(u8 addr)
{
	//循环控制变量
	u8 i = 0;
	//一位存储变量
	u8 temp = 0;
	//一字节存储变量
	u8 value = 0;
	//复位并拉低时钟
	DS1302_RST = 0;
	_nop_();
	DS1302_CLK = 0;
	_nop_();
	DS1302_RST = 1;
	//写入地址
	for(i=0;i<8;i++)
	{
		DS1302_IO = addr & 0x01;
		addr >>= 1;
		DS1302_CLK = 1;
		_nop_();
		DS1302_CLK = 0;
		_nop_();
	}
	//由低到高读取数据
	for(i=0;i<8;i++)
	{
		//存储一位
		temp = DS1302_IO;
		//将字节整体右移一位并将新数据移到最高位后放入
		value = (temp<<7) | (value>>1);
		DS1302_CLK = 1;
		_nop_();
		//产生下降沿读取下一位
		DS1302_CLK = 0;
		_nop_();
	}
	//拉低复位线等待下次操作
	DS1302_RST = 0;
	//如果板载P3.4没有外接上拉电阻需要手动产生上升沿脉冲
	DS1302_CLK = 1;
	_nop_();
	DS1302_IO = 0;
	_nop_();
	DS1302_IO = 1;
	_nop_();
	//返回读取到的字节
	return value;
}

//时间初始化函数
void ds1302_init(void)
{
	//循环控制变量
	u8 i = 0;
	//将写保护寄存器的写保护位置零以关闭写保护
	ds1302_write_byte(0x8e, 0x00);
	for(i=0;i<7;i++)
	{
		//将寄存器地址与时间数据一一对应写入
		ds1302_write_byte(gWRITE_RTC_ADDR[i], gDS1302_TIME[i]);
	}
	//打开写保护
	ds1302_write_byte(0x8e, 0x00);
}

//时间读取函数
//由于函数不便返回数组,因此直接用开头定义好的数组存储
void ds1302_read_time(void)
{
	//循环控制变量
	u8 i = 0;
	for(i=0;i<7;i++)
	{
		//将对应寄存器地址的时间数据读取到数组
		gDS1302_TIME[i] = ds1302_read_byte(gREAD_RTC_ADDR[i]);
	}
}

主函数

c 复制代码
#include "public.h"
#include "smg.h"
#include "ds1302.h"

void main()
{
	//存储数码管显示段码值数组
	u8 time_buf[8];
	//时间初始化
	ds1302_init();
	while(1)
	{
		//读取时间
		ds1302_read_time();
		//八位数码管依次存储时分秒的十位和个位,中间用杠隔开
		//BCD码整除16提取十位,对16取余提取个位
		time_buf[0] = gseg_code[gDS1302_TIME[2]/16];
		time_buf[1] = gseg_code[gDS1302_TIME[2]%16];
		time_buf[2] = 0x40;
		time_buf[3] = gseg_code[gDS1302_TIME[1]/16];
		time_buf[4] = gseg_code[gDS1302_TIME[1]%16];
		time_buf[5] = 0x40;
		time_buf[6] = gseg_code[gDS1302_TIME[0]/16];
		time_buf[7] = gseg_code[gDS1302_TIME[0]%16];
		//显示在数码管上
		seg_display(time_buf, 1);
	}
}
相关推荐
逐步前行3 分钟前
HAL_NVIC
stm32·单片机·嵌入式硬件
恒森宇电子有限公司30 分钟前
芯晞微CSM4056H 单节锂离子电池充电器芯片 封装ESOP-8
单片机·嵌入式硬件
果果燕39 分钟前
ARM嵌入式学习(五)---IMX6ULL外部中断
单片机·嵌入式硬件
无人机90144 分钟前
Delphi网络编程实战:UDP通信与多线程网络优化详解
单片机·嵌入式硬件
笨笨饿44 分钟前
博客目录框架
c语言·开发语言·arm开发·git·嵌入式硬件·神经网络·编辑器
知识分享小能手1 小时前
MongoDB入门学习教程,从入门到精通,MongoDB副本集的核心机制(11)
数据库·学习·mongodb
Lugas Luo2 小时前
SATA Port Multiplier (SATA 集线器) 原理与驱动架构深度剖析
linux·嵌入式硬件
zmj3203242 小时前
KW45的ISP模式
stm32·单片机·嵌入式硬件·kw45
小美单片机2 小时前
十字路交通灯系统设计
c语言·单片机·51单片机·proteus·课设
爬山算法3 小时前
MongoDB(75)如何配置TLS/SSL加密?
数据库·mongodb·ssl