8051单片机Proteus仿真与开发实例-DS1302 RTC驱动仿真

Posted 视觉智能

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了8051单片机Proteus仿真与开发实例-DS1302 RTC驱动仿真相关的知识,希望对你有一定的参考价值。

DS1302 RTC驱动仿真

1、DS1302介绍

DS1302 涓流充电计时芯片包含一个实时时钟/日历和 31 字节的静态 RAM。它通过一个简单的串行接口与微处理器通信。实时时钟/日历提供秒、分、小时、日、日、月和年信息。对于少于 31 天的月份,月末日期会自动调整,包括闰年的更正。时钟以 24 小时或 12 小时格式运行,带有 AM/PM 指示器。

通过使用同步串行通信简化了 DS1302 与微处理器的接口。与时钟/RAM 通信只需要三根线:CE( R S T \\over RST RST)、I/O(数据线)和 SCLK(串行时钟)。数据可以一次 1 个字节或最多 31 个字节的突发传输到时钟/RAM 或从时钟/RAM 传输。 DS1302 旨在以极低的功耗运行,并以低于 1µW 的功率保留数据和时钟信息。 DS1302 是 DS1202 的后继产品。除了 DS1202 的基本计时功能外,DS1302 还具有用于主电源和备用电源的双电源引脚、用于 VCC1 的可编程涓流充电器和七个额外字节的暂存器存储器的附加功能。

1)DS1302的命令组成

  • Bit7 必须始终为逻辑 1。否则写入 DS1302 将被禁用。
  • Bit6 指定时钟/日历或 RAM 选择。 如果它是 logic0 我们与时钟交谈,或者如果它是 logic1 我们与 RAM 交谈。
  • 位 5 至 1 指定要输入或输出的指定寄存器。 (地址)
  • Bit0 指定对 DS1302 的写或读操作。 如果是逻辑 0 则执行写操作,如果是逻辑 1 则执行读操作。
  • 命令字节总是从 LSB 开始(Bit0)。

2)DS1302数据传输过程

  • 在开始传输任何内容之前,必须将 CE 引脚拉高,以便与芯片通话。 (选择)

  • 之后,发送命令字节,通知 DS1302 将进行的操作。 (无论是读还是写,对时钟还是 RAM。)

  • 然后,如果执行写操作,则将要写入的数据发送到 RAM 或时钟中,或者如果执行读操作,则可以
    从时钟或 RAM 中读取数据。

如果从 DS1302 读取数据,则在写入命令字节的最后一位后的第一个下降沿上,数据将可用。相反,写入 DS1302 发生在命令字节传输后的低电平到高电平转换。要记住的四个注意事项,是所有发送和接收字节都是 LSB 优先,在命令字节和数据字节之后的写操作中发送到 DS1302 的附加 SCLK 脉冲将被忽略。

读取操作后立即发送的附加 SCLK 脉冲,数据将再次可供读取。最后,当与 DS1302 通信时,微控制器的时钟应处于 2MHZ 的最大速度,如下面的数据表所示。如果使用不同的速度,那么必须校准频率以满足 DS1302 的需要,并将其重新校准为之前的频率。

3)DS1302设置

DS1302的寄存器如下:

从左边开始,前两列是指命令字节。 是否要读取或写入 RTC 或 RAM。从 (bit7 到 bit0) 的列是指它将在 RTC 或 RAM 中传输的数据字节。

2、仿真电路原理图

3、仿真代码实现

1)发送数据

// 发送一位节数据
void ds1302_send(unsigned char byte_t) {	
	unsigned char mask = 0x01;				

	IO_OUT(DS1302_DDR, DS1302_SIO);			
	do {
		IO_CLR(DS1302_PORT, DS1302_SCK);		
		if (byte_t & mask) IO_SET(DS1302_PORT, DS1302_SIO);	
		else IO_CLR(DS1302_PORT, DS1302_SIO);				
		IO_SET(DS1302_PORT, DS1302_SCK);	
		mask = mask << 1;					
	} while (mask);
	IO_CLR(DS1302_PORT, DS1302_SCK);
}

// 向指定寄存写数据
void ds1302_write(unsigned char ch, unsigned char byte_t) {
	ds1302_select(DS1302_CS);				
	ds1302_send(ch | DS1302_CMD_WRITE);		
	ds1302_send(byte_t);
	ds1302_deselect(DS1302_CS);				
}

2)读数据

// 读取一位数据
unsigned char ds1302_get(void) {			
	unsigned char mask = 0x01;				
	unsigned char tmp = 0x00;				

	IO_IN(DS1302_DDR, DS1302_SIO);			
	do {
		IO_CLR(DS1302_PORT, DS1302_SCK);	
		NOP(); NOP();
		if (DS1302_PORT_IN & DS1302_SIO) tmp |= mask;	
		else tmp |= 0x00;					
		IO_SET(DS1302_PORT, DS1302_SCK);	
		mask = mask << 1;					
	} while (mask);
	IO_CLR(DS1302_PORT, DS1302_SCK);
	return tmp;
}

// 读指定寄存器数据
unsigned char ds1302_read(unsigned char ch) {
	unsigned char tmp;
	ds1302_select(DS1302_CS);				
	ds1302_send(ch | DS1302_CMD_READ);		
	tmp = ds1302_get();
	ds1302_deselect(DS1302_CS);				
	return tmp;				
}

3)年、月、日、时、分秒设置与读取

// 秒设置与读取
#define ds1302_sec_write(n)					ds1302_write(DS1302_SEC, (n))	
#define ds1302_sec_read()					ds1302_read(DS1302_SEC)	

// 分设置与读取
#define ds1302_min_write(n)					ds1302_write(DS1302_MIN, (n))	
#define ds1302_min_read()					ds1302_read(DS1302_MIN)			

// 时设置与读取
#define ds1302_hour_write(n)				ds1302_write(DS1302_HOUR, (n))
#define ds1302_hour_read()					ds1302_read(DS1302_HOUR)		

// 一个月的日设置与读取
#define ds1302_mdat_write(n)				ds1302_write(DS1302_MDAT, (n))	
#define ds1302_mdat_read()					ds1302_read(DS1302_MDAT)		

// 月读取与设置
#define ds1302_mon_write(n)					ds1302_write(DS1302_MON, (n))	
#define ds1302_mon_read()					ds1302_read(DS1302_MON)			

// 一周的日设置与读取
#define ds1302_wday_write(n)				ds1302_write(DS1302_WDAY, (n))
#define ds1302_wday_read()					ds1302_read(DS1302_WDAY)

// 年的设置与读取
#define ds1302_year_write(n)				ds1302_write(DS1302_YEAR, (n))
#define ds1302_year_read()					ds1302_read(DS1302_YEAR)

4)主程序

//#include <regx52.h>							//we use keil c51
#include "gpio.h"
#include "delay.h"
#include "ds1302.h"
#include "uart.h"
#include "i2c_sw.h"
#include <stdio.h>

unsigned int year,month,day,hours,minutes,seconds;

void mcu_init(void) {
	uart_init();
	ds1302_init();
	// 初始读取
	year = ds1302_year_read();
  month = ds1302_mon_read();
  day = ds1302_mdat_read();
  hours = ds1302_hour_read();
  minutes = ds1302_min_read();
  seconds = ds1302_sec_read();
}

int main(void) {
	mcu_init();								//reset the mcu
	uart_send_str("****DS1302****\\r\\n");
	while (1) {
		year = ds1302_year_read();
    month = ds1302_mon_read();
    day = ds1302_mdat_read();
    hours = ds1302_hour_read();
    minutes = ds1302_min_read();
    seconds = ds1302_sec_read();
		
		printf("%d-%d-%d %d:%d:%d\\r\\n",BCD2DEC(year),BCD2DEC(month),BCD2DEC(day),BCD2DEC(hours),BCD2DEC(minutes),BCD2DEC(seconds));
		
		delay_ms(1000);
	}
}

4、仿真结果

以上是关于8051单片机Proteus仿真与开发实例-DS1302 RTC驱动仿真的主要内容,如果未能解决你的问题,请参考以下文章

proteus仿真51流水灯和点阵(心形)

仿真软件proteus构建流水灯实验

利用Proteus仿真STM32实现按键控制LED灯设计

利用Proteus仿真STM32实现按键控制LED灯设计

仿真软件proteus构建七段数码管显示数字0-9实验

51单片机 PCF8591模数与数模转换实例+Proteus仿真