欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2384|回復: 4
收起左側

基于51單片機實現的匯編語言的帶優先級計算的簡易計算器 帶優先級,蜂鳴器存在些許問題

[復制鏈接]
ID:1085458 發表于 2023-6-30 22:35 | 顯示全部樓層 |閱讀模式
51hei.gif

        ORG 0000H
        LED EQU P2.0;P2.0控制的LED(RP9,8,D1)
        RW EQU P2.5;RW等值P2.5(讀寫控制位)
        RS EQU P2.6;RS等值P2.6(數據/指令控制位)
        E  EQU P2.7; E等值P2.7(使能控制位)
        BR EQU P2.5;BR等值P2.5(蜂鳴器)
        ON EQU P3.3;開機鍵等值P3.3
        OFF EQU P3.2;關機鍵等值P3.2
        POSITION EQU 30H;LM016L第一行的行地址
        TEMPORARY0 EQU 40H;數據臨時存放0
        TEMPORARY1 EQU 41H;數據臨時存放1
        TEMPORARY2 EQU 42H;數據臨時存放2
        TEMPORARY3 EQU 43H;數據臨時存放3
        TEMPORARY4 EQU 44H;數據臨時存放4
        TEMPORARY5 EQU 45H;數據臨時存放5
        TEMPORARY6 EQU 46H;數據臨時存放6
        TEMPORARY7 EQU 47H;數據臨時存放7
        POINTER EQU 48H;轉換后的數據儲存的范圍
        DATA0 EQU 50H;運算位0,儲存符號前一位的數據
        DATA1 EQU 51H;運算位1,儲存符號后一位的數據
        DATA2 EQU 52H;運算位2,在RESULT子程序中使用
        DATA3 EQU 53H;運算位3,在乘除法的命令中使用
        ANDS EQU 54H;結果存儲
        LJMP MAIN
        ORG 0300H
/*初始化LM016L的屏幕設置,該部分的功能包括:
        LM016L兩行顯示,每行8個字模,開啟光標,但光標不閃爍,在輸入字模時,屏幕不會隨著輸入移位,在輸入前清除屏幕顯示,同時關閉蜂鳴器*/
MAIN:
        SETB LED;關閉LED
        CLR BR;初始化蜂鳴器的狀態,關閉蜂鳴器
        MOV A,#38H;8位,2行,5*10點陣/字符
        LCALL COMMAND_WRITTING
        MOV A,#0EH;整體顯示,開光標,光標不閃爍
        LCALL COMMAND_WRITTING                                                                                 
        MOV A,#06H;設定輸入方式,增量不移位
        LCALL COMMAND_WRITTING
        MOV A,#01H;清除屏幕顯示
        LCALL COMMAND_WRITTING
        MOV POSITION,#0FFH;設定POSITION的初始地址
        MOV R0,#70H;存儲輸入的數據,儲存空間為70H~7FH
        MOV R1,#80H;修改輸入的數據,儲存空間為80H~100H
        MOV ANDS,#00H;初始化結果存儲
        AJMP DISPLAY;隔離指令
/*LM016L顯示功能部分,該部分的功能包括:
        判斷是否超過屏幕最大顯示范圍,執行清屏指令,執行等于指令,輸出按鍵對應的字模*/
DISPLAY:        
                LCALL RANGE;判斷是否超出第一行最大顯示范圍
                LCALL KEYS
                MOV DPTR,#TABLE;將字碼表傳送給DPTR
                MOVC A,@A+DPTR ;查表指令,A中儲存相應字碼
                JNZ WRITE;檢查A是否為00H,如果是則說明需執行AC或=操作
                LCALL DELAY;等待按鍵重新按下
                LJMP DISPLAY
                WRITE:
                        LCALL DATA_WRITTING;向P0口寫數
                        LCALL DELAY
                        INC POSITION;記錄當前的地址,并同時記錄指令執行的次數
                        MOV @R0,A;將輸入的字模放入R0中儲存起來了
                        INC R0;R0的地址加1
                        AJMP DISPLAY
KEYS:
        JNB ON,STEP0;如果ON鍵按下,P3.0為低電平
        JNB OFF,STEP1;如果OFF鍵按下,P3.1為低電平
        AJMP STEP2;隔離指令
STEP0:
        LCALL ON_SET
        AJMP STEP2;隔離指令
STEP1:
        LCALL OFF_SET
        AJMP STEP2;隔離指令
STEP2:
        MOV P1,#0FH;將P1口拉高電平
        MOV A,P1;讀P1口的狀態
        ANL A,#0FH;屏蔽高四位
        MOV B,A;將A中的內容放入B中保護
        MOV P1,#0F0H;將行線輸出為1,列線輸出為0
        MOV A,P1;讀P1口的狀態
        ANL A,#0F0H;屏蔽第四位
        ORL A,B;將兩次高4位,低4位合并,即為鍵碼        
        CJNE A,#0FFH,KEYPR0;不相等則有鍵按下,跳轉至KEYPR0
        LCALL DELAY
        SJMP KEYS;防止輸出方塊字符
        KEYPR0:
                MOV B,A;暫存鍵碼
                LJMP CLEAR
        TEMP:
                LJMP EQUAL
        KEY0:
                MOV DPTR,#KEYVALUE;將KEYVALUE的表頭給DPTR
                MOV R3,#0FFH;R3置初值
        KEY1:
                INC R3;鍵號加1
                MOV A,R3;將鍵號傳送給A
                MOVC A,@A+DPTR;查表指令
                CJNE A,B,KEY2;查得的鍵碼與B中暫存的鍵碼不相等,轉到KEY2
                LCALL BUZZER;響鈴一聲
                MOV A,R3;查得的鍵碼與B中暫存的鍵碼相等,轉存到A
                RET
        KEY2:
                CJNE A,#00H,KEY1;A≠0,轉到KEY1,進行查鍵碼
                RET;A=0,鍵盤異常,返回主程序
//執行運算子程序
EQUAL:
        CJNE A,#0EDH,KEY0;查詢是否為等于指令
        MOV A,#0C8H;給定下一個將要寫入的DDRAM地址
        LCALL COMMAND_WRITTING
        MOV A,#3DH;輸入等號
        LCALL DATA_WRITTING
        LCALL BUZZER;響鈴一聲
        INC POSITION;計數次數加1
        MOV R0,#70H;將儲存空間指向70H
        LCALL COUNT;記錄并修改數據
        LCALL SIGN_SCAN;跳轉至SIGN_SCAN子程序
        MOV POSITION,#00H;初始化POSITION的地址
        MOV A,#80H;從第一行首地址重新點亮字碼
        LCALL COMMAND_WRITTING
EQUAL0:
        MOV R0,#70H;將儲存空間指向70H
        MOV R4,#30H;計數次數,此處的計數次數為最大計數空間,從70H一直到9FH
        RET_SET0:
                MOV @R0,#00H
                INC R0
                DJNZ R4,RET_SET0        
        MOV R0,#70H;將儲存空間指向70H
        MOV R1,#80H;將修改空間指向80H
        LJMP DISPLAY;返回至調用口
//執行清屏子程序
CLEAR:
        CJNE A,#0E7H,TEMP;查詢是否為清屏指令
        MOV A,#01H;清屏指令
        LCALL COMMAND_WRITTING
        MOV ANDS,#00H;初始化結果存儲
        MOV A,#80H;從第一行首地址重新點亮字碼
        LCALL COMMAND_WRITTING
        MOV A,#52H;輸入R
        LCALL DATA_WRITTING
        MOV A,#45H;輸入E
        LCALL DATA_WRITTING
        MOV A,#53H;輸入S
        LCALL DATA_WRITTING
        MOV A,#54H;輸入T
        LCALL DATA_WRITTING
        MOV A,#41H;輸入A
        LCALL DATA_WRITTING
        MOV A,#52H;輸入R
        LCALL DATA_WRITTING
        MOV A,#54H;輸入T
        LCALL DATA_WRITTING
        LCALL DELAY
        MOV A,#01H;清屏指令
        LCALL COMMAND_WRITTING
        MOV POSITION,#00H;初始化POSITION的地址
        MOV A,#80H;從第一行首地址重新點亮字碼
        LCALL COMMAND_WRITTING
        LCALL BUZZER;響鈴一聲
        LCALL BUZZER;響鈴兩聲
        MOV ANDS,#00H;初始結果儲存
        MOV R0,#70H
        MOV R4,#30H;計數次數
        RET_SET1:
                MOV @R0,#00H
                INC R0
                DJNZ R4,RET_SET1        
        MOV R0,#70H;將儲存空間指向70H
        MOV R1,#80H;將修改空間指向80H
        LJMP DISPLAY;返回至調用口
//打開單片機
ON_SET:
        MOV A,#0EH;打開顯示功能,有光標且光標不閃爍
        LCALL COMMAND_WRITTING
        MOV A,#57H;輸入W
        LCALL DATA_WRITTING
        MOV A,#45H;輸入E
        LCALL DATA_WRITTING
        MOV A,#4CH;輸入L
        LCALL DATA_WRITTING
        MOV A,#43H;輸入C
        LCALL DATA_WRITTING
        MOV A,#4FH;輸入O
        LCALL DATA_WRITTING
        MOV A,#4DH;輸入M
        LCALL DATA_WRITTING
        LCALL DELAY
        MOV A,#01H;清屏指令
        LCALL COMMAND_WRITTING
        RET
//關閉單片機
OFF_SET:
        MOV A,#01H;清屏指令
        LCALL COMMAND_WRITTING
        MOV A,#09H;關閉顯示功能,無光標且光標不閃爍
        LCALL COMMAND_WRITTING
        RET
//超過第一行最大顯示范圍報錯
RANGE:
        MOV A,POSITION;將當前顯示地址裝入A中
        CJNE A,#10H,NON_RANGE;判斷當前POSITION是否為10H,如果是則說明超過范圍,輸出RANGE并光標歸位
        MOV A,#01H;清屏指令
        LCALL COMMAND_WRITTING
        MOV A,#4FH;輸入O
        LCALL DATA_WRITTING
        MOV A,#46H;輸入F
        LCALL DATA_WRITTING
        MOV A,#46H;輸入F
        LCALL DATA_WRITTING
        MOV A,#20H;輸入空
        LCALL DATA_WRITTING
        MOV A,#52H;輸入R
        LCALL DATA_WRITTING
        MOV A,#41H;輸入A
        LCALL DATA_WRITTING
        MOV A,#4EH;輸入N
        LCALL DATA_WRITTING
         MOV A,#47H;輸入G
        LCALL DATA_WRITTING
        MOV A,#45H;輸入E
        LCALL DATA_WRITTING
        LCALL DELAY
        MOV A,#01H;清屏指令
        LCALL COMMAND_WRITTING
        MOV POSITION,#0FFH;初始化POSITION的地址
        MOV A,#80H;從第一行首地址重新點亮字碼
        LCALL COMMAND_WRITTING
        RET;返回調用程序處
//未超出范圍,跳轉至NON_RANGE
NON_RANGE:
        RET
//報錯程序
ERROR:
        MOV A,#01H;清屏指令
        LCALL COMMAND_WRITTING
        MOV A,#01H;清屏指令
        LCALL COMMAND_WRITTING
        MOV A,#45H;輸入E
        LCALL DATA_WRITTING
        MOV A,#52H;輸入R
        LCALL DATA_WRITTING
        MOV A,#52H;輸入R
        LCALL DATA_WRITTING
        MOV A,#4FH;輸入O
        LCALL DATA_WRITTING
        MOV A,#52H;輸入R
        LCALL DATA_WRITTING
        LCALL BUZZER;響鈴一聲
        LCALL BUZZER;響鈴一聲
        LCALL BUZZER;響鈴一聲
        LCALL LIGHT;閃爍
        LCALL DELAY
        MOV A,#01H;清屏指令
        LCALL COMMAND_WRITTING
        MOV POSITION,#0FFH;初始化POSITION的地址
        MOV A,#80H;從第一行首地址重新點亮字碼
        LCALL COMMAND_WRITTING
        LJMP EQUAL0;打斷執行        
/*LM016L的計算功能部分,該部分的功能包括:
        判斷并轉換數據格式,單次運算實現小數點后兩位,連續運算實現取整數,帶優先級*/
//記錄并修改數據,將輸入的數據字模轉換為包含十位與個位的數據形式,字符字模不變,由R0導入到R1中,eg:7+89→07+89
COUNT:
        MOV A,@R0;取出存儲的字模
        INC R0;R0的地址加1,進入下一個字模的地址
        AJMP DIGIT0
        DIGIT0:
                MOV TEMPORARY0,A;將LM016L顯示的字模送入TEMPORARY0中保護起來
                ANL A,#0F0H;屏蔽低四位,如果為30H說明是數據,如果為20H,說明是字符
                CJNE A,#20H,INTEGER0;判斷為數據轉移到INTEGER0
                MOV @R1,TEMPORARY0;存放字符
                INC R1;R1的地址加1
                DJNZ POSITION,COUNT;計數指針不為0,繼續執行
                AJMP INTEGER1
        INTEGER0:
                MOV A,@R0;取出下一個存儲的字模
                CJNE A,#00H,DIGIT1;下一個字符如果為空,說明為一位數
                AJMP ONE_DIGIT
        DIGIT1:
                MOV TEMPORARY1,A;將LM016L顯示的下一位字模送入TEMPORARY1中保護起來
                ANL A,#0F0H;屏蔽低四位,如果為30H說明是數據,如果為20H,說明是字符
                CJNE A,#20H,DIGIT2;判斷為數據轉移到DIGIT2
                AJMP ONE_DIGIT
        ONE_DIGIT:
                MOV @R1,#00H;百位為0
                INC R1;R1的地址加1
                MOV @R1,#00H;十位為0
                INC R1;R1的地址加1
                MOV A,TEMPORARY0;將數據取出
                ANL A,#0FH;屏蔽高四位,得出對應的顯示數字
                MOV @R1,A;個位為數
                INC R1;R1的地址加1
                DJNZ POSITION,COUNT;計數指針不為0,繼續執行
                AJMP INTEGER1
        DIGIT2:
                INC R0;R0的地址再次加1,跳過下一個數
                MOV A,@R0;將進位兩次后的地址賦給A
                MOV TEMPORARY2,A;將LM016L顯示的下下個字模送入TEMPORARY2中保護起來
                CJNE A,#00H,DIGIT3;下一個字符如果為空,說明為兩位數
                AJMP TWO_DIGIT                 
        DIGIT3:
                ANL A,#0F0H;屏蔽低四位,如果為30H說明是數據,如果為20H,說明是字符
                CJNE A,#20H,THREE_DIGIT;判斷為數據轉移到THREE_DIGIT
                AJMP TWO_DIGIT
        TWO_DIGIT:
                MOV @R1,#00H;百位為0
                INC R1;R1的地址加1
                MOV A,TEMPORARY0;將數據取出
                ANL A,#0FH;屏蔽高四位,得出對應的顯示數字
                MOV @R1,A;十位為數
                INC R1;R1的地址加1
                MOV A,TEMPORARY1;將數據取出
                ANL A,#0FH;屏蔽高四位,得出對應的顯示數字
                MOV @R1,A;個位為數
                INC R1;R1的地址加1
                DJNZ POSITION,COUNT;計數指針不為0,繼續執行
                AJMP INTEGER1
        THREE_DIGIT:
                MOV A,TEMPORARY0;將數據取出
                ANL A,#0FH;屏蔽高四位,得出對應的顯示數字
                MOV @R1,A;百位為數
                INC R1;R1的地址加1
                MOV A,TEMPORARY1;將數據取出
                ANL A,#0FH;屏蔽高四位,得出對應的顯示數字
                MOV @R1,A;十位為數
                INC R1;R1的地址加1
                MOV A,TEMPORARY2;將數據取出
                ANL A,#0FH;屏蔽高四位,得出對應的顯示數字
                MOV @R1,A;個位為數
                INC R1;R1的地址加1
                INC R0;R0的地址加1,跳過下一個數
                DJNZ POSITION,COUNT;計數指針不為0,繼續執行
                AJMP INTEGER1
        INTEGER1:
        RET
//從左往右,按優先級依次判斷執行運算操作類型
SIGN_SCAN:
//乘除計算
                MOV POINTER,#30H;記錄計數次數
                MOV R1,#80H;初始化地址
                MOV ANDS,#00H;初始化結果存儲
                AJMP SCAN0;隔離指令
        SCAN0:
                MOV A,@R1;傳送數據給A               
                INC R1;R1的地址加1
                MOV TEMPORARY5,A;保護數據
                ANL A,#0F0H;屏蔽低四位
                CJNE A,#20H,SIGN2;如果是20H,說明為符號,反之則返回
                AJMP RITE0
        RITE0:
                DEC R1;R1回退并指向符號         
                MOV A,TEMPORARY5;取出數據
                MOV B,#05;給B賦5
                ANL A,#0FH;屏蔽高四位
                DIV AB;商放在A,余數放在B
                MOV A,B;傳遞余數
                CJNE A,#00H,INSTRUCTION;如果余數為0,說明是乘除指令,如果余數不為0,說明是加減指令,返回
                AJMP INSTRUCTION0;隔離指令
        INSTRUCTION0:
                MOV A,TEMPORARY5;取出數據
                CJNE A,#2AH,SIGN0;乘法判別
                LCALL CALCULATE_MULTIPLICATION;跳轉乘法處理運算
                INC R1;地址指針加1
                AJMP SIGN2
        SIGN0:
                CJNE A,#2FH,SIGN2;除法判別
                LCALL CALCULATE_DIVISION;跳轉除法處理運算
                INC R1;地址指針加1
                AJMP SIGN2
        INSTRUCTION:
                INC R1;地址指針加1
                AJMP SIGN2
           SIGN2:
                DJNZ POINTER,SCAN0;指針減1不為0繼續計算

//加減計算
                MOV POINTER,#30H;記錄計數次數
                MOV R1,#80H;初始化地址
        SCAN3:
                MOV A,@R1;傳送數據給A               
                INC R1;R1的地址加1
                MOV TEMPORARY5,A;保護數據
                ANL A,#0F0H;屏蔽低四位
                CJNE A,#20H,SIGN4;如果是20H,說明為符號,反之則返回
                DEC R1;R1回退并指向符號         
                MOV A,TEMPORARY5;取出數據
                CJNE A,#2BH,SIGN3;加法判別
                LCALL CALCULATE_ADDITION;跳轉加法處理運算
                INC R1;地址指針加1
                AJMP SIGN4
        SIGN3:
                CJNE A,#2DH,SIGN4;減法判別
                LCALL CALCULATE_SUBTRACTION;跳轉減法處理運算
                INC R1;地址指針加1
                AJMP SIGN4
           SIGN4:
                DJNZ POINTER,SCAN3;指針減1不為0繼續計算
                LCALL RESULT
        RET
//加法子程序
CALCULATE_ADDITION:
        LCALL ANTI;轉換數據并放在DATA0與DATA1中
        MOV A,DATA0;將DATA0的數據存放在A中
        ADD A,DATA1;進行加法運算
        MOV ANDS,A;將加法計算的結果存儲在ANDS中
        LCALL SORT;重新排序        
        RET
//減法子程序
CALCULATE_SUBTRACTION:
        LCALL ANTI;轉換數據并放在DATA0與DATA1中
        MOV A,DATA0
        CLR C
        SUBB A,DATA1;DATA0減去DATA1
        JC NEGATIVE;判斷DATA0和DATA1的大小
        MOV ANDS,A;將減法計算的結果存儲在ANDS中
        LCALL SORT;重新排序        
        RET
//負數,用DATA1減去DATA0
NEGATIVE:
        LJMP ERROR;報錯
        RET
/*
NEGATIVE:
        MOV A,#2DH;輸入負號
        LCALL DATA_WRITTING
        MOV A,DATA1
        CLR C
        SUBB A,DATA0;用DATA1減去DATA0
        LCALL RESULT;調用RESULT來實現屏幕顯示
        MOV ANDS,A;將減法計算的結果存儲在ANDS中        
        LCALL SORT;重新排序        
        RET
*/
//乘法子程序
CALCULATE_MULTIPLICATION:
        LCALL ANTI;轉換數據
        MOV A,DATA0
        MOV B,DATA1
        CLR C
        MUL AB;乘法的結果,低八位儲存在A,高八位儲存在B
        MOV ANDS,A;將乘法計算的結果存儲在ANDS中
        LCALL SORT;重新排序               
        RET
//除法子程序
CALCULATE_DIVISION:
        LCALL ANTI;轉換數據
        MOV A,DATA1
        JZ RE0;判斷被除數是否為0
        AJMP RE1;
RE0:
        LCALL ERROR;報錯
RE1:
        MOV A,DATA0
        MOV B,DATA1
        DIV AB;商放在A,余數放在B
        MOV DATA3,B;保護數據
        MOV ANDS,A;將除法計算的結果保存在ANDS中,只儲存了整數位
        MOV B,DATA3;取出數據
        MOV A,B;將余數賦給A
//        CJNE A,#00H,REMAINDER0;判斷余數是否為零
        LCALL SORT;重新排序        
        RET
//余數不為0計算小數點后一位
/*        REMAINDER0:
                MOV DATA3,A;放置數據
                MOV A,#2EH;賦字模.
                LCALL DATA_WRITTING
                MOV A,DATA3;取出數據
                MOV B,#10
                MUL AB;余數乘以10
                MOV B,DATA1;將除數給B
                DIV AB;商放在A,余數放在B
                MOV DATA3,B;保護數據
                LCALL RESULT;調用RESULT來實現屏幕顯示
                MOV B,DATA3;取出數據
                MOV A,B;將余數賦給A        
                CJNE A,#00H,REMAINDER1
                RET
//余數不為0計算小數點后第二位
        REMAINDER1:
                MOV B,#10
                MUL AB;余數乘以10
                MOV B,DATA1;將除數給B
                DIV AB;商放在A,余數放在B
                LCALL RESULT;調用RESULT來實現屏幕顯示
                RET
*/

//移位程序,新數據左移覆蓋原有數據
SORT:
        MOV        TEMPORARY4,R0;保護R0的地址
        MOV R4,#20H;計數次數
        MOV A,ANDS;將計算結果的數據傳給A
        MOV B,#100;取百位
        DIV AB;A取商,B取余數
        MOV TEMPORARY5,A;保存百位
        MOV A,B;將余數傳給A
        MOV B,#10;取十位
        DIV AB;A取十位,B取個位
        MOV TEMPORARY6,A;保存十位
        MOV TEMPORARY7,B;保存個位
        DEC R1;R1的地址減1
        MOV @R1,TEMPORARY7
        DEC R1;R1的地址減1
        MOV @R1,TEMPORARY6
        DEC R1;R1的地址減1
        MOV @R1,TEMPORARY5
        MOV A,R1
        ADD A,#03H
        MOV R1,A;
        MOV TEMPORARY6,R1;新數據起始地址
        MOV A,R1
        ADD A,#04H
        MOV R0,A;
        MOV R1,TEMPORARY6;新數據起始地址
        AJMP SORT0;隔離指令
SORT0:
        MOV A,@R0;新的數據存儲地址中存儲的數據
        MOV @R1,A;覆蓋數據
        INC R0;新數據地址
        INC R1;原數據地址
        DJNZ R4,SORT0        
        MOV R0,TEMPORARY4;取出地址
        MOV R1,#80H;初始化R1
        RET        
//將計算結果進行顯示
RESULT:
        MOV A,ANDS;取出數據
        MOV DATA2,A;保護數據
        MOV B,#100;給B賦值100
        DIV AB;A為百位,B為十位和個位
        CJNE A,#00H,THREE_BIT;百位不為0,則為三位數,反之則為兩位數        
        MOV A,DATA2;取出數據
        MOV B,#10;給B賦值10
        DIV AB;A為十位,B為個位
        CJNE A,#00H,TWO_BIT;十位不為0,則為兩位數,反之則為一位數
        AJMP ONE_BIT;隔離電路
THREE_BIT:
        ADD A,#30H;百位轉換為字碼
        LCALL DATA_WRITTING
        MOV A,B;取出數據
        MOV B,#10;給B賦值10
        DIV AB;A為十位,B為個位
        ADD A,#30H;十位轉換為字碼
        LCALL DATA_WRITTING
        MOV A,B;傳遞個位
        ADD A,#30H;個位轉換為字碼
        LCALL DATA_WRITTING
        AJMP BIT0        
TWO_BIT:        
        ADD A,#30H;十位轉換為字碼
        LCALL DATA_WRITTING
        MOV A,B;傳遞個位
        ADD A,#30H;個位轉換為字碼
        LCALL DATA_WRITTING
        AJMP BIT0        
ONE_BIT:
        MOV A,B;傳遞個位
        ADD A,#30H;個位轉換為字碼
        LCALL DATA_WRITTING
        AJMP BIT0
BIT0:
        RET
//逆轉換數據格式,將十位與個位重新組合
ANTI:
        MOV B,#100
        DEC R1
        DEC R1
        DEC R1
        MOV A,@R1;記錄百位
        MUL AB;保留低八位
        MOV TEMPORARY0,A;將百位儲存
        INC R1
        MOV B,#10        
        MOV A,@R1;記錄十位
        MUL AB;保留低八位
        ADD A,TEMPORARY0;組合百位數和十位數
        CLR C;清除進位標志
        INC R1;進位至個位
        ADD A,@R1;組合數
        MOV DATA0,A;將值存放在DATA0中
        INC R1
        INC R1;進位至百位
        MOV A,@R1;記錄百位
        MOV B,#100
        MUL AB;保留低八位
        MOV TEMPORARY0,A;將百位儲存
        INC R1
        MOV B,#10        
        MOV A,@R1;記錄十位
        MUL AB;保留低八位
        ADD A,TEMPORARY0;組合百位數和十位數
        CLR C;清除進位標志
        INC R1;進位至個位
        ADD A,@R1;組合數
        MOV DATA1,A;將值存放在DATA1中
        DEC R1;
        DEC R1;
        DEC R1;回退至符號位
        RET
//鍵號對應的鍵碼表
KEYVALUE:
        DB  77H, 7BH, 7DH, 7EH;鍵碼0,1,2,3
        DB 0B7H,0BBH,0BDH,0BEH;鍵碼4,5,6,7
        DB 0D7H,0DBH,0DDH,0DEH;鍵碼8,9,10,11
        DB 0E7H,0EBH,0EDH,0EEH;鍵碼12,13,14,15
//鍵號對應的LM016L字碼表,AC與=賦00H,執行特殊操作
TABLE:;
        DB        37H,38H,39H,2BH;字碼7,8,9,+
        DB        34H,35H,36H,2DH;字碼4,5,6,-
        DB        31H,32H,33H,2AH;字碼1,2,3,*
         DB        00H,30H,00H,2FH;字碼AC(空),0,=(空),/
//延遲電路
DELAY:
        MOV R5,#10H;單周期指令
        DLY1:
                MOV R6,#10H;單周期指令
        DLY2:
                MOV R7,#248;單周期指令
                DJNZ R7,$;雙周期指令
                DJNZ R6,DLY2;雙周期指令
        DJNZ R5,DLY1;雙周期指令
        RET;雙周期指令
//LM016L設置寫的命令輸入模式
COMMAND_WRITTING:
        CLR RS;RS=0
        CLR RW;RW=0
        MOV P0,A;單片機傳遞數據給LM016L
        CLR E;E=0
        LCALL DELAY;等待上升沿數據輸入
        SETB E;E=1
        RET
//LM016L設置寫的數字輸入模式
DATA_WRITTING:
        SETB RS;RS=1
        CLR RW;RW=0
        MOV P0,A;單片機傳遞數據給LM016L
        CLR E;E=0
        LCALL DELAY;等待上升沿數據輸入
        SETB E;E=1
        RET
//蜂鳴器響鈴電路
BUZZER:
        LCALL DELAY
        MOV R4,#64H
BUZZER0:
           SETB BR;開啟蜂鳴器
           CLR BR;關閉蜂鳴器
        DJNZ R4,BUZZER0;震蕩電路
        LCALL DELAY
        RET

//LED閃爍
LIGHT:
        LCALL DELAY
        CLR LED;打開LED
        LCALL DELAY
        SETB LED;關閉LED
        RET
END

01.7z

150.3 KB, 下載次數: 11

基于普中A2的仿真

回復

使用道具 舉報

ID:1085458 發表于 2023-7-2 20:40 | 顯示全部樓層
該計算器是8位計算器,輸出結果范圍為0—255,輸入的數據兩位正數或一位正數,無法進行負數計算,除法保留整數部分,程序中無輸入數據和符號的格式是否正確的判定,在輸入錯誤的情況下會出現錯誤的結果
回復

使用道具 舉報

ID:1085458 發表于 2023-7-2 20:47 | 顯示全部樓層
該程序的計算器針對的是輸入數據為正數,輸入輸出的結果不能超過255,否則會溢出,出現錯誤的輸出結果,具有的功能為帶優先級的加減乘除運算,輸入的字符顯示在第一行,超過16個字符會顯示“OFF RANGE”字樣,結果在按下等號后,輸出在下一行,按下“AC”鍵清零,屏幕出現“RESTART”并清零,當計算結果有負數或除法除以0時,提示“ERROR”并清零,按下“ON”鍵,開機,顯示“WELCOM”,按下“OFF”,關機
回復

使用道具 舉報

ID:1085458 發表于 2023-7-2 20:57 | 顯示全部樓層
BAKELOR 發表于 2023-7-2 20:40
該計算器是8位計算器,輸出結果范圍為0—255,輸入的數據兩位正數或一位正數,無法進行負數計算,除法保留 ...

如果想讓仿真中的蜂鳴器響,可以把無源蜂鳴器speaker替換為有源蜂鳴器,連線不變,并修改蜂鳴器的子程序為延時加高電平加延時加低電平即可,不過延時過短會無法區別多次蜂鳴
回復

使用道具 舉報

ID:1085458 發表于 2023-7-6 20:38 | 顯示全部樓層
BAKELOR 發表于 2023-7-2 20:40
該計算器是8位計算器,輸出結果范圍為0—255,輸入的數據兩位正數或一位正數,無法進行負數計算,除法保留 ...

如果把數據轉化的格式由原來的“百位,十位,個位”轉換為“符號位,百位,十位,個位”的形式,可以進行帶符號的運算,更進一步,可以把整數部分和小數部分轉換分開計算加減乘除,最后將和相加的方式完成帶小數的運算。與此同時,計算相關的程序都需要相關更改
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表