简介

DS1302是低功耗带RAM的实时时钟电路, 常见的SOP8封装体积很小, 它可以对年月日周时分秒进行计时, 具有闰年补偿功能, 工作电压为2.0V-5.5V, 采用三线接口与CPU进行同步通信, 并可采用突发方式一次传送多个字节的时钟信号或RAM数据. DS1302内部有一个31byte的用于临时性存放数据的RAM寄存器. DS1302是DS1202的升级产品, 与DS1202兼容, 但增加了主电源/后备电源双电源引脚, 同时提供了对后备电源进行涓细电流充电的能力.

几个需要知道的点:

  • 不带温度补偿, 所以在温度变化大的环境, 走时误差会比较大, 需要有校对机制
  • 三线接口机制与SPI相似, 但不是SPI, 因为它在同一根线上实现的双向IO
  • 自身不带电源/电容, 掉电即重置, 需要自己管理好主电备电
  • 备电的充电方式是可以通过寄存器控制的, 分三级控制, 第一级开关, 第二级可选1级或2级二极管降压, 第三级可选三种阻值
  • 额外的31个byte的存储可以自由读写
  • burst read有两处, 一处是8个字节的control+时间, 另一处是31字节的ram, 都是一次性全部读取, 但是可以编程控制读到第几个字节就停止.
  • 读取的结果是BCD码, 要转换

pin脚结构

对于SOP8封装, 将字面朝自己, 小圆点朝左上方, 从小圆点开始逆时针数分别为1至8脚

Left Right
1:Vcc2 8:Vcc1
2:X1 7:SCLK
3:X2 6:I/O
4:GND 5:RST/CE
  • X1,X2: X1和X2是振荡源, 可以直接外接 32.768 kHz 晶振
  • RST: 重置
  • I/O: 数据IO, 串行数据输入输出端(双向)
  • SCLK: 串口时钟
  • Vcc1: 备用电
  • Vcc2: 供电

Vcc1和Vcc2

DS1302的引脚中Vcc2为主电源, Vcc1为后备电源. 在主电源关闭的情况下, 也能保持时钟的连续运行. DS1302由Vcc1或Vcc2两者中的较大者供电, 当Vcc2大于Vcc1+0.2V时, Vcc2给DS1302供电, 当Vcc2小于Vcc1时, DS1302由Vcc1供电.

注意: 供电不要低于3.6V, 否则在秒进位时容易出现时间清零. 如果是在VCC端串联电阻限流, 电阻不要超过3K.

RST脚

RST是复位/片选线, 通过把RST输入驱动置高电平来启动所有的数据传送.

  • 当RST为高电平时, 允许地址/命令序列送入移位寄存器, 所有的数据传送被初始化, 允许对DS1302进行操作
  • 提供终止单字节或多字节数据传送的方法, 如果在传送过程中RST置为低电平,则会终止此次数据传送,I/O引脚变为高阻态
  • 上电运行时, 在Vcc>2.0V之前RST必须保持低电平. 只有在SCLK为低电平时, 才能将RST置为高电平.

写入逻辑:

  1. 将RST先拉低
  2. 将SCLK拉低(如果不拉低, 且本来是高电平, 则瞬间就发出了一个bit, 这时还没放数据)
  3. 将RST拉高, 形成一个上升沿
  4. 在IO口放入一个bit (字节发送顺序:从低位到高位)
  5. 将SCLK拉高, 形成上升沿, 这时候DS1302就会将IO口的数据移入它的寄存器
  6. 拉低SCLK, 为下一个字节做准备
  7. IO口再放一个bit, 再拉高, 直到发送完所有的16个字节
  8. 最后拉低RST, 完成写入过程

寄存器地址

与时间相关的寄存器从0x80到0x8F, 其中偶数为写地址, 奇数为读地址, 共控制8个字节, 这8个字节可以通过burst方式一次性读出

#define DS1302_W_SECOND     0x80
#define DS1302_W_MINUTE     0x82
#define DS1302_W_HOUR       0x84
#define DS1302_W_DAY        0x86
#define DS1302_W_MONTH      0x88
#define DS1302_W_WEEK       0x8A
#define DS1302_W_YEAR       0x8C
#define DS1302_W_PROTECT    0x8E#define DS1302_R_SECOND     0x81
#define DS1302_R_MINUTE     0x83
#define DS1302_R_HOUR       0x85
#define DS1302_R_DAY        0x87
#define DS1302_R_MONTH      0x89
#define DS1302_R_WEEK       0x8B
#define DS1302_R_YEAR       0x8D
#define DS1302_R_PROTECT    0x8F

与控制相关的寄存器为如下几个, 也是偶数写奇数读, 这些只能单个读写

#define DS1302_W_TK_CHARGER 0x90
#define DS1302_W_CLK_BURST  0xBE
#define DS1302_W_RAM_BURST  0xFE#define DS1302_R_TK_CHARGER 0x91
#define DS1302_R_CLK_BURST  0xBF
#define DS1302_R_RAM_BURST  0xFF

片内的31个字节RAM起始地址为0xC0, 这31个字节可以通过burst方式一次性读出

#define DS1302_RAM_SIZE     0x31 // Ram Size in bytes
#define DS1302_RAM_START    0xC0 // First byte Address

使用STC12 MCU读取DS1302

接线图, 测试中可以只接Vcc2或Vcc1, 可以串电阻或串二极管限流, 代码中使用的管脚与图中不一样, 具体看代码中的说明

实际的测试板, 接DS1302使用的是SOP8的测试座, 避免焊接, 中间的万能板仅仅是为了用一个IC座外接晶振, 可以忽略其他元件

测试座里的DS1302

代码例子, 包含单个读, 单个写, burst读时间, burst读RAM, 基于 HML_FwLib_STC12 封装库. 因为是非标准SPI, 所以实际上只用到了串口打印, 直接把这个方法拎出来也行, 就不需要引入这个封装库了.

/*****************************************************************************/
/** * 连接方式*               |           |               |*               | --------- | ------------  |*               |1:Vcc2 VCC | 8:Vcc1        |*               |2:X1   OCS | 7:SCLK   P1_0 |*               |3:X2   OCS | 6:I/O    P1_1 |*               |4:GND  GND | 5:RST/CE P1_2 |******************************************************************************/
#include "hml/hml.h"
#include <stdio.h>#define DS1302_W_SECOND     0x80
#define DS1302_W_MINUTE     0x82
#define DS1302_W_HOUR       0x84
#define DS1302_W_DAY        0x86
#define DS1302_W_MONTH      0x88
#define DS1302_W_WEEK       0x8A
#define DS1302_W_YEAR       0x8C
#define DS1302_W_PROTECT    0x8E
#define DS1302_W_TK_CHARGER 0x90
#define DS1302_W_CLK_BURST  0xBE
#define DS1302_W_RAM_BURST  0xFE#define DS1302_R_SECOND     0x81
#define DS1302_R_MINUTE     0x83
#define DS1302_R_HOUR       0x85
#define DS1302_R_DAY        0x87
#define DS1302_R_MONTH      0x89
#define DS1302_R_WEEK       0x8B
#define DS1302_R_YEAR       0x8D
#define DS1302_R_PROTECT    0x8F
#define DS1302_R_TK_CHARGER 0x91
#define DS1302_R_CLK_BURST  0xBF
#define DS1302_R_RAM_BURST  0xFF#define DS1302_RAM_SIZE     0x31 // Ram Size in bytes
#define DS1302_RAM_START    0xC0 // First byte Address#define HEX2BCD(v)  ((v) % 10 + (v) / 10 * 16)
#define BCD2HEX(v)  ((v) % 16 + (v) / 16 * 10)#define DS1302_SCK P1_0
#define DS1302_IO  P1_1
#define DS1302_RST P1_2const uint8_t READ_RTC_ADDR[7]  = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};
const uint8_t WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};
uint8_t BUF[8] = { 0 };// Write one byte to DS1302
void DS1302_WriteByte(uint8_t writeByte)
{for(uint8_t i=0; i < 8; i++){if(1 == (writeByte & 0x01)){DS1302_IO = 1;}else{DS1302_IO = 0;}DS1302_SCK = 1;DS1302_SCK = 0;writeByte >>= 1; // From low to high}
}// Read one byte from DS1302
uint8_t DS1302_ReadByte(void)
{uint8_t dat, readByte = 0;for(uint8_t i = 0; i < 8; i++){//dat = DS1302_IO;//readByte = (readByte>>1) | (dat << 7); // From low to highreadByte >>= 1;if(DS1302_IO){readByte |= 0x80;}DS1302_SCK = 1;DS1302_SCK = 0;}return readByte;
}void DS1302_WriteReg(uint8_t addr, uint8_t value)
{DS1302_RST = 0;DS1302_SCK = 0;DS1302_RST = 1;DS1302_WriteByte(addr);DS1302_WriteByte(value);DS1302_SCK = 1;DS1302_RST = 0;
}uint8_t DS1302_ReadReg(uint8_t addr)
{uint8_t readByte = 0;DS1302_RST = 0;DS1302_SCK = 0;DS1302_RST = 1;DS1302_WriteByte(addr);readByte = DS1302_ReadByte();DS1302_SCK = 1;DS1302_RST = 0;return readByte;
}void DS1302_ReadBurst(uint8_t cmd, uint8_t len, uint8_t *buf)
{uint8_t readByte = 0;DS1302_RST = 0;DS1302_SCK = 0;DS1302_RST = 1;DS1302_WriteByte(cmd);while(len--)*buf++ = DS1302_ReadByte();DS1302_SCK = 1;DS1302_RST = 0;
}void DS1302_Init(void)
{DS1302_WriteReg(DS1302_W_PROTECT, 0x00); // write unprotectDS1302_WriteReg(DS1302_W_TK_CHARGER, 0x01); // stop chargerDS1302_WriteReg(0XC0, 0x00);DS1302_WriteReg(0XC2, 0x01);DS1302_WriteReg(0XC4, 0x02);DS1302_WriteReg(0XC6, 0x03);DS1302_WriteReg(DS1302_W_PROTECT, 0x80); // write protect
}void DS1302_print(uint8_t dat)
{printf_tiny("%x%x ", dat >> 4, dat & 0x0F);
}void DS1302_printBuf(uint8_t len)
{for(uint8_t i = 0; i < len; i++){printf_tiny("%x%x ", BUF[i] >> 4, BUF[i] & 0x0F);}printf_tiny("\n");
}void main(void)
{UTIL_enablePrintf();DS1302_Init();while(1){uint8_t dat = DS1302_ReadReg(DS1302_R_SECOND);DS1302_print(dat);dat = DS1302_ReadReg(DS1302_R_MINUTE);DS1302_print(dat);dat = DS1302_ReadReg(DS1302_R_HOUR);DS1302_print(dat);printf_tiny("\n");DS1302_ReadBurst(DS1302_R_CLK_BURST, 8, BUF);DS1302_printBuf(8);DS1302_ReadBurst(DS1302_R_RAM_BURST, 8, BUF);DS1302_printBuf(8);sleep(491);}
}

参考

  • stc12c5a60s ds1302时钟 https://blog.csdn.net/wct3344142/article/details/103804770
  • stc89c52 ds1302 https://blog.csdn.net/qq_45476045/article/details/102640646
  • 接线和上拉电阻 https://www.amobbs.com/thread-4522628-1-1.html
  • stc89代码 https://blog.csdn.net/vvinggth204/article/details/17587993
  • https://www.maximintegrated.com/en/design/technical-documents/app-notes/3/3449.html
  • https://circuitdigest.com/microcontroller-projects/digital-clock-using-8051-microcontroller
  • https://github.com/julgonmej/stm32f7-ds1302-lib/blob/master/DS1302.c
  • https://github.com/msparks/arduino-ds1302/blob/master/DS1302.cpp

DS1302与STC12的连接电路和驱动实现相关推荐

  1. DBDesigner 4 与 MySql 5 不能连接主要是驱动的原因

    DBDesigner 4 与 MySql 5 不能连接主要是驱动的原因,到 http://crlab.com/dbx/download.html 下载最新的驱动并安装,在安装路径中找到dbexpmda ...

  2. Android Studio使用真机(连接安卓手机驱动)调试教程

    一.前言 当我们的电脑的运存较小时,在进行Android Studio的AVD进行模拟调试时,电脑可能会出现卡顿,运行时间较长.此时,我们可以利用自己的安卓手机(苹果手机不支持)充当模拟器,将写好的a ...

  3. 0809连接单片机c语言,adc0809引脚图及功能详解,adc0809与51单片机连接电路分析

    描述 adc0809是采样频率为8位的.以逐次逼近原理进行模-数转换的器件.其内部有一个8通道多路开关,它可以根据地址码锁存译码后的信号,只选通8路模拟输入信号中的一个进行A/D转换. 1.主要特性 ...

  4. 单片机_CT107D训练平台电路原理图\蓝桥杯训练板\输入输出模块\矩阵按键\蜂鸣器电路\继电器电路\LM386功率放大电路,驱动扬声器

    输入/输出模块 配置 4×4 键盘矩阵,其中四个按键可通过跳线配置为独立按键: 配置继电器.蜂鸣器: 配置功率放大电路,驱动扬声器. 1>4×4 键盘矩阵原理图如下: 图片中的按键电路可以切换成 ...

  5. stm32f429vref怎么接_STM32开发笔记58: STM32F407特殊引脚连接电路

    单片机型号:STM32F407VGT6 本文介绍STM32F407特殊引脚连接电路,见下图: 引脚:49.73 VCAP_1和VCAP_2,按照下列电路设计方法进行设计.这里应该着重看最后1句话,其表 ...

  6. linux下qt的odbc库编译,linux qt QODBC连接sql server 驱动 有关问题 ,实在是没辙了

    linux qt QODBC连接sql server 驱动 问题 ,实在是没辙了 程序在linux下,现在需要连接windows的sqlserver . db = QSqlDatabase::data ...

  7. 华为NPU卡ubuntu(无网络连接情况)驱动安装记录

    华为NPU卡ubuntu驱动安装记录 前奏:文中的绝大多数情况都是因为服务器没有网络服务,如果读者的电脑有完全的网络服务可能参考意义不是很大.不过,处理的方法和排查的思路可以作为一个借鉴. root@ ...

  8. ecilpse连接oracle ojdbc驱动

    package keshe; import java.sql.*; public class GetConn {public Connection getConnection() {Connectio ...

  9. access如何查询两张表的内容_为什么可以的话,不要使用星号 *,而是相应的字段名来进行查询 MySQL内连接如何选择驱动表

    参考: 掘金小册​juejin.im 首先要了解单表查询方法,也就是explain中出来的,ref,index,const,all之类的. 然后了解index查询方法,也就是在联合索引中,条件不是第一 ...

最新文章

  1. debian10 nfs简单搭建
  2. APPlication,Session和Cookie的区别
  3. html pc端万年历插件,# pc端个性化日历实现
  4. SAP CRM呼叫中心end按钮的实现逻辑
  5. 堆之大,ZGC亦可速清也!
  6. MySQL 加锁处理分析(二)
  7. 【语音识别】语音端点检测及Python实现
  8. 开发一个自己的 CSS 框架(二) 1
  9. Axis2发布webservice(3)--axis2生成wsdl文件,并利用wsdl文件来生成WebService的Java代码
  10. 如何正确彻底的删除2345软件
  11. rtc校准算法_CRC校验算法的实例解析
  12. 计算机专业的英文简历范文带翻译,英文个人简历带翻译【英文简历范文带翻译】...
  13. 【工具】损坏视频文件修复MP4/MOV格式
  14. 手撕Buck!Buck公式推导过程
  15. Shopee平台,对接运营经理是一条离成功更近的捷径
  16. java解析加密excel,java poi 打开加密 excel?该怎么处理
  17. yolo数据集标注软件安装+使用流程
  18. 牛客多校第九场K-The Flee Plan of Groundhog(树形DP)
  19. iOS m3u8本地缓存播放(控制下载并发、暂停恢复)
  20. linux proftpd 用户,linux之proftpd搭建(随时盖楼)

热门文章

  1. gridview嵌套实例
  2. FIR数字滤波器的设计
  3. 查询邓白氏编码时地址有误
  4. mysql完全卸载和重装
  5. ARD3M智能电动机保护器在河南心连心化学工业集团的应用
  6. 理解vue之element-ui中的 template slot-scope=scope
  7. Ignition Perspective容器
  8. java权限管理+授权与认证_权限管理(认证和授权)
  9. 安搭Share的人生知足者常乐
  10. MyBatis 分页插件