一個簡單的加減乘除計算器/*注意上面頭文件"bsp_GOG1.h"包含一個可選宏定義
若需使用擴展板請增加全局宏定義 _GOG1Plus
定義方式
菜單 Project->Options for Target->C51->Define
在此處填入 “_GOG1Plus”
在此代碼完全兼容,第三次課的矩陣按鍵程序,在此感謝魏同學的幫助 */
/*
計算器功能實現:4位數字的加,減,乘法,除法沒有做商的小數部分
1.對輸入運算數的有效性檢查,即超過9999時,顯示錯誤;
2,用LED--》D3來指示系統的正常運行狀態
3,運算的結果超過9999時,提示錯誤顯示;
4,當系統運行錯誤時,或者顯示亂碼時,按A鍵清除數碼管顯示;
5,除法運算時,的二個運算數為0時,提示錯誤顯示
6, 運算表達式不完整時,報錯:
(1)無數 * 第二個數 = 報錯
(2)第一個數 * 無數 = 報錯
(3)直接按等號,報錯
7,D3 LED燈實際是隔1ms 閃爍一次,
*/
/*矩陣按鍵 功能定義:
#define ADD 15 //'#':加法 S15
#define SUB 12 //'C':減法 S12
#define MUL 14 //'*':乘法 S13
#define DIV 11 //'B':除法 S8
#define EQU 13 //'D':等于 S16
#define CLE 10 //'A':清除 S4
仿真圖:
仿真圖.png (44.65 KB, 下載次數: 93)
下載附件
2018-11-15 20:15 上傳
單片機源程序如下:
- #include <REG52.H> //51單片機標準寄存器聲明頭文件
- #include "bsp_GOG1.h" //這個頭文件用于映射GOG1學習板載硬件接口
- /*計算器的運算狀態定義:*/
- #define NoKey 0xaa //沒有按鍵按下的狀態
- #define ErrKey 0xff //錯誤的按鍵狀態/干擾
- #define DpyErr 0x0e //錯誤顯示狀態(碼表數組第14個元素:'E')
- #define DpyCle 0x10 //清屏(碼表數組第16個元素:0xff 關閉數碼管)
- #define InCount 0xf0 //有運算符輸入狀態
- #define InErrEqu 0x0f //有等號輸入狀態
- #define NoCountFlag 0xa5 //沒有運算符的狀態
- /*矩陣按鍵 功能定義: */
- #define ADD 15 //'#':加法 S15
- #define SUB 12 //'C':減法 S12
- #define MUL 14 //'*':乘法 S13
- #define DIV 11 //'B':除法 S8
- #define EQU 13 //'D':等于 S16
- #define CLE 10 //'A':清除 S4
- /*相關子函數的聲明:*/
- void delayms(unsigned int ms); //延時函數
- void SegDisplay(unsigned char casebit); //數碼管顯示函數
- unsigned char ReadKeyPad(void); //讀取矩陣鍵盤函數
- void Timer0Init(void); //定時器0初始化函數
- unsigned char CheckInput(void); //計算器檢查輸入狀態函數
- void DatUnpack(unsigned int dat); //計算器數據拆分函數
- bit CheckNum(unsigned int dat); //計算器數據有效性檢查函數
- void WarmDpy(unsigned char err); //計算器錯誤顯示函數
- void ComputeState(unsigned char dat); //計算器計算過程函數
- //數碼管段碼表 共陽 17個元素: 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; //運算結果
- bit AnsFlag=0; //運算結果存在標志
- bit InFlag1=0; //輸入有效數字1標志
- bit InFlag2=0; //輸入有效數字2標志
- unsigned char CountFlag; //運算符
- unsigned int temp1=0,temp2=0;//輸入的2個運算的數字
- unsigned char DisBuff[4]={DpyCle,DpyCle,DpyCle,DpyCle};//數碼管顯示緩存
- /*******************************************************************************
- * @brief mian (簡介)
- * @param 無 (參數)
- * @retval 無 (返回值)
- ******************************************************************************/
- void main(void) //程序從這里開始
- {
- unsigned char in; //保存單個按鍵值的變量
-
- CountFlag=NoCountFlag; //運算符初始狀態
- Timer0Init(); //定時器0初始化
- while(1)
- {
- in=CheckInput();
- while(in == NoKey) in=CheckInput(); //沒有按鍵按下,在此等待
- if(in !=ErrKey) //按鍵有效
- {
- ComputeState(in);
- }
- else WarmDpy(DpyErr); //按鍵無效,報錯 'E'
- }
- }
- /*******************************************************************************
- * @brief ComputeState: 計算過程程序
- * @param unsigned char dat
- * @retval 無
- *******************************************************************************/
- void ComputeState(unsigned char dat)
- {
- unsigned int num; //保存運算操作數的變量
- if(AnsFlag == 1) //判斷上一次運算結果完成標志
- {
- WarmDpy(DpyCle); //清屏
- AnsFlag=0; //清除有效運算完成標志
- }
- if((dat !=InCount)&(dat !=InErrEqu)&(dat <10)) //按下的鍵為數字
- {
- if(CountFlag == NoCountFlag) //沒有運算符存在,保存第一個數
- {
- num = temp1;
- num *= 10; //輸入的數字依次進高位
- num += dat;
- if( CheckNum(num)==1 ) //判斷數據有效性
- { //有效在數字范圍
- temp1 = num; //保存第一個數字
- InFlag1 = 1; //輸入有效數字1標志
- DatUnpack(temp1); //拆分數據,更新顯示緩存
- }
- else WarmDpy(DpyErr); //超出范圍報錯
- }
- else //運算符存在 ,保存第二個數
- {
- num = temp2;
- num *= 10;
- num += dat;
- if(CheckNum(num)==1)
- {
- temp2 = num;
- InFlag2 = 1; //輸入有效數字2標志
- WarmDpy(DpyCle); //清除第一個數的顯示,消除'余暉'
- DatUnpack(temp2);//更新顯示緩存
- }
- else WarmDpy(DpyErr);
- }
- }
- else //按下的鍵為非數字(4則運算符被保存,這里考慮 清除鍵和 錯誤等號)
- {
- if(CLE == dat) //按下的為清除鍵
- {
- CountFlag = NoCountFlag; //清除運算符
- InFlag1 =0; //清除輸入有效數字1標志
- InFlag2 =0; //清除輸入有效數字2標志
- AnsFlag=0; //清除運算結果存在標志
- temp1=0,temp2=0; //清除輸入的2個運算數
- WarmDpy(DpyCle); //清屏
- Ans=0; //清除上一次運算結果
- }
-
- if(InErrEqu == dat) //運算表達式不完整時,按下等號的情況
- WarmDpy(DpyErr); //報錯 'E'
- }
- }
- /*******************************************************************************
- * @brief ReadKeyPad 用于讀取矩陣鍵盤鍵值
- * @param 無
- * @retval 矩陣鍵盤鍵值
- * @note 鍵盤鍵值設置請修改case分支臨時變量b的賦值
- 0xff 作為錯誤代碼,表示讀取出錯
- ******************************************************************************/
- unsigned char ReadKeyPad(void)
- {
- unsigned char a,c,b=NoKey; //b 初始值為無按鍵的狀態
- KeyPad = 0x0f; //初始狀態,行號(P3^0~P3^3)高電平,列號(P3^4~P3^7)低電平
- if(KeyPad != 0x0f)
- {
- delayms(20); //按鍵消抖動(延時實現)
- if(KeyPad != 0x0f) //按鍵被按下,初始狀態改變
- {
- a = KeyPad; //讀取矩陣鍵盤的行號
- }
- KeyPad = 0xf0; //初始狀態反轉
- c = KeyPad; //讀取矩陣鍵盤的列號
- a |= c; //按位'或',通過行號,列號唯一確定矩陣按鍵值
- switch (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; //關閉所有數碼管
- Seg7_Data = 0xff;
- break;
- }
- }
- /************************************************************************************
- * @brief DatUnpack:數據拆分,同時把數據的千位,百位,十位,個位賦給顯示緩存數組DisBuff[]
- * @param unsigned int dat
- * @retval 無
- ***********************************************************************************/
- void DatUnpack(unsigned int dat)
- {
- if((dat<10)) //1位數
- DisBuff[0]=dat;
- else if((dat<100)&&(dat>=10)) //2位數
- {
- DisBuff[1]=dat/10;
- DisBuff[0]=dat%10;
- }
- else if((dat<1000)&&(dat>=100)) //3位數
- {
- DisBuff[2]=dat/100;
- DisBuff[1]=dat%100/10;
- DisBuff[0]=dat%100%10;
- }
- else if ((dat<10000)&&(dat>=1000))//4位數
- {
- 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(): 檢查矩陣鍵盤輸入按鍵的類型(簡介)
- * @param 無 (參數)
- * @retval 數字,功能鍵(CLE,EQU,+,-,*,/),無按鍵的狀態 (返回值)
- ******************************************************************************/
- unsigned char CheckInput(void)
- {
- unsigned char x;
- x=ReadKeyPad(); //調用讀按鍵子程序
- if(x != ErrKey) //是否為錯誤按鍵值
- {
- if((x<10)|(x == NoKey)| (x == CLE))//按下的為數字,或沒有按鍵按下,或清除鍵
- {
- return (x);
- }
- else //按下的為 運算符(四則運算 和 等號)
- {
- if(x == EQU) // 按下的為 等號"="
- {
- 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) //除法分母為0,報錯
- {
- WarmDpy(DpyErr);
- break;
- }
- else
- {
- Ans = temp1/temp2;//只計算除法商的整數,暫沒有考慮小數
- break;
- }
- }
- if( CheckNum(Ans)&&(InFlag1 ==1)&&(InFlag2 ==1))//檢測運算的有效性
- {
- DatUnpack(Ans); //運算結果拆分,更新顯示緩存
- CountFlag = NoCountFlag; //清除運算符
- temp1=0,temp2=0; //清除運算數字
- AnsFlag = 1; //運算結果存在標志
- InFlag1 =0; //清除有效數字輸入標志
- InFlag2 =0;
- Ans=0; //清除運算結果
- return (NoKey); //此次運算完成,返回無按鍵狀態
- }
- else //WarmDpy(DpyErr) ;//運算表達式不完整或結果超出范圍,報錯
- return (InErrEqu); //返回有等號輸入的狀態
- }
- else //按下的為 4則 運算符(+ ,-,*, /)
- {
- CountFlag = x; //保存運算符
- return (InCount); //返回有運算符輸入的狀態
- }
- }
- }
- else return (ErrKey); //返回錯誤按鍵值狀態
- }
- /*******************************************************************************
- * @brief CheckNum: 檢查計算器運算數的有效性
- * @param dat
- * @retval bit 有效: 1,無效: 0
- ******************************************************************************/
- bit CheckNum(unsigned int dat)
- {
- if (dat < 10000)
- return 1; //數據有效
- else
- return 0;
- }
- /*******************************************************************************
- * @brief WarmDpy:數碼管錯誤顯示
- * @param err 實則:'E'的碼段值元素的下標
- * @retval 無
- ******************************************************************************/
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
0.png (8.53 KB, 下載次數: 79)
下載附件
2018-11-16 03:02 上傳
所有資料51hei提供下載:
counter程序(V2.0).zip
(122.64 KB, 下載次數: 165)
2018-11-15 20:14 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|