找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3682|回复: 3
打印 上一主题 下一主题
收起左侧

51单片机汇编版本,关于工作寄存器R1在程序运行过程中无缘无故被修改的问题

[复制链接]
跳转到指定楼层
楼主
ID:235079 发表于 2017-11-14 17:27 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
附上软件代码:TEMP EQU 07H        ;地址不要乱定 R7

硬件上:P3.0、P3.1口接了按键,P1口接了LED灯

问题:程序当中第一种模式ONE,里面的延时部分,有一个工作寄存器R1,在按键处理子程序KEYPRO中修改了之后,程序应该是一直保持修改之后的值的,但是显示的子程序循环执行几个来回后,R1发生了改变,好像恢复到初值了,显示(流水灯)的速度又快了。请教大佬们,R1工作寄存器的值变化是什么原因造成的?小弟不才,希望是代码错了,求大佬们指点迷津,感激不尽

  1. ORG 000H
  2.                         AJMP MAIN
  3. ORG 100H
  4. ;********;
  5. ;主程序;
  6. ;********;
  7. MAIN:                MOV R0,#000H        ;初始化LED模式为0
  8.                         MOV R1,#00AH        ;初始化LED的速度        
  9.                         MOV R2,#0FEH        ;LED初始状态        
  10.                         MOV R5,#0FFH
  11. WHILE:                LCALL KEYSCAN        ;按键扫描
  12. S1:                        LCALL KEYPRO        ;按键处理
  13. S2:                    LCALL SHOW                ;显示函数
  14. JMPEND:                AJMP WHILE
  15. ;********;
  16. ;显示子程序;
  17. ;********;
  18. SHOW:                MOV A,R0
  19.                         RL A
  20.                         MOV DPTR,#JMPTAB
  21.                         JMP @A+DPTR
  22.                         RET
  23. ;********;
  24. ;按键扫描子程序;
  25. ;********;                        ;03H = 0000 0011B
  26. KEYSCAN:        MOV P3,#03H                ;给端口置高电平,读取端口状态必须先置端口为高电平
  27.                         MOV A,P3                ;读入P3的状态也就是按键的状态
  28.                         ORL A,#0FCH                ;0FCH = 1111 1100B
  29.                         CPL A                        ;取反
  30.                         JZ        S2                        ;如果A键态为00,则无按键填过直接做显示部分        
  31.                         MOV TEMP,A                ;保存临时键值
  32.                         LCALL        DELAY10MS;消抖
  33.                         MOV A,P3
  34.                         ORL A,#0FCH
  35.                         CPL A
  36.                         CJNE A,TEMP,S2  ;判断如果第二次读取的按键值和第一次读取的按键值不相等
  37.                         MOV R5,A                ;保存键值

  38.                         RET
  39. ;********;
  40. ;按键处理子程序;
  41. ;********;        
  42. KEYPRO:                MOV A,R5                        ;把按键值给A
  43.                         CJNE A,#001H,IFK2        ;如果键状态为K1,则
  44.                         CJNE R0,#002H,K1PRO        ; R0 = 0000 0000B    #0000 0010B
  45.                         MOV R0,#000H
  46.                         SJMP KEYPROEND
  47. IFK2:                CJNE A,#002H,KEYPROEND
  48.                         CJNE R1,#0FAH,K2PRO
  49.                         MOV R1,#00AH
  50.                         SJMP KEYPROEND
  51. K1PRO:                INC R0
  52.                         SJMP KEYPROEND
  53. K2PRO:                MOV A,R1
  54.                         ADD A,#00AH
  55.                         MOV R1,A
  56.                         SJMP KEYPROEND
  57. KEYPROEND:        RET
  58. ;********;
  59. ;延时10ms子程序;
  60. ;********;
  61. DELAY10MS:                        ;@11.0592MHz
  62.                         PUSH 30H
  63.                         PUSH 31H
  64.                         MOV 30H,#18
  65.                         MOV 31H,#230
  66. NEXT:
  67.                         DJNZ 31H,NEXT
  68.                         DJNZ 30H,NEXT
  69.                         POP 31H
  70.                         POP 30H
  71.                         RET               
  72. ;********;
  73. ;分支1子程序;
  74. ;********;
  75. ONE:                        
  76.                         MOV A,R2                        ;R2是P1初始状态LED 1111 1110B = 0FEH
  77.                         MOV P1,A
  78.                         MOV A,R1
  79.                         MOV R3,A
  80.                         ;MOV P1,A
  81. L1:                        LCALL DELAY10MS
  82.                         DJNZ R3,L1

  83.                         MOV A,R2
  84.                         RL A
  85.                         MOV R2,A
  86.                         AJMP JMPEND
  87. ;********;
  88. ;分支2子程序;
  89. ;********;
  90. TWO:                MOV P1,#00FH
  91.                         SJMP $
  92.                         AJMP JMPEND
  93. ;********;
  94. ;跳转程序表;
  95. ;********;
  96. JMPTAB:                AJMP ONE
  97.                         AJMP TWO
  98.                         END
复制代码
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:123289 发表于 2017-11-15 13:35 | 只看该作者
请教一下,堆栈存从哪里开始?堆栈里的数据何时会发生变化?
回复

使用道具 举报

板凳
ID:235079 发表于 2017-11-15 21:43 | 只看该作者
yzwzfyz 发表于 2017-11-15 13:35
请教一下,堆栈存从哪里开始?堆栈里的数据何时会发生变化?

查阅一下51汇编的书籍,堆栈的一开始初始化的地址我忘记,堆栈地址可以改的,给sp赋值即可。MOV SP,060H。堆栈的数据,当你调用子程序了就会压栈,返回的时候就出栈。或者直接对堆栈进行操作PUSH或者POP
回复

使用道具 举报

地板
ID:235079 发表于 2017-11-15 21:56 | 只看该作者
问题已找到,谢谢老师和同学以及论坛的大佬们。这个代码逻辑上应该对的,但是存在一个问题就是主程序明明调用了按键扫描子程序 LCALL KEYSCAN,但是在这个按键扫描的子程序里,我写了一个判断数据是否相等跳转的命令 CJNE A,TEMP,S2,而这个跳转的地址S2确实主程序里的,因此在按键子程序还没有RET返回就已经跳转到另外一个子程序里面了,此时堆栈就溢出,调用了却没有执行返回,调用的时候会压栈的,那么返回就是出栈,如果没有返回就会使得堆栈溢出,程序多跑几次直接复位。总结就是:调用了子程序一定要返回,不能调用了子程序再跳转到另外一个子程序,这样返回那句命令就废了。(如果调用了子程序,在自己的子程序里跳转是可以的)哈哈开心解决了一个很不容易发现的问题。再一次感谢老师同学以及论坛的大佬们。

附上正确的代码:

TEMP EQU 07H        ;地址不要乱定 R7
ORG 000H
                        AJMP MAIN
ORG 100H
;********;
;主程序;
;********;
MAIN:                MOV R0,#000H        ;初始化LED模式为0
                        MOV R1,#00AH        ;初始化LED的速度       
                        MOV R2,#0FEH        ;LED初始状态       
                        MOV R5,#0FFH        ;初始化键代码
                        MOV R6,#008H        ;初始化计数器
WHILE:                LCALL KEYSCAN        ;按键扫描
                        LCALL KEYPRO        ;按键处理
                             LCALL KEYAGIN        ;按键弹起
                        AJMP SHOW                ;显示函数
JMPEND:                AJMP WHILE
;********;
;显示子程序;
;********;
SHOW:                MOV A,R0
                        RL A
                        MOV DPTR,#JMPTAB
                        JMP @A+DPTR
;********;
;按键扫描子程序;
;********;                        ;03H = 0000 0011B
KEYSCAN:                MOV P3,#03H                ;给端口置高电平,读取端口状态必须先置端口为高电平
                        MOV A,P3                ;读入P3的状态也就是按键的状态
                        ORL A,#0FCH                ;0FCH = 1111 1100B
                        CPL A                        ;取反
                        JZ        ONKEY                        ;如果A键态为00,则无按键填过直接做显示部分       
                        MOV TEMP,A                ;保存临时键值
                        LCALL        DELAY10MS;消抖
                        MOV A,P3
                        ORL A,#0FCH
                        CPL A
                        CJNE A,TEMP,ONKEY  ;判断如果第二次读取的按键值和第一次读取的按键值不相等
                        MOV R5,A                ;保存键值
                        AJMP KSEND
ONKEY:            MOV R5,#000H
KSEND:            RET
;********;
;按键处理子程序;
;********;       
KEYPRO:                MOV A,R5                        ;把按键值给A
                        CJNE A,#000H,DOWNKEY
                        AJMP KEYPROEND
DOWNKEY:        CJNE A,#001H,IFK2        ;如果键状态为K1,则
                        CJNE R0,#003H,K1PRO        ;
                        MOV R0,#000H
                        MOV R2,#0FEH
                        SJMP KEYPROEND
IFK2:                        CJNE A,#002H,KEYPROEND
                        CJNE R1,#0FAH,K2PRO
                        MOV R1,#00AH
                        SJMP KEYPROEND
K1PRO:                INC R0
                        MOV R2,#0FEH
                        SJMP KEYPROEND
K2PRO:                MOV A,R1
                        ADD A,#00AH
                        MOV R1,A
                        SJMP KEYPROEND
KEYPROEND:        RET
;********;
;按键弹起子程序;
;********;       
KEYAGIN:           MOV A,R5
                        CJNE A,#000H,KEYTQ
                        AJMP NOKEYTQ
KEYTQ:                MOV P3,#03H
KEYTA:                MOV A,P3
                        ORL A,#0FCH
                        CPL  A
                        CJNE A,TEMP,KEYCH
                        SJMP KEYTA
KEYCH:                    NOP
NOKEYTQ:           RET
;********;
;延时10ms子程序;
;********;
DELAY10MS:                        ;@11.0592MHz
                        PUSH 30H
                        PUSH 31H
                        MOV 30H,#18
                        MOV 31H,#230
NEXT:
                        DJNZ 31H,NEXT
                        DJNZ 30H,NEXT
                        POP 31H
                        POP 30H
                        RET               
;********;
;分支1子程序;
;********;
ONE:                       
                        MOV A,R2                        ;R2是P1初始状态LED 1111 1110B = 0FEH
                        MOV P1,A
                        MOV A,R1
                        MOV R3,A
L1:                        LCALL DELAY10MS
                        DJNZ R3,L1

                        MOV A,R2
                        RL A
                        MOV R2,A
                        AJMP JMPEND
;********;
;分支2子程序;
;********;
TWO:                MOV A,R2
                        CLR C
                        MOV P1,A
                        MOV A,R1
                        MOV R3,A
L2:                        LCALL DELAY10MS
                        DJNZ R3,L2
                        MOV A,R2
                        RLC A
                        MOV R2,A
                        DJNZ R6,TWOEND
                        MOV R6,#009H
                        MOV R2,#0FFH
TWOEND:                AJMP JMPEND
;********;
;分支3子程序;
;********;
THREE:                MOV P1,#00FH
                        MOV A,R1
                        MOV R3,A
L3:                        LCALL DELAY10MS
                        DJNZ R3,L3
                        MOV P1,#0F0H
                        MOV A,R1
                        MOV R3,A
L4:                        LCALL DELAY10MS
                        DJNZ R3,L4
                        AJMP JMPEND
;********;
;分支4子程序;
;********;
FOUR:                MOV P1,#0C3H
                        MOV A,R1
                        MOV R3,A
L5:                        LCALL DELAY10MS
                        DJNZ R3,L5
                        MOV P1,#03CH
                        MOV A,R1
                        MOV R3,A
L6:                        LCALL DELAY10MS
                        DJNZ R3,L6
                        AJMP JMPEND
;********;
;跳转程序表;
;********;
JMPTAB:                AJMP ONE
                        AJMP TWO
                        AJMP THREE
                        AJMP FOUR
                        END

评分

参与人数 1黑币 +60 收起 理由
admin + 60 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表