历史上的今天
今天是:2024年11月02日(星期六)
2021年11月02日 | DS1302时钟 ---- 自学笔记
2021-11-02 来源:eefocus
一、什么是DS1302时钟
具有实时时钟计算能力,能计算2100年之前的秒、分、时、日、日期、星期、月、年及闰年调整能力。
内部含有31个字节静态RAM,可提供用户访问。
采用串行数据传送方式,使得管脚数量最少,简单SPI3线接口。
工作电压范围宽:2.0~5.5V。
工作电流:2.0v时,小于300NA。
时钟或RAM数据的读/写有两种传送方式:单字节传送和多字节传送方式
采用8脚DIP封装或SOIC封装。
与TTL兼容,Vcc=5v
可选工业级温度范围:-40摄氏度~+85摄氏度
具有涓流充电能力
采用主电源和备份电源双电源供应
备份电源可由电池或大容量电容实现
二、SPI总线
2.1、概念
SPI接口(Serial Peripheral Interface):串行外围接口
SPI接口主要应用在EEPROM,FLASH,实时时钟,AD转换器,数字信号处理器和数字信号解码器之间
SPI接口是在CUP外围低速器件之间进行同步串行数据传输,在主器件的移位脉冲下,数据按位传输,高位在前,低位在后,全双工通信数据传输速度总体来说比IIC总线要快,速度可达到几Mbps.
SPI接口是以从方式工作的,这种模式通常有一个主器件和一个或多个从器件,器接口包括以下四种信号;
MOSI ---- 主器件数据输出,从器件数据输入。 (MO:主机输出 SI:从机输入)
MISO ---- 主器件数据输入,从器件数据输出。 (MI:主机输入 SO:从机输出)
SCLK ---- 时钟信号,由主器件产生。
/CS(CAN信号) ---- 从器件使能信号,主器件控制。

2.2、SPI接口内部结构

缺点:没有指定的流控制,没有应答机制确认是否接收到数据
2.3、DS1302的引脚
三、DS1302的寄存器及片内RAM
DS1302有一个控制寄存器,12个日历,时钟寄存器和31个RAM。
3.1、控制寄存器
控制寄存器由于存放DS1302的控制命令字,DS1302的RST引脚回到高电平后写入的第一个字就为控制命令。
它用于对DS1302读写过程进行控制,它的格式如下

D7:固定位1
D6:RAM/CK位,=1片内RAM,=0日历、时钟寄存器选择位。
D5~D1:地址位,用于选择进行读写的日历时钟寄存器或片内RAM。
D0:读写选择,=0写,=1读

3.2、日历、时钟寄存器
DS1302共有12个寄存器,其中有7个与日历,时钟相关,存放的数据为BCD码形式。日历、时钟寄存见下表
数据都以BCD码形式表现
小时寄存器的D7位为12小时制/24小时制的选择位,当为1时选12小时制,当为0时选24小时制。当12小时制时,D5位为1时是上午,D5位位为0时是下午,D4为小时的十位。当24小时制时,D5,D4位为小时的十位。
秒寄存器中的CH位为时钟暂停位,当1为时钟暂停,为0时钟开启启动。
写保护寄存器:wp位写保护位,当wp=1,写保护,当wp=0未写保护、当对日历、时钟寄存器或片内RAM进行写时wp应当清零,当对日历,时钟寄存器或片内RAM进行读时WP一般置1。
慢充电寄存器的TCS位为控制慢充电的选择,当它为1010才能使慢充电工作。DS位二极管选择位。DS位01选择一个二极管,DS为10选择二个二级管。DS为11或00充电器被禁止,与TCS无关。RS用与选择连接在Vcc2与Vcc1之间的电阻,RS为00,充电器被禁止,与TCS无关,电阻选择情况见表

3.3、什么是BCD码
BCD码是通过4位二进制来表示1位十进制中的0~9这10个数码
二进制码转换位BCD码的方式为:4位二进制码大于1001(十进制:9)时,加6
如:BCD码0000 1100 的二进制为 0000 1100 +6 = 0001 0010

四、片内RAM
DS1302片内有31个RAM单元,对片内RAM的操作有两种方式:单字节方式和多字节方式当控制命令位COH~FDH时位单字节读写方式,命令字中的D5~D1用于选择对应的RAM单元,其中奇数为读操作,偶数为写操作。
当控制命令字节为FEH,FFH时为多字节操作(表中RAM突发模式),多字节操作可一次把所有的RAM单元内容进行读写。FEH为写操作,FFH为读操作。
4.1、数据输入输出(i/o)
在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。同样,在紧跟8位的控制指令字节的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7.
4.2、单字节的读写

DS1302是通过SPI串行总线跟单片机通信的,当进行一次读写操作时最少得读写两个字节,第一个字节是控制字节,就是一个命令,告诉DS1302是读还是写操作,是对RAM还是对CLOK寄存器操作,第二个自己就是要读或写的数据。
单字节读写:只有在SCLK位低电平时,才能将CE置为高电平,所以在进行操作之前先将SCLK置低电平,然后将CE置位高电平,接着开始在IO上面放入要传送的电平信号,然后跳变SCLK,数据在SCLK上升沿时,DS1302读写数据,在SCLK下降沿时,DS1302放置数据到IO上。
五、硬件设计
六、软件设计
6.1、ds1302.h
#ifndef __DS1302_H_
#define __DS1302_H_
//---包含头文件---//
#include #include //---重定义关键词---// #ifndef uchar // 如果没有定义uchar #define uchar unsigned char // 那么就将uchar定义为无符号的字符形 #endif #ifndef uint // 如果没有定义uint #define uint unsigned int // 那么就将uchar定义为无符号整型 #endif //---定义ds1302使用的IO口---// sbit DSIO=P3^4; // 输出/输入端口 sbit RST=P3^5; //CE复位端口 sbit SCLK=P3^6; // 串行时钟 //---定义全局函数---// void Ds1302Write(uchar addr, uchar dat); uchar Ds1302Read(uchar addr); void Ds1302Init(); void Ds1302ReadTime(); //---加入全局变量--// extern uchar TIME[7]; //加入全局变量 #endif 6.2、ds1302.c #include"ds1302.h" //---DS1302写入和读取时分秒的地址命令---// //---秒分时日月周年 最低位读写位;-------// /******************************************************* DS1302的寄存器及片内RAM D7 D6 D5 D4 D3 D2 D1 D0 1 RAM/CK D5~D1,地址位用与选择读写日历 RD/W 固定 1片内RAM 时钟寄存器或片内RAM 0写 0日历,时钟寄存器选择位 1读 *********************************************************** 寄存器名称 D7 D6 D5 D4 D3 D2 D1 D0 1 RAM/ck A4 A3 A2 A1 A0 R/W 读十六进制 写十六进制 秒寄存器 1 0 0 0 0 0 0 0 or 1 0x81 0x80 分寄存器 1 0 0 0 0 0 1 0 or 1 0x83 0x82 小时寄存器 1 0 0 0 0 1 0 0 or 1 0x85 0x84 日寄存器 1 0 0 0 0 1 1 0 or 1 0x87 0x86 月寄存器 1 0 0 0 1 0 0 0 or 1 0x89 0x88 星期寄存器 1 0 0 0 1 0 1 0 or 1 0x8b 0x8a 年寄存器 1 0 0 0 1 1 0 0 or 1 0x8d 0x8c 写保护寄存器 1 0 0 0 1 1 1 0 or 1 0x8f 0x8e 慢充电寄存器 1 0 0 1 0 0 0 0 or 1 0x91 0x90 时钟突发模式 1 0 1 1 1 1 1 0 or 1 0xbf 0xbe RAM0 1 1 0 0 0 0 0 0 or 1 0xc1 0xc0 RAM30 1 1 1 1 1 1 0 0 or 1 0xfd 0xfc RAM突发模式 1 1 1 1 1 1 1 0 or 1 0xff 0xfe */ uchar code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d}; uchar code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c}; //---DS1302时钟初始化2016年5月7日星期六12点00分00秒。---// /*uchar TIME[7] = {0, 0, 0x12, 0x07, 0x05, 0x06, 0x16}; 秒,分,时,日, 月, 周, 年 */ //---存储顺序是秒分时日月周年,存储格式是用BCD码---// //2020年5月16日 星期六 10点30分 uchar TIME[7] = {0,0x30,0x10,0x16,0x05,0x06,0x20}; /******************************************************************************* * 函 数 名 : Ds1302Write * 函数功能 : 向DS1302命令(地址+数据) * 输 入 : addr,dat * 输 出 : 无 *******************************************************************************/ /*DS1302是通过SPI串行总线跟单片机通信的, 当进行一次读写操作时最少得读写两个字节,第一个字节是控制字节, 就是一个命令,告诉DS1302是读还是写操作, 是对RAM还是对CLOK寄存器操作。第二个字节就是要读或写的数据了。*/ void Ds1302Write(uchar addr, uchar dat) { uchar n; RST = 0; // 复位 RST=P3^5; _nop_(); // 延时一个机器周期 SCLK = 0; //先将SCLK置低电平。 SCLK=P3^6; 串行时钟输入引脚 _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_(); } RST = 0;//传送数据结束 _nop_(); } /******************************************************************************* * 函 数 名 : Ds1302Read * 函数功能 : 读取一个地址的数据 * 输 入 : addr * 输 出 : dat *******************************************************************************/ /*只有在SCLK位低电平时,才能将CE置为高电平,所以在进行操作之前先将SCLK置低电平, 然后将CE置位高电平,接着开始在IO上面放入要传送的电平信号,然后跳变SCLK, 数据在SCLK上升沿时,DS1302读写数据,在SCLK下降沿时,DS1302放置数据到IO上。*/ 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; } /******************************************************************************* * 函 数 名 : Ds1302Init * 函数功能 : 初始化DS1302. * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void Ds1302Init() { uchar n; Ds1302Write(0x8E,0X00); //禁止写保护,就是关闭写保护功能 for (n=0; n<7; n++)//写入7个字节的时钟信号:分秒时日月周年 { Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]); } Ds1302Write(0x8E,0x80); //打开写保护功能 } /******************************************************************************* * 函 数 名 : Ds1302ReadTime * 函数功能 : 读取时钟信息 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void Ds1302ReadTime() { uchar n; for (n=0; n<7; n++)//读取7个字节的时钟信号:分秒时日月周年 { TIME[n] = Ds1302Read(READ_RTC_ADDR[n]); } } 6.3、main.c /************************************************************************************* * 实验现象:下载程序后,数码管显示时钟 接线说明: (具体接线图可见开发攻略对应实验的“实验现象”章节) 1,单片机-->DS1302时钟模块 P34-->DIO P35-->CE P36-->CLK 2,单片机-->动态数码管模块 J22-->J6 P22-->J9(A) P23-->J9(B) P24-->J9(C) 注意事项: ************************************************************************************** 
史海拾趣
|
目前用ut6410想实现 radio的功能使用si47xx的模块 ut6410本身有提供i2c的接口和驱动 kernel linux2.6.24 硬件部份問題排除 有用示波器 sda sck脚位有讯号出来. 现在遇到的状况是想从user space透过i2c对si47xx丢cmd 但是write read回传都是-1 部 ...… 查看全部问答> |
|
背光代码 volatile S3C2440A_IOPORT_REG * v_pIOPregs= NULL; BOOL BacklightInitialize() { BOOL bRet = TRUE; BL_PowerOn(TRUE); & ...… 查看全部问答> |
|
msp430芯片RAM居然不能外扩??很郁闷,最近程序大了,需要大于2K的RAM了,可是msp430芯片RAM不能外扩,这个怎么办呢?课题做到一半,555555555555 谢谢各位,请出出主意!… 查看全部问答> |
|
TinyOS在MSP430F2618+CC2520平台上移植交流 目前TinyOS还仅支持MSP430低端的MCU比如f1611,以及CC2420等射频芯片。针对MSP430高端系列单片机,以及TI推出的第二代射频芯片CC2520还未能支持 前段时间把TinyOS移植到了上述平台上,基本功能都已经实现,针对无线协议栈还需要进一步优化!希望有 ...… 查看全部问答> |
|
CC2530串口中断接收的自定义缓存BUF最大可以定义多大? 我现在需要一个最少160字节的BUF存接收到的数据进行解析;但是定义buf[160]后用IAR编译总是提示IDATA空间不够;后来通过调节IAR-option -stack/heap 中的设置;但是最大也是只能设置到buf[135 ...… 查看全部问答> |
|
一般来说,七段数码管(也有称日字管)只能显示10个阿拉伯数字和部分英文字母,但是,按排列组合来算,七段数码管可以有128个组合,因此,就七段数码管可包含的信息量来说,显示26个字母加10个数字共36个字符是没问题的,只是人们没有建立一套显示 ...… 查看全部问答> |
|
做了块CC2500模块,模块发射数据很正常,但是接收的数据全部异常,找了两天了还没找到原因,程序问题已经排除(用别人的模块发射和接受都正常),请懂的人帮下小弟,小弟搞开始搞RF… 查看全部问答> |













