迅维网

查看: 3416|回复: 18
打印 上一主题 下一主题

谁能帮忙检查一下这个程序

[复制链接]
跳转到指定楼层
1#
发表于 2009-10-19 14:13:09 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式 来自: 广西南宁 来自 广西南宁

马上注册,获取阅读精华内容及下载权限

您需要 登录 才可以下载或查看,没有帐号?注册

x
MAIN:        LCALL        DELAY
        CLR P1.0
        LCALL        DELAY
        CLR P1.1
        LCALL        DELAY
        CLR P1.2
        LCALL        DELAY
        CLR P1.3
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        MOV P1,#0FFH
        LCALL        DELAY
        LCALL        DELAY
        CLR P1.0
        LCALL        DELAY
        CLR P1.4
        LCALL        DELAY
        CLR P1.5
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        MOV P1,#0FFH
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY        ;以上OK=================
        MOV R1,#5
        DJNZ R1,SHAN
        LJMP MAIN
SHAN:        MOV P1,#0F0H
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        MOV P1,#0FFH
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        MOV P1,#0CEH
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        MOV P1,#0FFH
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        RET

DELAY:        MOV        R7,#250
D1:        MOV R6,#250
D2:        DJNZ R6,D2
        DJNZ R7,D1
        RET
        END

红色部分为什么不能按“MOV R1,#5 ---- DJNZ R1,SHAN”这两条指今循环5次,然后“LJMP MAIN”返回主程序,进入下一轮循环???
现在的情况是只跑完一次后灯就全灭了

2#
发表于 2009-10-19 19:15:06 | 只看该作者 来自: 河北保定 来自 河北保定
倒,为什么不用C写

回复 支持 反对

使用道具 举报

3#
发表于 2009-10-19 21:01:52 | 只看该作者 来自: 重庆 来自 重庆
你能用仿真软件在这句(DJNZ R1,SHAN)弄个断点,监视下R1的变化。我怀疑是不是 SHAN 和DELAY 子程序在执行RET后将 R1清零了?

你是学51的吧,现在都用C了。除非对实时要求非常高的应用。

回复 支持 反对

使用道具 举报

4#
发表于 2009-10-20 12:00:17 | 只看该作者 来自: 广西南宁 来自 广西南宁
之前用C写过一次,可能C学得还不是很深入,感觉有时候C在做延时的时候,不如汇编,比如3句“for(a=0,a<62500,a++)”延时比3句“LCALL   DELAY”快
程现在已经改好了,都怪自己没有对DJNZ这个指今了解所造成的,下面给你们转上:

回复 支持 反对

使用道具 举报

5#
发表于 2009-10-20 12:01:41 | 只看该作者 来自: 广西南宁 来自 广西南宁
MAIN:        LCALL        DELAY
        CLR P1.0
        LCALL        DELAY
        CLR P1.1
        LCALL        DELAY
        CLR P1.2
        LCALL        DELAY
        CLR P1.3
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        MOV P1,#0FFH
        LCALL        DELAY
        LCALL        DELAY
        CLR P1.0
        LCALL        DELAY
        CLR P1.4
        LCALL        DELAY
        CLR P1.5
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        MOV P1,#0FFH
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY        ;以上OK=================
        MOV R1,#5
D:DJNZ R1,SHAN
        LJMP MAIN
SHAN:MOV P1,#0F0H
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        MOV P1,#0FFH
        LCALL        DELAY
        LCALL        DELAY
        MOV P1,#0CEH
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        LCALL        DELAY
        MOV P1,#0FFH
        LCALL        DELAY
        LCALL        DELAY
        LCALL D
        RET
DELAY:MOV        R7,#250
D1:        MOV R6,#250
D2:        DJNZ R6,D2
                DJNZ R7,D1
                RET
                END

回复 支持 反对

使用道具 举报

6#
发表于 2009-10-20 12:07:22 | 只看该作者 来自: 广西南宁 来自 广西南宁
晕,复制出错了,红色字的应该为:
MOV R1,#5
D:DJNZ R1,SHAN
LJMP MAIN




LCALL D

回复 支持 反对

使用道具 举报

7#
发表于 2009-10-20 17:45:55 | 只看该作者 来自: 重庆 来自 重庆
逻辑太乱了,嵌套太多。我说的软件仿真调试,你做了没?

回复 支持 反对

使用道具 举报

8#
发表于 2009-10-21 11:53:55 | 只看该作者 来自: 广西南宁 来自 广西南宁
做了软件仿真,之前这个程序,R1并没有清零,因为没有写好,程度只走了一遍,没有循环

回复 支持 反对

使用道具 举报

9#
发表于 2009-10-21 13:41:09 | 只看该作者 来自: 重庆城口县 来自 重庆城口县
我找了一个延时代码:
芯片AVR M16, 时钟4MHZ,1t=0.25us,这里将r16的初始值取197,就实现了LED灯1秒亮、1秒灭的效果。

....初始化代码....
         lid r16,197          ;将立即数197放入R16寄存器(取1-255,可得到6.25us-2.17s的延时)
loop: cbi portc,0          ;PORTC.0位置0,LED灯亮
      rcall delay           ;调用1s延时子程序
      sbi portc.0          ;PORTC.0位置1,LED灯灭
      rcall delay           ;调用1s延时子程序
      rjmp loop            ;循环
;通用延时子程序
delay: push r16           ;压堆(2t)
del1:  push r16           ; 压堆(2t)
del2:   push r16           ; 压堆(2t)
del3:   dec r16             ;减1,R16=R16-1(1t)
           brne del3          ;若R16不为0跳转,R16=0顺序执行(2t/1t)
       pop r16             ;弹出(2t)
       dec r16              ;减1R16=R16-1(1t)
           brne del2          ;若R16不为0跳转,R16=0顺序执行(2t/1t)
           pop r16             ;弹出(2t)
           brne del1           ;减1R16=R16-1(1t)
           pop r16              ;弹出(2t)
           ret                      ;子程序返回(4t)

回复 支持 反对

使用道具 举报

10#
发表于 2009-10-21 13:50:32 | 只看该作者 来自: 重庆城口县 来自 重庆城口县
下面给出CVAVR下的C代码:

#include <mag16.h>     //器件头文件
#include <delay.h>       //CVAVR函数头文件

void main(void)            
{
    PORTC=0X01;           //PORTC的0位置1,LED熄灭
    DDRC=0X01;            //PORTC配置为输出
   
    while(1)                   //主循环开始
    {
         delay_ms(1000);  //调用CVAVR的毫秒延时函数
         PORTC.0=~PORTC.0;  //PORTC的0位取反,实现LED熄灭、LED亮的两种状态。
    };
}

回复 支持 反对

使用道具 举报

11#
发表于 2009-10-21 13:55:09 | 只看该作者 来自: 重庆城口县 来自 重庆城口县
这里只是为了说明延时的代码,实际应用中是不建议这样做的,因该使用中断来延时。

回复 支持 反对

使用道具 举报

12#
发表于 2009-10-24 16:56:49 | 只看该作者 来自: 广西南宁 来自 广西南宁
谢谢老大的指导

回复 支持 反对

使用道具 举报

13#
发表于 2009-10-27 13:11:09 | 只看该作者 来自: 江苏镇江 来自 江苏镇江
我来回复吧,DJNZ是跳转指令.你的SHAN 是子程序,后面带有RET指令.

明白哪里有问题了吧.

你跳转到SHAN后,MCU做了pop PC动做.全乱了,呵呵....

回复 支持 反对

使用道具 举报

14#
发表于 2009-10-27 13:14:35 | 只看该作者 来自: 江苏镇江 来自 江苏镇江
本帖最后由 王利群 于 2009-10-27 13:17 编辑

再补充一点,你只要将SHAN 最后一个RET指令换成 LJMP D 就可以了.

跑软件仿真的时候,注意看PC寄存器.明白跳转与调用的区别.从上面的程序来看,你暂时还没有理解这两点,

评分

参与人数 1下载分 +18 收起 理由
yzz163 + 18 热心帮助会员

查看全部评分

回复 支持 反对

使用道具 举报

15#
发表于 2009-10-27 13:19:08 | 只看该作者 来自: 江苏镇江 来自 江苏镇江
LCALL        DELAY
        MOV P1,#0FFH
        LCALL        DELAY
        LCALL        DELAY
        LCALL D
        RET

跑完几个周期后,一样出错,因为RET 会影响PC.而你前面并没有CALL介指令 push PC

回复 支持 反对

使用道具 举报

16#
发表于 2009-10-27 21:12:38 | 只看该作者 来自: 广西南宁 来自 广西南宁
王兄说的对,跑完几个周期后,出错了,但我现在还不是很明白,因为我还没学完那些指今,这个都是按照自己的感觉来写的,看来,我还得多抽时间学习了

回复 支持 反对

使用道具 举报

17#
发表于 2009-10-27 21:53:14 | 只看该作者 来自: 广东珠海 来自 广东珠海
call 指令会压栈PC,并改变PC,RET指令会弹出PC,JMP指令只是改变PC

当你的SHAN子程序.执行RET指令的时候,会有一个PC出栈.这时的PC是你的SP-1,-2的值,如果是空那么会回到开头0000,但是你的SP指针却改变了,直到PC用的你用的第一组R0-R7时,这时弹出的PC将不再是0000H,这时你的程序就跑飞了.

这么讲应该明白了吧.

回复 支持 反对

使用道具 举报

18#
发表于 2009-10-27 23:51:46 | 只看该作者 来自: 浙江温州 来自 浙江温州
呵呵,应该是嵌套和返回的指令没有掌握好。一般还是用LCALL吧。

回复 支持 反对

使用道具 举报

19#
发表于 2009-10-28 08:37:04 | 只看该作者 来自: 江苏镇江 来自 江苏镇江
楼上的,我所说的CALL,仅指CALL类的指令,如LCALL ACALL CALL,楼主并不是不懂 嵌套和返回 ,只是对这些指令影响的寄存器还没有了解透.

回复 支持 反对

使用道具 举报

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

本版积分规则

快速回复 返回顶部 返回列表
附近
店铺
微信扫码查看附近店铺
维修
报价
扫码查看手机版报价
信号元
件查询
点位图


芯片搜索

快速回复