zoukankan      html  css  js  c++  java
  • 基于51单片机的多功能秒表(校赛作品)

    设计方案

    设计基于LCD1602的多功能秒表,要满足在不间断计时的同时进行其他操作,由此可以联想出定时器的中断系统是其最好的选择。通过定时器中断函数的设计,可以让程序每隔一段时间进行一次计数,让LCD1602在不间断显示时间的同时,进行按键检测与计时的需要。


    在代码具体时间中,为了避免代码过长、累赘、麻烦,本小组使用了模块化编程的思想,将定时器延迟函数、LCD1602操作函数、按键检测函数、延迟函数分别进行了模块化处理,这样不仅可以让主函数代码简短不少,而且可以使逻辑思维更加清晰,不再受基础函数的改动而烦恼。


    在设计日历功能时,考虑到实际的电子表在平常状态下,不论是计时还是闹钟模式,日历中的时间计数都是未曾中断的,因此设计日历模式函数时,一旦日历模式被首次进入,日历中的计时就不会停止,除非重新设定日历时间。而在设定日历模式中,由于能力的不足与串口的关联性太强,本小组采用了让其在旁显示操作第几位的做法,用另一种方法,让操作者可以清晰的知道自己正在更改日历中的哪个数值。借鉴于日历模式是电子表的中心,本小组将其他模式的接口统统通向日历模式,这样在日历模式下,可以随意进入任意一个其他模式中。


    在设计计时模式时,考虑到真正的电子表都有开始/暂停按键,所以本小组也参照该设计,设计了一个按键控制计时的开始与暂停。并且根据题目要求设计出了一个清零并暂停的按键满足题目需要。再次由于题目的需求,本小组设计出了检查保存结果模式,来检查可被保存的五次时间。考虑到真正的电子表和实际的按键数量,本小组并未在日历函数中安装此功能,而是将该模式接口移动到计时模式上,并且由于单片机内存有限,故酌情考虑设计了5个保存时间。
    在设计倒计时模式时,由于题目本身的需要,本小组决定让操作者自己先设定倒计时的时间,再进行倒计时操作,这样能增加倒计时模式的可用性。倒计时模式仍支持检查保存结果模式,因为倒计时模式的底层逻辑与计时模式基本相同,区别在于倒计时模式可以自己设定倒计时的初始时间,而计时模式将这一功能代替为开始/暂停。倒计时模式的设定模式与日历设定模式的底层原理相同。倒计时模式与计时模式的保存结果是公用的,一是为了防止代码过长导致的操作繁琐与累赘,二是考虑到单片机的内存大小实在有限。


    在设计检查保存结果模式中,设计了5个可被保存的时间。由于独立按键的缺少与代码实现的复杂度,只设计了其能一键全部清零的功能。其功能相对单一,并且只提供了前往日历功能的接口,因为日历功能下,可以前往其他任意功能,可以增加便捷性。
    在实际代码中,发现日历功能、计时功能、倒计时功能的计时可能可以并被允许同时进行,故在定时器中断函数中本小组设计了3个标志变量来检查其是否能被统计计数.因为实际使用中,并不能保证程序从整毫秒开始计时,并且计时与倒计时要求的精度都比较高,所以才采用了此种方法,来保证3个功能能同时在后台进行。
    总结来说,在具体实现上,代码保证的基本原则就是统一性原则,这样利于编程者的编程方便,也利于后来人的代码阅读理解,代码风格的同一可以让逻辑更加清晰,使得代码更加可读,也让该程序更好实现。


    ps.51单片机的运行不太理想啊,它它它它……有点慢啊,可能是我的中断函数里写的语句太多了,不论怎么样,这其实是一个学习性的代码,参考即可啦(* ̄3 ̄)╭

    MatrixKey.h

    #ifndef __MATRIXKEY_H__
    #define __MATRIXKEY_H__
    
    unsigned char MatrixKey();
    
    #endif
    

    MatrixKey.c

    #include<reg51.h>
    #include<Delayms.h>
    /**
      * @brief  3*4矩阵键盘读取按键键码
      * @param  无
      * @retval KeyNumber 按下按键的键码值
    	          如果按键按下不放,程序会停留在此函数,松手的一瞬间,返回按键键码,没有按键按下时,返回0
      */
    unsigned char MatrixKey(){
    	unsigned char KeyNumber=0;
    	
    	P3=0xFF;
    	T1=0; 
    	if(RXD==0){ Delayms(20); while(RXD==0); Delayms(20); KeyNumber=1; }
    	if(TXD==0){ Delayms(20); while(TXD==0); Delayms(20); KeyNumber=4; }
    	if(INT0==0){ Delayms(20); while(INT0==0); Delayms(20); KeyNumber=7; }
    	if(INT1==0){ Delayms(20); while(INT1==0); Delayms(20); KeyNumber=10; }
    	
    	P3=0xFF;
    	WR=0; 
    	if(RXD==0){ Delayms(20); while(RXD==0); Delayms(20); KeyNumber=2; }
    	if(TXD==0){ Delayms(20); while(TXD==0); Delayms(20); KeyNumber=5; }
    	if(INT0==0){ Delayms(20); while(INT0==0); Delayms(20); KeyNumber=8; }
    	if(INT1==0){ Delayms(20); while(INT1==0); Delayms(20); KeyNumber=11; }
    	
    	
    	P3=0xFF;
    	RD=0; 
    	if(RXD==0){ Delayms(20); while(RXD==0); Delayms(20); KeyNumber=3; }
    	if(TXD==0){ Delayms(20); while(TXD==0); Delayms(20); KeyNumber=6; }
    	if(INT0==0){ Delayms(20); while(INT0==0); Delayms(20); KeyNumber=9; }
    	if(INT1==0){ Delayms(20); while(INT1==0); Delayms(20); KeyNumber=12; }
    	
    	return KeyNumber;
    }
    

    Delayms.h

    #ifndef __DELAYMS_H__
    #define __DELAYMS_H__
    
    void Delayms(unsigned int x);
    
    #endif
    

    Delayms.c

    void Delayms(unsigned int x)		//@11.0592MHz
    {
    	unsigned char i, j;
    
    	while(x--){
    		i = 2;
    		j = 199;
    		do
    		{
    			while (--j);
    		} while (--i);
    	}
    }
    

    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 <REGX52.H>
    
    //引脚配置:
    
    sbit LCD_RS=P3^5;
    sbit LCD_EN=P3^4;
    //sbit LCD_RW;
    
    #define LCD_DataPort P0
    
    //函数定义:
    /**
      * @brief  LCD1602延时函数,12MHz调用可延时1ms
      * @param  无
      * @retval 无
      */
    void LCD_Delay()
    {
    	unsigned char i, j;
    
    	i = 2;
    	j = 199;
    	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');
    	}
    }
    
    

    Timer0.h

    #ifndef __TIMER0_H__
    #define __TIMER0_H__
    
    void Timer0_Init(void);
    
    #endif
    

    Timer0.c

    #include<reg51.h>
    
    /**
      * @brief  定时器0初始化,1毫秒@11.0592MHz
    	* @param  无
    	* @retval 无
    	*/
    void Timer0_Init(void){ //定时器初始化 
    	//TMOD=0x01; //0000 0001 设置模式
    	TMOD&=0xF0; //把TMOD的低四位清零,高四位保持不变
    	TMOD|=0x01; //把TMOD的最低位置1,高四位保持不变
    	//不可位寻址寄存器 不能 将每一位单独赋值
    	//  可位寻址寄存器   能 将每一位单独赋值
    	TF0=0; //中断溢出标志位 TF0=1 表示 产生中断
    	TR0=1; //定时器是否开启
    	TL0=0x66;		
    	TH0=0xFC;
    	ET0=1;
    	EA=1;
    	PT0=0;
    }
    
    /*
    定时器中断函数模板
    void Timer0_Routine() interrupt 1{
    	static unsigned int T0Count;
    	TL0=0x66;		
    	TH0=0xFC;
    	++T0Count;
    	if(T0Count>=1000){
    		T0Count=0;
    		led1=~led1;
    	}
    }
    */
    

    mian.c

    #include<reg51.h>
    #include<Delayms.h>
    #include<MatrixKey.h>
    #include<LCD1602.h>
    #include<Timer0.h>
    
    sbit beep=P2^3;
    
    unsigned char Min,Sec,Ms; //分,秒,毫秒
    unsigned char CountFlag;  //CountFlag --> 0 表示非计时状态,1 表示计时状态
    unsigned char KeyNum;     //矩阵键盘键码
    unsigned char SaveMin[6],SaveSec[6],SaveMs[6],SaveCount,CheckCount;
    unsigned int CYear=2020,CMonth=2,CDay=29,CHour=23,CMin=58,CSec=30,CFlag;
    unsigned char CSettmp,CSettmp2,CSetFlag;
    unsigned char DMin,DSec,DMs,DownFlag,Dtmp;
    
    void StartMemu();
    void TimeMode();
    void CheckMode();
    void CalendarMode();
    void CountdownMode();
    void CSettingMode();
    void DownSetting();
    
    void main(){
    //初始化LCD1602和定时器----
    	LCD_Init();
    	Timer0_Init();
    //-------------------------
    	while(1) StartMemu();
    }
    
    /**
      * StartMemu      开始菜单
      * s9(KeyNum=3)   日历功能
      * s13(KeyNum=6)  计时功能
      * s17(KeyNum=9)  倒计时功能
      */
    void StartMemu(){
    	LCD_ShowString(1,1,"Work  ");
    	LCD_ShowString(2,1,"For Contest     ");
    	while(1){
    		KeyNum=MatrixKey();
    		if(KeyNum==3)  CalendarMode();
    		if(KeyNum==6)  TimeMode();
    		if(KeyNum==9)  CountdownMode();
    	}
    }
    
    
    /**
      * CalendarMode   日历模式
      * s9(KeyNum=3)   更换模式(计时模式)
      * s13(KeyNum=6)  更换模式(倒计时模式)
      * s17(KeyNum=9)  更换模式(检查保存结果模式)
      * s21(KeyNum=12) 更改日历
      */
    void CalendarMode(){
    	CFlag=1;
    	CSetFlag=0;
    	LCD_ShowString(1,1,"    -  -        ");
    	LCD_ShowString(2,1,"  :  :          ");
    	while(1){
    		LCD_ShowNum(1,1,CYear,4);
    		LCD_ShowNum(1,6,CMonth,2);
    		LCD_ShowNum(1,9,CDay,2);
    		LCD_ShowNum(2,1,CHour,2);
    		LCD_ShowNum(2,4,CMin,2);
    		LCD_ShowNum(2,7,CSec,2);
    		KeyNum=MatrixKey();
    		if(KeyNum==3)  TimeMode();
    		if(KeyNum==6)  CountdownMode();
    		if(KeyNum==9)  CheckMode();
    		if(KeyNum==12) CSettingMode();
    	}
    }
    
    
    /**
      * CSettingMode   更改日历模式
      * s9(KeyNum=3)   确认并返回日历模式
      * s13(KeyNum=6)  +1
      * s17(KeyNum=9)  -1
    	* s21(KeyNum=12) 换位
      */
    void CSettingMode(){
    	CFlag=0;
    	CSetFlag=1;
    	CSettmp=1;
    	LCD_ShowString(2,10,"Setting");
    	while(1){
    		LCD_ShowNum(1,16,CSettmp,1);
    		LCD_ShowNum(1,1,CYear,4);
    		LCD_ShowNum(1,6,CMonth,2);
    		LCD_ShowNum(1,9,CDay,2);
    		LCD_ShowNum(2,1,CHour,2);
    		LCD_ShowNum(2,4,CMin,2);
    		LCD_ShowNum(2,7,CSec,2);
    		KeyNum=MatrixKey();
    		if(KeyNum==3)  CalendarMode();
    		if(KeyNum==6){
    			if(CSettmp==1) ++CYear;
    			if(CSettmp==2){ ++CMonth; if(CMonth==13) CMonth=1; }
    			if(CSettmp==3){
    				++CDay;
    				if((CMonth==1|CMonth==3|CMonth==5|CMonth==7|CMonth==8|CMonth==10|CMonth==12)&&CDay==32) CDay=1;
    				if((CMonth==4|CMonth==6|CMonth==9|CMonth==11)&&CDay==31) CDay=1;
    				if(((CYear%4==0&&CYear%100!=0)||CYear%400==0)&&CMonth==2&&CDay==30) CDay=1;
    				if(!((CYear%4==0&&CYear%100!=0)||CYear%400==0)&&CMonth==2&&CDay==29) CDay=1;
    			}
    			if(CSettmp==4) CHour=(CHour+1)%24;
    			if(CSettmp==5) CMin=(CMin+1)%60;
    			if(CSettmp==6) CSec=(CSec+1)%60;
    		}
    		if(KeyNum==9){
    			if(CSettmp==1&&CYear) --CYear;
    			if(CSettmp==2){ --CMonth; if(CMonth==0) CMonth=12; }
    			if(CSettmp==3){
    				--CDay;
    				if((CMonth==1|CMonth==3|CMonth==5|CMonth==7|CMonth==8|CMonth==10|CMonth==12)&&CDay==0) CDay=31;
    				if((CMonth==4|CMonth==6|CMonth==9|CMonth==11)&&CDay==0) CDay=30;
    				if(((CYear%4==0&&CYear%100!=0)||CYear%400==0)&&CMonth==2&&CDay==0) CDay=29;
    				if(!((CYear%4==0&&CYear%100!=0)||CYear%400==0)&&CMonth==2&&CDay==0) CDay=28;
    			}
    			if(CSettmp==4){ --CHour; if(CHour==-1) CHour=23; }
    			if(CSettmp==5){ --CMin; if(CMin==-1) CMin=59; }
    			if(CSettmp==6){ --CSec; if(CSec==-1) CSec=59; }
    		}
    		if(KeyNum==12){ ++CSettmp; CSettmp2=0; if(CSettmp==7) CSettmp=1; }
    	}
    }
    
    
    
    /**
    	* RunMode        计时模式
      * s9(KeyNum=3)   更换模式(检查保存结果模式)
    	* s13(KeyNum=6)  清零并暂停操作
    	* s17(KeyNum=9)  继续/暂停操作
    	* s21(KeyNum=12) 保存当前计时功能,可保存5个
      */
    void TimeMode(){
    	//CountFlag=1;
    	LCD_ShowString(1,1,"  :  :     S: /5");
    	LCD_ShowString(2,1,"Now Timing      ");
    	while(1){
    		LCD_ShowNum(1,1,Min,2);
    		LCD_ShowNum(1,4,Sec,2);
    		LCD_ShowNum(1,7,Ms,2);
    		LCD_ShowNum(1,14,SaveCount,1);
    		KeyNum=MatrixKey();
    		if(KeyNum==3) CheckMode();
    		if(KeyNum==6){ Min=Sec=Ms=0; CountFlag=0; }
    		if(KeyNum==9) CountFlag^=1;
    		if(KeyNum==12&&SaveCount<5){
    			++SaveCount;
    			SaveMin[SaveCount]=Min;
    			SaveSec[SaveCount]=Sec;
    			SaveMs[SaveCount]=Ms;
    		}
    	}
    }
    
    /**
      * CountdownMode  倒计时模式
      * s9(KeyNum=3)   更换模式(检查保存结果模式)
      * s13(KeyNum=6)  清零并停掉蜂鸣器操作
      * s17(KeyNum=9)  设定操作
    	* s21(KeyNum=12) 保存当前计时功能,可保存5个(与计时模式共用)
      */
    void CountdownMode(){
    	LCD_ShowString(1,1,"  :  :     S: /5");
    	LCD_ShowString(2,1,"Now Downing     ");
    	while(1){
    		LCD_ShowNum(1,1,DMin,2);
    		LCD_ShowNum(1,4,DSec,2);
    		LCD_ShowNum(1,7,DMs,2);
    		LCD_ShowNum(1,14,SaveCount,1);
    		if(DownFlag==1&&DMin==0&&DSec==0&&DMs==0){ DownFlag=0; beep=0; }
    		KeyNum=MatrixKey();
    		if(KeyNum==3) CheckMode();
    		if(KeyNum==6){ 
    			DMin=DSec=DMs=0; DownFlag=0; beep=1; 
    		}
    		if(KeyNum==9) DownSetting();
    		if(KeyNum==12&&SaveCount<5){
    			++SaveCount;
    			SaveMin[SaveCount]=DMin;
    			SaveSec[SaveCount]=DSec;
    			SaveMs[SaveCount]=DMs;
    		}
    	}
    }
    
    /**
      * DownSetting  倒计时设定
      * s9(KeyNum=3)   确认并返回倒计时模式
      * s13(KeyNum=6)  +1
      * s17(KeyNum=9)  -1
    	* s21(KeyNum=12) 换位
      */
    void DownSetting(){
    	beep=1;
    	DownFlag=0;
    	Dtmp=1;
    	LCD_ShowString(1,1,"  :  :          ");
    	LCD_ShowString(2,1,"Now DownSetting ");
    	while(1){
    		LCD_ShowNum(1,1,DMin,2);
    		LCD_ShowNum(1,4,DSec,2);
    		LCD_ShowNum(1,7,DMs,2);
    		LCD_ShowNum(1,16,Dtmp,1);
    		KeyNum=MatrixKey();
    		if(KeyNum==3){ DownFlag=1; CountdownMode(); }
    		if(KeyNum==6){ 
    			if(Dtmp==1){ ++DMin; if(DMin>99) DMin=0; }
    			if(Dtmp==2){ ++DSec; if(DSec>59) DSec=0; }
    			if(Dtmp==3){ ++DMs; if(DMs>99) DMs=0; }
    		}
    		if(KeyNum==9){ 
    			if(Dtmp==1){ --DMin; if(DMin==-1) DMin=99; }
    			if(Dtmp==2){ --DSec; if(DSec==-1) DSec=59; }
    			if(Dtmp==3){ --DMs; if(DMs==-1) DMs=99; }
    		}
    		if(KeyNum==12){ ++Dtmp; if(Dtmp>3) Dtmp=1; }
    	}
    }
    
    /**
      * CheckMode      检查保存结果模式
      * s9(KeyNum=3)   为更换模式(日历模式)
    	* s13(KeyNum=6)  上一个
      * s17(KeyNum=9)  下一个
      * s21(KeyNum=12) 全部清空
      */
    void CheckMode(){
    	LCD_ShowString(1,1,"  :  :     C: / ");
    	LCD_ShowString(2,1,"Now Checking    ");
    	if(SaveCount) CheckCount=1; else CheckCount=0;
    	while(1){
    		LCD_ShowNum(1,1,SaveMin[CheckCount],2);
    		LCD_ShowNum(1,4,SaveSec[CheckCount],2);
    		LCD_ShowNum(1,7,SaveMs[CheckCount],2);
    		LCD_ShowNum(1,14,CheckCount,1);
    		LCD_ShowNum(1,16,SaveCount,1);
    		KeyNum=MatrixKey();
    		if(KeyNum==3) CalendarMode();
    		if(KeyNum==6&&CheckCount>1&&SaveCount!=0) --CheckCount;
    		if(KeyNum==9&&CheckCount<SaveCount) ++CheckCount;
    		if(KeyNum==12){
    			SaveCount=0;
    			CheckCount=0;
    		}
    	}
    }
    
    
    void Timer0_Routine() interrupt 1{
    	static unsigned int T0Count;
    	static unsigned int CCount;
    	static unsigned int DownCount;
    	TL0=0x66;		
    	TH0=0xFC;
    	if(DownFlag==1){
    		++DownCount;
    		if(DownCount>=10){
    			DownCount=0;
    			if(DMs) --DMs;
    			if(DMs==0&&(DSec||DMin)){
    				DMs=99;
    				if(DSec>0) --DSec;
    				else if(DSec==0&&DMin){
    					DSec=59;
    					--DMin;
    				}
    			}
    		}
    	}
    //如果处于即使状态每隔10毫秒进行计时---
    	if(CountFlag==1){
    		++T0Count;
    		if(T0Count>=10){
    			T0Count=0;
    			++Ms;
    			if(Ms>99){
    				Ms=0;
    				++Sec;
    				if(Sec>59){
    					Sec=0;
    					++Min;
    					if(Min>99)
    						Min=0;
    				}
    			}
    		}
    	}
    //-------------------------------------
    //如果处于即使状态每隔1秒进行计时---
    	if(CFlag==1){
    		++CCount;
    		if(CCount>=1000){
    			CCount=0;
    			++CSec;
    			if(CSec>59){
    				CSec=0;
    				++CMin;
    				if(CMin>59){
    					CMin=0;
    					++CHour;
    					if(CHour>23){
    						CHour=0;
    						++CDay;
    						if(CMonth==12&&CDay==32){
    							CMonth=1; CDay=1;
    							++CYear;
    						}
    						if((CMonth==1|CMonth==3|CMonth==5|CMonth==7|CMonth==8|CMonth==10)&&CDay==32){
    							CDay=1;
    							++CMonth;
    						}
    						if((CMonth==4|CMonth==6|CMonth==9|CMonth==11)&&CDay==31){
    							CDay=1;
    							++CMonth;
    						}
    						if(((CYear%4==0&&CYear%100!=0)||CYear%400==0)&&CMonth==2&&CDay==30){
    							CDay=1;
    							++CMonth;
    						}
    						if(!((CYear%4==0&&CYear%100!=0)||CYear%400==0)&&CMonth==2&&CDay==29){
    							CDay=1;
    							++CMonth;
    						}
    					}
    				}
    			}
    		}
    	}
    //-------------------------------------
    }
    
  • 相关阅读:
    『转』VC 工具使用和调试方法
    『轉』WINCE下如何实现发短信
    『转』Fatal error: Call to undefined function curl_init
    『转』WinCE驱动程序的分类
    『轉』Windows CE下的串口通讯类
    『轉』VC 6.0 “fatal error LNK1104: cannot open file "mfc42u.lib"”问题解决
    水晶报表乱码中文乱码问题(收藏)
    水晶报表如何完美导出一个Excel表格(收藏)
    ASP.NET AJAX(开发代号Atlas)重要参考资源大收集
    表格排序
  • 原文地址:https://www.cnblogs.com/Potrem/p/51_Clock_1.html
Copyright © 2011-2022 走看看