不是很明白按键是怎么样传递值给Tmp1和Tmp2的

2019-07-16 02:00发布

这是网上一个人写的程序,我给加了注释,对于大家理解程序很有帮助,但是始终不明到两个操作数是怎样传递给Tmp1和Tmp2的!
/*
* Easy calculator
*
* K4:+ K8:- K12:* K16:/ K14:Clear K15:=
*
* Made by Kingst-刚哥
* date: 2010.12.21
*/

#include <reg52.h>

typedef   unsigned char  uint8;
typedef   unsigned int   uint16;
typedef   unsigned long  uint32;
typedef   char  int8;
typedef   int   int16;
typedef   long  int32;

sbit KeyIn1 = P2^4;
sbit KeyIn2 = P2^5;
sbit KeyIn3 = P2^6;
sbit KeyIn4 = P2^7;
sbit KeyOut1 = P2^3;
sbit KeyOut2 = P2^2;
sbit KeyOut3 = P2^1;
sbit KeyOut4 = P2^0;
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
sbit BUZZ  = P1^6;                 //蜂鸣器控制位

#define FADD        10
#define FSUB        11
#define FMUL        12
#define FDIV        13
#define FRES        14
#define FEQU        15

#define KEY_DELAY 300                //延时常数
#define BUZ_DELAY 80

code uint8 Ledcode[13]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf,0x86};
uint8 Led_n=0;                        //co为0,f9为1,类推

uint8 Led_buf[6];    //定义Led_buf[6]数?

float Tmp1=0, Tmp2=0;  //用于存储输入的两个变量

int8 C_flag=0;


/*
* 延时
*/


void delay(uint16 n)
{
        while (n--);
}


/*
* 蜂鸣器发声
*/


void buzzer_sound(void)
{
        uint16 i;

        for (i=0; i<BUZ_DELAY; i++)
        {
                BUZZ = ~BUZZ;           //BUZZ初始状态为高电平,蜂鸣器熄灭
                delay(100);
        }

        BUZZ = 1;
}


/*
* 按键扫描
*/


int8 scan_key(void)
{
        int8 val=-1;   //此处未初始化val,val为按键的标志位
                                   //当没有按键时,val的值为-1
        KeyOut1 = 0;
        KeyOut2 = 1;
        KeyOut3 = 1;
        KeyOut4 = 1;

        if (KeyIn1 == 0)
        {
                delay(KEY_DELAY);
                if (KeyIn1 == 0)
                        val = 1;
        }
        if (KeyIn2 == 0)
        {
                delay(KEY_DELAY);
                if (KeyIn2 == 0)
                        val = 2;
        }
        if (KeyIn3 == 0)
        {
                delay(KEY_DELAY);
                if (KeyIn3 == 0)
                        val = 3;
        }
        if (KeyIn4 == 0)
        {
                delay(KEY_DELAY);
                if (KeyIn4 == 0)
                        val = FADD;                   //FADD此处为10
        }
        while ((KeyIn1 == 0)||(KeyIn2 == 0)||(KeyIn3 == 0)||(KeyIn4 == 0));          
        /*此处只要有一个按键被按下,就在此处循环*/

        KeyOut1 = 1;
        KeyOut2 = 0;
        KeyOut3 = 1;
        KeyOut4 = 1;

        if (KeyIn1 == 0)
        {
                delay(KEY_DELAY);          //KEY_DELAY为300
                if (KeyIn1 == 0)
                        val = 4;
        }
        if (KeyIn2 == 0)
        {
                delay(KEY_DELAY);
                if (KeyIn2 == 0)
                        val = 5;
        }
        if (KeyIn3 == 0)
        {
                delay(KEY_DELAY);
                if (KeyIn3 == 0)
                        val = 6;
        }
        if (KeyIn4 == 0)
        {
                delay(KEY_DELAY);
                if (KeyIn4 == 0)
                        val = FSUB;                   //此处FSUB为11
        }
        while ((KeyIn1 == 0)||(KeyIn2 == 0)||(KeyIn3 == 0)||(KeyIn4 == 0));
        /*此处只要有一个按键被按下,就在此处循环*/

        KeyOut1 = 1;
        KeyOut2 = 1;
        KeyOut3 = 0;
        KeyOut4 = 1;

        if (KeyIn1 == 0)
        {
                delay(KEY_DELAY);
                if (KeyIn1 == 0)
                        val = 7;
        }
        if (KeyIn2 == 0)
        {
                delay(KEY_DELAY);
                if (KeyIn2 == 0)
                        val = 8;
        }
        if (KeyIn3 == 0)
        {
                delay(KEY_DELAY);
                if (KeyIn3 == 0)
                        val = 9;
        }
        if (KeyIn4 == 0)
        {
                delay(KEY_DELAY);
                if (KeyIn4 == 0)
                        val = FMUL;                 //此处FMUL为12
        }
        while ((KeyIn1 == 0)||(KeyIn2 == 0)||(KeyIn3 == 0)||(KeyIn4 == 0));

        KeyOut1 = 1;
        KeyOut2 = 1;
        KeyOut3 = 1;
        KeyOut4 = 0;

        if (KeyIn1 == 0)
        {
                delay(KEY_DELAY);
                if (KeyIn1 == 0)
                        val = 0;
        }
        if (KeyIn2 == 0)
        {
                delay(KEY_DELAY);
                if (KeyIn2 == 0)
                        val = FRES;                //FRES        14
        }
        if (KeyIn3 == 0)
        {
                delay(KEY_DELAY);
                if (KeyIn3 == 0)
                        val = FEQU;           //FEQU        15
        }
        if (KeyIn4 == 0)
        {
                delay(KEY_DELAY);
                if (KeyIn4 == 0)
                        val = FDIV;                  //此处FDIV为13
        }
        while ((KeyIn1 == 0)||(KeyIn2 == 0)||(KeyIn3 == 0)||(KeyIn4 == 0));

        if (val > 0)         //        此处为当有按键按下时,蜂鸣器响起,根据val的值判断
                buzzer_sound();

        return val;
}


/*
* 验证数据有效性
*/


bit check_num(float f_num)
{
        if (f_num >= 100000)
                return 1;

        return 0;                   //返回值为位0
}


/*
* 制作数码管错误标志
*/


void make_led_error(void)
{
        int8 i;

        for (i=0; i<5; i++)
        Led_buf[i] = Ledcode[10];        //Ledcode[10]为0xf为小灯全部熄灭

        Led_buf[5] = Ledcode[12];        //Ledcode[12]为0x86此处为字符E


}


/*
* 制作数码管整数数据
*/


void make_led_inumber(int32 i_num)          //函数参数传递i_num的值为0
{
        bit s_flag=0;
        int16 sit;
        int8 i;

        if (i_num < 0)
        {
                s_flag = 1;
                i_num = -i_num;
        }
       
        ET0 = 0;         //禁止T0溢出中断

        for (i=4, sit=10000; i>=1; i--, sit/=10) //当sit为1
        {
                if (i_num >= sit)
                        break;
                Led_buf[i] = Ledcode[10];         //Ledcode[10]为0xf为小灯全部熄灭
                i_num -= i_num/sit*sit;
        }
        for (;i>=1; i--, sit/=10)
        {
                Led_buf[i] = Ledcode[i_num/sit];
                i_num -= i_num/sit*sit;
        }
        Led_buf[0] = Ledcode[i_num] & 0x7F;
        if (s_flag)
                Led_buf[5] = Ledcode[11];
        else
                Led_buf[5] = Ledcode[10];
        ET0 = 1;

}


/*
* 制作数码管浮点数据
*/


void make_led_fnumber(float f_num)
{
        bit s_flag=0;
        int32 num;
        int16 sit;
        int8 i, decimal, dot_sit=0;


        if (f_num < 0)
        {
                s_flag = 1;          //如果计算结果f_num <0 ; 则s_flag的值则为1
                f_num = -f_num;        //把f_num的值按整数计算                                  
        }
       
        num = (int32)(f_num*10000+0.5);         //把计算结果乘以10000,再加0.5,然后强制取整

        for (decimal=4; decimal>0; decimal--)  //对于10取余,直到余数不等于0,跳出循环体
        {
                if (num % 10 != 0)
                        break;
                num /= 10;
        }
       
        dot_sit = decimal;        // decimal为小数点位数

        if (f_num >= 10000)          //如果f_num的值大于10000,怎小数点位数为0
                dot_sit = 0;
        else if (f_num >= 1000)         //如果此数大于1000,且小数点位数多于以为,则取一位小数
                if (decimal >= 1)         //因为数码管的显示范围
                        dot_sit = 1;
        else if (f_num >= 100)
                if (decimal >= 2)
                        dot_sit = 2;
        else if (f_num >= 10)
                if (decimal >= 3)
                        dot_sit = 3;

        for (i=0; i<dot_sit; i++)
                f_num *= 10;
        num = (int32)(f_num+0.5);

        ET0 = 0;        //禁止T0溢出中断

/*          此分为两步分别讨论
1 第一步,把此数用不到的各位的数码管分别熄灭
2 第二步,把有数位分别赋值到数码管上去    */

        for (i=4, sit=10000; i>=1; i--, sit/=10)
        {
                if (num >= sit)
                        break;                         //如果此数大于10000,或者小数点位数为4位,则跳出,同理
                if (i == dot_sit)
                        break;

                Led_buf[i] = Ledcode[10]; //Ledcode[10]为0xf为小灯全部熄灭
                num -= num/sit*sit;         //此处为不断的获取书num上以后各位的数值大小
        }

        /*此处的for语句用于不断的给数组Led_buf[i]赋上计算结果的各位*/

        for (;i>=1; i--, sit/=10)
        {
                Led_buf[i] = Ledcode[num/sit];        //利用Ledcode[]直接给Led_buf[i]依此赋值

                num -= num/sit*sit;           //此处为不断的获取书num上以后各位的数值大小
        }
        Led_buf[0] = Ledcode[num];        //赋上个位的数值

        Led_buf[dot_sit] &= 0x7F; //与上0111,1111,点亮小数点

        if (s_flag)
                Led_buf[5] = Ledcode[11]; //如果计算结果小于0,则Led_buf[5]则为0xbf为“-”
        else
                Led_buf[5] = Ledcode[10]; //Ledcode[10]为0xff为小灯全部熄灭        ,不显示

        ET0 = 1;   //允许T0溢出中断

}

/*
* 数码管显示
*/
void show_num(uint8 *buf)
{
        ENLED = 1;
        switch (Led_n)
        {
                case 0:
                        ADDR0 = 0;
                        ADDR1 = 0;
                        ADDR2 = 0;
                        P0 = buf[0];
                        break;
                case 1:
                        ADDR0 = 1;
                        ADDR1 = 0;
                        ADDR2 = 0;
                        P0 = buf[1];
                        break;
                case 2:
                        ADDR0 = 0;
                        ADDR1 = 1;
                        ADDR2 = 0;
                        P0 = buf[2];
                        break;
                case 3:
                        ADDR0 = 1;
                        ADDR1 = 1;
                        ADDR2 = 0;
                        P0 = buf[3];
                        break;
                case 4:
                        ADDR0 = 0;
                        ADDR1 = 0;
                        ADDR2 = 1;
                        P0 = buf[4];
                        break;
                case 5:
                        ADDR0 = 1;
                        ADDR1 = 0;
                        ADDR2 = 1;
                        P0 = buf[5];
                        break;
        }
        ENLED = 0;

        if (Led_n >= 5)
                Led_n = 0;
        else
                Led_n++;
}

/*
* 计算程序
*/
void calculate(int8 key_val) //键盘输入的按键标识符key_val
{
        float ans;
        bit err=0;

        if ((key_val >= FADD) && (key_val <= FDIV))         //判断输入的值是否为运算符
        {
                C_flag = key_val; //如果运算符是四则运算符,则C_flag的值等于key_val
        }
       
        else if (key_val == FEQU)         //FEQU为等于号
        {
                switch (C_flag)
                {
                        case FADD:         ans = Tmp1+Tmp2; break;           //ans为浮点数值
                        case FSUB:         ans = Tmp1-Tmp2; break;
                        case FMUL:         ans = Tmp1*Tmp2; break;
                        case FDIV:         if (Tmp2 == 0)
                                                {
                                                        err = 1;  //如果输入除数为零,则错误
                                                        break;
                                                }
                                                else
                                                {
                                                        ans = Tmp1/Tmp2;
                                                        break;
                                                }
                }
               
                if (check_num(ans))        //如果数据发生溢出,则报错
                        err = 1;
                if (err)
                        make_led_error();        //如果发生错误,则显示错误
                else
                        make_led_fnumber(ans);
                C_flag = 0;
                Tmp1 = 0;
                Tmp2 = 0;
        }
        //此处与第一个if语句相对应
        else if (key_val == FRES)         //如果按下复位键
        {
                make_led_fnumber(0);
                C_flag = 0;
                Tmp1 = 0;
                Tmp2 = 0;
        }
        else
        {
                if (C_flag == 0)
                {
                        ans = Tmp1;
                        ans *= 10;
                        ans += key_val;
                        if (check_num(ans))
                                return;
                        else
                                Tmp1 = ans;
                        make_led_inumber(Tmp1);
                }
                else
                {
                        ans = Tmp2;
                        ans *= 10;
                        ans += key_val;
                        if (check_num(ans))
                                return;
                        else
                                Tmp2 = ans;
                        make_led_inumber(Tmp2);         //制作数码管整数数据
                }

        }

}



                /*此处为主函数*/
main()
{
        int8 key_val;

        ADDR3 = 1;
        ENLED = 0;

        make_led_inumber(0); //        在按键之前先显示制作数码管整数数据

    TMOD = 0x01;          //使用T0的16为定时器方式
    TH0 = 0xF8;              //使用T0的时间为1.84sec
        TL0 = 0xCC;               
    TR0 = 1;                   //启动定时器T0
        ET0 = 1;                 //允许定时器T0溢出中断
        EA = 1;                         //打开中断总开关,允许中断

        while (1)
        {
                key_val = scan_key();        //根据val,确定按键的值
                if (key_val == -1)
                        continue;
                calculate(key_val);          //计算数值

        }
}


void time0() interrupt 1         //中断程序使用定时器T0
{
        TR0 = 0;
        TH0 = 0xF8;
        TL0 = 0xCC;

        show_num(Led_buf);

        TR0 = 1;
}


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。