C/C++教程

STC89C516驱动DS12C887时钟模块

本文主要是介绍STC89C516驱动DS12C887时钟模块,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

DS12C887

  • DS12C887时钟芯片能输出世纪、年、月、日、时、分、秒等时间信息
  • 集成电池, 外部掉电时, 时间不会丢失.
  • 有12小时和24小时两种模式. 在12小时制模式中, 用AM和PM区分上午和下午
  • 时间的存储方式有两种: 一种用二进制数表示, 另一种是用BCD码表示
  • 带有128 byte RAM, 其中11 byte用来存储时间信息, 4 byte用来存储DS12C887的控制信息, 称为控制寄存器; 113 byte 通用RAM, 供用户使用. * 可以对DS12C887进行编程, 实现多种方波输出
  • 可对其内部的三路中断通过软件进行屏蔽
  • 芯片内部有一个精密的温度补偿电路用来监视Vee的状态, 如果检测到主电源故障, 该器件可以自动切换到备用电源供电
  • VBAeKUP引脚用于支持可充电电池或超级电容, 内部包括一个始终有效的涓流充电器.
  • 可以通过一个多路复用的单字节接口访问, 该接口支持Intel和Motorola模式

引脚功能

GND、 VCC
VCC接+5V输入, 当VCC输入为+5V时, 用户可以访问DS12C887内RAM中的数据, 并可对其进行读写操作. 当VCC的输入小于+4.25V时, 禁止用户对内部RAM进行读写操作, 此时用户不能正确获取芯片内的时间信息. 当VCC的输入小于+3V时, DS12C887会自动将电源发换到内部自带的锂电池上.

MOT
模式选择脚. DA12C887有两种工作模式: Motorola模式和Intel模式, 当MOT接VCC时是Motorola模式, 当MOT接GND时是Intel模式. 一般使用Intel模式.

SQW
方波输出脚. 当供电电压VCC大于4.25V时, SQW脚可进行方波输出, 此时用户可以通过对控制寄存器编程来得到13种方波信号的输出

AD0-AD7
复用地址数据总线, 该总线采用时分复用技术, 在总线周期的前半部分出现在AD0-AD7上的是地址信息, 可用以选通DS12C887内的RAM, 总线周期的后半部分出现在AD0-AD7上的是数据信息.

AS
地址选通输入脚, 在进行读写操作时, AS的上升沿将AD0-AD7上出现的地址信息锁存到DS12C887上, 而下一个下降沿清除AD0-AD7上的地址信息, 不论是否有效, DS12C887都将执行该操作.

DS/RD
数据选择或读输入脚, 该引脚有两种工作模式

  • MOT接VCC时, 为Motorola工作模式, 在这种工作模式中, 每个总线周期的后一部分的DS为高电平, 被称为数据选通, 在读操作中, DS的上升沿使DS12C887将内部数据送往总线AD0-AD7上, 以供外部读取, 在写操作中, DS的下降沿将使总线 AD0-AD7上的数据锁存在DS12C887中.

R/W
读/写输入端. 该管脚也有2种工作模式

  • 当MOT接VCC时, 工作在Motorola模式, 此时该引脚的作用是区分进行的是读操作还是写操作, 当R/W为高电平时为读操作, R/W 为低电平时为写操作.
  • 当MOT接GND时, 工作在Intle模式, 此时该引脚作为写允许输入

STC89C516连接DS12C877

连接

  • 操作DS12C887时钟芯片共需要13条信号线, 分别是并行数据地址复用线ADO~AD7, CS, AS, R/W, DS 和 IRQ
  • 将RESET引脚固定接高电平
  • DS, AS, R/W,CS分别连接单片机的P1.0 - P1.4口, 当然连接其他口也可以, 只要可以正常操作即可
  • IRQ是DS12C887的中断申请端, 该引脚不能随便连接, 必须与单片机的外部中断引脚相连, 这样当DS12C887芯片向单片机申请中断时, 单片机才不会遗漏的检测出所有的中断, 这里我们将其与单片机的P3.2相连.
左侧
MOT => GND
AD0 => P0.0
...
AD7 => P0.7
GND => GND

右侧
VCC => VCC
SQW
IRQ => P3.2
RESET => VCC
DS  => P1.0
RW  => P1.1
AS  => P1.2
CS  => P1.4

USB2TTL连线

TX  => P3.0
RX  => P3.1

代码

读取时间信息的测试代码

#include <reg52.h>
#include <stdio.h>

typedef unsigned int u16;
typedef unsigned char u8;

u8 num,time,moshi,moshi1,flag,kaiqi,c;
char shi,fen,miao,shiji,nian,yue,ri,xingqi,ashi,afen,amiao,kaiz;

void delay(u16 z) {
	u16 x,y;
	for(x=z;x>0;x--)
		for(y=110;y>0;y--);   
}

sbit dsds_ds12c887 = P1^0;
sbit dsrw_ds12c887 = P1^1;
sbit dsas_ds12c887 = P1^2;
sbit dscs_ds12c887 = P1^4;
sbit dsirq_ds12c887 = P3^2;

void write_ds_ds12c887(u8 add_ds12c887, u8 data_ds12c887)
{
	delay(1);
	dscs_ds12c887 = 0; // ds12c887de 使能端 cs=0
	delay(1);
	dsas_ds12c887=1;
	dsds_ds12c887=1;
	dsrw_ds12c887=1;
	delay(1);
	P0 = add_ds12c887;
	delay(1);
	dsas_ds12c887=0;
	dsrw_ds12c887=0;
	P0 = data_ds12c887;
	dsrw_ds12c887=1;
	dsas_ds12c887=1;
	delay(1);
	dscs_ds12c887 = 1; // ds12c887de 使能端 cs=1
	delay(1);
}

u8 read_ds_ds12c887(u8 add_ds12c887)
{
	u8 ds_date; 
	dsas_ds12c887=1;
	dsds_ds12c887=1;
	dsrw_ds12c887=1;
	delay(1);
	dscs_ds12c887 = 0; // ds12c887de 使能端 cs=0
	delay(1);
	P0 = add_ds12c887;
	delay(1);
	dsas_ds12c887=0;
	dsds_ds12c887=0;
	P0 = 0XFF;
	ds_date=P0;
	dsds_ds12c887=1;
	dsas_ds12c887=1;
	dscs_ds12c887 = 1; // ds12c887de 使能端 cs=1
	return ds_date;	
}

void init_ds12c887()
{ 
	write_ds_ds12c887(0x0b,0x26); //如果開啓設置 控制器B, 數據爲BCD碼, 時間爲24小時制, 產生鬧鐘中斷
	write_ds_ds12c887(0x0a,0x20); //打開時鐘震盪   
	amiao=read_ds_ds12c887(1);
	afen=read_ds_ds12c887(3);
	ashi=read_ds_ds12c887(5); //讀DS12C887 鬧鐘 時, 分, 秒 即當進入鬧鐘設置狀態下, 顯示當前設定鬧鐘的時間
}

 void set_alarm_ds12c887(u8 ashi, u8 afen, u8 amiao)
{
	write_ds_ds12c887(1,amiao);
	write_ds_ds12c887(3,afen);
	write_ds_ds12c887(5,ashi);  //在DS12C887鬧鐘寄存器中寫入 鬧鐘時間 函數 
}

void main()
{
  P0=0x00; //P0口送清零, 關LED數碼管的必要數據準備. 
  P1=0xff; //P1口送全1, 關8位發光二極管的必要數據準備. 

  init_ds12c887();//ds12c887 初始化

	EA=1;
	IT0=1;
	EX0=1;
  
  // 初始化UART
  TMOD = 0x20;
  SCON = 0x40;
  TH1 = 256 - 11.0592 * 1000 * 1000 / 12 / 32 / 9600 + 0.5;
  TCON |= 0x40;
  SCON |= 0x02;
  // 初始化UART结束

  c=read_ds_ds12c887(0x0c);
  //write_ds_ds12c887(0x0b,0x26);//如果開啓設置 控制器B, 數據爲BCD碼, 時間爲24小時制, 產生鬧鐘中斷
  num=0;time=0;moshi=0;moshi1=0;flag=0;kaiqi=0;

  /*	該部分是調試程序時候使用, 當出現時間日期亂碼時候, 可以嘗試重新寫入給定數據
  判斷是否是內部保存數據長時間未用導致出現亂碼.  
  write_ds_ds12c887(4,9);      //小時寄存器 寫 9點
  write_ds_ds12c887(2,27);	    //分鐘寄存器 寫 27分
  write_ds_ds12c887(0,25);	    //秒鐘寄存器 寫 25秒  
  write_ds_ds12c887(6,7);      //星期寄存器寫 7 星期天	  
  write_ds_ds12c887(9,11);     //年寄存器 寫 11年
  write_ds_ds12c887(8,8);      //月份寄存器 寫 8月
  write_ds_ds12c887(7,7);      //日期寄存器 寫 7號
  */ 

	while(1) {
    miao  = read_ds_ds12c887(0x00); //讀 秒			 
    fen   = read_ds_ds12c887(0x02); //讀 分
    shi   = read_ds_ds12c887(0x04); //讀 時
    ri    = read_ds_ds12c887(0x07); //讀 日
    yue   = read_ds_ds12c887(0x08); //讀 月
    nian  = read_ds_ds12c887(0x09); //讀 年
    xingqi= read_ds_ds12c887(0x06); //讀 星期
    shiji = read_ds_ds12c887(0x10); //讀 實際   保存實際數據, 內部不自加, 只是當做存儲器用			
    kaiz  = read_ds_ds12c887(0x0e); //讀 鬧鐘 標誌位
    ashi  = read_ds_ds12c887(0x05); //讀 鬧鐘 時
    afen  = read_ds_ds12c887(0x03); //讀 鬧鐘 分
    amiao = read_ds_ds12c887(0x01); //讀 鬧鐘 秒
    
    printf("%bu-%bu-%bu\r\n", nian, yue, ri);
    printf(" %bu:%bu:%bu\r\n", shi, fen, miao);

    //把讀出的時間, 日期數據,  寫到1602液晶顯示 
    /*write_twoline_ds12c887_1602(5,shi);	   //寫 時
    write_twoline_ds12c887_1602(8,fen);    //寫 分
    write_twoline_ds12c887_1602(11,miao);  //寫 秒
    write_oneline_ds12c887_1602(10,ri);	   //寫 日
    write_oneline_ds12c887_1602(7,yue);    //寫 月
    write_oneline_ds12c887_1602(4,nian);   //寫 年
    write_oneline_ds12c887_1602(14,xingqi);//寫 星期
    write_oneline_ds12c887_1602(2,shiji);  //寫 世紀
    write_twoline_ds12c887_1602(2,kaiz);   //寫 鬧鐘開啓位
    */
  }	 	 
}


void exter() interrupt 0
{	
	flag=1;                   //開外部中斷 0
}

参考

  • https://blog.csdn.net/dai_wen/article/details/81050120
  • http://www.51hei.com/bbs/dpj-184639-1.html
  • https://blog.csdn.net/huang873036652/article/details/91460594
  • http://www.51hei.com/bbs/dpj-29544-1.html
  • http://news.eeworld.com.cn/mcu/ic466119.html
  • c51的printf格式 https://www.keil.com/support/man/docs/c51/c51_printf.htm
这篇关于STC89C516驱动DS12C887时钟模块的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!