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

项目实现功能: 使 用开发板板扩展时钟芯片 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时钟芯片的引脚排列如下图所示,与单片机典型接口如下下图所示。各引脚功能说明如下:

STC51入门笔记(郭天祥C语言)---第十一节:使用DS12C887时钟芯片设计高精度时钟_第1张图片

STC51入门笔记(郭天祥C语言)---第十一节:使用DS12C887时钟芯片设计高精度时钟_第2张图片
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模式总线读/写时序图下面三个图。

STC51入门笔记(郭天祥C语言)---第十一节:使用DS12C887时钟芯片设计高精度时钟_第3张图片

STC51入门笔记(郭天祥C语言)---第十一节:使用DS12C887时钟芯片设计高精度时钟_第4张图片

STC51入门笔记(郭天祥C语言)---第十一节:使用DS12C887时钟芯片设计高精度时钟_第5张图片

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 实物图如下图左所示, 杜邦线如下图右所示, 电路板如下下图所示:

STC51入门笔记(郭天祥C语言)---第十一节:使用DS12C887时钟芯片设计高精度时钟_第6张图片

四、原理图分析:

STC51入门笔记(郭天祥C语言)---第十一节:使用DS12C887时钟芯片设计高精度时钟_第7张图片

五、程序代码:

主函数

#include 
#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

#include "1602_Sum.h"

/*
* 文 件 名:1602led.c.c
* 芯    片:1602液晶
* 晶    振:11.0592MHz
* 创 建 者:XK
* 创建日期:2011.8.6
* 修 改 者:Sumjess
* 修改日期:2019.5.29
* 功能描述:1602,写数据函数 
*/

#include 
#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

#include "ds12c887_Sum.h"

#include 
#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 
#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<

#include "boardinit_Sum.h"

/*
* 文 件 名:boardinit_Sum.c
* 芯    片:
* 晶    振:11.0592MHz
* 创 建 者:XK
* 创建日期:2011.9.17
* 修 改 者:Sumjess
* 修改日期:2019.4.18
* 功能描述:EASYBOARD xk-2 v2.0开发板把卡硬件初始化。  
*/
#include 
#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口数据保存(既关发光二极管)。  
}

 

你可能感兴趣的:(STC89C51从入门到进阶)