道清
发表于 2025-8-26 08:38:35
其他我多看的懂,也知道逻辑。就是这部分的逻辑我想不通,方便的话能详细解释吗?
谢谢
PROCESS_HIGH:
MOV A, R6
JZ PROCESS_LOW; 高8位为0且低8位<10,处理最后一位
; 高8位减1,补充十位25和个位6
DEC R6
MOV A, #6
ADD A, 34H
MOV 34H, A
MOV A, #25
ADD A, 33H
MOV 33H, A
; 处理各数位进位
LCALL HANDLE_CARRY
SJMP PROCESS_HIGH ; 再次检查高8位 这条好像是多余的吧
PROCESS_LOW:
; 低8位处理
MOV A, R7
MOV B, #10
DIV AB ; 仅对低8位使用DIV
MOV R7, A ; 保存商到低8位
MOV A, B ; 余数作为当前十进制位
; 将余数累加到结果缓冲区的个位
ADD A, 34H
MOV 34H, A
; 将商累加到结果缓冲区的十位
MOV A,R7
ADD A, 33H
MOV 33H, A
MOV R7,#0
; 处理各数位进位
LCALL HANDLE_CARRY
RET
还有程序中的这条( SJMP PROCESS_HIGH ; 再次检查高8位) 这条好像是多余的吧
ercircle
发表于 2025-8-26 09:01:16
道清 发表于 2025-8-26 08:38
其他我多看的懂,也知道逻辑。就是这部分的逻辑我想不通,方便的话能详细解释吗?
谢谢
PROCESS_HIGH是循环,每次高位字节减一,拿去补充十位和个位,高字节的1分拆成25*10+6,直到减完高位字节再去处理低位。
PROCESS_LOW只执行一次,把低字节刷入十进制缓冲区。
“JZ PROCESS_LOW; 高8位为0且低8位<10,处理最后一位” 这条注释改为 “高8位为0,跳转处理低八位”
Ayb_ice
发表于 2025-8-26 09:15:59
道清 发表于 2025-8-25 20:12
非常感谢您的帮助,从程序逻辑上我有启发,如果12345这个数是事先就是知道的,123和45分开存放是这个程序 ...
网上搜索一下,需要循环比较
道清
发表于 2025-8-26 11:29:14
ercircle 发表于 2025-8-26 09:01
PROCESS_HIGH是循环,每次高位字节减一,拿去补充十位和个位,高字节的1分拆成25*10+6,直到减完高位字节 ...
看来我是想不通这个题目了,越看越不懂,等会我吧我的程序整理一下,麻烦您帮我看看,谢谢
道清
发表于 2025-8-26 12:20:46
ercircle 发表于 2025-8-26 09:01
PROCESS_HIGH是循环,每次高位字节减一,拿去补充十位和个位,高字节的1分拆成25*10+6,直到减完高位字节 ...
SMG1 EQU P1.0 ;数码管1
SMG2 EQU P1.1 ;数码管2
SMG3 EQU P1.3 ;数码管3
SMG4 EQU P1.2 ;数码管4
;数据 EQU P3.0 ;164
;时间 EQU P3.1 ;164
FMQ EQU P3.4 ;蜂鸣器
GNAN EQU P3.0 ;按下启动两只电机
ANB EQU P3.1 ;按钮B
ANA EQU P3.2 ;按钮A
JDQ EQU P3.5 ;送料电机
BJD EQU P1.6 ;数量到报警灯
P1K EQU 0EEH
P2K EQU 0EDH
P3K EQU 0ECH
DLA EQU 0EFH
ORG 00H
JMP QQ
;------FH1------程序运行一次无返回-----------
;;----程序开始-------------
QQ: CLR FMQ ;关闭蜂鸣器
MOV DPTR,#12345
CALL MAIN
;这四行的意思是把您分解出来的数 放到我显示的H里,我再调用显示程序,依次一位的显示
MOV 38H,30H
MOV 35H,31H
MOV 36H,32H
MOV 37H,33H
C1: CALL XS ;调用显示程序
JMP C1 ;回调用显示程序
;-------------------------------------------------------------------------
;=================您写的程序开始=====我复制的========================
MAIN: MOV R6, DPH ; 高8位示例值
MOV R7, DPL ; 低8位示例值
LCALL HEX2DEC ; 调用转换子程序
;STOP: SJMP STOP ; 程序暂停
RET
; 转换子程序:R6R7 -> 30H-34H
HEX2DEC:
MOV 30H, #0 ; 初始化5字节缓冲区(万位)
MOV 31H, #0 ; 千位
MOV 32H, #0 ; 百位
MOV 33H, #0 ; 十位
MOV 34H, #0 ; 个位
LCALL PROCESS_HIGH
RET ; 转换完成返回
; 十进位处理子程序
HANDLE_CARRY:
; 处理个位进位到十位
MOV A, 34H
MOV B, #10
DIV AB ; A=商(进位), B=余数(个位)
MOV 34H, B ; 保存个位
MOV R0, A ; 暂存进位值
; 处理十位进位到百位 - 累加进位
MOV A, 33H
ADD A, R0 ; 原有十位值 + 进位
MOV B, #10
DIV AB ; A=商(进位), B=余数(十位)
MOV 33H, B ; 保存十位
MOV R0, A ; 更新进位值
; 处理百位进位到千位 - 累加进位
MOV A, 32H
ADD A, R0 ; 原有百位值 + 进位
MOV B, #10
DIV AB ; A=商(进位), B=余数(百位)
MOV 32H, B ; 保存百位
MOV R0, A ; 更新进位值
; 处理千位进位到万位 - 累加进位
MOV A, 31H
ADD A, R0 ; 原有千位值 + 进位
MOV B, #10
DIV AB ; A=商(进位), B=余数(千位)
MOV 31H, B ; 保存千位
MOV R0, A ; 更新进位值
; 处理万位进位
MOV A, 30H
ADD A, R0 ; 原有万位值 + 进位
MOV 30H, A ; 保存万位(最多为65535,不会超过10)
RET
PROCESS_HIGH:
MOV A, R6
JZ PROCESS_LOW; 高8位为0且低8位<10,处理最后一位
; 高8位减1,补充十位25和个位6
DEC R6
MOV A, #6
ADD A, 34H
MOV 34H, A
MOV A, #25
ADD A, 33H
MOV 33H, A
; 处理各数位进位
LCALL HANDLE_CARRY
SJMP PROCESS_HIGH ; 再次检查高8位
PROCESS_LOW:
; 低8位处理
MOV A, R7
MOV B, #10
DIV AB ; 仅对低8位使用DIV
MOV R7, A ; 保存商到低8位
MOV A, B ; 余数作为当前十进制位
; 将余数累加到结果缓冲区的个位
ADD A, 34H
MOV 34H, A
; 将商累加到结果缓冲区的十位
MOV A,R7
ADD A, 33H
MOV 33H, A
MOV R7,#0
; 处理各数位进位
LCALL HANDLE_CARRY
RET
;=================您写的程序结束=====我复制的==============================================================================================================
;----74164显示----过程是把放在35H.36H。37H.38H,里的数字一次一位的送去显示在数码管上-----------------
;目前显示只有四位,只要能显示1234或2345,我再自己加一位
XS: MOV A,36H ;把分解出来的放在36H里的数送到A里
CALL MB ;调用码表
CALL L164 ;调用164控制子程序
CLR SMG3 ;让控住脚接通负极,让这位数码管灯亮
CALL T2MS ;让数码管延时点亮20毫秒
SETB SMG3 ;让控住脚接通正极,让这位数码管灯灭
;--------------------下面依次;亮;灭。数码管---四位共阴数码管-----我就不依次备注了-
MOV A,37H
CALL MB
CALL L164
CLR SMG4
CALL T2MS
SETB SMG4
;-------------------------
MOV A,35H
CALL MB
XSD: CALL L164
CLR SMG2
CALL T2MS
SETB SMG2
;-----------------------------
MOV A,38H
CALL MB
XSD1: CALL L164
CLR SMG1
CALL T2MS
SETB SMG1
RET
;================L164=========================
L164: MOV 65H,#08
SETB P3.3
NOP
LOOP_0: CLR P3.3
NOP
RRC A
NOP
MOV P3.7,C
NOP
NOP
SETB P3.3
NOP
NOP
NOP
NOP
DJNZ 65H,LOOP_0
RET
;===========2MS延时===================
T2MS: MOV 60H,#03H ;08
D2MS_0: MOV 61H,#03H ;40
D2MS_1: NOP
DJNZ 61H,D2MS_1
DJNZ 60H,D2MS_0
NOP
RET
;=============段码表===========================
MB: INC A
MOVC A,@A+PC
RET
DB 0EEH,22H,0BCH,0B6H,72H,0D6H,0DEH,0A2H,0FEH,0F6H,0FAH,5EH,0CCH,3EH,0DCH,0D8H,0CEH,7AH,8H,2EH,7CH,4CH,9AH,1AH,1EH,0F8H,0F2H,18H,0D2H,5CH,6EH,70H,8EH,74H,76H,94H,00H,4H,14H,94H, ; 灯不亮是36;一点是37
RET ;二点是38 ;三点是39
;=================================================
;--------------传感器AD信号-------------------
STCAD:
MOV 0BCH,#11101100B ;P1.4做传感器AD
NOP
NOP
NOP
NOP
NOP
NOP
WAD5: MOV A,0BCH
JNB ACC.4,WAD5
MOV A,0BDH
MOV 10H,A
SETB P1.4
RET
;--------------延时AD信号-------------------
STCAD1:
MOV 0BCH,#11101101B ;P1.5做延时AD
NOP
NOP
NOP
NOP
NOP
NOP
WAF5: MOV A,0BCH
JNB ACC.4,WAF5
MOV A,0BDH
SUBB A,#85
JNC AF1
MOV A,#0
NOP
AF1: NOP
SETB P1.5
RET
;=============蜂鸣器响壹声===========================
FMQKJ: SETB FMQ
MOV R1,#255
Z1: CALL XS
DJNZ R1,Z1
CLR FMQ
MOV R1,#255
Z2: CALL XS
DJNZ R1,Z2
RET
;=========读第X扇区============
;MOV DPTR,#000H
DU: MOV 0C7H,#10000010B ;设置反映时间
MOV 0C5H,#1 ;1是读的指令
MOV 0C3H,DPH
MOV 0C4H,DPL
MOV 0C6H,#5AH ;0C6H必须做2个动作
MOV 0C6H,#0A5H ;0C6H必须做2个动作
NOP
MOV A,0C2H ;读出来的数据放在0C2H
NOP
RET
;=============擦除===========
; MOV DPTR,#000H
CHA: MOV 0C7H,#10000010B
MOV 0C5H,#3
MOV 0C3H,DPH
MOV 0C4H,DPL
MOV 0C6H,#5AH
MOV 0C6H,#0A5H
NOP
RET
;=============写============
; MOV DPTR,#000H
XIE: MOV 0C7H,#10000010B
MOV 0C5H,#2
MOV 0C3H,DPH
MOV 0C4H,DPL
MOV 0C2H,A ;数据放在0C2H,写进去
MOV 0C6H,#5AH
MOV 0C6H,#0A5H
NOP
CALL FZWCZ
RET
;=============================================
;===========单片机片内储存防止误抄作============
FZWCZ: MOV 07CH,#0
MOV 0C5H,#0
MOV 0C6H,#0
MOV 0C3H,#80H
MOV 0C4H,#0
RET
END
ercircle
发表于 2025-8-26 14:15:53
道清 发表于 2025-8-26 12:20
SMG1 EQU P1.0 ;数码管1
SMG2 EQU P1.1 ;数码管2
...
看到一些语法问题,
MAIN一般是程序入口,代码库当函数用建议另起各名字,并且用CALL调用MAIN没加RET,原程序是main执行完无限循环停止程序。
还有比如CALL XS,CALL对应的代码块一般用RET结束,或者JMP去别的有RET结束的代码块,这个检查下哈
另外这个程序调试建议分两部分独立调试再组合
1.给个固定值数码管能正常显示
2.双字节转十进制缓存,这部分在仿真里就可以验证
3.再是联调
道清
发表于 2025-8-26 16:40:40
ercircle 发表于 2025-8-26 14:15
看到一些语法问题,
MAIN一般是程序入口,代码库当函数用建议另起各名字,并且用CALL调用MAIN没加RET,原 ...
我的程序韦福运行了,没有报错的,
但你的图片里的,好像有不一样,不懂
我们还是讨论现存的程序好了,以免大家说跑偏了。
谢谢
ercircle
发表于 2025-8-26 17:19:38
道清 发表于 2025-8-26 16:40
我的程序韦福运行了,没有报错的,
但你的图片里的,好像有不一样,不懂
我们还是讨论现存的程序好了,以 ...
我上面发的不一定编译时报错,运行时可能异常或跑飞。
有CALL就要有RET,不明白建议可以看下陈桂友老师的汇编课程:
陈桂友老师-STC单片机教学视频 国芯人工智能技术交流网站 - AI32位8051交流社区
先把上面问题搞明白,代码修改后再试下,然后讨论现存程序要发细节:
第一步只调试数码管,验证情况怎么样,缓冲区固定值4567能显示4567吗
第二步仿真 算法,输入什么,输出是什么,验证情况怎么样
第三步联调,现在什么问题,什么现象,
道清
发表于 2025-8-26 19:37:30
道清 发表于 2025-8-26 16:40
我的程序韦福运行了,没有报错的,
但你的图片里的,好像有不一样,不懂
我们还是讨论现存的程序好了,以 ...
感谢,加 RET后就显示1234了
谢谢
我再试试其他
道清
发表于 2025-8-26 19:42:19
ercircle 发表于 2025-8-26 17:19
我上面发的不一定编译时报错,运行时可能异常或跑飞。
有CALL就要有RET,不明白建议可以看下陈桂友老师 ...
反复测试多成功了,感谢