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 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******************************************************************************/ ……………………