项目实现功能: 使 用开发板板扩展时钟芯片 DS12C887 设计一个时钟, 要求如下:

( 1 ) 在 1602 液晶上显示年、月、日、星期、时、分、秒, 并且按秒实时更新显示。
( 2 ) 具有闹铃设定及到时报警功能, 报警响起时按任何键可取消报警。
( 3 ) 能够使用板上的按键随时调节各个参数, 按键可设计 4 个有效键, 分别为功能选择键、数值增大键、数值减小键和闹钟查看键。
( 4 ) 每次有键按下时, 蜂鸣器都以短“滴"声报警。
( 5 ) 利用 DS12C887 自身掉电可继续走时的特性, 设计实现断电时间不停、再次上电时时间仍然准确显示在液晶上的功能。

      读者可先根据项目实现功能自行尝试编写程序,当遇到困难时再参考本例中的源代码, 认真反省为何自己没有找到合适的解决办法。如果可能, 建议读者详细阅读DS12C887 的数据手册, 进 一步挖掘它的其他特性, 设计出更有意义的功能。

一、时钟芯片概述:

       在许多电子设备中,通常会进行一些与时间有关的控制,如果用系统的定时器来设计时钟的话,偶然的掉电或晶振的误差都会造成时间的错乱,更糟糕的是,若完全用程序设计时钟还会占用大量的系统资源,从而严重影响系统的其他功能。为此,很多芯片制造公司都设计出了各种各样的实时时钟芯片。
       常见的时钟芯片有两种。
       一种是体积非常小的表贴式元件,通常用在高端小型手持式仪器或设备中,如手机、PDA、MP4播放器、GPS导航仪等。这种芯片在使用时需要外接备份电池和外部晶振,电池用来保持主系统在意外掉电时为时钟芯片供电,外部晶振用来提供时钟芯片所必须的振荡来源,标准频率为32.768kHz,这种芯片体积小、所以引脚也很少,操作起来非常方便,比如,DALLAS公司生产的串行实时时钟芯片DS1302,    DS1337,    DS1338,    DS1390和并行的DS1558等,大家可上美芯官方网站查看更多型号,其中我们日常用的较多的是DS1302。
       另一种体积相对较大,一般为直插式,它的内部集成有可充电锥电池,同时内部还集成了32.768kHz的标准晶振,一旦设定好时间,即使系统的主电源掉电,该时钟芯片仍然可以靠它内部集成的悝电池走数年,当系统重新上电时,又可为锤电池重新充电,这样一来可以非常有效地保持时间的连续性,使用时非常方便。这类芯片如DALLAS公司生产DS12887,DS12887A,DS12B887,DS12C887等。本例讲解的芯片是具有代表性且综合性能较高的DS12C887时钟芯片。

二、DS12C887  时钟芯片介绍:

       DS12C887时钟芯片能够自动产生世纪、年、月、日、时、分、秒等时间信息,其内部有世纪寄存器,从而利用硬件电路解决“千年”问题。DS12C887    中自带锥电池,外部掉电时,其内部时间信息还能够保持10年之久。对千一天内的时间记录,有    12小时制和24小时制两种模式。在12小时制模式中,用    AM和PM区分上午和下午;芯片内部时间的存储方式也有两种,一种用二进制数表示,另一种是用BCD码表示。DS12C887时钟芯片中带有128BRAM,其中11BRAM用来存储时间信息;4BRAM用来存储DS12C887的控制信息,称为控制寄存器;113B    通用RAM供用户使用。此外,用户还可对DS12C887进行编程以实现多种方波输出,并可对其内部的三路中断通过软件进行屏蔽。该芯片内部有一个精密的温度补偿电路用来监视Vee的状态,如果检测到主电源故障,该器件可以自动切换到备用电源供电。VBAeKUP引脚用于支持可充电电池或超级电容,内部包括一个始终有效的涓流充电器。DS12C887可以通过一个多路复用的单字节接口访问,该接口支持Intel和Motorola模式。DS12C887将它自已与石英晶体和电池集成在一起。
       DS12C887特性描述如下:

  • 为充电电池或超级电容提供涓流充电。
  • RTC 计算秒、分、时、星期、日、月、年信息, 具 有润年补偿, 有 效 期至 2099 年。
  • 用二进制数或 BCD 码表示时间。
  • 具有 AM,   PM 标示的 12 小时或 24 小时模式。
  • 夏时制选择。
  • 可选择Intel 或 Motorola 总线时序。
  • 三路中断可分别通过软件屏蔽与检测。
  • 闹钟可设置为每秒一次至每星期一次。
  • 周期可设置在 122µs      500ms 之间。
  • 时钟终止刷新周期标志。
  • 可编程的方波输出信号。
  • 自动电源失效检测和切换电路。
  • 可选的工业级温度范围。

      DS12C887时钟芯片的引脚排列如下图所示,与单片机典型接口如下下图所示。各引脚功能说明如下:


1(MOT)—总线操作时序选择端。它有两种总线工作模式,即Motorola和Intel模式。当MOT接Vcc时,选用Motorola模式;当MOT接GND或悬空时,选用Intel模式。本文主要讨论Intel模式。
2,3,16,20,22(NC)—空引脚。
4~11(AD0~AD7)—复用地址数据总线。该总线采用时分复用技术,在总线周期的前半部分,出现在AD0~AD7上的是地址信息,可用以选通DS12C887内的RAM,总线周期的后半部分出现在AD0~AD7上的是数据信息。

12,24(GND,Vcc)一系统电源接入端。其中Vcc接+5V输入,GND接地,当Vcc输入为+5V时,用户可以访问DS12C887内RAM中的数据,并可对其进行读/写操作;当Vee的输入小于+4.25V时,禁止用户对内部RAM进行读/写操作,此时用户不能正确获取芯片内的时间信息;当Vcc的输入小于+3V时,DS12C887会自动将电源切换到内部自带的梩电池上,以保证内部的电路能够正常工作。
13(c/s/)—芯片片选端。低电平有效。
14(AS)—地址选通输入端。在进行读/写操作时,AS的上升沿将AD0~AD7上出现的地址信息锁存到DS12C887上,而下一个下降沿清除AD0~AD7上的地址信息,不论CS是否有效,DS12C887都将执行该操作。
15(R/W)—读/写输入端。该引脚也有两种工作模式,当MOT接Vcc时,R/W_工作在Motorola模式。此时,该引脚的作用是区分读操作还是写操作,R/W_高电平时为读操作,R/W_低电平时为写操作;当MOT接GND时,该引脚工作在Intel模式,此时该引脚作为写允许输入,即WriteEnable,此信号的上升沿锁存数据。
17(DS)—数据选择或读输入脚。该引脚有两种工作模式,当MOT接Vcc时,选用Motorola工作模式,此时,每个总线周期的后一部分的DS为高电平,称为数据选通。在读操作中,DS的上升沿使DS12C887将内部数据送往总线AD0~AD7上,以供外部读取。在写操作中,DS的下降沿将使总线AD0~AD7上的数据锁存在DS12C887中。当MOT接GND时,选用Intel工作模式,此时该引脚是读允许输入引脚,即ReadEnable。
18(RESET)—芯片复位引脚。低电平有效,通常将该引脚接Vcc即可。
19(I/R/Q/)一中断请求输出。低电平有效,用做处理器的中断申请输入。只要引起中断的状态位置位,并且相应中断使能位也置位,I/R/Q/将一直保持低电平,处理器程序通常读取C寄存器来清除I/R/Q/引脚输出,RESET引脚也会清除未处理的中断。没有中断发生时,I/R/Q/为高阻状态,可将多个中断器件接到一条I/R/Q/总线上,只要它们均为漏极开路输出即可。I/R/Q/引脚为漏极开路输出,需要使用一个外接上拉电阻与Vcc相连。
23(SQW)一方波输出引脚。当供电电压Vcc大于4.25V时,SQW引脚可输出方波,

此时,用户可以通过对控制寄存器编程来得到13种方波信号的输出。
DS12C887时钟芯片各寄存器定义如下表所示。

1、控制寄存器A:

       UIP—更新(UIP)位,用来标志芯片是否即将进行更新。当UIP=1时,更新即将开始;当UIP=0时,表示至少在244µs内芯片不会更新,此时,时钟、日历和闹钟信息可以通过读/写相应的字节获得并设置。UIP位为只读位且不受复位信号(RESET)的影响。通过把寄存器B中的SET位设置为1,可以禁止更新并将UIP位清0。
       DV2,DV1,    DV0—这三位用来开/关晶体振荡器和复位分频器。
       当[DV0,DV1,DV2]=[010]时,晶体振荡器开启且保持时钟运行。
       当[DV0,DV1,DV2]=[11X]时,晶体振荡器开启,但分频保持复位状态。
       RS3,RS2,RS1,RS0—速率选择位。这4个速率选择位用来选择15级分频器的13种分频之一,或禁止分频器输出。按照所选择的频率产生方波输出(SWQ引脚)和/或一个周期性中断。用户可进行如下操作:
(1) 设置周期中断允许位(PIE);
(2) 设置方波输出允许位(SQWE);
(3) 两位同时设置为有效,并且设置频率;
(4) 两者都禁止。
       下表为周期性中断率和方波中断频率表,该表列出了可通过RS寄存器选择的周期中断的频率和方波的频率。这 4 个可读/写位不受复位信号的影响。

2、控制寄存器B:

SET—SET=0,芯片更新正常进行;SET=1,芯片更新被禁止。SET位可读/写,并不受复位信号的影响。
PIE—PIE=0,禁止周期中断输出到IRQ;PIE=1,允许周期中断输出到IRQ。
AIE—AIE=0,禁止闹钟中断输出到IRQ;AIE=1,允许闹钟中断输出到蔽5。
UIE—UIE=0,禁止更新结束中断输出到IRQ;UIE=1,允许更新结束中断输出到IRQ。此位在复位或设置SET位为高时清0。
SQWE—SQWE=0,SQW引脚为低电平;SQWE=1,SQW输出设定频率的方波。
DM—DM=0,设置寄存器存储数据格式为BCD码格式;DM=1,设置寄存器存储数据格式为二进制数格式,此位不受复位信号影响。
24/12—为1,24小时制;为0,12小时制。
DSE一夏令时允许标志。在四月的第一个星期日的1:59:59AM,时钟调到3:00:00AM;在十月的最后一个星期日的1:59:59AM,    时钟调到1:00:    00AM。

3、控制寄存器C:

IRQF—中断请求标志。
当以下4种情况中有一种或几种发生时,IRQF置高:
•PF=PIE=1•AF=AIE=1
•UF=UIE=1    `
•IRQF=PF•PIE+AF•AIE+UF•UIE
IRQF—旦为高,IRQ脚输出低电平。
所有标志位在读寄存器C或复位后清0。
PF—周期中断标志。
AF—闹钟中断标志。
UF—更新中断标志。

4、控制寄存器D:

VRT—VRT=0,表示内置电池能量耗尽,,此时RAM中数据的正确性就不能保证了。

5、时序图分析:

Mototola和Intel模式总线读/写时序图下面三个图。

6、操作时需要注意的5个问题:

(1)  本章仅介绍了DS12C887时钟芯片的主要内容,具体操作时要求读者务必到其官方网站下载完整资料仔细阅读。
(2)  有一点要特别申明,大家在自己连接电路时,首先要确认自己连接好的电路是绝对正确的,否则无论如何修改程序也难以得出预期的结果。
(3)  按键可按如下方式设置:功能键为S2、数值增大键为S13、数值减小键为S17、闹钟查看键为S4。
(4)  存储器数据格式有两种模式:BCD码和二进制数。为方便操作,我们设置为二进制数模式,通过设置寄存器B中的DM=1来选择二进制数模式。
(5)  DS12C887时钟芯片在出厂时内部振荡器均为关闭状态,这是为了避免在开始使用前消耗捚电池能量。寄存器A的第4~6位为010时,打开振荡器并使计时链可用。为11X组合时,(DV2=1,DV1=1,DV0=X)打开振荡器,但振荡器的计时链保持为复位状态。这三位的其他组合方式均使振荡器关闭。因此,在首次操作DS12C887芯片时,必须首先设置这三位的状态。

三、如何用实验板扩展本实验?

DS12C887 是一款纯数字式的芯片,只 要它与单片机的1/0 口直接相连就可以操作它了, 连接 TX- IC 实验板时需要准备一小块面包电路板,一些杜邦线。DS12C887 实物图如下图左所示, 杜邦线如下图右所示, 电路板如下下图所示:

四、原理图分析:

五、程序代码:

主函数

#include <reg52.h>
#include "delay_Sum.h"
#include "1602_Sum.h"
#include "ds12c887_Sum.h"
#include "74hc595_Sum.h"
#include "delay_Sum.h"
#include "boardinit_Sum.h"uchar num,time,moshi,moshi1,flag,kaiqi,c;
char shi,fen,miao,shiji,nian,yue,ri,xingqi,ashi,afen,amiao,kaiz;void didi()
{write_byte_74hc595(0x02);  //蜂鸣器关delay(500);write_byte_74hc595(0x06);  //蜂鸣器响delay(500);
}void main()
{boardinit();    //XK-2板卡初始化 lcdinit_1602(); //1602液晶初始化init_ds12c887();//ds12c887 初始化EA=1;IT0=1;EX0=1;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号*/
//***************************************************************************//在1602上写时间的框架Disp_1602(1,1," 20  -  -       ",16);Disp_1602(1,2," 00   -  -      ",16); while(1){keyscan();if(flag==1){didi();}if(kaiqi==0){
//****************************************************************************************          //读出DS12C887芯片里的 时间,日期  数据    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); //读 闹钟 秒//****************************************************************************************         //把读出的时间,日期数据, 写到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}

#include "delay_Sum.h"

/*
*文 件 名:  delay_Sum.c
* 晶  振 : 11.0592MHz
*创 建 者:  Sumjess
*创建时间:   2019.4.18
*/#include "delay_Sum.h"void delay(uint z)     //毫秒
{uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);
}
void delay_smg(uint z)
{uint x,y;for(x=z;x>0;x--)for(y=50;y>0;y--);
}
void delay_ds18b20(uint time)   //液晶专用
{uint  i,j;for(i=0;i<time;i++)for(j=0;j<1;j++);
}
void delayms(unsigned int n)    //延时子程序
{
unsigned int i,j;
for(i=0;i<n;i++)for(j=0;j<2000;j++);
}

#include "1602_Sum.h"

/*
* 文 件 名:1602led.c.c
* 芯    片:1602液晶
* 晶    振:11.0592MHz
* 创 建 者:XK
* 创建日期:2011.8.6
* 修 改 者:Sumjess
* 修改日期:2019.5.29
* 功能描述:1602,写数据函数
*/#include <reg52.h>
#include "1602_Sum.h"
#include "delay_Sum.h"
#include "74hc595_Sum.h"sbit rs_1602=P2^5; //1602rs信号
sbit rw_1602=P2^6; //1602rw信号
sbit e=P2^4;  /*
void write_zl(uchar zl)
{rs=0;P0=zl;delay(5);e=1;delay(5);e=0;
}void write_sj(uchar sj)
{rs=1;P0=sj;delay(5); e=1;delay(5);e=0;
}     */
void write_order_1602(uchar order_data)
{e=0;rs_1602=0;P0=order_data;e=1;delay(1);e=0;
}void write_data_1602(uchar data_1602)
{   e=0;rs_1602=1;P0=data_1602;e=1;delay(1);e=0;
}/
//功能:按指定位置显示一串字符
///
//输入:
//列显示地址x_1602(取值范围1-16)
//行显示地址y_1602(取值范围1-2),
//指定字符串指针*p_1602,
//要显示的字符个数count_1602 (取值范围1-16)
///
// 子函数使用例子: Disp_1602(1,1," TEMP:    .     ",16);  //在1602第一行第一列写16个字符,既字符串数据
/void Disp_1602(unsigned char x_1602,unsigned char y_1602,unsigned char *p_1602,unsigned char count_1602)
{
unsigned char i;    for(i=0;i<count_1602;i++){if (1 == y_1602) x_1602 |= 0x80; //当要显示第一行时地址码+0x80;else x_1602 |= 0xC0;        //在第二行显示是地址码+0xC0;write_order_1602(x_1602-1);write_data_1602(*p_1602);x_1602++;                  p_1602++;}
}  void write_oneline_1602(uchar add_1602,uint date_1602)
{uchar bai,ge,shi;            bai=date_1602/100;shi=(date_1602%100)/10;ge=date_1602%10;          write_order_1602(0x80+add_1602-1);write_data_1602(0x30+bai);write_order_1602(0x80+add_1602);write_data_1602(0x30+shi);write_order_1602(0x80+add_1602+1);write_data_1602(0x30+ge);//在1602上写时间函数  即在1602第二行指定位置上写显示    //在1602上写时间函数  即在1602第二行指定位置上写显示}void write_twoline_1602(uchar add_1602,uint date_1602)
{uchar bai,ge,shi;            bai=date_1602/100;shi=(date_1602%100)/10;ge=date_1602%10;          write_order_1602(0x80+0x40+add_1602-1);write_data_1602(0x30+bai);write_order_1602(0x80+0x40+add_1602);write_data_1602(0x30+shi);write_order_1602(0x80+0x40+add_1602+1);write_data_1602(0x30+ge);//在1602上写时间函数  即在1602第二行指定位置上写显示}void write_oneline_DS18b20_1602(uchar add_1602,uint date_1602)
{uchar qian,bai,shi,ge;qian=date_1602/1000;bai=(date_1602%1000)/100;shi=(date_1602%100)/10;ge=date_1602%10;write_order_1602(0x40+0x40+add_1602-1);write_data_1602(0x30+qian);write_order_1602(0x40+0x40+add_1602);write_data_1602(0x30+bai);write_order_1602(0x40+0x40+add_1602+1);write_data_1602(0x30+shi);write_order_1602(0x40+0x40+add_1602+3);write_data_1602(0x30+ge);          //在1602上写时间函数  即在1602第二行指定位置上写显示}void write_sfm(uchar add,char date)
{//1602液晶刷新时分秒函数4为时,7为分,10为秒char shi,ge;shi=date/10;ge=date%10;write_order_1602(0x80+0x40+add);write_data_1602(0x30+shi);write_data_1602(0x30+ge);
}
void write_nyr(uchar add,char date)
{//1602液晶刷新年月日函数3为年,6为分,9为秒char shi,ge;shi=date/10;ge=date%10;write_order_1602(0x80+add);write_data_1602(0x30+shi);write_data_1602(0x30+ge);
}
void write_week(char we)
{//写液晶星期显示函数write_order_1602(0x80+12);switch(we){case 1:   write_data_1602('M');delay(5);write_data_1602('O');delay(5);write_data_1602('N');break;case 2:    write_data_1602('T');delay(5);write_data_1602('U');delay(5);write_data_1602('E');break;case 3:    write_data_1602('W');delay(5);write_data_1602('E');delay(5);write_data_1602('D');break;case 4:    write_data_1602('T');delay(5);write_data_1602('H');delay(5);write_data_1602('U');break;case 5:    write_data_1602('F');delay(5);write_data_1602('R');delay(5);write_data_1602('I');break;case 6:    write_data_1602('S');delay(5);write_data_1602('A');delay(5);write_data_1602('T');break;case 7:    write_data_1602('S');delay(5);write_data_1602('U');delay(5);write_data_1602('N');break;}
}void write_oneline_ds12c887_1602(uchar add_1602,uint date_1602)
{uchar ge,shi;shi=date_1602/10;ge=date_1602%10;write_order_1602(0x80+add_1602-1);write_data_1602(0x30+shi);write_order_1602(0x80+add_1602);write_data_1602(0x30+ge);  //在1602上写时间函数  即在1602第二行指定位置上写显示}void write_twoline_ds12c887_1602(uchar add_1602,uint date_1602)
{uchar shi,ge;shi=date_1602/10;ge=date_1602%10;write_order_1602(0x80+0x40+add_1602-1);write_data_1602(0x30+shi);write_order_1602(0x80+0x40+add_1602);write_data_1602(0x30+ge);           //在1602上写时间函数  即在1602第二行指定位
}void lcdinit_1602()
{rw_1602=0;e=0;write_byte_74hc595(0X02);//关流水灯使能 关蜂鸣器 光继电器 打开1602背光打开 write_order_1602(0x38);  //液晶设置不判忙模式write_order_1602(0x0c);  //开显示 不显示光标write_order_1602(0x06);  //当写一个字符是,地址指针加 1write_order_1602(0x01);     //显示清屏
}

#include "ds12c887_Sum.h"

#include <reg52.h>
#include "ds12c887_Sum.h"
#include "74hc595_Sum.h"
#include "delay_Sum.h"sbit dsds_ds12c887=P1^0;
sbit dsrw_ds12c887=P1^1;
sbit dsas_ds12c887=P1^2;
//sbit dscs_ds12c887=P1^4;  //该板卡的dscs 信号是通过74hc595提供 该使能信号需在下面子函数处理
sbit dsirq_ds12c887=P3^2; 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(uchar ashi,uchar afen,uchar amiao)
{write_ds_ds12c887(1,amiao);write_ds_ds12c887(3,afen);write_ds_ds12c887(5,ashi);  //在DS12C887闹钟寄存器中写入 闹钟时间 函数
}void write_ds_ds12c887(uchar add_ds12c887,uchar data_ds12c887)
{delay(1);write_byte_74hc595(0X02);//  ds12c887de 使能端 cs=0    1602背光打开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);write_byte_74hc595(0X12);//  ds12c887de 使能端 cs=1     1602背光打开delay(1);
}//ds12c887 写数据子函数
//------------------------------------------------------------------------------
uchar read_ds_ds12c887(uchar add_ds12c887)
{uchar ds_date; dsas_ds12c887=1;dsds_ds12c887=1;dsrw_ds12c887=1;delay(1);write_byte_74hc595(0X02);//  ds12c887de 使能端 cs=0      1602背光打开             delay(1);P0=add_ds12c887;delay(1);dsas_ds12c887=0;dsds_ds12c887=0;P0=0XFF;ds_date=P0;dsds_ds12c887=1;dsas_ds12c887=1;write_byte_74hc595(0X12); //  ds12c887de 使能端 cs=1     1602背光打开 return ds_date;
}

#include "74hc595_Sum.h"

/*
* 文 件 名:74hc595_Sum.c
* 芯    片:74hc595
* 晶    振:11.0592MHz
* 创 建 者:XK
* 创建日期:2011.8.6
* 修 改 者:Sumjess
* 修改日期:2019.4.18* 功能描述:给74hc595芯片写一字节数据芯片使用说明:SI 是串行数据输入口,当SRCK来一个上升沿时,写入此刻SI上的数据,到移位寄存器,同时左移一位。当八位数据发送完时,给RCK一个上升沿,移位寄存器的八位数据输出到QA-Q7芯片比较;74hc164和74hc595功能,基本相同。其根本的区别在RCK上,只有当RCK来上升沿输出QA-Q7,才会更新。其次,595的驱动能力更强。芯片使用;
第一步:目的:将要准备输入的位数据移入74HC595数据输入端上。方法:送位数据到_595。
第二步:目的:将位数据逐位移入74HC595,即数据串入方法:SH_CP产生一上升沿,将DS上的数据移入74HC595移位寄存器中,先送低位,后送高位。
第三步:目的:并行输出数据。即数据并出方法:ST_CP产生一上升沿,将由DS上已移入数据寄存器中的数据送入到输出锁存器。
说明: 从上可分析:从SH_CP产生一上升沿(移入数据)和ST_CP产生一上升沿(输出数据)是二个独立过程,实际应用时互不干扰。即可输出数据的 同时移入数据。 [2] //芯片作用;74hc573使能端送高电平,为的是让LED所连接的74hc573芯片使能,才可能驱动LED。//
*/  #include <reg52.h>
#include "74hc595_Sum.h"
#include "delay_Sum.h"sbit data_595si   =P1^0;  //595数据输入口
sbit clk_595srck  =P1^4;  //595数据写进移位寄存器时钟输入口
sbit e_595rck     =P2^3;  //595移位寄存器,数据送输出的时钟void write_byte_74hc595(uchar dat) //74hc164芯片写一字节数据函数
{                         uchar i;             e_595rck=0;       //给595RCK低电平  for(i=0;i<8;i++)  {                             clk_595srck=0;     //给595SRCK低电平             data_595si=(dat<<i)&0x80;       //把我们要使用的数据进行左移处理,保证最终输出的数据与 我们 uchar dat 对应clk_595srck=1;     //给595SRCK高电平     }e_595rck=1;  //给595SRCK高电平,既把 DAT数据数据送到输出  data_595si=1;//因该数据口和别的电路共用,因此当74hc595使用完后,置“1”解除冲突
}  

#include "boardinit_Sum.h"

/*
* 文 件 名:boardinit_Sum.c
* 芯    片:
* 晶    振:11.0592MHz
* 创 建 者:XK
* 创建日期:2011.9.17
* 修 改 者:Sumjess
* 修改日期:2019.4.18
* 功能描述:EASYBOARD xk-2 v2.0开发板把卡硬件初始化。
*/
#include <reg52.h>
#include "74hc595_Sum.h"
#include "boardinit_Sum.h"sbit duanxuan=P2^5;    // 数码管,的段选使能,1 通 0关
sbit weixuan=P2^6; // 数码管,的位选使能,1 通 0关void boardinit()
{duanxuan=1; //数码管,的段选使能,1 通 0关weixuan=1;  //数码管,的位选使能,1 通 0关P0=0x00; //P0口送清零,关LED数码管的必要数据准备。duanxuan=0; //数码管,的段选使能,1 通 0关weixuan=0;  //数码管,的位选使能,1 通 0关write_byte_74hc595(0x40); //选通8位发光二极管控制芯片u6(74HC573)锁存器的使能端   P1=0xff; //P1口送全1,关8位发光二极管的必要数据准备。//写完上句理论上8个发光二级管都会熄灭,因74HC595数据口复用了P1.0故P1.0的二极管可能不能被熄灭。write_byte_74hc595(0x00);    //关闭8位发光二极管控制芯片u6(74HC573)锁存器的使能端,把P1口数据保存(既关发光二极管)。
}

STC51入门笔记(郭天祥C语言)---第十一节:使用DS12C887时钟芯片设计高精度时钟相关推荐

  1. STC51入门笔记(郭天祥C语言)---第七节:l2C总线AT24C02芯片应用

    声明:本篇文章只是个人知识盲区.知识弱点.重点部分的归纳总结,望各位大佬不喜勿喷.梳理顺序是按照书籍的实际顺序梳理,转载请注明出处. 作者:sumjess 一.I2c总线概述: 1.I2c总线介绍   ...

  2. STC51入门笔记(郭天祥C语言)---第四节:键盘检测原理及应用实现

    声明:本篇文章只是个人知识盲区.知识弱点.重点部分的归纳总结,望各位大佬不喜勿喷.梳理顺序是按照书籍的实际顺序梳理,转载请注明出处. 作者:sumjess 键盘分为编码键盘和非编码键盘.键盘上闭合键的 ...

  3. STC51入门笔记(郭天祥C语言)---第二节:Keil 软件使用及流水灯设计

    声明:本篇文章只是个人知识盲区.知识弱点.重点部分的归纳总结,望各位大佬不喜勿喷.梳理顺序是按照书籍的实际顺序梳理,转载请注明出处. 作者:sumjess 本章详细介绍单片机程序常用编译软件 Keil ...

  4. STC51入门笔记(郭天祥C语言)---第三节:数码管显示原理及应用实现

    这里是引用 声明:本篇文章只是个人知识盲区.知识弱点.重点部分的归纳总结,望各位大佬不喜勿喷.梳理顺序是按照书籍的实际顺序梳理,转载请注明出处. 作者:sumjess 一.数码管显示原理 我们先来看几 ...

  5. STC51入门笔记(郭天祥C语言)---第八节:通用型1602,12232,12864液晶操作方法

    声明:本篇文章只是个人知识盲区.知识弱点.重点部分的归纳总结,望各位大佬不喜勿喷.梳理顺序是按照书籍的实际顺序梳理,转载请注明出处. 作者:sumjess 一.液晶概述: 液晶(LiquidCryst ...

  6. Web前端开发笔记——第三章 CSS语言 第四节 CSS列表、表格样式

    目录 一.CSS列表样式 (一)设计列表项前标志类型 (二)设计列表项前标志位置 (三)设计列表项图片 (四)设计整体列表属性 二.CSS表格样式 (一)设计表格大小 (二)设计表格边框 (三)奇偶选 ...

  7. Kotlin学习笔记 第二章 类与对象 第十一节 枚举类 第八节密封类

    参考链接 Kotlin官方文档 https://kotlinlang.org/docs/home.html 中文网站 https://www.kotlincn.net/docs/reference/p ...

  8. Web前端开发笔记——第三章 CSS语言 第七节 圆角边框、阴影

    目录 前言 一.圆角边框 (一)border-×-×-radius (二)border-radius 二.阴影 (一)基本阴影设置 (二)内部阴影设置 结语 前言 本节介绍仅在CSS3中的新内容,例如 ...

  9. Web前端开发笔记——第三章 CSS语言 第六节 CSS定位

    目录 一.定义 二.文档流定位 (一)block类型元素 (二)inline类型元素 (三)inline-block类型元素 三.浮动定位 (一)左浮动和右浮动 (二)清除浮动 四.层定位 (一)st ...

  10. Web前端开发笔记——第三章 CSS语言 第五节 盒子模型

    目录 一.CSS布局与定位 二.盒子模型 三.盒子模型的组成 四.设置边框的属性 五.设置外.内边距的属性 六.overflow 属性 结语 一.CSS布局与定位 在CSS中对一个网页进行布局与定位, ...

最新文章

  1. 鸿蒙霸榜GitHub,从最初的Plan B到“取代Android”?
  2. ML之DT:基于DT算法对泰坦尼克号乘客数据集进行二分类(是否获救)预测
  3. vue知识总结第一篇vue组件的定义以及父子组件的传值。
  4. Java中的mapreduce没了_MapReduce的过程总结
  5. 类型全部为string_python小讲堂丨学了这么久的,这6种基本数据类型你真的理解了吗...
  6. nagios整合cacti2011版(五)
  7. Jsoup的简易使用示例
  8. 沈伟华:图神经网络的三连问
  9. 干货!3 个重要因素,带你看透 AI 技术架构方案的可行性
  10. Android之开发杂记(一)
  11. UDP打洞原理及代码
  12. WORD出错:布局也会超出内容区
  13. Seasonal-ARIMA模型
  14. c语言编译器不支持c99,Visual Studio2013的C语言编译器对C99标准的支持情况
  15. 前端实现电子签名(vue组件)
  16. 掉线(自创--根据刘德华《今天》歌词改编)
  17. spring boot 转pdf (html转pdf)
  18. 极部落TrueChain公链训练营_长沙站[湘链技术社区]
  19. ssm项目---人事管理系统:员工与部门、职位实现一对一
  20. 和小鲜肉相比,老程序员该由哪些优势?

热门文章

  1. I2S音频接口的理解
  2. 威纶触摸屏使用说明书_PLC变频器触摸屏综合实训
  3. sql 替换字段中的部分字符,替换指定字符
  4. 数据治理方案技术调研 Atlas VS Datahub VS Amundsen
  5. 知网下载学位论文PDF版本的一个方法
  6. c# html导出excel,C#将HTML导出Excel
  7. 基于MDK编译器 STM32与12864液晶显示程序 和电路连接
  8. 【转载】Altera官方资料整理
  9. cocos2d-html5 仿微信打飞机游戏
  10. Office SharePoint Designer 2007 RTM 中文版 BT、HTTP、Emule下载