;硬件端口
PortDigPS EQU P0 ;数码管段选硬件端口
PortDigCS EQU P2 ;数码管位选硬件端口
PortKB EQU P1 ;键盘输入硬件端口
;数码管使能
Dig4EN EQU 0x01 ;数码管1使能
Dig3EN EQU 0x02 ;数码管2使能
Dig2EN EQU 0x04 ;数码管3使能
Dig1EN EQU 0x08 ;数码管4使能
DigClose EQU 0x00 ;数码管关闭使能
DigValueNegative EQU 0x10 ;负号
;数码管值存储地址
Dig1Value EQU 0x10 ;数码管1值
Dig2Value EQU 0x11 ;数码管2值
Dig3Value EQU 0x12 ;数码管3值
Dig4Value EQU 0x13 ;数码管4值
;按键输入
KeyValue EQU 0x14 ;键值
;特殊键值
KeyNull EQU 0xFF ;错误键值,立即数
;计算用变量
Operator EQU 0x15 ;运算符
OperandA EQU 0x16 ;操作数A
OperandB EQU 0x17 ;操作数B
ResultC EQU 0x18 ;结果C
;状态变量
StateWord EQU 0x20 ;标志字
StateError EQU 0x20.0 ;错误标志
StateNegative EQU 0x20.1 ;负数标志
StateOperandB EQU 0x20.2 ;当前输入操作数B
;操作符常量,与键值对应
OperatorAdd EQU 0x0A
OperatorSub EQU 0x0B
OperatorMul EQU 0x0C
OperatorDiv EQU 0x0D
;代码
ORG 0x0000
AJMP Start
;数码管显示函数
;参数:Dig1Value、Dig2Value、Dig3Value、Dig4Value
DigitalDisplay:
PUSH ACC
MOV DPTR,#DigitalTubeValue ;加载数码管显示内容地址
;显示数码管1
MOV PortDigPS,#0x00 ;清空之前的显示
MOV A,Dig1Value
MOVC A,@A+DPTR
MOV PortDigCS,#Dig1EN
MOV PortDigPS,A
;显示数码管2
MOV PortDigPS,#0x00
MOV A,Dig2Value
MOVC A,@A+DPTR
MOV PortDigCS,#Dig2EN
MOV PortDigPS,A
;显示数码管3
MOV PortDigPS,#0x00
MOV A,Dig3Value
MOVC A,@A+DPTR
MOV PortDigCS,#Dig3EN
MOV PortDigPS,A
;显示数码管4
MOV PortDigPS,#0x00
MOV A,Dig4Value
MOVC A,@A+DPTR
MOV PortDigCS,#Dig4EN
MOV PortDigPS,A
POP ACC
RET
;关闭数码管显示函数
DigitalClose:
MOV PortDigCS,#DigClose
RET
;矩阵键盘扫描函数,行列翻转法
;获取到的键值送入KeyValue,没有按键按下送入KeyNull
KeyBoardScan:
PUSH PSW
PUSH DPH
PUSH DPL
PUSH ACC
PUSH B
;PortKB 7-Row3,Row2,Row1,Row0,Col3,Col2,Col1,Col0-0
ReadRowValue:
MOV PortKB,#0xF0
MOV A,PortKB
CJNE A,#0xF0,ReadColValue ;A不为0xF0,认为有按键被按下
SJMP KeyBoardScanNull
ReadColValue:
MOV B,A
ORL A,#0x0F
MOV PortKB,A
MOV A,PortKB
GetKeyValue:
MOV DPTR,#KeyBoardValue
ANL A,#0x0F
ORL B,A ;键值
MOV R2,#0x00 ;计数器
SearchKeyValueTable:
MOV A,R2
MOVC A,@A+DPTR
CJNE A,B,KeyValueAdd
MOV KeyValue,R2 ;写键值
WaitKeyRelease: ;等待按键松开
MOV PortKB,#0xF0
MOV A,PortKB
CJNE A,#0xF0,WaitKeyRelease
SJMP KeyBoardScanFinish
KeyValueAdd:
INC R2
CJNE R2,#0x10,SearchKeyValueTable ;键值大于等于0x10,发生错误,KeyValue设置为0xFF,然后直接返回
KeyBoardScanNull:
MOV KeyValue,#KeyNull ;设置错误键值
KeyBoardScanFinish:
POP B
POP ACC
POP DPL
POP DPH
POP PSW
RET
;清除
ClearEntity:
MOV Dig1Value,#0
MOV Dig2Value,#0
MOV Dig3Value,#0
MOV Dig4Value,#0
MOV Operator,#0x00
MOV OperandA,#0x00
MOV OperandB,#0x00
MOV ResultC,#0x00
MOV StateWord,#0x00
RET
;数码管显示数字
;参数:ACC
DigitDisplayNumber:
;清除原来的显示
MOV Dig1Value,#0
MOV Dig2Value,#0
MOV Dig3Value,#0
MOV Dig4Value,#0
PUSH ACC
PUSH B
MOV B,#10
DIV AB
MOV Dig4Value,B
MOV B,#10
DIV AB
MOV Dig3Value,B
MOV B,#10
DIV AB
MOV Dig2Value,B
POP B
POP ACC
RET
;测试1
Test1:
MOV SP,#0x40 ;重设堆栈指针,防止覆盖数据
Loop:
CALL DigitalClose ;数码管关显示
CALL KeyBoardScan ;扫描矩阵键盘
;根据键值进行操作
MOV A,KeyValue
CJNE A,#KeyNull,KVJudge1
SJMP KVIsNull ;A==KeyNull
KVJudge1:
CJNE A,#0x09,KVJudge2
SJMP KVIsNumber ;A==0x09
KVJudge2:
JC KVIsNumber ;A <0x09
CJNE A,#0x0D,KVJudge3
SJMP KVIsOperator ;A==0x0D
KVJudge3:
JC KVIsOperator ;A==any(0x0A,0x0B,0x0C)
CJNE A,#0x0E,KVJudge4
SJMP KVIsCE ;A==0x0E
KVJudge4:
CJNE A,#0x0F,KVIsNull
SJMP KVIsEqual ;A==0x0F
;空值类型操作
KVIsNull:
AJMP LoopFinish
;数字类型操作
KVIsNumber:
JB StateOperandB,OperandBInput
OperandAInput: ;操作数A输入
MOV A,OperandA
MOV B,#10
MUL AB
ADD A,KeyValue
MOV OperandA,A
CALL DigitDisplayNumber ;设置显示数字
SJMP LoopFinish
OperandBInput: ;操作数B输入
MOV A,OperandB
MOV B,#10
MUL AB
ADD A,KeyValue
MOV OperandB,A
CALL DigitDisplayNumber ;设置显示数字
SJMP LoopFinish
;运算符类型操作
KVIsOperator:
MOV Operator,KeyValue
SETB StateOperandB ;置操作数为B
SJMP LoopFinish
;清空类型操作
KVIsCE:
CALL ClearEntity
SJMP LoopFinish
;等于类型操作
KVIsEqual:
MOV A,Operator
CJNE A,#OperatorAdd,IsItSub
SJMP CalculateAdd
IsItSub:
CJNE A,#OperatorSub,IsItMul
SJMP CalculateSub
IsItMul:
CJNE A,#OperatorMul,CalculateDiv
SJMP CalculateMul
CalculateAdd:
CLR C
MOV A,OperandA
MOV B,OperandB
ADDC A,B
MOV ResultC,A
SJMP CalculateFinish
CalculateSub:
CLR C
MOV A,OperandA
MOV B,OperandB
SUBB A,B
MOV ResultC,A
SJMP CalculateFinish
CalculateMul:
CLR C
MOV A,OperandA
MOV B,OperandB
MUL AB
MOV ResultC,A
SJMP CalculateFinish
CalculateDiv:
CLR C
MOV A,OperandA
MOV B,OperandB
DIV AB
MOV ResultC,A
SJMP CalculateFinish
CalculateFinish:
;结果显示
MOV A,ResultC
CALL DigitDisplayNumber ;设置显示数字
LoopFinish:
CALL DigitalDisplay ;显示
AJMP Loop
RET
Test2:
MOV P0,#0xFF
MOV P2,#00000011B
SJMP $
RET
;程序入口
Start:
CALL Test1
;数码管值0~9、A~H对应值
DigitalTubeValue:
DB 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F ;0~9,编码0x00~0x09
DB 0x77,0x7C,0x39,0x5E,0x79,0x71,0x3D,0x76 ;A~H,编码0x0A~0x0H
DB 0x40 ;'-'
;按键值
KeyBoardValue:
DB 0x77,0x7B,0x7D,0x7E ;Row3 7
DB 0xB7,0xBB,0xBD,0xBE ;Row2 B
DB 0xD7,0xDB,0xDD,0xDE ;Row1 D
DB 0xE7,0xEB,0xED,0xEE ;Row0 E
; Col3 Col2 Col1 Col0
; 7 B D E
END
参考接线图,仿真与代码不对应,部分信号有效性需要修改
单片机课设写的计算器,51汇编,键盘扫描有点儿问题,没加延时消抖。
做个课设还被怀疑抄袭就离谱,是代码写得太整洁了还是注释加的太多了???