常见的时钟芯片DS1302 的应用
eeskill 2021-09-23

大家好,通过前一期的学习,我们已经对ICD2 仿真烧写器和增强型PIC 实验板的使用方法及学习方式有所了解与熟悉,学会了如何用单片机来控制发光管、继电器、蜂鸣器、按键、数码管、RS232串口、步进电机、温度传感器、I2C 总线、SPI 总线等资源,体会到了学习板的易用性与易学性,这一期我们将介绍市面上常见的时钟芯片DS1302 的应用。

一、DS1302时钟芯片简介

DS1302 是DALLAS 公司推出的涓流充电时钟芯片,内含一个实时时钟/ 日历和31 字节静态RAM,可以通过串行接口与单片机进行通信。实时时钟/ 日历电路提供秒、分、时、日、星期、月、年的信息,每个月的天数和闰年的天数可自动调整,时钟操作可通过AM/PM 标志位决定采用24 或12 小时时间格式。DS1302 与单片机之间能简单地采用同步串行的方式进行通信,仅需三根I/O 线:复位(RST)、I/O 数据线、串行时钟(SCLK)。时钟/RAM 的读/写数据以一字节或多达31 字节的字符组方式通信。

DS1302 工作时功耗很低,保持数据和时钟信息时,功耗小于1mW。

1. DS1302 的内部结构

DS1302 的外部引脚功能说明如图1 所示。

图1 DS1302封装图

DS1302 的内部结构如图2 所示,主要组成部分为:移位寄存器、控制逻辑、振荡器、实时时钟以及RAM。虽然数据分成两种,但是对单片机的程序而言,其实是一样的,就是对特定的地址进行读写操作。

图2 DS1302的内部结构图

DS1302 含充电电路,可以对作为后备电源的可充电电池充电,并可选择充电使能和串入的二极管数目,以调节电池充电电压。不过对我们目前而言,最需要熟悉的是和时钟相关部分的功能,对于其它参数请参阅数据手册。

2. DS1302 的工作原理

DS1302 工作时为了对任何数据传送进行初始化,需要将复位脚(RST)置为高电平且将8 位地址和命令信息装入移位寄存器。数据在时钟(SCLK)的上升沿串行输入,前8 位指定访问地址,命令字装入移位寄存器后,在之后的时钟周期,读操作时输出数据,写操作时输出数据。时钟脉冲的个数在单字节方式下为8+8(8 位地址+8 位数据),在多字节方式下为8 加最多可达248 的数据。

3. DS1302 的寄存器和控制命令

对DS1302 的操作就是对其内部寄存器的操作,DS1302 内部共有12 个寄存器,其中有7 个寄存器与日历、时钟相关,存放的数据位为BCD 码形式。

此外,DS1302 还有年份寄存器、控制寄存器、充电寄存器、时钟突发寄存器及与RAM 相关的寄存器等。

时钟突发寄存器可一次性顺序读写除充电寄存器以外的寄存器。日历、时间寄存器及控制字如表1 所示。

表1 日历、时钟寄存器与控制字对照表

最后一位RD/W 为“0”时表示进行写操作,为“1”时表示读操作。

DS1302 内部寄存器列表如表2 所示。

DS1302 内部的RAM 分为两类,一类是单个RAM 单元,共31 个,每个单元为一个8 位的字节,其命令控制字为COH~FDH,其中奇数为读操作,偶数为写操作;再一类为突发方式下的RAM,此方式下可一次性读写所有的RAM 的31 个字节,命令控制字为FEH(写)、FFH(读)。

表2 DS14302内部主要寄存器分布表

我们现在已经知道了控制寄存器和RAM 的逻辑地址,接着就需要知道如何通过外部接口来访问这些资源。单片机是通过简单的同步串行通讯与DS1302通讯的,每次通讯都必须由单片机发起,无论是读还是写操作,单片机都必须先向DS1302 写入一个命令帧,最高位BIT7 固定为1,BIT6 决定操作是针对RAM 还是时钟寄存器,接着的5 个BIT 是RAM或时钟寄存器在DS1302 的内部地址,最后一个BIT表示这次操作是读操作抑或是写操作。

物理上,DS1302 的通讯接口由3 个口线组成,即RST,SCLK,I/O。其中RST 从低电平变成高电平启动一次数据传输过程,SCLK 是时钟线,I/O 是数据线。具体的读写时序参考图3,但是请注意,无论是哪种同步通讯类型的串行接口,都是对时钟信号敏感的,而且一般数据写入有效是在上升沿,读出有效是在下降沿(DS1302 正是如此的,但是在芯片手册里没有明确说明),如果不是特别确定,则把程序设计成这样:平时SCLK 保持低电平,在时钟变动前设置数据,在时钟变动后读取数据,即数据操作总是在SCLK 保持为低电平的时候,相邻的操作之间间隔有一个上升沿和一个下降沿。

图3 DS1302的命令字结构

通过前文的原理介绍,我们已经对DS1302 时钟芯片的特性以及工作原理有了大致地了解,但当我们拿到一个时钟器件时要正确地应用它还是一时不知如何下手,比如我们要做一个简单的时间显示,需要怎么办呢?首先,时钟芯片与单片机的连接非常简单,一般来说,我们只需要将IIC 器件的复位“RST”、数据“I/O”、时钟“SCLK”端与单片机的I/O 口相连,就可以进行时间、日期数据的写入或读取了。现在,我们来一起看一个使用DS1302 做时间显示的例子,通过一个实例,相信会给大家带来一个感性的认识。

首先, 我们来看一下增强型PIC 实验板上DS1302 器件的接口电路,因为我们需要将软件和硬件相结合进行考虑如何来编程,完成该实验的硬件原理图如图4 所示,U2 为实验板上DS1302 芯片,“I/O”

与单片机的RB5 口相连,“SCLK”与单片机RB6 相连,“RST”与单片机RB7 相连,七段数码管D5、D7、D8 组成了显示单元,字形码的数据通过RC 口送入,各数码管的显示片选信号分别不同的RA 口进行控制。

图4 硬件原理图

对于单机软件的编程,我们使用MPLab IDE 软件来进行C 语言编程,它是我们的编程环境,同时我们可以通过使用ICD2 仿真烧写器和增强型PIC 实验板连接进行程序的仿真调试和烧写步骤,具体的操作步骤,我们已经在前几期做了详细的说明和介绍,在此就不再重复说明,读者朋友可以参阅以前的文章或直接登陆我们的网站查看资料。现在我们可以输入程序代码进行调试了,我们在MPLab IDE 软件中新建工程,加入源程序代码,同时进行芯片型号的选择和配置位的设置,我们实验所用的芯片型号为PIC16F877A。编写的程序代码如下,其中程序流程图如图5 所示,实际运行效果如图6 所示。

图5 软件流程

图6 DS1302 实验演示图

二、软件代码

/*************************************************/

/*DS1302 读写演示程序 */

/* 目标器件:PIC16F877A */

/* 晶振:4.0MHZ */

/* 编译环境:MPLAB V7.51 */

/**************************************************/

#include<pic.h>

#define i_o RB5

#define sclk RB6

#define rst RB7

unsigned char time_rx @ 0x30;

// 定义接收寄存器

static volatile bit time_rx7 @ (unsigned)&time_rx*8+7;

// 接收寄存器的最高位

/***************************************************

子函数定义

**************************************************/

void port_init(); // 申明引脚初始化函数

void ds1302_init(); // 申明DS1302 初始化函数

void set_time(); // 申明设置时间函数

void get_time(); // 申明读取时间函数

void display(); // 申明显示函数

void time_write_1(unsigned char time_tx);

// 申明写一个字节函数

unsigned char time_read_1();

// 申明读一个字节函数

void delay(); // 申明延时函数

/***************************************************

时间和日期存放表

**************************************************/

const char table[]={0x00,0x30,0x12,0x8,0x3,0x06,0x06,0x00};

char table1[7];

/**************************************************

共阴LED 段码表

**************************************************/

const char table2[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E};

void main()

{

port_init(); // 调用引脚初始化函数

TRISC =0x00;

ds1302_init(); // 调用DS1302 初始化函数

set_time(); // 调用设置时间函数

while(1)

{

get_time(); // 调用取时间函数

display(); // 调用显示函数

}

}

void ds1302_init() // DS1302 初始化函数子程序

{

sclk=0; // 拉低时钟信号

rst =0; // 复位DS1302

rst=1; // 使能DS1302

time_write_1(0x8e); // 发控制命令

time_write_1(0); // 允许写DS1302

rst=0; // 复位

}

void set_time() // 设置时间函数子程序

{

int i; // 定义循环变量

rst=1; // 使能DS1302

time_write_1(0xbe); // 时钟多字节写命令

for(i=0;i<8;i++) // 连续写8 个字节数据

{

time_write_1(table[i]); // 调用写一个字节函数

delay();

}

rst=0; // 复位

}

void get_time() // 读取时间函数子程序

{

int i; // 设置循环变量

rst=1; // 使能DS1302

time_write_1(0xbf); // 发送多字节读取命令

for(i=0;i<7;i++) // 连续读取7 个字节数据

{

table1[i]=time_read_1();

// 调用读取1 个字节数据的函数

delay();

}

rst=0; // 复位DS1302

}

void time_write_1(unsigned char time_tx)

{

int j; // 设置循环变量

for(j=0;j<8;j++) // 连续写8bit

{

i_o=0; // 先设置数据为0

sclk=0; // 时钟信号拉低

if(time_tx&0x01) // 判断待发送的数据位是0 或1

{

i_o=1; // 待发送数据位是1

}

time_tx=time_tx》1; // 待发送的数据右移1 位

sclk=1; // 拉高时钟信号

}

sclk=0; // 写完一个字节,拉低时钟信号

}

unsigned char time_read_1()

{

int j; // 设置循环变量

TRISB5=1; // 设置数据口方向为输入

for(j=0;j<8;j++) // 连续读取8bit

{

sclk=0; // 拉低时钟信号

time_rx=time_rx》1; // 接收寄存器右移1 位

time_rx7=i_o;

// 把接收到的数据放到接收寄存器的最高位sclk=1; // 拉高时钟信号

}

TRISB5=0; // 恢复数据口方向为输出

sclk=0; // 拉低时钟信号

return(time_rx); // 返回读取到的数据

}

void port_init()

{

TRISA=0x00; // 设置A 口全输出

TRISC=0X00; // 设置C 口全输出

TRISB=0x00;

}

void display() // 显示子程序

{

int i; // 定义查表变量

i=table1[0]&0x0f; // 求秒的个位

PORTC=table2[i]; // 送C 口显示

PORTA=0xFD; // 点亮秒的个位

delay(); // 延长一段时间,保证亮度

i=table1[0]&0xf0; // 求秒的十位

i=i》4; // 右移4 位

PORTC=table2[i]; // 送C 口显示

PORTA=0xFE; // 点亮秒的十位

delay(); // 延长一段时间,保证亮度

i=table1[1]&0x0f; // 求分的个位

PORTC=table2[i]&0x7f;

// 送C 口显示,并显示小数点

PORTA=0xF7; // 点亮分的个位

delay(); // 延时一定时间,保证亮度

i=table1[1]&0xf0; // 求分的十位

i=i》4;

PORTC=table2[i]; // 送C 口显示

PORTA=0xFB; // 点亮分的十位

delay(); // 延长一段时间,保证亮度

i=table1[2]&0x0f; // 求时的个位

PORTC=table2[i]&0x7f;

// 送C 口显示,并加上小数点

PORTA=0xDF; // 点亮时的个位

delay(); // 延时一定时间,保证亮度

i=table1[2]&0xf0; // 求时的十位

i=i》4;

PORTC=table2[i]; // 送C 口显示

PORTA=0xEF; // 点亮时的十位

delay(); // 延长一段时间,保证亮度

}

void delay() // 延时程序

{

int i; // 定义整形变量

for(i=100;i--;); // 延时

}

看到这里,相信你现在已经可以完成一些简单的电子钟实验,DS1302 的原理与使用我们讲到这里。

增强型PIC 实验板系统资源丰富,可做实验有:6 位LED 数码管、8 路LED、直控键盘、蜂鸣器喇叭、继电器试验、I2C 总线接口、SPI 总线接口、160X 液晶、128X64 液晶、红外接收头接口、步进电机驱动接口、AD 模/ 数转换接口、串行时钟芯片DS1302、温度传感器DS18B20 接口、RS232 串口通讯、外扩展接口以便外接更多的实验资源。

声明: 本文转载自其它媒体或授权刊载,目的在于信息传递,并不代表本站赞同其观点和对其真实性负责,如有新闻稿件和图片作品的内容、版权以及其它问题的,请联系我们及时删除。(联系我们,邮箱:evan.li@aspencore.com )
0
评论
热门推荐
  • 相关技术文库
  • 单片机
  • 嵌入式
  • MCU
  • STM
  • ARM Cortex系列处理器知识点汇总

    最近因为要为芯片选定核,所以就在了解哪些核合适且性价比好,这是一个需要结合产品各类技术、市场分析的活,看似简单却还是需要一些储备的,今天选了一篇ARM Cortex系列的科普文章与大家分享。 众所周知,英国的ARM公司是嵌入式微处理器世界当中的佼佼者。AR

    05-11
  • 你的CPU属于哈佛结构还是冯诺依曼结构?

    现代的CPU基本上归为冯诺伊曼结构(也称普林斯顿结构)和哈佛结构。 冯洛伊曼结构就是我们所说的X86架构,而哈佛结构就是ARM架构。一个广泛用于桌面端(台式/笔记本/服务器/工作站等),一个雄踞移动领域,我们的手持设备(平板\手机用的大多就是他了)。 01

    05-10
  • 如何批量修改MCU封装管脚定义

    在做产品开发时,为了缩短研发周期,我们一般都是直接找来参考设计做参考。这些参考资料要么是来自原厂的,要么是来自方案商的。  接触过这么多的参考设计资料,发现大部分的资料都有一个通病,就是不少MCU的PIN脚定义都只是标出IO口的定义,其它复用​​​​功能

    05-08
  • MCU为什么要消抖动

    简单的说,进入了电子,不管是学纯模拟,还是学单片机,DSP、ARM等处理器,或者是我们的FPGA,一般没有不用到按键的地方。按键:人机交互控制,主要用于对系统的控制,信号的释放等。因此在这里,FPGA上应用的按键消抖动,也不得不讲! 一、为什么要消抖动 在

    05-07
  • 51单片机的ISP下载知识

    本文详细介绍了串口、51单片机的ISP下载等基础知识,已经学过单片机的也可以看看,加强一下对这方面的了解。 串口 串行接口简称串口,也称串行通信接口,是采用串行通信方式的扩展接口。 我们比较熟悉的USB接口,全名通用串行总线(Universal Serial BUS),就

    05-06
  • 硬件开发如何选择合适的MCU

    点击上方关注我们! 我在做硬件开发时,如果遇到的是一个新产品,新项目,之前没有做过的,没有任何的经验,在选MCU时,我一般是这样操作的。 首先,根据产品的需求,整理出一份硬件规格。比如,电源管理,传感器接口,人机交互接口等。 然后,整理出整个原理

    05-06
  • 单片机的功耗怎么算的?

    单片机的功耗是非常难算的,而且在高温下,单片机的功耗还是一个特别重要的参数。暂且把单片机的功耗按照下面的划分。 暂且把单片机的功耗按照下面的划分。 1.内部功耗(与频率有关) 2.数字输入输出口功耗 2.1输入口 2.2输出高 2.3输出低 3.模拟输入口功耗从

    05-07
  • 嵌入式工程师必备工具:I2C和SPI总线协议

    IIC vs SPI 现今,在低端数字通信应用领域,我们随处可见IIC (Inter-Integrated Circuit) 和 SPI (Serial Peripheral Interface)的身影。原因是这两种通信协议非常适合近距离低速芯片间通信。Philips(for IIC)和Motorola(for SPI) 出于不同背景和市场需求

    04-30
  • 嵌入式面试注意事项

    找工作也是一门技能,有的人很快就找到自己喜欢的工作,有的人找了很久也没找到合适的工作。 下面给大家分享几点找工作过程中存在的“潜规则”内容。 1、面试的本质不是考试,而是告诉面试官你会做什么 经验不够的小伙伴特别容易犯的一个错误,不清楚面试官到

    04-29
  • 为什么需要RTOS?

    很多单片机初学者都是从裸机开始的,裸机确实也能开发出好的产品,但作为一个嵌入式软件工程师,如果只能用裸机开发产品,那肯定是不够的。 要从裸机的思维转变到RTOS的思维,其实需要一个过程,而且开始的一段时间会很痛苦。但过一段时间理解了一些内容,能

    04-28
  • 使用RTOS的8个理由

    嵌入式系统中,有很多方式实现任务调度。功能有限的小系统中,无限循环足够实现系统功能。当软件设计变得庞大且复杂时,设计师应该考虑使用实时操作系统。 下面给大家分享使用RTOS的8个理由: 1.硬实时响应 基于优先级抢占的RTOS,根据任务的实时需求,执行优

    04-26
  • 单片机延时程序,Keil C编译器实现

    应用单片机的时候,经常会遇到需要短时间延时的情况。需要的延时时间很短,一般都是几十到几百微妙(us)。有时候还需要很高的精度,比如用单片机驱动 DS18B20的时候,误差容许的范围在十几us以内,不然很容易出错。这种情况下,用计时器往往有点小题大做。而

    04-26
下载排行榜
更多
EE直播间
更多
广告
X
广告