1695 views|1 replies

6587

Posts

0

Resources
The OP
 

Realization of Simple Single Chip Microcomputer Calculator [Copy link]

The MCU source program is as follows: #include          //51 MCU standard register declaration header file #include "bsp_GOG1.h" //This header file is used to map the GOG1 learning board hardware interface /*Calculator operation status definition: */ #define NoKey 0xaa //No key pressed status #define ErrKey 0xff //Wrong key status/interference #define DpyErr 0x0e //Error display status (the 14th element of the code table array: 'E') #define DpyCle 0x10 //Clear screen (the 16th element of the code table array: 0xff Turn off the digital tube) #define InCount 0xf0 //Operator input status #define InErrEqu 0x0f //Equal sign input status #define NoCountFlag 0xa5 //No operator status /*Matrix key function definition: */ #define ADD 15 //'#':Addition S15 #define SUB 12 //'C':Subtraction S12 #define MUL 14 //'*': multiplication S13 #define DIV 11 //'B': division S8 #define EQU 13 //'D': equal to S16 #define CLE 10 //'A': clear S4 /*Declaration of related sub-functions: */ void delayms(unsigned int ms); //Delay function void SegDisplay(unsigned char casebit); //Digital tube display function unsigned char ReadKeyPad(void); //Read matrix keyboard function void Timer0Init(void); //Timer 0 initialization function unsigned char CheckInput(void); //Calculator check input status function void DatUnpack(unsigned int dat); //Calculator data split function bit CheckNum(unsigned int dat); //Calculator data validity check function void WarmDpy(unsigned char err); //Calculator error display function void ComputeState(unsigned char dat); //Calculator calculation process function //The digital tube segment code table has 17 elements: 0~F & 0xff unsigned char code SegCode[17]= {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80, 0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff}; unsigned int Ans; //Operation result bit AnsFlag=0; //Operation result existence flag bit InFlag1=0; //Input valid number 1 flag bit InFlag2=0; //Input valid number 2 flag unsigned char CountFlag; //Operator unsigned int temp1=0,temp2=0;//Input 2 operation numbers unsigned char DisBuff[4]={DpyCle,DpyCle,DpyCle,DpyCle};//Digital tube display cache/*************************************************************************** * @brief main (introduction) * @param None (parameter) * @retval None (return value) ******************************************************************************/ void main(void) //Program starts here{ unsigned char in; //Variable to save single key value CountFlag=NoCountFlag; //Operator initial state Timer0Init(); //Timer 0 initializationwhile(1) { in=CheckInput(); while(in == NoKey) in=CheckInput(); //No key is pressed, wait hereif(in !=ErrKey) //Key is valid{ ComputeState(in); } else WarmDpy(DpyErr); //Invalid button, error 'E' } } /*********************************************************************************** * @brief ComputeState:Calculation process program* @param unsigned char dat * @retval None************************************************************************/ void ComputeState(unsigned char dat) { unsigned int num; //Variable to save the operation operandif(AnsFlag == 1) //Judge the completion flag of the last operation result{ WarmDpy(DpyCle); //Clear the screenAnsFlag=0; //Clear the valid operation completion flag} if((dat !=InCount)&(dat !=InErrEqu)&(dat <10)) //The pressed key is a number{ if(CountFlag == NoCountFlag) //No operator exists, save the first number{ num = temp1; num *= 10; //The input number is carried to the high position in turnnum += dat; if( CheckNum(num)==1 ) //Judge the data validity{ //Valid in the number rangetemp1 = num; //Save the first numberInFlag1 = 1; //Enter valid number 1 flag DatUnpack(temp1); //Split data, update display cache } else WarmDpy(DpyErr); //Out of range error } else //Operator exists, save the second number { num = temp2; num *= 10; num += dat; if(CheckNum(num)==1) { temp2 = num; InFlag2 = 1; //Enter valid number 2 flag WarmDpy(DpyCle); //Clear the display of the first number, eliminate the 'afterglow' DatUnpack(temp2);//Update display cache } else WarmDpy(DpyErr); } } else //The key pressed is non-digital (4 then the operator is saved, here consider the clear key and the wrong equal sign) { if(CLE == dat) //The key pressed is the clear key { CountFlag = NoCountFlag; //Clear operator InFlag1 =0; //Clear input valid number 1 flag InFlag2 =0; //Clear input valid number 2 flag AnsFlag=0; //Clear the operation result flag temp1=0,temp2=0; //Clear the two input operands WarmDpy(DpyCle); //Clear the screen Ans=0; //Clear the last operation result } if(InErrEqu == dat) //When the operation expression is incomplete, press the equal sign WarmDpy(DpyErr); //Error 'E' } } /*********************************************************************************** * @brief ReadKeyPad Used to read the matrix keyboard key value* @param None* @retval Matrix keyboard key value* @note For keyboard key value setting, please modify the assignment of 0xff to the temporary variable b in the case branch as the error code, indicating a reading error***************************************************************************/ unsigned char ReadKeyPad(void) { unsigned char a,c,b=NoKey; //The initial value of b is the no-key state KeyPad = 0x0f; //Initial state, row number (P3^0~P3^3) high level, column number (P3^4~P3^7) low levelif(KeyPad != 0x0f) { delayms(20); //Key debounce (delay implementation) if(KeyPad != 0x0f) //Key is pressed, initial state changes{ a = KeyPad; //Read the row number of the matrix keyboard} KeyPad = 0xf0; //Initial state inversionc = KeyPad; //Read the column number of the matrix keyboarda |= c; //Bitwise 'or', uniquely determine the matrix key value through the row number and column numberswitch (a) { case 0xee:b = 1;                          //S1
            break;
        case 0xed:
            b = 4;                          //S5
            break;
        case 0xeb:
            b = 7;                          //S9
            break;
        case 0xe7:
            b = MUL;                  //S13'MUL'
            break;
        case 0xde:
            b = 2;                          //S2
            break;
        case 0xdd:
            b = 5;                          //S6
            break;
        case 0xdb:
            b = 8;                          //S10
            break;
        case 0xd7:
            b = 0;                          //S14
            break;
        case 0xbe:
            b = 3;                         //S3
            break;
        case 0xbd:
            b = 6;                         //S7
            break;
        case 0xbb:
            b = 9;                         //S11
            break;
        case 0xb7:
            b = ADD;                 //S15 'ADD'
            break;
        case 0x7e:
            b = CLE;                 //S4 'CLE'
            break;
        case 0x7d:
            b = DIV;                 //S8 'DIV'
            break;
        case 0x7b:
            b = SUB;                 //S12 'SUB'
            break;
        case 0x77:
            b = EQU;                 //S16 '='
            break;
        default :                         //没有和 a 的匹配项
            b = ErrKey;                 //错误的按键值
            break;
        }
        KeyPad = 0xf0;                        //松手检测
        while (KeyPad != 0xf0);        //当没有松手,将在此一直等待
    }
    return (b);                                //返回读取的按键值
}

/******************************************************************************
  * @brief  delayms        毫秒级延时函数
  * @param  ms        延时的毫秒数 允许值 unsigned int范围
  * @retval 无
  * @attention   这个函数只是用于12T 8051内核的单片机运行于12Mhz
  *****************************************************************************/
void delayms(unsigned int ms)         //延时子程序(晶振12Mhz)
{
    unsigned char i;
    while(ms--)
    {
        for(i = 0; i < 120; i++);
    }
}

/******************************************************************************
  * @brief  SegDisplay 数码管显示&定时器中断程序组成动态显示
  * @param  casebit        用于选择数码管的位 允许值 0~4
  * @retval 无
  * @attention   这个函数需配合定时器中断服务程序
  *****************************************************************************/
void SegDisplay(unsigned char casebit)
{
    Seg7_Bits = 0xff;                             //关闭所有数码管
    Seg7_Data =SegCode[DisBuff[casebit]];//先把段码值赋给P1(段选端口)
    switch(casebit)
    {
    case 0:
        Seg7_Bit1 = 0;
        break;
    case 1:
        Seg7_Bit2 = 0;
        break;
    case 2:
        Seg7_Bit3 = 0;
        break;
    case 3:
        Seg7_Bit4 = 0;
        break;
    default :Seg7_Bits = 0xff; //Turn off all digital tubes Seg7_Data = 0xff; break; } } /******************************************************************************** * @brief DatUnpack: Data splitting, and assigning the thousands, hundreds, tens and ones of the data to the display buffer array DisBuff[] * @param unsigned int dat * @retval None *************************************************************************************/ void DatUnpack(unsigned int dat) { if((dat<10)) //1-digit DisBuff[0]=dat; else if((dat<100)&&(dat>=10)) //2-digit { DisBuff[1]=dat/10; DisBuff[0]=dat%10; } else if((dat<1000)&&(dat>=100)) //3 digits { DisBuff[2]=dat/100; DisBuff[1]=dat%100/10; DisBuff[0]=dat%100%10; } else if ((dat<10000)&&(dat>=1000))//4 digits { DisBuff[3]=dat/1000; DisBuff[2]=dat%1000/100; DisBuff[1]=dat%1000%100/10; DisBuff[0]=dat%1000%100%10; } } /******************************************************************************* * @brief unsigned char CheckInput(): Check the type of matrix keyboard input keys (introduction) * @param None (parameter) * @retval Number, function key (CLE, EQU, +, -, *, /), no key status (return value) **************************************************************************/ unsigned char CheckInput(void) { unsigned char x; x=ReadKeyPad(); //Call the key reading subroutine if(x != ErrKey) //Is it an error key value? { if((x<10)|(x == NoKey)| (x == CLE))//The key pressed is a number, or no key is pressed, or the clear key is pressed { return (x); } else //The key pressed is an operator (arithmetic and equal sign) { if(x == EQU) //The key pressed is the equal sign "=" { switch (CountFlag) { case ADD: Ans = temp1+temp2; break; case SUB: Ans = temp1-temp2; break; case MUL: Ans = temp1*temp2; break; case DIV: if (temp2 == 0) //The denominator of the division is 0, an error is reported{ WarmDpy(DpyErr); break; } else { Ans = temp1/temp2;//Only calculate the integer of the division quotient, and do not consider the decimal break; } } if( CheckNum(Ans)&&(InFlag1 ==1)&&(InFlag2 ==1))//Check the validity of the operation{ DatUnpack(Ans); //Split the operation result and update the display cacheCountFlag = NoCountFlag; //Clear the operatortemp1=0,temp2=0; //Clear operation numberAnsFlag = 1; //Operation result existence flagInFlag1 =0; //Clear valid number input flagInFlag2 =0; Ans=0; //Clear operation resultreturn (NoKey); //This operation is completed, return to no key state} else //WarmDpy(DpyErr); //Operation expression is incomplete or result is out of range, report errorreturn (InErrEqu); //Return to the state with equal sign input} else //The 4 operators pressed (+, -, *, /) { CountFlag = x; //Save operatorreturn (InCount); //Return to the state with operator input} } } else return (ErrKey); //Return to the state of wrong key value} /******************************************************************************* * @brief CheckNum: Check the validity of the calculator operand* @param dat * @retval bit valid: 1, invalid: 0 ******************************************************************************/ bit CheckNum(unsigned int dat) { if (dat < 10000) return 1; //Data is validelse return 0; } /******************************************************************************* * @brief WarmDpy: Digital tube error display* @param err Actual: subscript of the code segment value element of 'E'* @retval None******************************************************************************/ ……………………


This post is from Microcontroller MCU

Latest reply

It is best to use a timer plus a state machine to debounce buttons  Details Published on 2019-2-14 09:07
 

1368

Posts

6

Resources
2
 
It is best to use a timer plus a state machine to debounce buttons
This post is from Microcontroller MCU
 
Personal signature专注智能产品的研究与开发,专注于电子电路的生产与制造……QQ:2912615383,电子爱好者群: void
 

Guess Your Favourite
Find a datasheet?

EEWorld Datasheet Technical Support

Related articles more>>

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list