最重要的是逻辑问题和调试的过程,需要耐心!
1、首先是定义两个参数用于按键一来切换编辑或者显示模式
KeyNum用于接收按键键码
Mode用来判断当前模式
unsigned char KeyNum,Mode;
在主函数中写出按下按键1切换模式
void main(void)
{
LCD_Init();
DS1302_Init();
DS1302_TimeSet();
LCD_ShowString(1,5,"- -");
LCD_ShowString(2,3,": :");
while(1)
{
KeyNum = Key();
if(KeyNum == 1)
{
if(Mode ==1) {Mode = 0;}
else if(Mode == 0) {Mode = 1;}
}
}
}
2、再编写出显示时间函数和编辑时间函数
显示函数,比较简单,只是把定义好的时间显示出来
void TimeShow(void)
{
DS1302_TimeRead();
LCD_ShowNum(1,1,20,2);
LCD_ShowNum(1,3,Time_R[0],2);//Äê
LCD_ShowNum(1,6,Time_R[1],2);//ÔÂ
LCD_ShowNum(1,9,Time_R[2],2);//ÈÕ
LCD_ShowNum(2,1,Time_R[3],2);//ʱ
LCD_ShowNum(2,4,Time_R[4],2);//·Ö
LCD_ShowNum(2,7,Time_R[5],2);//Ãë
}
编辑函数
有三个要素
第一是选择编辑的量,第二是加,第三是减。
首先是选择编辑的量,先定义一个选择定义Time_R的索引值的变量
unsigned char TimeSetSelect;
在函数中如是编写,因为只有6个选项,且数组索引值是0~5,所以要做溢出判断。
最后一行语句是用于调试的,可以观察当前的索引值指向哪一位。
void TimeSet(void)
{
if(KeyNum == 2)
{
TimeSetSelect++;
if(TimeSetSelect == 6) TimeSetSelect = 0;
}
LCD_ShowNum(2,15,TimeSetSelect,2);
}
接下来就是写加减的语句了,不难懂
else if(KeyNum == 3)
{
Time_R[TimeSetSelect]++;
}
else if(KeyNum == 4)
{
Time_R[TimeSetSelect]--;
}
还要记得更新显示,不然结果是不会显示出来的
LCD_ShowNum(1,1,20,2);
LCD_ShowNum(1,3,Time_R[0],2);//Äê
LCD_ShowNum(1,6,Time_R[1],2);//ÔÂ
LCD_ShowNum(1,9,Time_R[2],2);//ÈÕ
LCD_ShowNum(2,1,Time_R[3],2);//ʱ
LCD_ShowNum(2,4,Time_R[4],2);//·Ö
LCD_ShowNum(2,7,Time_R[5],2);//Ãë
但是这个加减法太简单了,以至于会出现数值越界,即13月26时66分89秒等等情况
所以要对加减法做出相对应的越界判断(不仅包括越界,还包括判断闰年,大月小月等情况)
加法的越界判断
else if(KeyNum == 3)
{
Time_R[TimeSetSelect]++;
if(Time_R[0] > 99) Time_R[0] = 0;//Year
if(Time_R[1] > 12) Time_R[1] = 1;//Month
if(Month(Time_R[1]) == 1){if(Time_R[2] > 31) Time_R[2] = 1;}
else if(Month(Time_R[1]) == 2)
{
if(Time_R[0] % 4==0 && Time_R[0] % 100 !=0 || Time_R[0]%400==0)
{
if(Time_R[2] > 29) Time_R[2] = 1;
}
else
{
if(Time_R[2] > 28) Time_R[2] = 1;
}
}
else if(Month(Time_R[1]) == 3){if(Time_R[2] > 30) Time_R[2] = 1;}//Èç¹ûÊÇСÔÂ
//Date
if(Time_R[3] > 23) Time_R[3] = 0;//Hour
if(Time_R[4] > 59) Time_R[4] = 0;//Minute
if(Time_R[5] > 59) Time_R[5] = 0;//Second
}
减法的越界判断
else if(KeyNum == 4)
{
Time_R[TimeSetSelect]--;
if(Time_R[0] < 0) Time_R[0] = 99;//Year
if(Time_R[1] < 1) Time_R[1] = 12;//Month
if(Month(Time_R[1]) == 1){if(Time_R[2] < 1) Time_R[2] = 31;}
else if(Month(Time_R[1]) == 2)
{
if(Time_R[0] % 4==0 && Time_R[0] % 100 !=0 || Time_R[0]%400==0)
{
if(Time_R[2] < 1) Time_R[2] = 29;
}
else
{
if(Time_R[2] < 1) Time_R[2] = 28;
}ê
}
else if(Month(Time_R[1]) == 3){if(Time_R[2] < 1) Time_R[2] = 30;}//Date
if(Time_R[3] < 0) Time_R[3] = 23;//Hour
if(Time_R[4] < 0) Time_R[4] = 59;//Minute
if(Time_R[5] < 0) Time_R[5] = 59;//Second
}
可得最终TimeSet()
void TimeSet(void)
{
if(KeyNum == 2)
{
TimeSetSelect++;
if(TimeSetSelect == 6) TimeSetSelect = 0;
}
else if(KeyNum == 3)
{
Time_R[TimeSetSelect]++;
if(Time_R[0] > 99) Time_R[0] = 0;//Year
if(Time_R[1] > 12) Time_R[1] = 1;//Month
if(Month(Time_R[1]) == 1){if(Time_R[2] > 31) Time_R[2] = 1;
else if(Month(Time_R[1]) == 2)
{
if(Time_R[0] % 4==0 && Time_R[0] % 100 !=0 || Time_R[0]%400==0)
{
if(Time_R[2] > 29) Time_R[2] = 1;
}
else
{
if(Time_R[2] > 28) Time_R[2] = 1;
}
}
else if(Month(Time_R[1]) == 3){if(Time_R[2] > 30) Time_R[2] = 1;}
//Date
if(Time_R[3] > 23) Time_R[3] = 0;//Hour
if(Time_R[4] > 59) Time_R[4] = 0;//Minute
if(Time_R[5] > 59) Time_R[5] = 0;//Second
}
else if(KeyNum == 4)
{
Time_R[TimeSetSelect]--;
if(Time_R[0] < 0) Time_R[0] = 99;//Year
if(Time_R[1] < 1) Time_R[1] = 12;//Month
if(Month(Time_R[1]) == 1){if(Time_R[2] < 1) Time_R[2] = 31;}
else if(Month(Time_R[1]) == 2)
{
if(Time_R[0] % 4==0 && Time_R[0] % 100 !=0 || Time_R[0]%400==0)
{
if(Time_R[2] < 1) Time_R[2] = 29;
}
else
{
if(Time_R[2] < 1) Time_R[2] = 28;
}
}
else if(Month(Time_R[1]) == 3){if(Time_R[2] < 1) Time_R[2] = 30;}//Date
if(Time_R[3] < 0) Time_R[3] = 23;//Hour
if(Time_R[4] < 0) Time_R[4] = 59;//Minute
if(Time_R[5] < 0) Time_R[5] = 59;//Second
}
LCD_ShowNum(2,15,TimeSetSelect,2);
LCD_ShowNum(1,1,20,2);
LCD_ShowNum(1,3,Time_R[0],2);//Äê
LCD_ShowNum(1,6,Time_R[1],2);//ÔÂ
LCD_ShowNum(1,9,Time_R[2],2);//ÈÕ
LCD_ShowNum(2,1,Time_R[3],2);//ʱ
LCD_ShowNum(2,4,Time_R[4],2);//·Ö
LCD_ShowNum(2,7,Time_R[5],2);//Ãë
}
在写好两个函数后,需要在main函数中调用这两个函数
在Mode == 0时为时间显示模式,在Mode==1时为时间编辑模式
if(Mode == 0) TimeShow();
else if(Mode == 1) TimeSet();
但是我们可以看到即使我们已经设置好了新的时间,可显示还是按照之前的时间运行,所以我们需要重新调用DS1302来设置时间,只需在按下按键一转换为显示模式后再加一个DS1302_TimeSet()即可
如图,其中还有些小细节
3、接下来就是编写编辑时间元素时闪烁的代码了
需要用到Timer0.c
首先先初始化
Timer0_Init();
然后是引入先前编好的中断号函数
unsigned int T0Count = 0;
void Timer0_Rountine(void) interrupt 1
{
T0Count++;
TL0 = 0x66;
TH0 = 0xFC;
if (T0Count >= 500)
{
T0Count = 0;
}
}
思路:引入一个变量,让这个变量没0.5s从0~1之间变化一次,当变量为1时,选中的时间变为空,当变量为0时,选中的时间恢复原状,这样在0.5s变化一次的频率下,选中的时间就没0.5s闪烁一次。
这里引入SetFlash
unsigned char SetFlash
写入中断函数中
void Timer0_Rountine(void) interrupt 1
{
T0Count++;
TL0 = 0x66;
TH0 = 0xFC;
if (T0Count >= 500)
{
T0Count = 0;
SetFlash = ! SetFlash;
}
}
(注意:!0 = 1,按逻辑取反;~0 = 0xff,按位取反)
在TimeSet中
if(TimeSetSelect == 0 && SetFlash == 1) {LCD_ShowString(1,1," ");}
else{LCD_ShowNum(1,1,20,2);LCD_ShowNum(1,3,Time_R[0],2);}//Year
if(TimeSetSelect == 1 && SetFlash == 1) {LCD_ShowString(1,6," ");}
else{LCD_ShowNum(1,6,Time_R[1],2);}//Month
if(TimeSetSelect == 2 && SetFlash == 1) {LCD_ShowString(1,9," ");}
else{LCD_ShowNum(1,9,Time_R[2],2);}
if(TimeSetSelect == 3 && SetFlash == 1) {LCD_ShowString(2,1," ");}
else{LCD_ShowNum(2,1,Time_R[3],2);}
if(TimeSetSelect == 4 && SetFlash == 1) {LCD_ShowString(2,4," ");}
else{LCD_ShowNum(2,4,Time_R[4],2);}
if(TimeSetSelect == 5 && SetFlash == 1) {LCD_ShowString(2,7," ");}
else{LCD_ShowNum(2,7,Time_R[5],2);}
则可完成目标!
总体:
DS1302.c
#include <REGX52.H>
void DS1302_WriteByte(unsigned char Command,Data);
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
unsigned char Time_R[] = {23,9,8,6,20,10,5};
unsigned char Time_W[] = {
DS1302_Year,DS1302_Month,DS1302_Date,
DS1302_Hour,DS1302_Minute,DS1302_Second,
DS1302_Day
};
void DS1302_Init(void)//³õʼ»¯DS1302
{
DS1302_CE = 0;
DS1302_SCLK = 0;
}
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;
}
unsigned char DS1302_ReadByte(unsigned char Command)
{
unsigned char i,Result = 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) {Result |= (0x01 << i);}
}
DS1302_CE = 0;
DS1302_IO = 0;
return Result;
}
void DS1302_TimeSet(void)
{
unsigned char i,Time;
DS1302_WriteByte(DS1302_WP, 0x00);//¹Ø±Õд±£»¤
for (i = 0; i < 7; i++)
{
Time = Time_R[i];
DS1302_WriteByte(Time_W[i], Time_R[i] / 10 * 16 + Time_R[i] % 10);
}
DS1302_WriteByte(DS1302_WP, 0x80);
}
void DS1302_TimeRead(void)
{
unsigned char i,Temp,Time_Re;
for (i = 0; i < 7; i++)
{
Temp = DS1302_ReadByte(Time_W[i]);
Time_R[i] = Temp / 16 * 10 + Temp % 16;
}
}
DS1302.h
#ifndef ___DS1302_H__
#define __DS1302_H__
extern unsigned char Time_R[];
void DS1302_Init(void);
void DS1302_WriteByte(unsigned char Command,Data);
unsigned char DS1302_ReadByte(unsigned char Command);
void DS1302_TimeSet(void);
void DS1302_TimeRead(void);
#endif
Month.c
unsigned char Month(unsigned char num)
{
unsigned char result,i;
unsigned char Month_B[]={1,3,5,7,8,10,12};
unsigned char Month_S[]={4,6,9,11};
for(i = 0; i < 7; i++)
{
if(num == Month_B[i]){return 1;}
}
if(num == 2){return 2;}
for(i = 0; i < 4; i++)
{
if(num == Month_S[i]){return 3;}
}
}
main.c
#include <REGX52.H>
#include "LCD1602.h"
#include "DS1302.h"
#include "Key.h"
#include "Timer0.h"
#include "Month.h"
unsigned char KeyNum,Mode,TimeSetSelect,SetFlash;
//KeyNum¼üÂ룬Mode¿ØÖÆTimeSetºÍTimeShow,TimeSetSelectÊÇTimeSetÑ¡ÔñµÄλÖÃ
unsigned int T0Count = 0;
void Timer0_Rountine(void);
void TimeShow(void)
{
DS1302_TimeRead();
LCD_ShowNum(1,1,20,2);
LCD_ShowNum(1,3,Time_R[0],2);//Äê
LCD_ShowNum(1,6,Time_R[1],2);//ÔÂ
LCD_ShowNum(1,9,Time_R[2],2);//ÈÕ
LCD_ShowNum(2,1,Time_R[3],2);//ʱ
LCD_ShowNum(2,4,Time_R[4],2);//·Ö
LCD_ShowNum(2,7,Time_R[5],2);//Ãë
}
void TimeSet(void)
{
if(KeyNum == 2)
{
TimeSetSelect++;
if(TimeSetSelect == 6) TimeSetSelect = 0;
}//TimeSetSelect¹²ÓÐ6¸öÊý£¬0~5¿ÉÒÔ±íʾTime_R[]ÖеÄÿ¸öÔªËصÄË÷ÒýÖµ
else if(KeyNum == 3)
{
Time_R[TimeSetSelect]++;
//Ô½½çÅжÏ
if(Time_R[0] > 99) Time_R[0] = 0;//Year
if(Time_R[1] > 12) Time_R[1] = 1;//Month
if(Month(Time_R[1]) == 1){if(Time_R[2] > 31) Time_R[2] = 1;}//Èç¹ûÊÇ´óÔÂ
else if(Month(Time_R[1]) == 2)
{
if(Time_R[0] % 4==0 && Time_R[0] % 100 !=0 || Time_R[0]%400==0)
{
if(Time_R[2] > 29) Time_R[2] = 1;
}//ÈòÄê
else
{
if(Time_R[2] > 28) Time_R[2] = 1;
}//·ÇÈòÄê
}//Èç¹ûÊÇ2ÔÂ
else if(Month(Time_R[1]) == 3){if(Time_R[2] > 30) Time_R[2] = 1;}//Èç¹ûÊÇСÔÂ
//Date
if(Time_R[3] > 23) Time_R[3] = 0;//Hour
if(Time_R[4] > 59) Time_R[4] = 0;//Minute
if(Time_R[5] > 59) Time_R[5] = 0;//Second
}
else if(KeyNum == 4)
{
Time_R[TimeSetSelect]--;
//Ô½½çÅжÏ
//×¢ÒâÕâÀïÈç¹ûʹÓõÄÊÇÎÞ·ûºÅµÄÀàÐÍ£¬Time_R[] = 0 ÔÙ--ºó»á±ä³É255
//ҪʹÓÃ<ÅжϵĻ°£¬Òª°ÑÎÞ·ûºÅ¸Ä³ÉÓзûºÅ£¬¼´È¥µôunsigned
if(Time_R[0] < 0) Time_R[0] = 99;//Year
if(Time_R[1] < 1) Time_R[1] = 12;//Month
if(Month(Time_R[1]) == 1){if(Time_R[2] < 1) Time_R[2] = 31;}
else if(Month(Time_R[1]) == 2)
{
if(Time_R[0] % 4==0 && Time_R[0] % 100 !=0 || Time_R[0]%400==0)
{
if(Time_R[2] < 1) Time_R[2] = 29;
}//ÈòÄê
else
{
if(Time_R[2] < 1) Time_R[2] = 28;
}//·ÇÈòÄê
}
else if(Month(Time_R[1]) == 3){if(Time_R[2] < 1) Time_R[2] = 30;}//Date
if(Time_R[3] < 0) Time_R[3] = 23;//Hour
if(Time_R[4] < 0) Time_R[4] = 59;//Minute
if(Time_R[5] < 0) Time_R[5] = 59;//Second
}
//ÓÃÓÚµ÷ÊÔTimeSetSelectµÄÊýÖµ
LCD_ShowNum(2,15,TimeSetSelect,2);
if(TimeSetSelect == 0 && SetFlash == 1) {LCD_ShowString(1,1," ");}
else{LCD_ShowNum(1,1,20,2);LCD_ShowNum(1,3,Time_R[0],2);}//Year
if(TimeSetSelect == 1 && SetFlash == 1) {LCD_ShowString(1,6," ");}
else{LCD_ShowNum(1,6,Time_R[1],2);}//Month
if(TimeSetSelect == 2 && SetFlash == 1) {LCD_ShowString(1,9," ");}
else{LCD_ShowNum(1,9,Time_R[2],2);}
if(TimeSetSelect == 3 && SetFlash == 1) {LCD_ShowString(2,1," ");}
else{LCD_ShowNum(2,1,Time_R[3],2);}
if(TimeSetSelect == 4 && SetFlash == 1) {LCD_ShowString(2,4," ");}
else{LCD_ShowNum(2,4,Time_R[4],2);}
if(TimeSetSelect == 5 && SetFlash == 1) {LCD_ShowString(2,7," ");}
else{LCD_ShowNum(2,7,Time_R[5],2);}
}
void main(void)
{
LCD_Init();
DS1302_Init();
DS1302_TimeSet();
Timer0_Init();
LCD_ShowString(1,5,"- -");
LCD_ShowString(2,3,": :");
while(1)
{
KeyNum = Key();
if(KeyNum == 1)
{
if(Mode ==1)
{
Mode = 0;
LCD_ShowString(2,15," ");//°ÑÊý×éË÷ÒýÒþ²Ø
DS1302_TimeSet();//ÉèÖñ༺õÄʱ¼ä
}
else if(Mode == 0) {Mode = 1;TimeSetSelect = 0;}
}//°´Ï°´¼üÒ»Çл»Ä£Ê½
if(Mode == 0) TimeShow();
else if(Mode == 1) TimeSet();
//¸ù¾ÝModeµÄÖµÅжÏģʽ
}
}
void Timer0_Rountine(void) interrupt 1
{
T0Count++;
TL0 = 0x66;
TH0 = 0xFC;
if (T0Count >= 500)
{
T0Count = 0;
SetFlash = ! SetFlash;
//Âß¼·Ç,0 = £¡1
//~°´Î»È¡·´£¬~0 = 0xff;
}
}