⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 19计算器.asm

📁 学习单片机的程序与电路
💻 ASM
📖 第 1 页 / 共 2 页
字号:
PUB_SHORT_BCD1_A:
		MOV	A,@R0
		SWAP	A
		ANL	A,#0F0H
		INC	R0
		MOV	B,@R0
		ANL	B,#0FH
		ORL	A,B
		MOV	@R1,A
		INC	R0
		INC	R1
		DEC	KEY_LEN
		DJNZ	KEY_LEN,PUB_SHORT_BCD1_A
		POP	KEY_LEN
		MOV	A,KEY_LEN
		JNB	ACC.0,PUB_SHORT_BCD1_B
		INC	A			;是奇数则长度加1再除以2
PUB_SHORT_BCD1_B:
		CLR	C
		RRC	A			;转换后的长度为KEY_LEN除以2
		MOV	R7,A			
		RET
PUB_SHORT_BCD1_C:
		POP	KEY_LEN
		MOV	R7,#1
		RET

;------------------------------------------
;将压缩BCD码转换为非压缩BCD码
;入口:
;	R0	:压缩BCD码数据源地址(前256B)
;	R7	:压缩BCD码长度 
;	KEY_BUF	:非压缩BCD码目标地址(默认)
;出口:	KEY_BUF KEY_LEN
;------------------------------------------
PUB_LONG_BCD:	
		MOV	R1,#KEY_BUF
		MOV	A,R7
		RL	A					
		MOV	KEY_LEN,A		;转换后的长度为R7乘以2
PUB_LONG_BCD1_A:	
		MOV	A,@R0			;取数
		SWAP	A
		ANL	A,#0FH
		MOV	@R1,A			;高位十进制数转换完毕
		INC	R1			;目标地址加1
		MOV	A,@R0
		ANL	A,#0FH
		MOV	@R1,A			;低位十进制数转换完毕
		INC	R0			;源地址加1
		INC	R1
		DJNZ	R7,PUB_LONG_BCD1_A
		RET
;------------------------------------
;清除指定的RAM单元
;入口:	R0:源地址 R7:长度
;------------------------------------
PUB_CLEAR_RAM1:
		CJNE 	R7,#0,PUB_CLEAR_RAM1_1
		SJMP 	PUB_CLEAR_RAM1_E
PUB_CLEAR_RAM1_1:
		MOV 	@R0,#0
		INC 	R0
		DJNZ 	R7,PUB_CLEAR_RAM1_1
PUB_CLEAR_RAM1_E:
		RET
;----------------------------------------
;在前256B内使源串数据右对齐到目标串
;R0:源串首地址   R1:目标串尾地址 R7:长度
;要求:R1>R0+R7
;------------------------------------------
PUB_MOV_RAM_R:	
		PUSH	ACC
		MOV	A,R7
		JZ	PUB_MOV_RAM_R1A
		MOV	A,R0
		ADD	A,R7
		DEC	A
		MOV	R0,A
PUB_MOV_RAM_R1B:
		MOV	A,@R0
		MOV	@R1,A
		DEC	R0
		DEC	R1
		DJNZ	R7,PUB_MOV_RAM_R1B
PUB_MOV_RAM_R1A:	
		POP	ACC
		RET
;--------------------------------------
;前256B RAM空间数据串移动:
;入口:	R0:源地址  R1:目标地址 R7:长度
;--------------------------------------
PUB_MOV_RAM11:	
		PUSH ACC
		CJNE R7,#0,PUB_MOV_RAM11_0
		SJMP PUB_MOV_RAM11_E
PUB_MOV_RAM11_0:
		MOV A,@R0
		MOV @R1,A
		INC R0
		INC R1
		DJNZ R7,PUB_MOV_RAM11_0
PUB_MOV_RAM11_E:
		POP ACC
		RET
;--------------------------------
;发送一字节数据
;入口:ACC
;--------------------------------
LED_DISP_BYTE:
		PUSH	ACC
		CLR	LED_SCL
		MOV	R7,#8
LED_DISP_BYTE1:	
		RLC	A
		MOV	LED_SDA,C
		NOP
		NOP
		SETB	LED_SCL
		NOP
		NOP
		CLR	LED_SCL
		DJNZ	R7,LED_DISP_BYTE1
		POP	ACC
		RET
;---------------------------------------------
;右对齐显示LED_DIS_BUF缓冲区中的非压缩BCD数据
;入口:	LED_DIS_BUF:起始地址
;	DIS_LEN:显示长度
;----------------------------------------------
LED_DISP_DATA:
		PUSH	PSW
		PUSH	ACC
		PUSH	DPH
		PUSH	DPL
		MOV	PSW,#BANK2_REG
		
		MOV	A,#LED_DIS_BUF
		ADD	A,DIS_LEN
		DEC	A
		MOV	R0,A
		MOV	R6,DIS_LEN
		MOV	DPTR,#DIS_TAB
LED_DISP_DATA_A:
		MOV	A,@R0
		ANL	A,#0FH
		MOVC	A,@A+DPTR
		LCALL	LED_DISP_BYTE
		DEC	R0
		DJNZ	R6,LED_DISP_DATA_A
		
		MOV	A,#MAX_DATA_LEN
		CLR	C
		SUBB	A,DIS_LEN
		JZ	LED_DISP_DATA_END
		MOV	R6,A
		MOV	A,#0FFH
LED_DISP_DATA_B:
		LCALL	LED_DISP_BYTE
		DJNZ	R6,LED_DISP_DATA_B
LED_DISP_DATA_END:
		POP	DPL
		POP	DPH
		POP	ACC
		POP	PSW
		RET
;------------------------------------
;清除LED上的显示内容
;------------------------------------
LED_CLR_FULL:
		PUSH	PSW
		PUSH	ACC
		PUSH	DPH
		PUSH	DPL
		MOV	PSW,#BANK2_REG
		MOV	R6,#6
LED_CLR_A:
		MOV	A,#0FFH
		LCALL	LED_DISP_BYTE
		DJNZ	R6,LED_CLR_A
		POP	DPL
		POP	DPH
		POP	ACC
		POP	PSW
		RET
;----------------------------------------------------------------------
DIS_TAB:	;字形表
		DB	0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,88H,83H,0C6H,0A1H,86H,8EH,0FFH	;共阳极LED
		DB	3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,77H,7CH,39H,5EH,79H,71H,00H	;共阴极LED
NOP9:
		NOP
		NOP
		NOP
		NOP
		NOP
		NOP
		NOP
		RET
;--------------------------------
;键盘扫描子程序
;键盘连接方式:	P1.0-P1.3:KR1-KR4
;		P1.4-P1.7:KC1-KC4
;入口:	无
;出口:	A(所扫描到的逻辑键值K0-K12)
;使用:	第1组寄存器
;--------------------------------
KEY_SCAN:	
		PUSH 	PSW
		PUSH 	DPH
		PUSH 	DPL
		MOV	PSW,#BANK1_REG		;选择使用第1组寄存器(0-3)
;---------------------------------------
		CLR	K_DIGIT_FLAG
		CLR	K_CLR_FLAG
		CLR	K_DEL_FLAG
		CLR	K_ADD_FLAG
		CLR	K_SUB_FLAG
		CLR	K_ENT_FLAG
		CLR	K_ESC_FLAG
;---------------------------------------
KEY_SCAN_A:	
		ANL	P1,#0FH			;P1口高4位置低,所有键的列线为低
		MOV	A,P1
		ANL	A,#KEY_ROW_MASK
		XRL	A,#KEY_ROW_MASK
		JZ	KEY_SCAN_A		;快速键判断
		MOV	KEY_COL,#0EFH
		MOV	R7,#KEY_COLS
KEY_SCAN_B:
		ORL	P1,#0F0H
		MOV	A,KEY_COL
		ANL	P1,A			;将列逐个设置为低
		NOP
		NOP
		NOP
		MOV	A,P1			;从低4位读进行值
		ANL	A,#KEY_ROW_MASK
		MOV	KEY_ROW,A
		CJNE	A,#KEY_ROW_MASK,KEY_SCAN_C
		MOV	A,KEY_COL
		RL	A
		MOV	KEY_COL,A
		DJNZ	R7,KEY_SCAN_B
		LJMP	KEY_SCAN_A
KEY_SCAN_C:	
		LCALL	KEY_READ_DELAY
		MOV	A,P1			;从低4位读进行值
		ANL	A,#KEY_ROW_MASK
		XRL	A,#KEY_ROW_MASK
		JZ	KEY_SCAN_A		;确定是否真的有键被按下
KEY_SCAN_C1:	
		MOV	A,P1			;从低4位读进行值
		ANL	A,#KEY_ROW_MASK
		CJNE	A,#KEY_ROW_MASK,KEY_SCAN_C1	;是否键释放了
		LCALL	KEY_READ_DELAY
		MOV	A,P1
		ANL	A,#KEY_ROW_MASK
		XRL	A,#KEY_ROW_MASK
		JNZ	KEY_SCAN_C1
;-------------------------------------------------
		MOV	R3,#0			;R3用于计算行值
		MOV	R2,#KEY_ROWS		;检测行值的循环次数
		MOV	A,KEY_ROW
KEY_SCAN_D1:	
		RRC	A
		JNC	KEY_SCAN_D2		;行值不为零则使行值加上1
		INC	R3			;计算行值
		DJNZ	R2,KEY_SCAN_D1
KEY_SCAN_D2:
		MOV	R4,#0			;R4用于计算列值
		MOV	R2,#KEY_COLS
		MOV	A,KEY_COL
		SWAP	A
KEY_SCAN_D3:	
		RRC	A
		JNC	KEY_SCAN_D4
		INC	R4			;计算列值
		DJNZ	R2,KEY_SCAN_D3
KEY_SCAN_D4:	
		MOV	A,R3
		RL	A
		RL	A			;列值左移2次
		ORL	A,R4			;取出行值与列值相或
;---------------------------------------------------
		MOV	DPTR,#KEY_VAL_TAB
		MOVC	A,@A+DPTR		;把物理键值变成逻辑键值
		MOV	R0,A			;保存键值
		RL	A
		RL	A			;乘以4
		MOV	DPTR,#KEY_SET_FLAG
		JMP	@A+DPTR
KEY_SET_FLAG:	
		SETB 	K_DIGIT_FLAG
		SJMP 	KEY_SCAN_END				;0
;-----------------------------------------------------
		SETB 	K_DIGIT_FLAG
		SJMP 	KEY_SCAN_END				;1
;-----------------------------------------------------
		SETB 	K_DIGIT_FLAG
		SJMP 	KEY_SCAN_END				;2
;-----------------------------------------------------
		SETB 	K_DIGIT_FLAG
		SJMP 	KEY_SCAN_END				;3
;-----------------------------------------------------
		SETB 	K_DIGIT_FLAG
		SJMP 	KEY_SCAN_END				;4
;-----------------------------------------------------
		SETB 	K_DIGIT_FLAG
		SJMP 	KEY_SCAN_END				;5
;-----------------------------------------------------
		SETB 	K_DIGIT_FLAG
		SJMP 	KEY_SCAN_END				;6
;-----------------------------------------------------
		SETB 	K_DIGIT_FLAG
		SJMP 	KEY_SCAN_END				;7
;-----------------------------------------------------
		SETB 	K_DIGIT_FLAG
		SJMP 	KEY_SCAN_END				;8
;-----------------------------------------------------
		SETB 	K_DIGIT_FLAG
		SJMP 	KEY_SCAN_END				;9
;-----------------------------------------------------
		SETB 	K_CLR_FLAG
		SJMP 	KEY_SCAN_END
;-----------------------------------------------------
		SETB 	K_DEL_FLAG
		SJMP 	KEY_SCAN_END
;-----------------------------------------------------
		SETB 	K_ADD_FLAG
		SJMP 	KEY_SCAN_END
;-----------------------------------------------------
		SETB 	K_SUB_FLAG
		SJMP 	KEY_SCAN_END
;-----------------------------------------------------
		SETB 	K_ENT_FLAG
		SJMP 	KEY_SCAN_END
;-----------------------------------------------------
		SETB	K_ESC_FLAG
KEY_SCAN_END:	
		MOV 	A,R0		;ACC 键值返回
		POP 	DPL
		POP 	DPH
		POP 	PSW
		RET
;---------------------------------
KEY_VAL_TAB:		;键值表 当需要时可更改此表 实现不同的按键排列
		DB	K7
		DB	K8
		DB	K9
		DB	K_ESC
;---------------------------------
		DB	K4
		DB	K5
		DB	K6
		DB	K_CLR
;---------------------------------
		DB	K1
		DB	K2
		DB	K3
		DB	K_DEL
;---------------------------------
		DB	K0
		DB	K_ENT
		DB	K_ADD
		DB	K_SUB
;--------------------------------------------
;延时10MS消除按键抖动
;--------------------------------------------
KEY_READ_DELAY:	
		MOV	A,#10
KEY_READ_DEY_A:
		LCALL	PUB_DELAY_1MS
		DEC	A
		JNZ	KEY_READ_DEY_A
		RET
;--------------------------------------------
;延时1ms
;--------------------------------------------
PUB_DELAY_1MS:
		PUSH   ACC
		CLR    A
PD1_0:
		NOP
		INC    A
		CJNE   A,#0E4H,PD1_0	    ;#E4H = 228D
		POP    ACC
		RET
		END

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -