大家好,通过前一期的学习,我们已经对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

#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 串口通讯、外扩展接口以便外接更多的实验资源。

为了方便大家更好的学习,畅学电子网特别增加了针对单片机和EDA的公众号,每天推送相关知识,希望能对你的学习有所帮助!

两个单片机iic通讯程序_PIC单片机之DS1302时钟相关推荐

  1. 利用4位led显示本机秒表时间的单片机c语言程序,基于单片机的一个2位的led数码显示作为_秒表_设计.doc...

    基于单片机的一个2位的led数码显示作为_秒表_设计 PAGE 1 PAGE 29 工程技术学院 课程设计 题 目:用单片机AT89C51设计一个2位的LED数码显示作为"秒表" ...

  2. 寻路机器人单片机程序示例_单片机精华程序代码示例:DS1302时钟程序

    真正的熟练掌握单片机,实际操作是很重要的.多看程序,多分析,从别人规范的程序代码中学习技巧是很必要的. 硬件部分: 程序部分: main.c文件 /************************** ...

  3. 单片机如何烧录程序?单片机的下载方式讲解

    对于单片机项目,编完程序后要将hex文件下载到单片机中,程序才能够执行,才能实现相应的功能.单片机程序的下载方式有多种,下面介绍几种常用的下载方式:ISP(串口下载),SW,JTAG.所涉及到的单片机 ...

  4. 51单片机两只老虎c语言程序,51单片机两只老虎仿真加代码

    /*************************************************************************** 程序名称:program4-1.c 程序功能: ...

  5. pic单片机低电压检测_pic单片机汇编语言讲解(上)

    pic 单片机为最常用单片机之一,许多程序均基于 pic 单片机进行开发.因此,熟练 pic 单片机编程尤为重要.为保证大家能准确.熟练掌握 pic 单片机的使用,本文特带来 pic 单片机的各种汇编 ...

  6. 单片机定时器精准定时_PIC单片机的定时器精准计时的计算

    关于PIC单片机的定时器精准计时的计算 在此用了16C711单片机的TMR0做定时中断,希望实现精准计时,在程序中,TMR0用了晶振的32分频,初值#0FCH,因此POPBEAR兄弟计算出每个定时中断 ...

  7. 51单片机按键计数器程序_51单片机是如何存储程序和数据的

    在学校很少用到外扩ROM/RAM的情况,都是用C语言编程,不差空间,代码太大了,买个大ROM的芯片就行了.现在工作了,单位是做SoC的,采用了51的IP核,才算对51的代码/数据空间有了清晰的认识. ...

  8. 单片机按键防抖程序_单片机独立按键使用程序

    独立按键是单片机中很重要的一个器件,在这篇文章里,通过这个用独立按键控制LED灯的小程序来介绍独立按键开关的使用. 1.按键分类与输入原理         按键按照结构原理科分为两类,一类是触点式开关 ...

  9. 设定pic单片机端口为输入_PIC单片机的模块和功用

    PIC16F616是一款14引脚.8位的CMOS单片机.选用精简指令集,仅有35条指令,因为选用了数据总线和指令总线别离的哈佛总线构造,使得除少数指令不是单周期以外,大有些的指令都是单周期指令.这么有 ...

最新文章

  1. CentOS下SVN服务的启动与关闭
  2. 《云图计划》的动效简析
  3. String Stringbuilder StringBuffer的区别和应用
  4. Android 9.0新特性
  5. 练习题|网络编程-socket开发
  6. 安卓手机软件开发_无代码手机app软件开发,让人人都是专业开发工程师
  7. 微信小程序上传大于4m_微信定制小程序开发
  8. 3DTouch - iOS新特性
  9. mysql 主备监控_mysql 主从备份监控slave状态nagios脚本
  10. c traps and pitfalls reading notes(2)
  11. java foreach跳出本次循环_java控制流程最全示例
  12. 计算机软件 题目,计算机软件论文题目
  13. 四、Sensor组成
  14. java dns缓存清理_清除DNS缓存信息方法
  15. html显示十进制特殊字符,一些有可能用到的HTML特殊字符十进制代码
  16. 航测无人机las点云数据生成DEM
  17. iOS 非越狱下的代码注入
  18. 计算机专业术语简单释义
  19. 如何在linux服务器下载文件夹,linux服务器怎么下载文件到本地
  20. 独享带宽和共享带宽的区别

热门文章

  1. 利用jQuery如何获取当前被点击的按钮
  2. ES6生成器函数generator
  3. 7.hdfs工作流程及机制
  4. linux 查看磁盘空间大小命令
  5. 实现Android 动态载入APK(Fragment or Activity实现)
  6. webkit内核浏览器的CSS写法
  7. ComboBox信息读取
  8. linux编译多个函数,Swift on Linux —— 多文件协同编译
  9. [UE4]虚幻引擎UE4如何制作可拖动(Drag and Drop)的背包(Scrollbox)(转载)
  10. 快速阅读软件工程后的几个问题