51_数码管 - DS1302可调时钟

DS1302.c

#include "DS1302.h"

//引脚定义
sbit DS1302_SCLK=P3^6;
sbit DS1302_IO=P3^4;
sbit DS1302_CE=P3^5;

//寄存器写入地址/指令定义
#define DS1302_miao		0x80
#define DS1302_feng		0x82
#define DS1302_shi			0x84
#define DS1302_ri			0x86
#define DS1302_yue		0x88
#define DS1302_xingqi			0x8A
#define DS1302_nian			0x8C
#define DS1302_WP			0x8E       //写保护


//时间数组,索引0~6分别为年、月、日、时、分、秒、星期,设置为有符号的便于<0的判断
char DS1302_Time[]={19,11,16,22,56,0,6};

void DS1302_Init(void)  //DS1302初始化
{
	DS1302_CE=0;
	DS1302_SCLK=0;  
}

void DS1302_WriteByte(unsigned char Command,Data) //DS1302写一个字节 Command 命令字/地址 Data 要写入的数据
{
	unsigned char i;
	DS1302_CE=1;                    //CE时钟高开始写数据
	for(i=0;i<8;i++)                //写命令
	{
//		DS1302_IO=Command&(0x01<<i);  //最低位开始写
    DS1302_IO=Command&0x01;    //读数据
    Command >>= 1;
		DS1302_SCLK=1;               //SCLK高写数据
		DS1302_SCLK=0;
	}
	for(i=0;i<8;i++)              //写数据
	{
		DS1302_IO=Data&(0x01<<i);   //最低位开始写
//     DS1302_IO=Data&0x01;    //读数据
//     Data >>= 1;
		DS1302_SCLK=1;             //SCLK高写数据
		DS1302_SCLK=0; 
	}
	DS1302_CE=0;                //写完释放时钟CE置零
}

unsigned char DS1302_ReadByte(unsigned char Command)  //DS1302读一个字节 Command 命令字/地址
{
	unsigned char i,Data=0x00;

	Command|=0x01;	//将指令转换为读指令
	DS1302_CE=1;       //CE时钟高开始读数据a
	for(i=0;i<8;i++)               //读命令
	{
		DS1302_IO=Command&(0x01<<i);    //读数据
//    DS1302_IO=Command&0x01;    //读数据
//    Command >>= 1;
		DS1302_SCLK=0;
		DS1302_SCLK=1;  //SCLK高写数据
	}
	for(i=0;i<8;i++)    //读数据
	{
   
		DS1302_SCLK=1;   
		DS1302_SCLK=0;     //SCLK读数据

   if(DS1302_IO){Data|=(0x01<<i);} //{Data=Data|(0x01<<i);}  读出端口是1就置1
//     Data>>=1; 
//    if(DS1302_IO){Data|=0x80;} //{Data=Data|(0x01<<i);}  读出端口是1就置1


	}
	DS1302_CE=0;       //读完释放时钟CE置零
	DS1302_IO=0;	//读取后将IO设置为0,否则读出的数据会出错
	return Data;

}

uchar dat_to_BCD(uchar dat)//数据转BCD码
{
	uchar dat1,dat2;
	dat1 = dat / 10;
	dat2 = dat % 10;
	dat2 = dat2 + dat1 * 16;
	return dat2;
}

uchar BDD_to_dat(uchar dat)//BCD码转数据
{
	uchar dat1,dat2;
	dat1 = dat /16;
	dat2 = dat % 16;
	dat2 = dat2 + dat1 * 10;
	return dat2;
}

void DS1302_SetTime(void)  //十进制转BCD码后写入DS1302中
{
	DS1302_WriteByte(DS1302_WP,0x00);  //WP=0 写操作
	DS1302_WriteByte(DS1302_nian,dat_to_BCD(DS1302_Time[0]));//
	DS1302_WriteByte(DS1302_yue,dat_to_BCD(DS1302_Time[1])); //
	DS1302_WriteByte(DS1302_ri	,dat_to_BCD(DS1302_Time[2]));//
	DS1302_WriteByte(DS1302_shi	,dat_to_BCD(DS1302_Time[3]));//
	DS1302_WriteByte(DS1302_feng,dat_to_BCD(DS1302_Time[4]));//
	DS1302_WriteByte(DS1302_miao,dat_to_BCD(DS1302_Time[5]));//
	DS1302_WriteByte(DS1302_xingqi,dat_to_BCD(DS1302_Time[6]));//星期
	DS1302_WriteByte(DS1302_WP,0x80);    //WP=0x80打开写保护功能

}

void DS1302_ReadTime(void)  //BCD码转十进制后保存到数组准备读取
{
  DS1302_Time[0]=BDD_to_dat(DS1302_ReadByte(DS1302_nian));
  DS1302_Time[1]=BDD_to_dat(DS1302_ReadByte(DS1302_yue));
  DS1302_Time[2]=BDD_to_dat(DS1302_ReadByte(DS1302_ri));
  DS1302_Time[3]=BDD_to_dat(DS1302_ReadByte(DS1302_shi));
  DS1302_Time[4]=BDD_to_dat(DS1302_ReadByte(DS1302_feng));
  DS1302_Time[5]=BDD_to_dat(DS1302_ReadByte(DS1302_miao));
  DS1302_Time[6]=BDD_to_dat(DS1302_ReadByte(DS1302_xingqi));
}

DS1302.h

#include "system.h"

//外部可调用时间数组,索引0~6分别为年、月、日、时、分、秒、星期,设置为有符号的便于<0的判断
extern char DS1302_Time[];

void DS1302_Init(void);
void DS1302_WriteByte(unsigned char Command,Data);
unsigned char DS1302_ReadByte(unsigned char Command);
void DS1302_SetTime(void);
void DS1302_ReadTime(void);

uchar dat_to_BCD(uchar dat);//数据转BCD码
uchar BDD_to_dat(uchar dat);//BCD码转数据

//void DS1302_WriteByte(unsigned char addr,dat);	//向DS1302 命令(地址+数据);

#endif

smg.c

#include "smg.h"
#include "DS1302.h"
#include "led.h"
#include "key.h"
 uchar code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
					0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//显示0~F的值

uchar DisplayData[8];	//定义8位数组
int x=0,y=0;				//段选数码管赋值给x,y,x表示列,y表示行
uchar num;
uchar key,wei;

void DigDisplay()	 //数码管显示位选
{
//  uchar i;			//位选变量
//	for(i=0;i<8;i++)
//	{
//		switch(i)	 //位选,选择点亮的数码管,
//		{
//			case(0):
//				LSA=1;LSB=1;LSC=1; break;//显示第7
//			case(1):
//				LSA=0;LSB=1;LSC=1; break;//显示第6
//			case(2):
//				LSA=1;LSB=0;LSC=1; break;//显示第5
//			case(3):
//				LSA=0;LSB=0;LSC=1; break;//显示第4
//			case(4):
//				LSA=1;LSB=1;LSC=0; break;//显示第3 
//			case(5):
//				LSA=0;LSB=1;LSC=0; break;//显示第2 
//			case(6):
//				LSA=1;LSB=0;LSC=0; break;//显示第1 
//			case(7):
//				LSA=0;LSB=0;LSC=0; break;//显示第0	
//		}
//		P0=DisplayData[i];//发送段码
//		Delay_us(100); //间隔一段时间扫描	
//		P0=0x00;//消隐
//  }
  static	uchar i;												
	
	P0=0x00;//消隐
	switch(i)	 //位选,选择点亮的数码管,
	{
		case(0):
			LSA=1;LSB=1;LSC=1; P0=DisplayData[0];break;//显示第0
		case(1):
			LSA=0;LSB=1;LSC=1; P0=DisplayData[1];break;//显示第1
		case(2):
			LSA=1;LSB=0;LSC=1; P0=DisplayData[2];break;//显示第2
		case(3):
			LSA=0;LSB=0;LSC=1; P0=DisplayData[3];break;//显示第3
		case(4):
			LSA=1;LSB=1;LSC=0; P0=DisplayData[4];break;//显示第4 
		case(5):
			LSA=0;LSB=1;LSC=0; P0=DisplayData[5];break;//显示第5 
		case(6):
			LSA=1;LSB=0;LSC=0; P0=DisplayData[6];break;//显示第6 
		case(7):
			LSA=0;LSB=0;LSC=0; P0=DisplayData[7];break;//显示第7	
	}	

	i++;	//
	if(i>7){i=0;}
}

void TimeShow(void)//时间显示功能
{
	DS1302_ReadTime();//读取时间
  DisplayData[0] = smgduan[DS1302_Time[3]/10]; //
	DisplayData[1] = smgduan[DS1302_Time[3]%10]; //
	DisplayData[2] = 0x40;
	DisplayData[3] = smgduan[DS1302_Time[4]/10]; //
	DisplayData[4] = smgduan[DS1302_Time[4]%10]; //
	DisplayData[5] = 0x40;
	DisplayData[6] = smgduan[DS1302_Time[5]/10]; //
	DisplayData[7] = smgduan[DS1302_Time[5]%10]; //
}

void key_xs ()
{ 
  if(key==2)    //设置选择位加1
	 {
		wei++;//设置选择位加1
    wei%=3;//位选越界清零
    //显示
		 DisplayData[0] = smgduan[DS1302_Time[3]/10]; //
		 DisplayData[1] = smgduan[DS1302_Time[3]%10]; //
		 DisplayData[3] = smgduan[DS1302_Time[4]/10]; //
		 DisplayData[4] = smgduan[DS1302_Time[4]%10]; //
		 DisplayData[6] = smgduan[DS1302_Time[5]/10]; //
		 DisplayData[7] = smgduan[DS1302_Time[5]%10]; //
	 }  
	if(key==3)    //选中的位选--
	 {
    switch(wei)	//选中的位选--
			{
				case 0:  DS1302_Time[3]++; break;  //

				case 1:  DS1302_Time[4]++; break;  //++

				case 2:  DS1302_Time[5]++; break;  //++
			}	
       //更新显示
			 DisplayData[0] = smgduan[DS1302_Time[3]/10]; //
			 DisplayData[1] = smgduan[DS1302_Time[3]%10]; //
			 DisplayData[3] = smgduan[DS1302_Time[4]/10]; //
			 DisplayData[4] = smgduan[DS1302_Time[4]%10]; //
       DisplayData[6] = smgduan[DS1302_Time[5]/10]; //
			 DisplayData[7] = smgduan[DS1302_Time[5]%10]; //
			 DS1302_SetTime(); //十进制转BCD码后写入
	 } 
	else  if(key==4)  //选中的位选--
	 {
		switch(wei)	//选中的位选--
			{
				case 0:  DS1302_Time[3]--; break; //

				case 1:  DS1302_Time[4]--; break; //

				case 2:  DS1302_Time[5]--; break; //
			}	
       //更新显示
			 DisplayData[0] = smgduan[DS1302_Time[3]/10]; //
			 DisplayData[1] = smgduan[DS1302_Time[3]%10]; //
			 DisplayData[3] = smgduan[DS1302_Time[4]/10]; //
			 DisplayData[4] = smgduan[DS1302_Time[4]%10]; //
			 DisplayData[6] = smgduan[DS1302_Time[5]/10]; //
			 DisplayData[7] = smgduan[DS1302_Time[5]%10]; //
			 DS1302_SetTime(); //十进制转BCD码后写入
	 } 
   //越界处理
   if(DS1302_Time[5]==60){DS1302_Time[5]=0;} //
	 if(DS1302_Time[4]==60){DS1302_Time[4]=0;} //
	 if(DS1302_Time[3]==24){DS1302_Time[3]=0;} //
   if(DS1302_Time[5]<0){DS1302_Time[5]=59;}  //
	 if(DS1302_Time[4]<0){DS1302_Time[4]=59;}  //
	 if(DS1302_Time[3]<0){DS1302_Time[3]=23;}  //
}

void moshi()  //模式切换
{
  static	uchar moshi=0;	//1位设置模式,0为非设置模式
  key=KeyScan();	 //key=调用检测按键函数

	if(key==1)
	 {
	 moshi++;
	
	 if(moshi>1){moshi=0;}
//     moshi%=2;//越界清零
//     moshi=moshi%2;//越界清零
	 }
	switch(moshi)
		{
			case 0:	TimeShow();break;//时间显示功能	
			case 1:key_xs ();smg_sansuo();DS1302_SetTime();break;    
		}
}

void smg_sansuo()
{
 static uint i;
	 i++;
	if(i==30)//250ms
	{  
		switch(wei)	   //选中的位选
		{
      case 0: DisplayData[0] =0x00;DisplayData[1] = 0x00;break;	 //
			case 1: DisplayData[3] =0x00;DisplayData[4] = 0x00;break;	 //
			case 2: DisplayData[6] =0x00;DisplayData[7] = 0x00;break;	 //
  	}	
	}
	if(i==60)   //500ms
	{
		i=0;
		switch(wei)	 //选中的位选
		{
		  case 0: DisplayData[0]= smgduan[DS1302_Time[3]/10]; DisplayData[1] = smgduan[DS1302_Time[3]%10];break;	 //
			case 1: DisplayData[3]= smgduan[DS1302_Time[4]/10]; DisplayData[4]=smgduan[DS1302_Time[4]%10];break;	   //
			case 2: DisplayData[6]= smgduan[DS1302_Time[5]/10]; DisplayData[7]=smgduan[DS1302_Time[5]%10];break;	   //
  	}			
	}

}

smg.h

#include "system.h"

sbit LSA=P2^2;	   //数码管位选管脚
sbit LSB=P2^3;
sbit LSC=P2^4;

void TimeShow(void);//时间显示功能
void DigDisplay(); //数码管显示位选
void  smg_xs ();   //数码管显示显示
 void key_xs ();
void smg_sansuo();

key.c

#include "key.h"	 //把led.h文件包含进来
#include "system.h"	   //把timer0.h文件包含进来
#include "led.h"
u8 KeyScan ()		//按键扫描函数
{
	static	uint timer=0;

	if(k1==0)
	{  
		timer++;
		if(timer==10){return 1;} //定时10毫秒返回
    else if(timer==1000){timer=500;return 1;} //否则长按不停加1
	}
	else if(k2==0)
	{
		timer++;  
		if(timer==10){return 2;} //定时10毫秒返回
		//else if(timer==1000){timer=900;return 2;} //否则长按不停加1
		else if(timer==1000){timer=500;return 2;} //否则长按不停加1
	}
	else if(k3==0)
	{
		timer++;
		if(timer==10){return 3;} //定时10毫秒返回
		else if(timer==1000){timer=500;return 3;} //否则长按不停加1
	}
	else if(k4==0)
	{
		timer++;
		if(timer==10){return 4;}  //定时10毫秒返回
    else if(timer==1000){timer=500;return 4;} //否则长按不停加1
	}
	else
	{
		timer=0;	   //定时清0
	}
	return 0;	
}

key.h

#include "system.h"	   //把timer0.h文件包含进来

sbit k1=P3^1;
sbit k2=P3^0;
sbit k3=P3^2;
sbit k4=P3^3;	 //定义按键端口
		
u8 KeyScan ();		//按键扫描函数
void datapros();

main.c

#include "system.h"
#include "key.h"
#include "led.h"

#include "system.h"
#include "smg.h"
#include "DS1302.h"

extern	uchar flag_1ms;	   //在其他模块中寻找其定义。另外,extern也可用来进行链接指定。

void main(void)			//程序的主函数
{
	Timer0_Init(); ////定时器0函数调用

	DS1302_Init();
//	
	DS1302_SetTime();//设置时间
  
	while(1)  			//大括号里面的东西,被不停的循环执行
	{ 
   
		//1ms进入一次
		if(flag_1ms==1)	//加了我之后,我的大括号里面的东西,被定期的1ms执行一次,反复执行	 	
		{
			flag_1ms=0;
//      DigDisplay(); //数码管显示位选
     
      moshi(); //模式切换

		}
	}
}
			 

system.c

#include "system.h"
 #include "led.h"
#include "smg.h"
uchar flag_1ms=0;

void	Timer0_Init(void)
{
	TH0 = T1MS>>8; //赋初值
	TL0 = T1MS;	   //赋初值
	TMOD = 0x01;  //设置定时器0用十六位定时器方式
    EA = 1;			 //打开总中断
  	ET0 = 1;		 //打开定时器0中断
  	TR0 = 1;		 //启动定时器0		
}

void Timer0() interrupt 1		 //中断号1
{	
	TH0 = T1MS>>8; //赋初值
	TL0 = T1MS;	   //赋初值
	flag_1ms=1;

  DigDisplay(); //数码管显示位选

}

system.h

#include "reg51.h"


#define	uchar unsigned char	//定义无符号字符
#define	uint  unsigned int	//定义无符号整形

#define	u8 unsigned char	//定义无符号字符
#define	u16  unsigned int	//定义无符号整形

#define	FOSC	12000000L	//定义晶振频率		   
#define	T1MS	(65536-FOSC/12/1000)  //定时1毫秒的时候,计数器要写入的值

void	Delay_us(uint xus);	//us级延时
void	Delay_ms(uint xms);	//ms级延时
void	Timer0_Init(void);  	//定时器初始化
  • 7
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值