找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 1918|回復(fù): 4
收起左側(cè)

基于51單片機(jī)實(shí)現(xiàn)的匯編語(yǔ)言的帶優(yōu)先級(jí)計(jì)算的簡(jiǎn)易計(jì)算器 帶優(yōu)先級(jí),蜂鳴器存在些許問(wèn)題

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

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

//移位程序,新數(shù)據(jù)左移覆蓋原有數(shù)據(jù)
SORT:
        MOV        TEMPORARY4,R0;保護(hù)R0的地址
        MOV R4,#20H;計(jì)數(shù)次數(shù)
        MOV A,ANDS;將計(jì)算結(jié)果的數(shù)據(jù)傳給A
        MOV B,#100;取百位
        DIV AB;A取商,B取余數(shù)
        MOV TEMPORARY5,A;保存百位
        MOV A,B;將余數(shù)傳給A
        MOV B,#10;取十位
        DIV AB;A取十位,B取個(gè)位
        MOV TEMPORARY6,A;保存十位
        MOV TEMPORARY7,B;保存?zhèn)位
        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;新數(shù)據(jù)起始地址
        MOV A,R1
        ADD A,#04H
        MOV R0,A;
        MOV R1,TEMPORARY6;新數(shù)據(jù)起始地址
        AJMP SORT0;隔離指令
SORT0:
        MOV A,@R0;新的數(shù)據(jù)存儲(chǔ)地址中存儲(chǔ)的數(shù)據(jù)
        MOV @R1,A;覆蓋數(shù)據(jù)
        INC R0;新數(shù)據(jù)地址
        INC R1;原數(shù)據(jù)地址
        DJNZ R4,SORT0        
        MOV R0,TEMPORARY4;取出地址
        MOV R1,#80H;初始化R1
        RET        
//將計(jì)算結(jié)果進(jìn)行顯示
RESULT:
        MOV A,ANDS;取出數(shù)據(jù)
        MOV DATA2,A;保護(hù)數(shù)據(jù)
        MOV B,#100;給B賦值100
        DIV AB;A為百位,B為十位和個(gè)位
        CJNE A,#00H,THREE_BIT;百位不為0,則為三位數(shù),反之則為兩位數(shù)        
        MOV A,DATA2;取出數(shù)據(jù)
        MOV B,#10;給B賦值10
        DIV AB;A為十位,B為個(gè)位
        CJNE A,#00H,TWO_BIT;十位不為0,則為兩位數(shù),反之則為一位數(shù)
        AJMP ONE_BIT;隔離電路
THREE_BIT:
        ADD A,#30H;百位轉(zhuǎn)換為字碼
        LCALL DATA_WRITTING
        MOV A,B;取出數(shù)據(jù)
        MOV B,#10;給B賦值10
        DIV AB;A為十位,B為個(gè)位
        ADD A,#30H;十位轉(zhuǎn)換為字碼
        LCALL DATA_WRITTING
        MOV A,B;傳遞個(gè)位
        ADD A,#30H;個(gè)位轉(zhuǎn)換為字碼
        LCALL DATA_WRITTING
        AJMP BIT0        
TWO_BIT:        
        ADD A,#30H;十位轉(zhuǎn)換為字碼
        LCALL DATA_WRITTING
        MOV A,B;傳遞個(gè)位
        ADD A,#30H;個(gè)位轉(zhuǎn)換為字碼
        LCALL DATA_WRITTING
        AJMP BIT0        
ONE_BIT:
        MOV A,B;傳遞個(gè)位
        ADD A,#30H;個(gè)位轉(zhuǎn)換為字碼
        LCALL DATA_WRITTING
        AJMP BIT0
BIT0:
        RET
//逆轉(zhuǎn)換數(shù)據(jù)格式,將十位與個(gè)位重新組合
ANTI:
        MOV B,#100
        DEC R1
        DEC R1
        DEC R1
        MOV A,@R1;記錄百位
        MUL AB;保留低八位
        MOV TEMPORARY0,A;將百位儲(chǔ)存
        INC R1
        MOV B,#10        
        MOV A,@R1;記錄十位
        MUL AB;保留低八位
        ADD A,TEMPORARY0;組合百位數(shù)和十位數(shù)
        CLR C;清除進(jìn)位標(biāo)志
        INC R1;進(jìn)位至個(gè)位
        ADD A,@R1;組合數(shù)
        MOV DATA0,A;將值存放在DATA0中
        INC R1
        INC R1;進(jìn)位至百位
        MOV A,@R1;記錄百位
        MOV B,#100
        MUL AB;保留低八位
        MOV TEMPORARY0,A;將百位儲(chǔ)存
        INC R1
        MOV B,#10        
        MOV A,@R1;記錄十位
        MUL AB;保留低八位
        ADD A,TEMPORARY0;組合百位數(shù)和十位數(shù)
        CLR C;清除進(jìn)位標(biāo)志
        INC R1;進(jìn)位至個(gè)位
        ADD A,@R1;組合數(shù)
        MOV DATA1,A;將值存放在DATA1中
        DEC R1;
        DEC R1;
        DEC R1;回退至符號(hào)位
        RET
//鍵號(hào)對(duì)應(yīng)的鍵碼表
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
//鍵號(hào)對(duì)應(yīng)的LM016L字碼表,AC與=賦00H,執(zhí)行特殊操作
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設(shè)置寫的命令輸入模式
COMMAND_WRITTING:
        CLR RS;RS=0
        CLR RW;RW=0
        MOV P0,A;單片機(jī)傳遞數(shù)據(jù)給LM016L
        CLR E;E=0
        LCALL DELAY;等待上升沿?cái)?shù)據(jù)輸入
        SETB E;E=1
        RET
//LM016L設(shè)置寫的數(shù)字輸入模式
DATA_WRITTING:
        SETB RS;RS=1
        CLR RW;RW=0
        MOV P0,A;單片機(jī)傳遞數(shù)據(jù)給LM016L
        CLR E;E=0
        LCALL DELAY;等待上升沿?cái)?shù)據(jù)輸入
        SETB E;E=1
        RET
//蜂鳴器響鈴電路
BUZZER:
        LCALL DELAY
        MOV R4,#64H
BUZZER0:
           SETB BR;開(kāi)啟蜂鳴器
           CLR BR;關(guān)閉蜂鳴器
        DJNZ R4,BUZZER0;震蕩電路
        LCALL DELAY
        RET

//LED閃爍
LIGHT:
        LCALL DELAY
        CLR LED;打開(kāi)LED
        LCALL DELAY
        SETB LED;關(guān)閉LED
        RET
END

01.7z

150.3 KB, 下載次數(shù): 11

基于普中A2的仿真

回復(fù)

使用道具 舉報(bào)

ID:1085458 發(fā)表于 2023-7-2 20:40 | 顯示全部樓層
該計(jì)算器是8位計(jì)算器,輸出結(jié)果范圍為0—255,輸入的數(shù)據(jù)兩位正數(shù)或一位正數(shù),無(wú)法進(jìn)行負(fù)數(shù)計(jì)算,除法保留整數(shù)部分,程序中無(wú)輸入數(shù)據(jù)和符號(hào)的格式是否正確的判定,在輸入錯(cuò)誤的情況下會(huì)出現(xiàn)錯(cuò)誤的結(jié)果
回復(fù)

使用道具 舉報(bào)

ID:1085458 發(fā)表于 2023-7-2 20:47 | 顯示全部樓層
該程序的計(jì)算器針對(duì)的是輸入數(shù)據(jù)為正數(shù),輸入輸出的結(jié)果不能超過(guò)255,否則會(huì)溢出,出現(xiàn)錯(cuò)誤的輸出結(jié)果,具有的功能為帶優(yōu)先級(jí)的加減乘除運(yùn)算,輸入的字符顯示在第一行,超過(guò)16個(gè)字符會(huì)顯示“OFF RANGE”字樣,結(jié)果在按下等號(hào)后,輸出在下一行,按下“AC”鍵清零,屏幕出現(xiàn)“RESTART”并清零,當(dāng)計(jì)算結(jié)果有負(fù)數(shù)或除法除以0時(shí),提示“ERROR”并清零,按下“ON”鍵,開(kāi)機(jī),顯示“WELCOM”,按下“OFF”,關(guān)機(jī)
回復(fù)

使用道具 舉報(bào)

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

如果想讓仿真中的蜂鳴器響,可以把無(wú)源蜂鳴器speaker替換為有源蜂鳴器,連線不變,并修改蜂鳴器的子程序?yàn)檠訒r(shí)加高電平加延時(shí)加低電平即可,不過(guò)延時(shí)過(guò)短會(huì)無(wú)法區(qū)別多次蜂鳴
回復(fù)

使用道具 舉報(bào)

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

如果把數(shù)據(jù)轉(zhuǎn)化的格式由原來(lái)的“百位,十位,個(gè)位”轉(zhuǎn)換為“符號(hào)位,百位,十位,個(gè)位”的形式,可以進(jìn)行帶符號(hào)的運(yùn)算,更進(jìn)一步,可以把整數(shù)部分和小數(shù)部分轉(zhuǎn)換分開(kāi)計(jì)算加減乘除,最后將和相加的方式完成帶小數(shù)的運(yùn)算。與此同時(shí),計(jì)算相關(guān)的程序都需要相關(guān)更改
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表