DS1302和LCD1602整合长短按键电子钟

以下代码来自学习江科大自化协和手把手教你学51单片机后的整合

 

 

 

 

//LCD1602.h
#ifndef __LCD1602_H__
#define __LCD1602_H__

//用户调用函数:
void LCD_Init();
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char);
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String);
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);

#endif


//LCD1602.c

#include <STC89C5xRC.H>

//引脚配置:
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
#define LCD_DataPort P0

//函数定义:
/**
  * @brief  LCD1602延时函数,12MHz调用可延时1ms
  * @param  无
  * @retval 无
  */
void LCD_Delay()
{
	unsigned char i, j;

	i = 2;
	j = 239;
	do
	{
		while (--j);
	} while (--i);
}

/**
  * @brief  LCD1602写命令
  * @param  Command 要写入的命令
  * @retval 无
  */
void LCD_WriteCommand(unsigned char Command)
{
	LCD_RS=0;
	LCD_RW=0;
	LCD_DataPort=Command;
	LCD_EN=1;
	LCD_Delay();
	LCD_EN=0;
	LCD_Delay();
}

/**
  * @brief  LCD1602写数据
  * @param  Data 要写入的数据
  * @retval 无
  */
void LCD_WriteData(unsigned char Data)
{
	LCD_RS=1;
	LCD_RW=0;
	LCD_DataPort=Data;
	LCD_EN=1;
	LCD_Delay();
	LCD_EN=0;
	LCD_Delay();
}

/**
  * @brief  LCD1602设置光标位置
  * @param  Line 行位置,范围:1~2
  * @param  Column 列位置,范围:1~16
  * @retval 无
  */
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
	if(Line==1)
	{
		LCD_WriteCommand(0x80|(Column-1));
	}
	else if(Line==2)
	{
		LCD_WriteCommand(0x80|(Column-1+0x40));
	}
}

/**
  * @brief  LCD1602初始化函数
  * @param  无
  * @retval 无
  */
void LCD_Init()
{
	LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵
	LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关
	LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动
	LCD_WriteCommand(0x01);//光标复位,清屏
}

/**
  * @brief  在LCD1602指定位置上显示一个字符
  * @param  Line 行位置,范围:1~2
  * @param  Column 列位置,范围:1~16
  * @param  Char 要显示的字符
  * @retval 无
  */
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{
	LCD_SetCursor(Line,Column);
	LCD_WriteData(Char);
}

/**
  * @brief  在LCD1602指定位置开始显示所给字符串
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  String 要显示的字符串
  * @retval 无
  */
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=0;String[i]!='\0';i++)
	{
		LCD_WriteData(String[i]);
	}
}

/**
  * @brief  返回值=X的Y次方
  */
int LCD_Pow(int X,int Y)
{
	unsigned char i;
	int Result=1;
	for(i=0;i<Y;i++)
	{
		Result*=X;
	}
	return Result;
}

/**
  * @brief  在LCD1602指定位置开始显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~65535
  * @param  Length 要显示数字的长度,范围:1~5
  * @retval 无
  */
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
	}
}

/**
  * @brief  在LCD1602指定位置开始以有符号十进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:-32768~32767
  * @param  Length 要显示数字的长度,范围:1~5
  * @retval 无
  */
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
{
	unsigned char i;
	unsigned int Number1;
	LCD_SetCursor(Line,Column);
	if(Number>=0)
	{
		LCD_WriteData('+');
		Number1=Number;
	}
	else
	{
		LCD_WriteData('-');
		Number1=-Number;
	}
	for(i=Length;i>0;i--)
	{
		LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');
	}
}

/**
  * @brief  在LCD1602指定位置开始以十六进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~0xFFFF
  * @param  Length 要显示数字的长度,范围:1~4
  * @retval 无
  */
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i,SingleNumber;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		SingleNumber=Number/LCD_Pow(16,i-1)%16;
		if(SingleNumber<10)
		{
			LCD_WriteData(SingleNumber+'0');
		}
		else
		{
			LCD_WriteData(SingleNumber-10+'A');
		}
	}
}

/**
  * @brief  在LCD1602指定位置开始以二进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~1111 1111 1111 1111
  * @param  Length 要显示数字的长度,范围:1~16
  * @retval 无
  */
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');
	}
}

//***********************************************************************************//********************
//DS1302.h
#ifndef __DS1302_H__
#define __DS1302_H__

char DS1302_data[];
extern unsigned char TimeSetFlashFlag;

void Time_Show();
void LCD_Show();
void LCD_Show_Button();

void DS1302_Init();
void DS1302_WriteByte(unsigned char command,unsigned char Data);
unsigned char DS1302_ReadByte(unsigned char command);
void DS1302_SetTime();
void DS1302_ReadTime();
	
#endif


//DS1302.c
#include <STC89C5xRC.H>
#include "LCD1602.h"
#include "Key.h"

sbit DS1302_SCLK = P3^6;
sbit DS1302_IO = P3^4;
sbit DS1302_CE = P3^5;

char DS1302_data[] = {21,12,31,23,59,56,2}; //定义年,月,日,时,分,秒,星期

unsigned char TimeSetFlashFlag;	//时间设置闪烁标志位。

#define DS1302_sec 0x80     //写地址最后一位为零,如果是读就让它|0x01,在DS1302_ReadByte()中已经置1了,所以不用再定义0x81
#define DS1302_min 0x82
#define DS1302_hour 0x84
#define DS1302_date 0x86    //日期
#define DS1302_mon 0x88
#define DS1302_day 0x8A     //星期
#define DS1302_year 0x8C
#define DS1302_wp 0x8E      //写保护

/************BCD码转换******************/
//DEC=BCD/16*10+BCD%16
//BCD=DEC/10*16+DEC%10

void DS1302_Init()
{
	DS1302_CE = 0;
	DS1302_SCLK = 0;
}

void DS1302_WriteByte(unsigned char command,unsigned char Data)
{
//	DS1302_CE = 1;
//	
//	DS1302_IO = command&0x01;
//	DS1302_SCLK = 1;   //一个上升延写入,
//	DS1302_SCLK = 0;   //随后又下降,为下一个上升延准备.
//	
//	DS1302_IO = command&0x02;
//	DS1302_SCLK = 1;   //一个上升延写入,
//	DS1302_SCLK = 0;   //随后又下降,为下一个上升延准备.
//	.                  查DS1302数据手册得知上升下降最小为50ns,结合单片机
//	.                  执行一条语句的时间为微秒级,所以中间不用延迟.
//	.优化如下:
	unsigned char i;
	DS1302_CE = 1;
	for(i=0;i<8;i++)
	{
		DS1302_IO = command&(0x01<<i);
		DS1302_SCLK = 1;   //一个上升延写入,
		DS1302_SCLK = 0;   //随后又下降,为下一个上升延准备.
	}
	
	//以上是时序图的前半段,以下是后半段
	for(i=0;i<8;i++)
	{
		DS1302_IO = Data&(0x01<<i);
		DS1302_SCLK = 1;   //一个上升延写入,
		DS1302_SCLK = 0;   //随后又下降,为下一个上升延准备.
	}
	DS1302_CE = 0;
	
}

unsigned char DS1302_ReadByte(unsigned char command)
{
	
	unsigned char i;
	unsigned char Data = 0x00;
	command |= 0x01; //读的最低位肯定为1
	DS1302_CE = 1;
	for(i=0;i<8;i++)
	{
		DS1302_IO = command&(0x01<<i);
		DS1302_SCLK = 0;   //先一个下降延,与初始一样,目的是最后一次循环后能落到读数据之前.
		DS1302_SCLK = 1;   //来一个上升延写入命令.		
	}
	//以上是时序图的前半段,以下是后半段	
	for(i=0;i<8;i++)
	{
		DS1302_SCLK = 1;   //接着上面重复置1就可以和时序一样.加起来等于15个上升延.
		DS1302_SCLK = 0;   //下降延读出数据.
		if(DS1302_IO)
		{
			Data |= (0x01<<i);
		}
	}
	DS1302_CE = 0;
	DS1302_IO = 0;
	return Data;	
}

void DS1302_SetTime()
{
	DS1302_WriteByte(DS1302_wp,0x00); //关闭写保护
	DS1302_WriteByte(DS1302_year,DS1302_data[0]/10*16+DS1302_data[0]%10);
	DS1302_WriteByte(DS1302_mon,DS1302_data[1]/10*16+DS1302_data[1]%10);
	DS1302_WriteByte(DS1302_date,DS1302_data[2]/10*16+DS1302_data[2]%10);
	DS1302_WriteByte(DS1302_hour,DS1302_data[3]/10*16+DS1302_data[3]%10);
	DS1302_WriteByte(DS1302_min,DS1302_data[4]/10*16+DS1302_data[4]%10);
	DS1302_WriteByte(DS1302_sec,DS1302_data[5]/10*16+DS1302_data[5]%10);
	DS1302_WriteByte(DS1302_day,DS1302_data[6]/10*16+DS1302_data[6]%10);
	DS1302_WriteByte(DS1302_wp,0x80); //打开写保护
}

void DS1302_ReadTime()
{
	unsigned char tmp;
	tmp = DS1302_ReadByte(DS1302_year);
	DS1302_data[0] = tmp/16*10+tmp%16;
	tmp = DS1302_ReadByte(DS1302_mon);
	DS1302_data[1] = tmp/16*10+tmp%16;
	tmp = DS1302_ReadByte(DS1302_date);
	DS1302_data[2] = tmp/16*10+tmp%16;
	tmp = DS1302_ReadByte(DS1302_hour);
	DS1302_data[3] = tmp/16*10+tmp%16;
	tmp = DS1302_ReadByte(DS1302_min);
	DS1302_data[4] = tmp/16*10+tmp%16;
	tmp = DS1302_ReadByte(DS1302_sec);
	DS1302_data[5] = tmp/16*10+tmp%16;
	tmp = DS1302_ReadByte(DS1302_day);
	DS1302_data[6] = tmp/16*10+tmp%16;
}

void LCD_Show_Button()				//设置时数字闪烁
{
	if(index==0 && TimeSetFlashFlag==1)
	{
		LCD_ShowString(1,1,"  ");
	}
		else
		{	
			LCD_ShowNum(1,1,DS1302_data[0],2);
		}
	if(index==1 && TimeSetFlashFlag==1)
	{
		LCD_ShowString(1,4,"  ");
	}
		else
		{
			LCD_ShowNum(1,4,DS1302_data[1],2);
		}
	if(index==2 && TimeSetFlashFlag==1)
	{
		LCD_ShowString(1,7,"  ");
	}
		else 
		{
			LCD_ShowNum(1,7,DS1302_data[2],2);
		}
	if(index==3 && TimeSetFlashFlag==1)
	{
		LCD_ShowString(2,1,"  ");
	}
		else 
		{
			LCD_ShowNum(2,1,DS1302_data[3],2);
		}
	if(index==4 && TimeSetFlashFlag==1)
	{
		LCD_ShowString(2,4,"  ");
	}
		else 
		{
			LCD_ShowNum(2,4,DS1302_data[4],2);
		}
	if(index==5 && TimeSetFlashFlag==1)
	{
		LCD_ShowString(2,7,"  ");
	}
		else 
		{
			LCD_ShowNum(2,7,DS1302_data[5],2);
		}	

}

void LCD_Show()
{
    LCD_ShowNum(1,1,DS1302_data[0],2);
	LCD_ShowNum(1,4,DS1302_data[1],2);
	LCD_ShowNum(1,7,DS1302_data[2],2);
	LCD_ShowNum(2,1,DS1302_data[3],2);
	LCD_ShowNum(2,4,DS1302_data[4],2);
	LCD_ShowNum(2,7,DS1302_data[5],2);
}

void Time_Show()
{
	DS1302_ReadTime(); //读取时间.		
	LCD_Show();
}

//***********************************************************************************//********************************
//key.h
#ifndef __KEY_H_
#define __KEY_H_

extern unsigned char MODE;
extern unsigned char KeySta[4][4];
extern unsigned long pdata KeyDownTime[4][4];
extern unsigned char index;
void KeyAction(unsigned char keycode);
void KeyDriver();
void KeyScan();
#endif

key.c
#include "LCD1602.H"
#include <STC89C5xRC.H>
#include "DS1302.H"

unsigned char MODE = 0;
unsigned char index = 0;
unsigned char KeySta[4][4] = {{1,1,1,1},		
							   {1,1,1,1},
							   {1,1,1,1},
							   {1,1,1,1}
							  };

unsigned char code KeyCodeMap[4][4]={
	{0x31,0x32,0x33,0x26}, //数字键1,数字键2,数字键3,向上键
	{0x34,0x35,0x36,0x25}, //数字键4,数字键5,数字键6,向左键
	{0x37,0x38,0x39,0x28}, //数字键7,数字键8,数字键9,向下键
	{0x30,0x1B,0x0D,0x27}	 //数字键0,Esc键,回车键,向右键
															};
unsigned long pdata KeyDownTime[4][4] = {
{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}
};
void KeyAction(unsigned char keycode)
{

	if((keycode>=0x30)&&(keycode<=0x39))    //如果是数字0~9
	{

	}
	else if(keycode==0x25)		//向左 ,设为切换模式	
	{
		MODE = !MODE;
	}
	else if(keycode==0x26)		//如果是向上键 ,加	
	{
		DS1302_data[index]++;
		if(DS1302_data[0]>99){DS1302_data[0]=0;}//年越界判断
		if(DS1302_data[1]>12){DS1302_data[1]=1;}//月越界判断
		if( DS1302_data[1]==1 || DS1302_data[1]==3 || DS1302_data[1]==5 || DS1302_data[1]==7 || 
			DS1302_data[1]==8 || DS1302_data[1]==10 || DS1302_data[1]==12)//日越界判断
		{
			if(DS1302_data[2]>31){DS1302_data[2]=1;}//大月
		}
		else if(DS1302_data[1]==4 || DS1302_data[1]==6 || DS1302_data[1]==9 || DS1302_data[1]==11)
		{
			if(DS1302_data[2]>30){DS1302_data[2]=1;}//小月
		}
		else if(DS1302_data[1]==2)
		{
			if(DS1302_data[0]%4==0)
			{
				if(DS1302_data[2]>29){DS1302_data[2]=1;}//闰年2月
			}
			else
			{
				if(DS1302_data[2]>28){DS1302_data[2]=1;}//平年2月
			}
		}
		if(DS1302_data[3]>23){DS1302_data[3]=0;}//时越界判断
		if(DS1302_data[4]>59){DS1302_data[4]=0;}//分越界判断
		if(DS1302_data[5]>59){DS1302_data[5]=0;}//秒越界判断
	}
	else if(keycode==0x27)		//如果是向右键 ,切换时间数组索引	
	{
		index++;
		index %= 6;
	}
	else if(keycode==0x28)//如果是向下键,减
	{
		DS1302_data[index]--;
		if(DS1302_data[0]<0){DS1302_data[0]=99;}//年越界判断
		if(DS1302_data[1]<1){DS1302_data[1]=12;}//月越界判断
		if( DS1302_data[1]==1 || DS1302_data[1]==3 || DS1302_data[1]==5 || DS1302_data[1]==7 || 
			DS1302_data[1]==8 || DS1302_data[1]==10 || DS1302_data[1]==12)//日越界判断
		{
			if(DS1302_data[2]<1){DS1302_data[2]=31;}//大月
			if(DS1302_data[2]>31){DS1302_data[2]=1;}
		}
		else if(DS1302_data[1]==4 || DS1302_data[1]==6 || DS1302_data[1]==9 || DS1302_data[1]==11)
		{
			if(DS1302_data[2]<1){DS1302_data[2]=30;}//小月
			if(DS1302_data[2]>30){DS1302_data[2]=1;}
		}
		else if(DS1302_data[1]==2)
		{
			if(DS1302_data[0]%4==0)
			{
				if(DS1302_data[2]<1){DS1302_data[2]=29;}//闰年2月
				if(DS1302_data[2]>29){DS1302_data[2]=1;}
			}
			else
			{
				if(DS1302_data[2]<1){DS1302_data[2]=28;}//平年2月
				if(DS1302_data[2]>28){DS1302_data[2]=1;}
			}
		}
		if(DS1302_data[3]<0){DS1302_data[3]=23;}//时越界判断
		if(DS1302_data[4]<0){DS1302_data[4]=59;}//分越界判断
		if(DS1302_data[5]<0){DS1302_data[5]=59;}//秒越界判断
	}	
	else if(keycode==0x1B)			//如果是回车键
	{
	
	}
}

void KeyDriver()
{
	static unsigned char backup[4][4] = { {1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}};
	unsigned char i,j;
	static unsigned long pdata TimeAdd[4][4] = {
	{1000,1000,1000,1000},{1000,1000,1000,1000},{1000,1000,1000,1000},{1000,1000,1000,1000}
	};
	for(i=0;i<4;i++)
	{
		for(j=0;j<4;j++)
		{
			if(backup[i][j] != KeySta[i][j])
			{
				if(backup[i][j] == 0)
				{
					KeyAction(KeyCodeMap[i][j]);
				}
				backup[i][j] = KeySta[i][j];
			}
			if(KeyDownTime[i][j] > 0)
			{				//LCD_ShowNum(1,5,KeyDownTime[i][j],5);
				if(KeyDownTime[i][j] >= TimeAdd[i][j])
				{			//LCD_ShowNum(2,8,KeyDownTime[i][j],5);
					KeyAction(KeyCodeMap[i][j]);
					TimeAdd[i][j] += 80;          //设置长按时跳动的速度,越小越快
				}
			}
			else
				TimeAdd[i][j] = 1000;

		}
	}														  
}

void KeyScan()
{
	static unsigned  char keyout = 0;
	unsigned char i = 0;
	static unsigned char keybuf[4][4] = {{0xFF,0xFF,0xFF,0xFF},
										   {0xFF,0xFF,0xFF,0xFF},
	                                       {0xFF,0xFF,0xFF,0xFF},
										   {0xFF,0xFF,0xFF,0xFF}
                                          };
	keybuf[keyout][0] = (keybuf[keyout][0]<<1) | P14; //所以每行要左移8次,4行就左移32次,32毫秒就能跳出抖动
	keybuf[keyout][1] = (keybuf[keyout][1]<<1) | P15;
	keybuf[keyout][2] = (keybuf[keyout][2]<<1) | P16;
	keybuf[keyout][3] = (keybuf[keyout][3]<<1) | P17;
	
	for(i=0;i<4;i++)
	{
		if((keybuf[keyout][i] & 0xFF) == 0x00) //0x00表示后8位为0就判断为0,因为初始值
		{                                      //为0xFF,所以至少要进入8次中断,左移8次
			KeySta[keyout][i] = 0;             //与0xFF才可能等于0x00
			KeyDownTime[keyout][i] += 4;       //所以这这里要加上4毫秒。
		}
		else if((keybuf[keyout][i] & 0xFF) == 0xFF) //0xFF表示8位为1就判断为1
		{
			KeySta[keyout][i] = 1;
			KeyDownTime[keyout][i] = 0;
		}
	}	
	keyout++;
//	if(keyout>=3)
//	{
//		keyout = 0;
//	}
	keyout &= 0x03; 
	switch(keyout)
	{
		//case 0: P00=1;P01=1;P02=1;P03=0;break;
		//case 1: P00=1;P01=1;P02=0;P03=1;break;
		//case 2: P00=1;P01=0;P02=1;P03=1;break;
		//case 3: P00=0;P01=1;P02=1;P03=1;break;
		//优化后如下:
		case 0: P10=1;P13=0; break;
		case 1: P13=1;P12=0; break;
		case 2: P12=1;P11=0; break;
		case 3: P11=1;P10=0; break;		
		default: break;
	}
}	

//***********************************************************************************//***********

mani.c 
#include <STC89C5xRC.H>
#include "LCD1602.h"
#include "DS1302.h"
#include "Key.h"

void main()
{	
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0x18;		//设置定时初值,1毫秒@12.000MHz
	TH0 = 0xFC;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	EA = 1;
	ET0 = 1;
	
	LCD_Init();
	DS1302_Init();
	LCD_ShowString(1,1,"  -  -");
	LCD_ShowString(2,1,"  :  :");
	DS1302_SetTime(); //设置时间,用数组里面的数值设置
	while(1)
	{
		KeyDriver();
		switch(MODE)
		{
			case 0 : Time_Show(); break;
			case 1 : DS1302_SetTime();LCD_Show_Button(); break;                      
		}
	
	}
}

void InterruptTimer0() interrupt 1
{		
	static unsigned int T0_Count = 0;	
	TL0 = 0x18;		
	TH0 = 0xFC;
	T0_Count++;
	if(T0_Count==500)
	{
		T0_Count = 0;
		TimeSetFlashFlag = !TimeSetFlashFlag;	
	}
		
	KeyScan();
}

 

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
DS1302是一种实时时钟芯片,常用于单片机的时钟系统。结合LCD1602显示屏,可以实现显示时间的功能。下面提供一个基于Keil环境下的51单片机的DS1302时钟LCD1602显示代码,同时可以利用按键设置时钟。 代码中使用了DS1302LCD1602的驱动程序,需要预先调用相关的库文件。同时,通过定义多个函数分别实现初始化、显示、设置时间等功能。 代码如下: #include<reg52.h> #include<intrins.h> #include<DS1302.h> #include<LCD1602.h> sbit Key1=P3^2; //定义按键 sbit Key2=P3^3; sbit write=P0^0; //定义DS1302写控制信号 sbit read=P0^1; //定义DS1302读控制信号 sbit ck=P0^2; //定义DS1302时钟控制信号 void Delay(unsigned int n) //延时函数 { int i, j; for (i = 0; i < n; i++) for (j = 0; j < 120; j++) ; } void Main() //主函数 { DS1302_Init(); //DS1302初始化 LCD1602_Init(); //LCD1602初始化 Set_K(); //设置K值 while (1) { unsigned char key=i; //按键变量 if (Key1==0) //判断按键 { Delay(10); if (Key1==0) { key=1; //设置按键值 } while(!Key1); //等待按键释放 } if (Key2==0) { Delay(10); if (Key2==0) { key=2; } while(!Key2); } switch(key) //判断按键值 { case 1:Set_Time();break; //设置时间 case 2:LCD_ShowTime();break; //显示时间 } } } void Set_Time() //设置时间函数 { unsigned char key; //按键变量 LCD_Clear(); //清屏 LCD_WriteString("Please set time:"); //显示提示信息 LCD_SetPosition(2, 0); while (1) //等待按键 { if (Key1==0) { Delay(10); if (Key1==0) { key=1; //设置按键值 } while(!Key1); } if (Key2==0) { Delay(10); if (Key2==0) { key=2; } while(!Key2); } switch(key) //根据按键值设置时间 { case 1: //设置时钟值 LCD_Clear(); LCD_WriteString("Please set hour:"); DS1302_Set(0x80); //打开写保护 DS1302_Set(0x82,10); //设置地址,初始值为10 while (key!=3) { if (Key1==0) { Delay(10); if (Key1==0) { if (DS1302_Get(0x82)>=23) //判断最大值 { DS1302_Set(0x82,0); //超过最大值则归零 } else { DS1302_Set(0x82,DS1302_Get(0x82)+1); //递增1 } key=3; } while(!Key1); } if (Key2==0) { Delay(10); if (Key2==0) { DS1302_Set(0x82, 0); //重置 key=3; } while(!Key2); } } DS1302_Set(0x80); //关闭写保护 break; case 2: //设置分钟值,代码与设置小时值类似,略 case 3: //设置秒值,代码与设置小时值类似,略 case 4: //设置日期,代码略 case 5: //设置月份,代码略 case 6: //设置星期几,代码略,注意星期几的取值范围 case 7: //设置年份,代码略 } if (key>=7) //设置完毕 { break; } } } void LCD_ShowTime() //显示时间函数 { DS1302_GetTime(); //获取时间 LCD_WriteString("Now time is:"); LCD_SetPosition(2, 0); LCD_WriteNum(DS1302_Get(0x82)); LCD_WriteString(":"); LCD_WriteNum(DS1302_Get(0x84)); LCD_WriteString(":"); LCD_WriteNum(DS1302_Get(0x86)); LCD_WriteString(" "); LCD_WriteNum(DS1302_Get(0x88)); LCD_WriteString("/"); LCD_WriteNum(DS1302_Get(0x8A)); LCD_WriteString("/"); LCD_WriteNum(DS1302_Get(0x8C)); } 以上是一个基于Keil环境下的51单片机的DS1302时钟LCD1602显示代码,同时可以利用按键设置时钟。需要注意的是,此代码仅供参考,需要根据实际连接情况和要求进行相应调整。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值