程序功能如下:
(1)数码管前四位可切换3个窗口,1-XX,2-YY,3-ZZ,XX,YY,ZZ分别代表3个可编辑的数据Gu8SetDate_1,Gu8SetDate_2,Gu8SetDate_3,数据范围0-99;
(2)按键1有短按和长按功能。长按第三或第四数码管闪烁,再短按在三四数码管之间切换;再长按没有闪烁,显示3个窗口其中一个窗口,短按在三个窗口间切换;
(3)按键2,在闪烁条件下累加
(4)按键3,在闪烁条件下依次减小
在窗口切换中用到整屏更新和局部更新。(此框架值得好好研究)

#include "REG52.H"  

#define KEY_FILTER_TIME  25    //按键的“短按”兼“滤波”的“稳定时间”
#define KEY_LONG_TIME    500   //按键的“长按”兼“滤波”的“稳定时间”

#define SCAN_TIME  1   
#define VOICE_TIME   50   
#define BLINK_TIME   250    //数码管闪烁跳动的时间的间隔

void T0_time();
void SystemInitial(void) ;
void Delay(unsigned long u32DelayTime) ;
void PeripheralInitial(void) ;

void KeyScan(void);  
void KeyTask(void);  

void VoiceScan(void);  
void DisplayScan(void);  
void DisplayTask(void);  //上层显示的任务函数
void Wd1(void);   //窗口1显示函数
void Wd2(void);   //窗口2显示函数
void Wd3(void);   //窗口3显示函数

void PartUpdate(unsigned char u8Part);  //局部选择对应的某个局部变量更新显示输出

void BeepOpen(void);   
void BeepClose(void);

sbit KEY_INPUT1=P3^4; //三个按键 
sbit KEY_INPUT2=P3^5;  
sbit KEY_INPUT3=P3^6;  

sbit P0_0=P0^0; //六个数码管的公共端 
sbit P0_1=P0^1;  
sbit P0_2=P0^2;  
sbit P0_3=P0^3;
sbit P0_4=P0^4;  
sbit P0_5=P0^5;

sbit beep=P2^3;//蜂鸣器

sbit dula=P2^6;
sbit wela=P2^7;//控制数码管两个锁存器的段选和位选

//数码管转换表
code unsigned char Cu8DigTable[]=
{
    0x3f,  //0       序号0
    0x06,  //1       序号1
    0x5b,  //2       序号2
    0x4f,  //3       序号3
    0x66,  //4       序号4
    0x6d,  //5       序号5
    0x7d,  //6       序号6
    0x07,  //7       序号7
    0x7f,  //8       序号8
    0x6f,  //9       序号9
    0x00,  //不显示  序号10
    0x40,  //横杠-   序号11
};

volatile unsigned char vGu8ScanTimerFlag=0;  
volatile unsigned int vGu16ScanTimerCnt=0;  

volatile unsigned char vGu8BeepTimerFlag=0;  
volatile unsigned int vGu16BeepTimerCnt=0;  

volatile unsigned char vGu8BlinkTimerFlag=0;   //数码管闪烁跳动的定时器
volatile unsigned int vGu16BlinkTimerCnt=0;  

unsigned char Gu8SetData_3=0; //单片机内部第3个可编辑的参数,在窗口3
unsigned char Gu8SetData_2=0; //单片机内部第2个可编辑的参数,在窗口2
unsigned char Gu8SetData_1=0; //单片机内部第1个可编辑的参数,在窗口1

/* 注释一:
*      在人机界面的程序框架中,常常会遇到需要以“位”来编辑某个数据的情况,这种情况
*  实际上是先把“待编辑数据”分解成几个“位”临时中间个体,然后显示并且编辑这些“位”
*  临时中间个体,编辑结束后,再把这些“位”临时中间个体合并成一个完整的数据赋值给
*  “待编辑数据”。以下Gu8EditData_2和Gu8EditData_1就是“位”临时中间个体的中间变量。
*/

unsigned char Gu8EditData_2=0;  //对应显示左起第3位数码管的“位”数据,是中间变量。
unsigned char Gu8EditData_1=0;  //对应显示左起第4位数码管的“位”数据,是中间变量。

unsigned char Gu8Wd=1;   //窗口选择变量。人机交互程序框架的支点。初始化开机后显示第1个窗口。
unsigned char Gu8WdUpdate=1;  //整屏更新变量。初始化为1开机后整屏更新一次显示。
unsigned char Gu8Part=0;   //局部选择变量。0代表当前窗口下没有数据被选中。
unsigned char Gu8PartUpdate_1=0;   //局部1的更新变量,
unsigned char Gu8PartUpdate_2=0;   //局部2的更新变量


volatile unsigned char vGu8Display_Righ_4=1;   //左起第1位初始化显示窗口“1”
volatile unsigned char vGu8Display_Righ_3=11;  //左起第2位初始化显示横杠“-”
volatile unsigned char vGu8Display_Righ_2=0;   //左起第3位初始化显示数值“0”
volatile unsigned char vGu8Display_Righ_1=0;   //左起第4位初始化显示数值“0”

//不显示小数点
volatile unsigned char vGu8Display_Righ_Dot_4=0;  
volatile unsigned char vGu8Display_Righ_Dot_3=0;     
volatile unsigned char vGu8Display_Righ_Dot_2=0;  
volatile unsigned char vGu8Display_Righ_Dot_1=0;  

volatile unsigned char vGu8KeySec=0;  

void main()
{
    SystemInitial();            
    Delay(10000);               
    PeripheralInitial();      
    while(1)  
    {  
        KeyTask();      //按键的任务函数
        DisplayTask();  //数码管显示的上层任务函数
    }
}

void PartUpdate(unsigned char u8Part)  //局部选择对应的某个局部变量更新显示输出
{
    switch(u8Part)
    {
        case 1:
            Gu8PartUpdate_1=1;
            break;
        case 2:
            Gu8PartUpdate_2=1;
            break;
    }

}

void KeyTask(void)    //按键的任务函数
{
    if(0==vGu8KeySec)
    {
        return;
    }

    switch(vGu8KeySec)
    {
        case 1:     //K1按键的“短按”,具有“切换窗口”和“切换局部”的双功能。
            if(0==Gu8Part)  //处于“没有闪烁”的时候,是“切换窗口”
            {
                switch(Gu8Wd) //在某个窗口下
                {
                    case 1:     //在窗口1下
                        Gu8Wd=2;  //切换到窗口2
                        Gu8EditData_2=Gu8SetData_2/10%10;  //“待编辑数据”分解成中间个体
                        Gu8EditData_1=Gu8SetData_2/1%10;   //“待编辑数据”分解成中间个体
                        Gu8WdUpdate=1;  //整屏更新
                        break;

                    case 2:     //在窗口2下
                        Gu8Wd=3;  //切换到窗口3
                        Gu8EditData_2=Gu8SetData_3/10%10;  //“待编辑数据”分解成中间个体
                        Gu8EditData_1=Gu8SetData_3/1%10;   //“待编辑数据”分解成中间个体
                        Gu8WdUpdate=1;  //整屏更新
                        break;

                    case 3:     //在窗口3下
                        Gu8Wd=1;  //切换到窗口1
                        Gu8EditData_2=Gu8SetData_1/10%10;  //“待编辑数据”分解成中间个体
                        Gu8EditData_1=Gu8SetData_1/1%10;   //“待编辑数据”分解成中间个体
                        Gu8WdUpdate=1;  //整屏更新
                        break;

                }
            }
            else    //处于“闪烁模式”的时候,是“切换局部”
            {
                PartUpdate(Gu8Part);  //切换之前的局部进行更新。
                Gu8Part++;  //切换局部
                if(Gu8Part>2)
                {
                    Gu8Part=1;
                }
                PartUpdate(Gu8Part);  //切换之后的局部进行更新。
            }       

            vGu8BeepTimerFlag=0;  
            vGu16BeepTimerCnt=VOICE_TIME;  //蜂鸣器发出“滴”一声
            vGu8BeepTimerFlag=1;  

            vGu8KeySec=0;  
            break;

        case 2:     //递增按键K2
            switch(Gu8Wd) //在某个窗口下
            {
                case 1:     //在窗口1下
                case 2:     //在窗口2下,窗口2与窗口1的代码完全一模一样,因此可以这样共享
                case 3:     //在窗口3下,窗口3与窗口1的代码完全一模一样,因此可以这样共享
                switch(Gu8Part)  //二级支点的局部选择
                {
                    case 1:  //局部1被选中,代表左起第3位数码管被选中。
                        Gu8EditData_2++;  //编辑“十位”个体的中间变量
                        if(Gu8EditData_2>9)
                        {
                        Gu8EditData_2=9;
                        }
                        PartUpdate(Gu8Part); //当前局部更新显示输出到数码管
                        break;

                    case 2:  //局部2被选中,代表左起第4位数码管被选中。
                        Gu8EditData_1++;  //编辑“个位”个体的中间变量
                        if(Gu8EditData_1>9)
                        {
                        Gu8EditData_1=9;
                        }
                        PartUpdate(Gu8Part); //当前局部更新显示输出到数码管
                        break;
                }
                break;
            }

            vGu8BeepTimerFlag=0;  
            vGu16BeepTimerCnt=VOICE_TIME;  //蜂鸣器发出“滴”一声
            vGu8BeepTimerFlag=1;  

            vGu8KeySec=0;  
            break;

        case 3:     //递减按键K3
            switch(Gu8Wd) //在某个窗口下
            {
                case 1:     //在窗口1下
                case 2:     //在窗口2下,窗口2与窗口1的代码完全一模一样,因此可以这样共享
                case 3:     //在窗口3下,窗口3与窗口1的代码完全一模一样,因此可以这样共享
                switch(Gu8Part)  //二级支点的局部选择
                {
                    case 1:  //局部1被选中,代表左起第3位数码管被选中。
                        if(Gu8EditData_2>0)
                        {
                        Gu8EditData_2--; //编辑“十位”个体的中间变量
                        }
                        PartUpdate(Gu8Part); //当前局部更新显示输出到数码管
                        break;

                    case 2:  //局部2被选中,代表左起第4位数码管被选中。
                        if(Gu8EditData_1>0)
                        {
                        Gu8EditData_1--; //编辑“个位”个体的中间变量
                        }
                        PartUpdate(Gu8Part); //当前局部更新显示输出到数码管
                        break;
                }
                break;
            }

            vGu8BeepTimerFlag=0;  
            vGu16BeepTimerCnt=VOICE_TIME;  //蜂鸣器发出“滴”一声
            vGu8BeepTimerFlag=1;  

            vGu8KeySec=0;  
            break;

        case 4:     //K1按键的“长按”,具有进入和退出“闪烁模式”的功能。“退出”隐含“确定”

            switch(Gu8Wd) //在某个窗口下
            {
            case 1:     //在窗口1下
                if(0==Gu8Part)  //处于“没有闪烁”的时候,将进入“闪烁模式”
                {
                    Gu8EditData_2=Gu8SetData_1/10%10;  //先把“待编辑数据”分解成中间个体
                    Gu8EditData_1=Gu8SetData_1/1%10;   //先把“待编辑数据”分解成中间个体
                    Gu8Part=1;  //进入“闪烁模式”,从“局部1”开始闪烁
                }
                else    //处于“闪烁模式”的时候,将退出到“没有闪烁”,隐含“确定”功能
                {
                    Gu8SetData_1=Gu8EditData_2*10+Gu8EditData_1; //把个体合并还原成数据
                    Gu8Part=0;  //退出“闪烁模式”
                    Gu8WdUpdate=1;  //整屏更新
                }
                break;

            case 2:     //在窗口2下
                if(0==Gu8Part)  //处于“没有闪烁”的时候,将进入“闪烁模式”
                {
                    Gu8EditData_2=Gu8SetData_2/10%10;  //先把“待编辑数据”分解成中间个体
                    Gu8EditData_1=Gu8SetData_2/1%10;   //先把“待编辑数据”分解成中间个体
                    Gu8Part=1;  //进入“闪烁模式”,从“局部1”开始闪烁
                }
                else    //处于“闪烁模式”的时候,将退出到“没有闪烁”,隐含“确定”功能
                {
                    Gu8SetData_2=Gu8EditData_2*10+Gu8EditData_1; //把个体合并还原成数据
                    Gu8Part=0;  //退出“闪烁模式”
                    Gu8WdUpdate=1;  //整屏更新
                }
                break;

            case 3:     //在窗口3下
                if(0==Gu8Part)  //处于“没有闪烁”的时候,将进入“闪烁模式”
                {
                    Gu8EditData_2=Gu8SetData_3/10%10;  //先把“待编辑数据”分解成中间个体
                    Gu8EditData_1=Gu8SetData_3/1%10;   //先把“待编辑数据”分解成中间个体
                    Gu8Part=1;  //进入“闪烁模式”,从“局部1”开始闪烁
                }
                else    //处于“闪烁模式”的时候,将退出到“没有闪烁”,隐含“确定”功能
                {
                    Gu8SetData_3=Gu8EditData_2*10+Gu8EditData_1; //把个体合并还原成数据
                    Gu8Part=0;  //退出“闪烁模式”
                    Gu8WdUpdate=1;  //整屏更新
                }
                break;

            }

            vGu8BeepTimerFlag=0;  
            vGu16BeepTimerCnt=VOICE_TIME;  //蜂鸣器发出“滴”一声
            vGu8BeepTimerFlag=1;  

            vGu8KeySec=0;  
            break;

    }
}

void DisplayTask(void) //数码管显示的上层任务函数
{
  switch(Gu8Wd)  //以窗口选择Gu8Wd为支点,去执行对应的窗口显示函数。又一次用到switch语句
{
    case 1:
        Wd1();   //窗口1显示函数
        break;
    case 2:
        Wd2();   //窗口2显示函数
        break;
    case 3:
        Wd3();   //窗口3显示函数
        break;
}

}

void Wd1(void)   //窗口1显示函数
{
    //需要借用的中间变量,用来拆分数据位。
    static unsigned char Su8Temp_4,Su8Temp_3,Su8Temp_2,Su8Temp_1; //需要借用的中间变量
    static unsigned char Su8BlinkFlag=0;  //两种状态的切换判断的中间变量


    if(1==Gu8WdUpdate) //如果需要整屏更新
    {
        Gu8WdUpdate=0; //及时清零,只更新一次显示即可,避免一直进来更新显示

        Su8Temp_4=1;   //左起第1位数码管,显示窗口“1”,属于静态数据,起“装饰”作用。
        Su8Temp_3=11;  //左起第2位数码管,显示横杠“-”,属于静态数据,起“装饰”作用。

        vGu8Display_Righ_4=Su8Temp_4;  //过渡需要显示的数据到底层驱动变量
        vGu8Display_Righ_3=Su8Temp_3;  //过渡需要显示的数据到底层驱动变量

        //不显示任何一个小数点,属于静态数据,起“装饰”作用,切换窗口后只扫描一次的代码。
        vGu8Display_Righ_Dot_4=0;  
        vGu8Display_Righ_Dot_3=0;  
        vGu8Display_Righ_Dot_2=0;  
        vGu8Display_Righ_Dot_1=0;  

        Gu8PartUpdate_1=1;  //局部1更新显示
        Gu8PartUpdate_2=1  ;//局部2更新显示
    }

    if(1==Gu8PartUpdate_1) //局部1更新显示
    {
        Gu8PartUpdate_1=0; //及时清零,只更新一次显示即可,避免一直进来更新显示

        Su8Temp_2=Gu8EditData_2;  //显示“十位”的临时中间个体,属于动态数据。

        vGu8Display_Righ_2=Su8Temp_2;  //过渡需要显示的数据到底层驱动变量
    }

    if(1==Gu8PartUpdate_2) //局部2更新显示
    {
        Gu8PartUpdate_2=0; //及时清零,只更新一次显示即可,避免一直进来更新显示

        Su8Temp_1=Gu8EditData_1;  //显示“个位”的临时中间个体,属于动态数据。

        vGu8Display_Righ_1=Su8Temp_1;  //过渡需要显示的数据到底层驱动变量
    }


    if(0==vGu16BlinkTimerCnt)  //某位被选中的数码管跳动闪烁的定时器
    {
        vGu8BlinkTimerFlag=0;
        vGu16BlinkTimerCnt=BLINK_TIME;  //重设定时器的定时时间
        vGu8BlinkTimerFlag=1;

        switch(Gu8Part)  //某个局部被选中,则闪烁跳动
        {
            case 1:
                if(0==Su8BlinkFlag)  //两种状态的切换判断
                {
                    Su8BlinkFlag=1;
                    Su8Temp_2=10;  //左起第3个显示“不显示”(10代表不显示)
                }
                else
                {
                    Su8BlinkFlag=0;
                    Su8Temp_2=Gu8EditData_2;  //显示“十位”的临时中间个体,属于动态数据。
                }

                break;

            case 2:
                if(0==Su8BlinkFlag)  //两种状态的切换判断
                {
                    Su8BlinkFlag=1;
                    Su8Temp_1=10;  //左起第4个显示“不显示”(10代表不显示)
                }
                else
                {
                    Su8BlinkFlag=0;
                    Su8Temp_1=Gu8EditData_1;  //显示“个位”的临时中间个体,属于动态数据。
                }

                break;

            default:   //都没有被选中的时候
                Su8Temp_2=Gu8EditData_2;  //显示“十位”的临时中间个体,属于动态数据。
                Su8Temp_1=Gu8EditData_1;  //显示“个位”的临时中间个体,属于动态数据。      
                break;
    }

    vGu8Display_Righ_2=Su8Temp_2;  //过渡需要显示的数据到底层驱动变量
    vGu8Display_Righ_1=Su8Temp_1;  //过渡需要显示的数据到底层驱动变量

    }
}

void Wd2(void)   //窗口2显示函数
{
    //需要借用的中间变量,用来拆分数据位。
    static unsigned char Su8Temp_4,Su8Temp_3,Su8Temp_2,Su8Temp_1; //需要借用的中间变量
    static unsigned char Su8BlinkFlag=0;  //两种状态的切换判断的中间变量


    if(1==Gu8WdUpdate) //如果需要整屏更新
    {
        Gu8WdUpdate=0; //及时清零,只更新一次显示即可,避免一直进来更新显示

        Su8Temp_4=2;   //左起第1位数码管,显示窗口“2”,属于静态数据,起“装饰”作用。
        Su8Temp_3=11;  //左起第2位数码管,显示横杠“-”,属于静态数据,起“装饰”作用。

        vGu8Display_Righ_4=Su8Temp_4;  //过渡需要显示的数据到底层驱动变量
        vGu8Display_Righ_3=Su8Temp_3;  //过渡需要显示的数据到底层驱动变量

        //不显示任何一个小数点,属于静态数据,起“装饰”作用,切换窗口后只扫描一次的代码。
        vGu8Display_Righ_Dot_4=0;  
        vGu8Display_Righ_Dot_3=0;  
        vGu8Display_Righ_Dot_2=0;  
        vGu8Display_Righ_Dot_1=0;  

        Gu8PartUpdate_1=1;  //局部1更新显示
        Gu8PartUpdate_2=1  ;//局部2更新显示
    }

    if(1==Gu8PartUpdate_1) //局部1更新显示
    {
        Gu8PartUpdate_1=0; //及时清零,只更新一次显示即可,避免一直进来更新显示

        Su8Temp_2=Gu8EditData_2;  //显示“十位”的临时中间个体,属于动态数据。

        vGu8Display_Righ_2=Su8Temp_2;  //过渡需要显示的数据到底层驱动变量
    }

    if(1==Gu8PartUpdate_2) //局部2更新显示
    {
        Gu8PartUpdate_2=0; //及时清零,只更新一次显示即可,避免一直进来更新显示

        Su8Temp_1=Gu8EditData_1;  //显示“个位”的临时中间个体,属于动态数据。

        vGu8Display_Righ_1=Su8Temp_1;  //过渡需要显示的数据到底层驱动变量
    }


    if(0==vGu16BlinkTimerCnt)  //某位被选中的数码管跳动闪烁的定时器
    {
        vGu8BlinkTimerFlag=0;
        vGu16BlinkTimerCnt=BLINK_TIME;  //重设定时器的定时时间
        vGu8BlinkTimerFlag=1;

        switch(Gu8Part)  //某个局部被选中,则闪烁跳动
        {
            case 1:
                if(0==Su8BlinkFlag)  //两种状态的切换判断
            {
                Su8BlinkFlag=1;
                Su8Temp_2=10;  //左起第3个显示“不显示”(10代表不显示)
            }
            else
            {
                Su8BlinkFlag=0;
                Su8Temp_2=Gu8EditData_2;  //显示“十位”的临时中间个体,属于动态数据。
            }

            break;

            case 2:
                if(0==Su8BlinkFlag)  //两种状态的切换判断
                {
                    Su8BlinkFlag=1;
                    Su8Temp_1=10;  //左起第4个显示“不显示”(10代表不显示)
                }
                else
                {
                    Su8BlinkFlag=0;
                    Su8Temp_1=Gu8EditData_1;  //显示“个位”的临时中间个体,属于动态数据。
                }

                break;

            default:   //都没有被选中的时候
                Su8Temp_2=Gu8EditData_2;  //显示“十位”的临时中间个体,属于动态数据。
                Su8Temp_1=Gu8EditData_1;  //显示“个位”的临时中间个体,属于动态数据。      
                break;
    }

    vGu8Display_Righ_2=Su8Temp_2;  //过渡需要显示的数据到底层驱动变量
    vGu8Display_Righ_1=Su8Temp_1;  //过渡需要显示的数据到底层驱动变量

    }
}

void Wd3(void)   //窗口3显示函数
{
    //需要借用的中间变量,用来拆分数据位。
    static unsigned char Su8Temp_4,Su8Temp_3,Su8Temp_2,Su8Temp_1; //需要借用的中间变量
    static unsigned char Su8BlinkFlag=0;  //两种状态的切换判断的中间变量


    if(1==Gu8WdUpdate) //如果需要整屏更新
    {
        Gu8WdUpdate=0; //及时清零,只更新一次显示即可,避免一直进来更新显示

        Su8Temp_4=3;   //左起第1位数码管,显示窗口“3”,属于静态数据,起“装饰”作用。
        Su8Temp_3=11;  //左起第2位数码管,显示横杠“-”,属于静态数据,起“装饰”作用。

        vGu8Display_Righ_4=Su8Temp_4;  //过渡需要显示的数据到底层驱动变量
        vGu8Display_Righ_3=Su8Temp_3;  //过渡需要显示的数据到底层驱动变量

        //不显示任何一个小数点,属于静态数据,起“装饰”作用,切换窗口后只扫描一次的代码。
        vGu8Display_Righ_Dot_4=0;  
        vGu8Display_Righ_Dot_3=0;  
        vGu8Display_Righ_Dot_2=0;  
        vGu8Display_Righ_Dot_1=0;  

        Gu8PartUpdate_1=1;  //局部1更新显示
        Gu8PartUpdate_2=1  ;//局部2更新显示
    }

    if(1==Gu8PartUpdate_1) //局部1更新显示
    {
        Gu8PartUpdate_1=0; //及时清零,只更新一次显示即可,避免一直进来更新显示

        Su8Temp_2=Gu8EditData_2;  //显示“十位”的临时中间个体,属于动态数据。

        vGu8Display_Righ_2=Su8Temp_2;  //过渡需要显示的数据到底层驱动变量
    }

    if(1==Gu8PartUpdate_2) //局部2更新显示
    {
        Gu8PartUpdate_2=0; //及时清零,只更新一次显示即可,避免一直进来更新显示

        Su8Temp_1=Gu8EditData_1;  //显示“个位”的临时中间个体,属于动态数据。

        vGu8Display_Righ_1=Su8Temp_1;  //过渡需要显示的数据到底层驱动变量
    }


    if(0==vGu16BlinkTimerCnt)  //某位被选中的数码管跳动闪烁的定时器
    {
        vGu8BlinkTimerFlag=0;
        vGu16BlinkTimerCnt=BLINK_TIME;  //重设定时器的定时时间
        vGu8BlinkTimerFlag=1;

        switch(Gu8Part)  //某个局部被选中,则闪烁跳动
        {
            case 1:
                if(0==Su8BlinkFlag)  //两种状态的切换判断
                {
                    Su8BlinkFlag=1;
                    Su8Temp_2=10;  //左起第3个显示“不显示”(10代表不显示)
                }
                else
                {
                    Su8BlinkFlag=0;
                    Su8Temp_2=Gu8EditData_2;  //显示“十位”的临时中间个体,属于动态数据。
                }

                break;

            case 2:
                if(0==Su8BlinkFlag)  //两种状态的切换判断
                {
                    Su8BlinkFlag=1;
                    Su8Temp_1=10;  //左起第4个显示“不显示”(10代表不显示)
                }
                else
                {
                    Su8BlinkFlag=0;
                    Su8Temp_1=Gu8EditData_1;  //显示“个位”的临时中间个体,属于动态数据。
                }

                break;

            default:   //都没有被选中的时候
                Su8Temp_2=Gu8EditData_2;  //显示“十位”的临时中间个体,属于动态数据。
                Su8Temp_1=Gu8EditData_1;  //显示“个位”的临时中间个体,属于动态数据。      
                break;
    }

    vGu8Display_Righ_2=Su8Temp_2;  //过渡需要显示的数据到底层驱动变量
    vGu8Display_Righ_1=Su8Temp_1;  //过渡需要显示的数据到底层驱动变量

    }
}


void KeyScan(void)  //按键底层的驱动扫描函数,放在定时中断函数里
{
   static unsigned char Su8KeyShortFlag=0;  //按键“短按”触发的标志   
   static unsigned char Su8KeyLock1;
   static unsigned int  Su16KeyCnt1;
   static unsigned char Su8KeyLock2;
   static unsigned int  Su16KeyCnt2;
   static unsigned char Su8KeyLock3;
   static unsigned int  Su16KeyCnt3;

   if(0!=KEY_INPUT1)
   {
      Su8KeyLock1=0;
      Su16KeyCnt1=0;
      if(1==Su8KeyShortFlag)  
      {
        Su8KeyShortFlag=0;   
        vGu8KeySec=1;    //触发K1的“短按”
      }  
   }
   else if(0==Su8KeyLock1)
   {
      Su16KeyCnt1++;

      if(Su16KeyCnt1>=KEY_FILTER_TIME)
      {
            Su8KeyShortFlag=1;  
      }

      if(Su16KeyCnt1>=KEY_LONG_TIME)
      {
            Su8KeyLock1=1;      
            Su8KeyShortFlag=0;  
            vGu8KeySec=4; //触发K1的“长按”
      }
   }

   if(0!=KEY_INPUT2)
   {
      Su8KeyLock2=0;
      Su16KeyCnt2=0;      
   }
   else if(0==Su8KeyLock2)
   {
      Su16KeyCnt2++;
      if(Su16KeyCnt2>=KEY_FILTER_TIME)
      {
         Su8KeyLock2=1;  
         vGu8KeySec=2;   
      }
   }

   if(0!=KEY_INPUT3)
   {
      Su8KeyLock3=0;
      Su16KeyCnt3=0;      
   }
   else if(0==Su8KeyLock3)
   {
      Su16KeyCnt3++;
      if(Su16KeyCnt3>=KEY_FILTER_TIME)
      {
         Su8KeyLock3=1;  
         vGu8KeySec=3;   
      }
   }

}

void DisplayScan(void)    //数码管底层的驱动扫描函数,放在定时中断函数里
{
    static unsigned char Su8GetCode;  
    static unsigned char Su8ScanStep=1;  

    if(0==vGu16ScanTimerCnt)  
    {

        dula=1;
        P0=0x00;
        dula=0;

        wela=1;
        P0_0=1;  
        P0_1=1;  
        P0_2=1;  
        P0_3=1;
        P0_4=1;  
        P0_5=1;
        wela=0;

        switch(Su8ScanStep)
        {
        case 1:
            Su8GetCode=Cu8DigTable[vGu8Display_Righ_4];

            if(1==vGu8Display_Righ_Dot_4)
            {
                Su8GetCode=Su8GetCode|0x80;  
            }
            dula=1;
            P0=Su8GetCode;
            dula=0;
            wela=1;
            P0_0=0;
            P0_1=1;  
            P0_2=1;  
            P0_3=1;
            P0_4=1;  
            P0_5=1;
            wela=0;    
            break;

        case 2:
            Su8GetCode=Cu8DigTable[vGu8Display_Righ_3];
            if(1==vGu8Display_Righ_Dot_3)
            {
            Su8GetCode=Su8GetCode|0x80;  
            }
            dula=1;
            P0=Su8GetCode;
            dula=0;
            wela=1;
            P0_0=1;  
            P0_1=0;
            P0_2=1;
            P0_3=1;
            P0_4=1;  
            P0_5=1;
            wela=0; 
            break;

        case 3:
            Su8GetCode=Cu8DigTable[vGu8Display_Righ_2];
            if(1==vGu8Display_Righ_Dot_2)
            {
                Su8GetCode=Su8GetCode|0x80;  
            }
            dula=1;
            P0=Su8GetCode;
            dula=0;
            wela=1;
            P0_0=1;  
            P0_1=1;  
            P0_2=0;  
            P0_3=1;
            P0_4=1;  
            P0_5=1;
            wela=0; 
            break;

        case 4:
            Su8GetCode=Cu8DigTable[vGu8Display_Righ_1];
            if(1==vGu8Display_Righ_Dot_1)
            {
                Su8GetCode=Su8GetCode|0x80;  
            }
            dula=1;
            P0=Su8GetCode;
            dula=0;
            wela=1;
            P0_0=1;  
            P0_1=1;  
            P0_2=1;  
            P0_3=0;
            P0_4=1;  
            P0_5=1;
            wela=0;  
            break;

        }

        Su8ScanStep++;
        if(Su8ScanStep>4)
        {
            Su8ScanStep=1;
        }

        vGu8ScanTimerFlag=0;
        vGu16ScanTimerCnt=SCAN_TIME;  
        vGu8ScanTimerFlag=1;  
    }
}


void VoiceScan(void) //蜂鸣器的驱动函数
{

    static unsigned char Su8Lock=0;  

    if(1==vGu8BeepTimerFlag&&vGu16BeepTimerCnt>0)
    {
        if(0==Su8Lock)
        {
            Su8Lock=1;  
            BeepOpen();
        }
        else  
        {     

            vGu16BeepTimerCnt--;         

            if(0==vGu16BeepTimerCnt)
            {
                Su8Lock=0;     
                BeepClose();  
            }

        }
    }         
}

void BeepOpen(void)
{
    beep=0;  
}

void BeepClose(void)
{
    beep=1;  
}

void T0_time() interrupt 1     
{
    VoiceScan();    //蜂鸣器的驱动函数
    KeyScan();      //按键底层的驱动扫描函数
    DisplayScan();  //数码管底层的驱动扫描函数

    if(1==vGu8ScanTimerFlag&&vGu16ScanTimerCnt>0)  
    {
        vGu16ScanTimerCnt--;  //递减式的软件定时器
    }

    if(1==vGu8BlinkTimerFlag&&vGu16BlinkTimerCnt>0)   //数码管闪烁跳动的定时器
    {
        vGu16BlinkTimerCnt--;  //递减式的软件定时器
    }

    TH0=0xfc;   
    TL0=0x66;   
}


void SystemInitial(void)
{
    dula=1;
	P0=0x00;
	dula=0;
	wela=1;
	P0_0=1;  
	P0_1=1;  
	P0_2=1;  
	P0_3=1;
    P0_4=1;  
	P0_5=1;
	dula=0; 

    TMOD=0x01;  
    TH0=0xfc;   
    TL0=0x66;   
    EA=1;      
    ET0=1;      
    TR0=1;      
}

void Delay(unsigned long u32DelayTime)
{
    for(;u32DelayTime>0;u32DelayTime--);
}

void PeripheralInitial(void)
{

}