⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 16字单绿点阵屏电子钟.c

📁 16点阵显示时钟 可以现实年月日 及温度 可调
💻 C
📖 第 1 页 / 共 2 页
字号:
/*****************************************************
       16字LED点阵屏+DS1302电子钟 C 程序
******************************************************
声明:
     本程序中DS1302读写部分是直接引用网上网友提供的共享程序,
	 本程序供大家学习之用,用勿用于商业用途。尊重作者版权。
	 
	 编写:邓椿薪
	 时间:2006年2月6日 晚
	 邮箱:love2151@xinhuanet.com
*******************************************************

 DS1302 接线图

         Vcc2  CLK I/O  /RST 
           
            |   |   |   |
           -------------------
          | 8   7   6   5  |
          |   DS1302       |
          |                |
          | 1   2   3   4  |
           -------------------
            |   |   |   |
         VCC1           GND

1 脚接+5V    2,3脚32768HZ晶振  4脚接地  5脚接S51的P02 6脚接S51的P01 7接S51的P00
8脚接后备电源,可以接老计算机主板上的3.6V电池,也可以通过二级管隔离接一个大容量电解电容
电压在2.5V以上即可维持


595连级输出数据,138行驱动。*/



#include <AT89x51.H>
#define uchar unsigned char
#define uint unsigned int

uchar code hanzi[18][32];
uchar code hanzi2[];
uchar code timer[12][16];
uchar code sw[];

void xs_out();                     /*输出显示*/
void out_rxd(unsigned char *d);    /*串口发送一行*/



/******************************************/
sbit resget=P1^3;			//时钟复位
sbit key_moda=P1^0;			//模式转换
sbit key_up=P1^1;			//时钟加
sbit key_Down=P1^2;			//时钟减

sbit T_CLK=P1^7;		//DS1302引脚连接
sbit T_IO =P1^6;
sbit T_RST=P1^5;

sbit ACC0=ACC^0;       //1bit数据存储位
sbit ACC7=ACC^7;

uchar inittime[7]={0x00,0x10,0x22,0x13,0x01,0x05,0x06};	 //初始化后设置
uchar yid,i,e,id,miao,fen,shi,nian,yue,ri,xinqi;  //时间变量
uint zimuo,ss;
uchar BUFF[10];			           // 缓存

void   RTInputByte(uchar);         /* 输入 1Byte */
uchar  RTOutputByte(void);         /* 输出 1Byte */
void   W1302(uchar, uchar);        // 向DS1302写入一个字节
uchar  R1302(uchar);               // 从DS1302读出一个字节
void   Set1302(uchar *);           // 写DS1302时间
void   du1302();                   // 读时间  
void   DelayMs(void);              // 延时
void   Set(uchar,uchar );          // 变量调整
void   in_data();				   // 调整移动数据
void   rxd_data();				   // 串口发送移动数据

/*主函数*/
void main()
{
   yid=0;
   zimuo=0;
  SCON=0;             //初始化串口为工作方式0(同步通信方式,TxD输出同步脉冲)
   while(1)            //重复循环显示
   {
  	 while(yid<16)				       //数据移位。
     {
	  for(e=0;e<8;e++)                  //移动速度
	  {	
	  if(resget==0)
	  {DelayMs();
       if(resget==0)
	   Set1302(inittime);           //初始化 
	   W1302(0x8e,0x00);           /* 控制命令,WP=0,写操作?*/                 
	   W1302(0x90,0xa5);           //打开充电二级管  一个二级管串联一个2K电阻 
	  }  
	 du1302();            //读取 秒 分 时 日 月 星期 年	  	
 	  if (key_moda==0)	           // 设置和选择项目键
       {DelayMs();
	    if(key_moda==0)
	     {
	       id++;if(id==8) {id=0;yid=0;zimuo=0;}
		   while(key_moda==0){ xs_out();}    
          }
	   }
	  
    
     if (key_up==0) //增加
      {
       DelayMs();
       if(key_up==0)
	   {
	   	while(key_up==0)
		 {xs_out();}
		 ss=0;
		 Set(id,0);
		}  
       }
   
   if (key_Down==0)  //减少
      {
       DelayMs();
       if(key_Down==0)
	    {
	     while(key_Down==0)
		{xs_out();}
		ss=0;
		Set(id,1);
		}         
      }
	 xs_out();		        /******调用显示****/
	}
   yid++;				//移动一步
   
  }
  yid=0;
  zimuo=zimuo+32;		//后移一个字,
  if(zimuo>=960)		//总数减2个字。
   zimuo=0;
  }
 }

/************************************************/
void xs_out()		   //串行输出显示
{
   for(i=0;i<16;i++)
      { 
       
	    ss++;					         //ss为闪烁延时计数器
		if (ss==1500)					 //定义SS的大小决定调整时闪烁的快慢,小于750时为亮,大于750时为黑
		   {ss=0;}
	  if(id==0)							 //当ID为零时显示移动的汉字。在时间设置时ID不为零
	    {								 //显示年。
         in_data();				  //调整移动数据
	     rxd_data();				  //串口发送移动数据
        }
	  else					   //id不为零时,显示年。只有在时钟设置时ID才不为零。
	   {
	     out_rxd(&timer[11][i]);	         //不显示
	     if(id==1&&ss>750)			     //当ID为1和SS大于1000时年不显示。
	      {
	        out_rxd(&timer[11][i]);	     //不显示 
			out_rxd(&timer[11][i]);	     //不显示
		    out_rxd(&timer[11][i]);	     //不显示
			out_rxd(&timer[11][i]);	     //不显示
	       }
		 else
		  { out_rxd(&timer[2][i]);       //20年   
	        out_rxd(&timer[0][i]);
            out_rxd(&timer[nian/16][i]); //年   
	        out_rxd(&timer[nian%16][i]);
	       }
		
	    out_rxd(&timer[11][i]);	      //不显示

	    out_rxd(&hanzi[0][i*2+1]);     //年字符  
	    out_rxd(&hanzi[0][i*2]);
       }
	   if(id==2&&ss>750)			  //当ID为2和SS大于1000时月不显示。
	      {out_rxd(&timer[11][i]);	  //不显示 
		   out_rxd(&timer[11][i]);}	  //不显示
	   else
	    {if(yue/16==0)
	       out_rxd(&timer[11][i]);	  //当月十位为零时不显示
	     else
	      out_rxd(&timer[yue/16][i]);	
          out_rxd(&timer[yue%16][i]); //月
	    }

	   out_rxd(&hanzi[1][i*2+1]);     //月字符
	   out_rxd(&hanzi[1][i*2]);

	   if(id==3&&ss>750)			  //当ID为3和SS大于1000时日不显示。
	      {out_rxd(&timer[11][i]);	  //不显示 
		   out_rxd(&timer[11][i]);}	  //不显示
	   else
		 {out_rxd(&timer[ri/16][i]);	
          out_rxd(&timer[ri%16][i]);}  //日
		 							
	   out_rxd(&hanzi[17][i*2+1]);     //日字符
	   out_rxd(&hanzi[17][i*2]);

	   out_rxd(&hanzi[2][i*2+1]);     //星字符
	   out_rxd(&hanzi[2][i*2]);
       out_rxd(&hanzi[3][i*2+1]);     //期字符
	   out_rxd(&hanzi[3][i*2]);

	   out_rxd(&timer[11][i]);	      //不显示

	   if(id==4&&ss>750)		 //当ID为3和SS大于1000时星期不显示。
	      {out_rxd(&timer[11][i]);	       //不显示 
		   out_rxd(&timer[11][i]);}	       //不显示
	   else
		 {out_rxd(&hanzi[xinqi+10][i*2+1]);//星期值字符
	      out_rxd(&hanzi[xinqi+10][i*2]);}
		 
	   out_rxd(&timer[11][i]);	        //不显示

	   if(id==5&&ss>750)			 //当ID为4和SS大于1000时时不显示。
	      {out_rxd(&timer[11][i]);	    //不显示 
		   out_rxd(&timer[11][i]);}	    //不显示
	   else
		 {
	      if(shi/16==0)
		    out_rxd(&timer[11][i]);	    //当时十位为零时不显示
	      else
	       out_rxd(&timer[shi/16][i]);	//从串口输出时十位。
	       out_rxd(&timer[shi%16][i]);	//从串口输出时个位。
		  }

       out_rxd(&timer[10][i]);          //从串口输出两点。

	   if(id==6&&ss>750)			 //当ID为6和SS大于1000时分不显示。
	      {out_rxd(&timer[11][i]);	    //不显示 
		   out_rxd(&timer[11][i]);}	    //不显示
		  
	  else
		 {out_rxd(&timer[fen/16][i]);	 //输出分值
          out_rxd(&timer[fen%16][i]);}
		 
	   out_rxd(&timer[10][i]);		     //从串口输出两点。

	   if(id==7&&ss>750)			     //当ID为6和SS大于1000时秒不显示。
	      {out_rxd(&timer[11][i]);	     //不显示 
		   out_rxd(&timer[11][i]);}     //不显示
		else
		 {out_rxd(&timer[miao/16][i]);	 //输出秒值
	      out_rxd(&timer[miao%16][i]);}
		  
	  
	 /*****************************************************************/
	  
	  P2_7=1;					  //锁存为高,595锁存信号
	  P2=sw[i];				  //输出行信号
	  DelayMs();	 //延时,等待一段时间,让这列显示的内容在人眼内产生“视觉暂留”现象。*/
	  P2=0x7f;		         //关闭显示。
	 }
	
 }


void in_data(void)		 //调整数据
{
 char s;
	for(s=4;s>=0;s--)			              //i为向后先择字节计数器,zimuoo为向后先字计数器
	{
	 BUFF[2*s+1]=hanzi2[zimuo+32*s+2*i];     // 把第一个字模的第一个字节放入BUFF0中,第二个字模和第一个字节放入BUFF2中
	 BUFF[2*s]=hanzi2[zimuo+1+32*s+2*i];	    // 把第一个字模的第二个字节放入BUFF1中,第二个字模的第二个字节放入BUFF3中
	}
}

/***********************发送移动的数据****************************/
void rxd_data(void)		            //串行发送数据
{
  uchar s;
  uchar inc,tempyid,temp;
  if(yid<8)
    inc=0;
  else 
    inc=1;
  for(s=0+inc;s<8+inc;s++)		   //发送8字节数据
	{
	 if(yid<8) 
      tempyid=yid;
     else 
     tempyid=yid-8;
     temp=(BUFF[s]>>tempyid)|(BUFF[s+1]<<(8-tempyid));	//h1左移tempyid位后和h2右移8-tempyid相或,取出移位后的数据。
    
	 SBUF=temp;                      //把BUFF中的字节从大到小移位相或后发送输出。
	  while(TI==0);       //等待发送完毕
      TI=0;
	 
	}
}


/*******************************************************/ 
 void out_rxd(unsigned char *d)	  /*从串口发送数据*/
{
     SBUF=*d;
	  while(TI==0);       //等待发送完毕
      TI=0;
	 
 } 
  


//根据选择调整相应项目
void Set(uchar sel,uchar sel_1) 
{
  uchar address,item;
  uchar max,mini;
  if(sel==7)  {address=0x80; max=0;mini=0;}     //秒
  if(sel==6)  {address=0x82; max=59;mini=0;}    //分钟
  if(sel==5)  {address=0x84; max=23;mini=0;}    //小时
  if(sel==4)  {address=0x8a; max=7; mini=1;}    //星期
  if(sel==3)  {address=0x86; max=31;mini=1;}    //日
  if(sel==2)  {address=0x88; max=12;mini=1;}    //月
  if(sel==1)  {address=0x8c; max=99;mini=0;}    //年
  
  
  item=R1302(address+1)/16*10+R1302(address+1)%16;
  if (sel_1==0) item++;  else item--;
  if(item>max) item=mini;   
  if(item<mini) item=max;
           
  W1302(0x8e,0x00);
  W1302(address,item/10*16+item%10);
  W1302(0x8e,0x80);  
}

/**************************延时***********************/

void DelayMs(void)
 {
  uchar TempCyc;
  for(TempCyc=100;TempCyc>1;TempCyc--)
     {;}
 }

//********DS1302读写程序***************//
/******************************************************************** 
函 数 名:RTInputByte()
功    能:实时时钟写入一字节
说    明:往DS1302写入1Byte数据 (内部函数)
入口参数:d 写入的数据 
返 回 值:无  
***********************************************************************/
void RTInputByte(uchar d) 
{ 
    uchar h;
    ACC = d;
    for(h=8; h>0; h--)
    {
        T_IO = ACC0;           /*相当于汇编中的 RRC */
        T_CLK = 1;
        T_CLK = 0;
        ACC = ACC >> 1; 
    } 
}
/******************************************************************** 
函 数 名:RTOutputByte()
功    能:实时时钟读取一字节
说    明:从DS1302读取1Byte数据 (内部函数)
入口参数:无  
返 回 值:ACC
设    计:zhaojunjie           日    期:2002-03-19
修    改:                     日    期: 
***********************************************************************/
uchar RTOutputByte(void) 
{ 
    uchar h;
    for(h=8; h>0; h--)
    {
        ACC = ACC >>1;         /*相当于汇编中的 RRC */
        ACC7 = T_IO;
        T_CLK = 1;
        T_CLK = 0;
    } 
    return(ACC); 
}
/******************************************************************** 
函 数 名:W1302()
功    能:往DS1302写入数据
说    明:先写地址,后写命令/数据 (内部函数)
调    用:RTInputByte() , RTOutputByte()
入口参数:ucAddr: DS1302地址, ucData: 要写的数据
返 回 值:无
***********************************************************************/
void W1302(uchar ucAddr, uchar ucDa)
{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -