迅维网
标题:
谁能帮忙检查一下这个程序
[打印本页]
作者:
韦永忠
时间:
2009-10-19 14:13
标题:
谁能帮忙检查一下这个程序
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”返回主程序,进入下一轮循环???
现在的情况是只跑完一次后灯就全灭了
作者:
单片机打印机
时间:
2009-10-19 19:15
倒,为什么不用C写
作者:
yzz163
时间:
2009-10-19 21:01
你能用仿真软件在这句(DJNZ R1,SHAN)弄个断点,监视下R1的变化。我怀疑是不是 SHAN 和DELAY 子程序在执行RET后将 R1清零了?
你是学51的吧,现在都用C了。除非对实时要求非常高的应用。
作者:
韦永忠
时间:
2009-10-20 12:00
之前用C写过一次,可能C学得还不是很深入,感觉有时候C在做延时的时候,不如汇编,比如3句“for(a=0,a<62500,a++)”延时比3句“LCALL DELAY”快
程现在已经改好了,都怪自己没有对DJNZ这个指今了解所造成的,下面给你们转上:
作者:
韦永忠
时间:
2009-10-20 12:01
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
作者:
韦永忠
时间:
2009-10-20 12:07
晕,复制出错了,红色字的应该为:
MOV R1,#5
D:DJNZ R1,SHAN
LJMP MAIN
。
。
。
LCALL D
作者:
yzz163
时间:
2009-10-20 17:45
逻辑太乱了,嵌套太多。我说的软件仿真调试,你做了没?
作者:
韦永忠
时间:
2009-10-21 11:53
做了软件仿真,之前这个程序,R1并没有清零,因为没有写好,程度只走了一遍,没有循环
作者:
yzz163
时间:
2009-10-21 13:41
我找了一个延时代码:
芯片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)
作者:
yzz163
时间:
2009-10-21 13:50
下面给出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亮的两种状态。
};
}
作者:
yzz163
时间:
2009-10-21 13:55
这里只是为了说明延时的代码,实际应用中是不建议这样做的,因该使用中断来延时。
作者:
韦永忠
时间:
2009-10-24 16:56
谢谢老大的指导
作者:
王利群
时间:
2009-10-27 13:11
我来回复吧,DJNZ是跳转指令.你的SHAN 是子程序,后面带有RET指令.
明白哪里有问题了吧.
你跳转到SHAN后,MCU做了pop PC动做.全乱了,呵呵....
作者:
王利群
时间:
2009-10-27 13:14
本帖最后由 王利群 于 2009-10-27 13:17 编辑
再补充一点,你只要将SHAN 最后一个RET指令换成 LJMP D 就可以了.
跑软件仿真的时候,注意看PC寄存器.明白跳转与调用的区别.从上面的程序来看,你暂时还没有理解这两点,
作者:
王利群
时间:
2009-10-27 13:19
LCALL DELAY
MOV P1,#0FFH
LCALL DELAY
LCALL DELAY
LCALL D
RET
跑完几个周期后,一样出错,因为RET 会影响PC.而你前面并没有CALL介指令 push PC
作者:
韦永忠
时间:
2009-10-27 21:12
王兄说的对,跑完几个周期后,出错了,但我现在还不是很明白,因为我还没学完那些指今,这个都是按照自己的感觉来写的,看来,我还得多抽时间学习了
作者:
王利群
时间:
2009-10-27 21:53
call 指令会压栈PC,并改变PC,RET指令会弹出PC,JMP指令只是改变PC
当你的SHAN子程序.执行RET指令的时候,会有一个PC出栈.这时的PC是你的SP-1,-2的值,如果是空那么会回到开头0000,但是你的SP指针却改变了,直到PC用的你用的第一组R0-R7时,这时弹出的PC将不再是0000H,这时你的程序就跑飞了.
这么讲应该明白了吧.
作者:
嘉诚电脑
时间:
2009-10-27 23:51
呵呵,应该是嵌套和返回的指令没有掌握好。一般还是用LCALL吧。
作者:
王利群
时间:
2009-10-28 08:37
楼上的,我所说的CALL,仅指CALL类的指令,如LCALL ACALL CALL,楼主并不是不懂 嵌套和返回 ,只是对这些指令影响的寄存器还没有了解透.
欢迎光临 迅维网 (https://www.chinafix.com/)
Powered by Discuz! X3.4