STC89C52 51单片机实现闹钟功能 #目前的时间倒计时 #选择位置闪烁 #计时 #清屏 #停止计时 #选择位置加减数字 #存储目前的数据 #读出目前的数据 #输入特定时间

前言

下面是按键实现功能的解释

本次内容主要是实现一般闹钟的基本功能, #目前的时间倒计时 #选择位置闪烁 #计时 #清屏 #停止计时 #选择位置加减数字 #存储目前的数据 #读出目前的数据 #输入特定时间 

//11是开始(11也可以停止,不过会有大概一秒左右的延迟)      12停止      16的功能是清屏
/*1  2  3  13        13存储数据
  4  5  6  14        14读出数据并显示
  7  8  9  15        15闹钟的倒计时
  10 11 12 16        
  
  1~10的功能是输入数字 (其中10代表的数字是0)  
  
  P3的按键  17 ~ 1     选择闪烁
			18 ~ 2     选中右移
			19 ~ 3     选中位置++ 
			20 ~ 4     选中位置--
*/ 

一、模块

        1.       (1)LCD1602.c文件

#include <REGX52.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');
	}
}

                  (2)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

        2.       (1)Delay延时.c文件


void Delay(unsigned int xms)
{
	unsigned char i, j;
	while(xms--)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
	}
}

                  (2)Delay延时.h文件

#ifndef __DELAY_H__
#define __DELAY_H__

void Delay(unsigned int xms);

#endif

        3.       (1)定时器模块.c文件

#include <REGX52.H>

/**
  * @brief  定时器0初始化,1毫秒@12.000MHz
  * @param  无
  * @retval 无
  */
void Timer0Init(void)
{
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 0;		//定时器0开始计时,1是开始,0是停止
	ET0=1;
	EA=1;
	PT0=0;
}

                  (2) 定时器模块.h文件

#ifndef __TIMER0_H__
#define __TIMER0_H__

void Timer0Init(void);

#endif

        4.        (1)矩阵键盘的按键控制模块.c文件

#include <REGX52.H>
#include "Delay.h"

/**
  * @brief  矩阵键盘读取按键键码
  * @param  无
  * @retval KeyNumber 按下按键的键码值
			如果按键按下不放,程序会停留在此函数,松手的一瞬间,返回按键键码,没有按键按下时,返回0
  */
unsigned char MatrixKey()
{
	unsigned char KeyNumber=0;
	
	P1=0xFF;
	P1_3=0;
	if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=1;}
	if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=4;}
	if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=7;}
	if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=10;}
	
	P1=0xFF;
	P1_2=0;
	if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=2;}
	if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=5;}
	if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=8;}
	if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=11;}
	
	P1=0xFF;
	P1_1=0;
	if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=3;}
	if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=6;}
	if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=9;}
	if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=12;}
	
	P1=0xFF;
	P1_0=0;
	if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=13;}
	if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=14;}
	if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=15;}
	if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=16;}
	
	
	return KeyNumber;
}

                   (2)矩阵键盘的按键控制模块.h文件

#ifndef __MATRIXKEY_H__
#define __MATRIXKEY_H__

unsigned char MatrixKey();

#endif

        5.        (1)四个独立按键的按键控制代码.c文件

#include <REGX52.H>
#include "Delay.h"

unsigned char P3receive()
{
	unsigned char receive;
	
	if(P3_1 == 0){Delay(20);while(P3_1 == 0);Delay(20);receive = 17;}
	if(P3_0 == 0){Delay(20);while(P3_0 == 0);Delay(20);receive = 18;}
	if(P3_2 == 0){Delay(20);while(P3_2 == 0);Delay(20);receive = 19;}
	if(P3_3 == 0){Delay(20);while(P3_3 == 0);Delay(20);receive = 20;}
	
	return receive;
}

                   (2)四个独立按键的按键控制代码.h文件

#ifndef _P3RECEIVE__H__
#define _P3RECEIVE__H__

unsigned char P3receive();

#endif

        6.        (1)DS1302存储模块的.c文件

#include <REGX52.H>

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

//寄存器写入地址/指令定义
#define DS1302_SECOND		0x80
#define DS1302_MINUTE		0x82
#define DS1302_HOUR			0x84
#define DS1302_DATE			0x86
#define DS1302_MONTH		0x88
#define DS1302_DAY			0x8A
#define DS1302_YEAR			0x8C
#define DS1302_WP			0x8E

char DS1302_Time[]={00,00,00,00};

/**
  * @brief  DS1302初始化
  * @param  无
  * @retval 无
  */
void DS1302_Init(void)
{
	DS1302_CE=0;
	DS1302_SCLK=0;
}

/**
  * @brief  DS1302写一个字节
  * @param  Command 命令字/地址
  * @param  Data 要写入的数据
  * @retval 无
  */
void DS1302_WriteByte(unsigned char Command,Data)
{
	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;
}

/**
  * @brief  DS1302读一个字节
  * @param  Command 命令字/地址
  * @retval 读出的数据
  */
unsigned char DS1302_ReadByte(unsigned char Command)
{
	unsigned char i,Data=0x00;
	Command|=0x01;	//将指令转换为读指令
	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;
		DS1302_SCLK=0;
		if(DS1302_IO){Data|=(0x01<<i);}
	}
	DS1302_CE=0;
	DS1302_IO=0;	//读取后将IO设置为0,否则读出的数据会出错
	return Data;
}

/**
  * @brief  DS1302设置时间,调用之后,DS1302_Time数组的数字会被设置到DS1302中
  * @param  无
  * @retval 无
  */
void DS1302_SetTime(void)
{
	DS1302_WriteByte(DS1302_WP,0x00);
	DS1302_WriteByte(DS1302_YEAR,DS1302_Time[0]/10*16+DS1302_Time[0]%10);//十进制转BCD码后写入
	DS1302_WriteByte(DS1302_MONTH,DS1302_Time[1]/10*16+DS1302_Time[1]%10);
	DS1302_WriteByte(DS1302_DATE,DS1302_Time[2]/10*16+DS1302_Time[2]%10);
	DS1302_WriteByte(DS1302_HOUR,DS1302_Time[3]/10*16+DS1302_Time[3]%10);
	DS1302_WriteByte(DS1302_WP,0x80);
}

/**
  * @brief  DS1302读取时间,调用之后,DS1302中的数据会被读取到DS1302_Time数组中
  * @param  无
  * @retval 无
  */
void DS1302_ReadTime(void)
{
	unsigned char Temp;
	Temp=DS1302_ReadByte(DS1302_YEAR);
	DS1302_Time[0]=Temp/16*10+Temp%16;//BCD码转十进制后读取
	Temp=DS1302_ReadByte(DS1302_MONTH);
	DS1302_Time[1]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_DATE);
	DS1302_Time[2]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_HOUR);
	DS1302_Time[3]=Temp/16*10+Temp%16;
}

                   (2)DS1302存储模块的.h文件

#ifndef __DS1302_H__
#define __DS1302_H__


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);

#endif

        7.        (1)为AT24C02服务的子程序I2.c文件

#include <REGX52.H>

sbit I2C_SCL=P2^1;
sbit I2C_SDA=P2^0;

/**
  * @brief  I2C开始
  * @param  无
  * @retval 无
  */
void I2C_Start(void)
{
	I2C_SDA=1;
	I2C_SCL=1;
	I2C_SDA=0;
	I2C_SCL=0;
}

/**
  * @brief  I2C停止
  * @param  无
  * @retval 无
  */
void I2C_Stop(void)
{
	I2C_SDA=0;
	I2C_SCL=1;
	I2C_SDA=1;
}

/**
  * @brief  I2C发送一个字节
  * @param  Byte 要发送的字节
  * @retval 无
  */
void I2C_SendByte(unsigned char Byte)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		I2C_SDA=Byte&(0x80>>i);
		I2C_SCL=1;
		I2C_SCL=0;
	}
}

/**
  * @brief  I2C接收一个字节
  * @param  无
  * @retval 接收到的一个字节数据
  */
unsigned char I2C_ReceiveByte(void)
{
	unsigned char i,Byte=0x00;
	I2C_SDA=1;
	for(i=0;i<8;i++)
	{
		I2C_SCL=1;
		if(I2C_SDA){Byte|=(0x80>>i);}
		I2C_SCL=0;
	}
	return Byte;
}

/**
  * @brief  I2C发送应答
  * @param  AckBit 应答位,0为应答,1为非应答
  * @retval 无
  */
void I2C_SendAck(unsigned char AckBit)
{
	I2C_SDA=AckBit;
	I2C_SCL=1;
	I2C_SCL=0;
}

/**
  * @brief  I2C接收应答位
  * @param  无
  * @retval 接收到的应答位,0为应答,1为非应答
  */
unsigned char I2C_ReceiveAck(void)
{
	unsigned char AckBit;
	I2C_SDA=1;
	I2C_SCL=1;
	AckBit=I2C_SDA;
	I2C_SCL=0;
	return AckBit;
}

                   (2)为AT24C02服务的子程序I2.h文件

#ifndef __I2C_H__
#define __I2C_H__

void I2C_Start(void);
void I2C_Stop(void);
void I2C_SendByte(unsigned char Byte);
unsigned char I2C_ReceiveByte(void);
void I2C_SendAck(unsigned char AckBit);
unsigned char I2C_ReceiveAck(void);


#endif

        8.        (1)写入地址模块AT24C02.c文件

#include <REGX52.H>
#include "I2C.h"

#define AT24C02_ADDRESS		0xA0

/**
  * @brief  AT24C02写入一个字节
  * @param  WordAddress 要写入字节的地址
  * @param  Data 要写入的数据
  * @retval 无
  */
void AT24C02_WriteByte(unsigned char WordAddress,Data)
{
	I2C_Start();
	I2C_SendByte(AT24C02_ADDRESS);
	I2C_ReceiveAck();
	I2C_SendByte(WordAddress);
	I2C_ReceiveAck();
	I2C_SendByte(Data);
	I2C_ReceiveAck();
	I2C_Stop();
}

/**
  * @brief  AT24C02读取一个字节
  * @param  WordAddress 要读出字节的地址
  * @retval 读出的数据
  */
unsigned char AT24C02_ReadByte(unsigned char WordAddress)
{
	unsigned char Data;
	I2C_Start();
	I2C_SendByte(AT24C02_ADDRESS);
	I2C_ReceiveAck();
	I2C_SendByte(WordAddress);
	I2C_ReceiveAck();
	I2C_Start();
	I2C_SendByte(AT24C02_ADDRESS|0x01);
	I2C_ReceiveAck();
	Data=I2C_ReceiveByte();
	I2C_SendAck(1);
	I2C_Stop();
	return Data;
}

                   (2)写入地址模块AT24C02.h文件

#ifndef __AT24C02_H__
#define __AT24C02_H__

void AT24C02_WriteByte(unsigned char WordAddress,Data);
unsigned char AT24C02_ReadByte(unsigned char WordAddress);


#endif

二、完整代码(闹钟)

主函数代码如下(示例):

#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "Timer0.h"
#include "MatrixKey.h"
#include "P3receive.h"
#include "DS1302.h"
#include "AT24C02.h"

#include <stdio.h>
#include <string.h>
#include <stdlib.h>


//11是开始(11也可以停止,不过会有大概一秒左右的延迟)      12停止      16的功能是清屏
/*1  2  3  13        13存储数据
  4  5  6  14        14读出数据并显示
  7  8  9  15        15闹钟的倒计时
  10 11 12 16        
  
  1~10的功能是输入数字 (其中10代表的数字是0)  
  
  P3的按键  17 ~ 1     选择闪烁
			18 ~ 2     选中右移
			19 ~ 3     选中位置++ 
			20 ~ 4     选中位置--
*/ 




unsigned char Key,Num;
unsigned char stop_flag = 1;
unsigned char MODE,TimeSetSelect,TimeSetFlashFlag;
unsigned char Number;
unsigned char Password,Count;

unsigned char hui;
	
Light_flag = 1;


void TimeShow(void)//时间显示功能
{
//	DS1302_ReadTime();//读取时间
	LCD_ShowNum(1,1,DS1302_Time[0],2);
	LCD_ShowNum(1,5,DS1302_Time[1],2);
	LCD_ShowNum(1,9,DS1302_Time[2],2);
	LCD_ShowNum(1,13,DS1302_Time[3],2);
}
void TimeSet(void)
{
	TR0 = 1;
	if(Num == 18)
		{
			TimeSetSelect++;
			TimeSetSelect %= 4;
		}
	if(Num == 19)
	{
		DS1302_Time[TimeSetSelect]++;
		if(DS1302_Time[0]>23){DS1302_Time[0] = 0;}   //时越界
		if(DS1302_Time[1]>59){DS1302_Time[1] = 0;}   //分越界
		if(DS1302_Time[2]>59){DS1302_Time[2] = 0;}   //秒越界
		if(DS1302_Time[3]>99){DS1302_Time[3] = 0;}//厘秒越界
	}
	if(Num == 20)
	{
		DS1302_Time[TimeSetSelect]--;
		if(DS1302_Time[0]<0){DS1302_Time[0] = 23;}   //时越界
		if(DS1302_Time[1]<0){DS1302_Time[1] = 59;}   //分越界
		if(DS1302_Time[2]<0){DS1302_Time[2] = 59;}   //秒越界
		if(DS1302_Time[3]<0){DS1302_Time[3] = 99;}//厘秒越界
	}
	//更新显示  闪烁功能
	
	if(TimeSetSelect==0 && TimeSetFlashFlag==1)
	{
		LCD_ShowString(1,1,"  ");
	}	else 
	{
		LCD_ShowNum(1,1,DS1302_Time[0],2);
	}
	if(TimeSetSelect==1 && TimeSetFlashFlag==1)
	{
		LCD_ShowString(1,5,"  ");
	}	else
	{
		LCD_ShowNum(1,5,DS1302_Time[1],2);
	}
	if(TimeSetSelect==2 && TimeSetFlashFlag==1)
	{
		LCD_ShowString(1,9,"  ");
	}	else
	{
		LCD_ShowNum(1,9,DS1302_Time[2],2);
	}
	if(TimeSetSelect==3 && TimeSetFlashFlag==1)
	{
		LCD_ShowString(1,13,"  ");
	}	else
	{
		LCD_ShowNum(1,13,DS1302_Time[3],2);
	}
}

void main()
{
	DS1302_Init();
	LCD_Init();
	Timer0Init();
	
	LCD_ShowString(1,1,"  h:  m:  s:  ");
	LCD_ShowString(2,1,"Nice to see you!");
	Delay(1000);
	LCD_ShowString(2,1,"                ");
	
	
	while(1)
	{
		Key = MatrixKey();

		Num = P3receive();
		if (Key == 11)
		{

			LCD_ShowString(2,1,"STA");
			Delay(1000);
			LCD_ShowString(2,1,"   ");
			TR0 = stop_flag;
			if(stop_flag == 0)
			{
				stop_flag = 1;
			}	
			else
			{
				stop_flag = 0;
			}
		}	
//		else
//		{
//			LCD_ShowNum(1,1,DS1302_Time[0],2);
//			LCD_ShowNum(1,5,DS1302_Time[1],2);
//			LCD_ShowNum(1,9,DS1302_Time[2],2);
//			LCD_ShowNum(1,13,DS1302_Time[3],2);
//		}	
		if(Key == 12)
			{
				if(stop_flag != 0)
					{
						stop_flag = 0;
					}
				TR0 = stop_flag;
				LCD_ShowString(2,5,"STO");
				Delay(1000);
				LCD_ShowString(2,5,"   ");
			}					
		if(Key == 16)
			{
				TR0 = 0;DS1302_Time[0] = 0;DS1302_Time[1] = 0;DS1302_Time[2] = 0;DS1302_Time[3] = 0;
				LCD_ShowString(2,9,"DEL");
				Delay(1000);
				LCD_ShowString(2,9,"   ");
			}
		if(Key == 13)
			{
				AT24C02_WriteByte(0,DS1302_Time[0]%256);
				Delay(5);
				AT24C02_WriteByte(1,DS1302_Time[0]/256);
				Delay(5);
				AT24C02_WriteByte(2,DS1302_Time[1]%256);
				Delay(5);
				AT24C02_WriteByte(3,DS1302_Time[1]/256);
				Delay(5);
				AT24C02_WriteByte(4,DS1302_Time[2]%256);
				Delay(5);
				AT24C02_WriteByte(5,DS1302_Time[2]/256);
				Delay(5);
				AT24C02_WriteByte(6,DS1302_Time[3]%256);
				Delay(5);
				AT24C02_WriteByte(7,DS1302_Time[3]/256);
				Delay(5);
			}
		if(Key == 14)
			{
				DS1302_Time[0]=AT24C02_ReadByte(0);
				DS1302_Time[0]|=AT24C02_ReadByte(1)<<8;
				LCD_ShowNum(1,1,DS1302_Time[0],2);
				
				DS1302_Time[1]=AT24C02_ReadByte(2);
				DS1302_Time[1]|=AT24C02_ReadByte(3)<<8;
				LCD_ShowNum(1,5,DS1302_Time[1],2);
				
				DS1302_Time[2]=AT24C02_ReadByte(4);
				DS1302_Time[2]|=AT24C02_ReadByte(5)<<8;
				LCD_ShowNum(1,9,DS1302_Time[2],2);
				
				DS1302_Time[3]=AT24C02_ReadByte(6);
				DS1302_Time[3]|=AT24C02_ReadByte(7)<<8;
				LCD_ShowNum(1,13,DS1302_Time[3],2);
			}
		if(Key) 						//功能分开,只能开头执行,而且只能执行一次
			{							//这里可以考虑用字符串拼接写
			if(Key <= 10)	
				{
					if(Count < 2)	
						{
							if(Key != 10)
								{
									DS1302_Time[2]*=10;				
									DS1302_Time[2]+=Key%10;		
									Count++;	
									LCD_ShowNum(1,9,DS1302_Time[2],2);
								} 
							else 
								{
									DS1302_Time[2]*=10;
									Count++;
									LCD_ShowNum(1,9,DS1302_Time[2],2);
								}
						}	
				}
			}			
		if(Key == 15)
			{
				DS1302_Time[3]=1;
				LCD_ShowNum(1,13,DS1302_Time[3],2);
				for(hui=0;DS1302_Time[3]>0;hui++)
				{
					Delay(10);
					DS1302_Time[3]--;
					LCD_ShowNum(1,13,DS1302_Time[3],2);
					if(DS1302_Time[3] == 0)
					{	
						
						DS1302_Time[3] = 99;
						DS1302_Time[2]--;
						LCD_ShowNum(1,13,DS1302_Time[3],2);
						LCD_ShowNum(1,9,DS1302_Time[2],2);
						if(DS1302_Time[2] == 0)
						{
							DS1302_Time[2]=60;
							DS1302_Time[1]--;
							LCD_ShowNum(1,1,DS1302_Time[0],2);
							LCD_ShowNum(1,5,DS1302_Time[1],2);
							LCD_ShowNum(1,9,DS1302_Time[2],2);
							LCD_ShowNum(1,13,DS1302_Time[3],2);
							if(DS1302_Time[1] == 0)
							{
								DS1302_Time[1]=60;
								DS1302_Time[0]--;
								LCD_ShowNum(1,1,DS1302_Time[0],2);
								LCD_ShowNum(1,5,DS1302_Time[1],2);
								LCD_ShowNum(1,9,DS1302_Time[2],2);
								LCD_ShowNum(1,13,DS1302_Time[3],2);
								if(DS1302_Time[0] == 0&&DS1302_Time[1] == 0&&DS1302_Time[2] == 0&&DS1302_Time[3] == 0)
								{
									break;
								}
							}
						}
					}
				}
			}	
		if(Num == 17)
			{
				TR0 =~ TR0;
				if(MODE == 0)
				{
					MODE = 1;
				}
				else
				{
					MODE = 0;
//					DS1302_SetTime();
				}
			}
		switch(MODE)
			{
				case 0:TimeShow();break;
				case 1:TimeSet();break;
			}

//	}
	}
}
unsigned int T0Count,T1Count;
void Timer0_Routine() interrupt 1
{
	TL0 = 0x18;		
	TH0 = 0xFC;		                         //中断程序里面不能写if else语句
	T0Count++;
	if(T0Count>=10)
		{
			DS1302_Time[3]++;
			T0Count = 0;
			T1Count++;	
			if(T1Count >= 40)
			{
				T1Count = 0;
				TimeSetFlashFlag =! TimeSetFlashFlag;
			}
			if(DS1302_Time[3] == 99)
				{
					DS1302_Time[3] = 0;	
					DS1302_Time[2]++;
					if(DS1302_Time[2] == 60)
						{
							DS1302_Time[2] = 0;
							DS1302_Time[1]++;
							if(DS1302_Time[1] == 60)
								{
									DS1302_Time[1] = 0;
									DS1302_Time[0]++;
									if(DS1302_Time[0] == 24)
										{
											DS1302_Time[0] = 0;
										}
								}
						}
				
				}
		}
}


总结

闹钟用32写可能更好,51的代码只是提供参考思路,为32做铺垫。这次的代码还是有一点美中不足的地方,比如说当你按下按键11(请看前言的按键使用定义)进行停止命令的时候,大概会有1秒左右的延迟,还有一个地方是在倒计时那里,比如你输入一个倒计时四秒钟,但是实际上就是倒计时五秒,这是显示问题,代码还不够优化,大佬们请指点指点,但是这个问题不会影响通过计时得到的时间的倒计时。

然后因为代码太多了,就不进行解释了,对代码的疑问请在评论区提出

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

#ifndef __JUAN_H__

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值