我创建了一个简单的汇编程序子程序(asmFunction),它应该每10 ms切换一次PORTD的输出。
这是汇编程序源代码:
#define __SFR_OFFSET 0
#include <avr/io.h>
.section .text ; Defines a code section
;initialize
initialize:
ldi r24,0xFF ; set 11111111 value to the r24 register
out DDRD,r24 ; put r24 register value into DDRD register
ldi r24,0x00 ; set the r24 register to 00000000 value
out PORTD,r24 ; put the r24 register value to PORTD
ret ; return from a branch
;wait 100uS
subdelay:
ldi r23,99 ; set register r23 to 99
loop:
dec r23 ; 1 cycle, decrement r23
cpi r23,0 ; 1 cycle, compare r23 and 0
;nop to get exactly 16 clock cycles per loop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
brne loop ; 2 cycles, if r23 not eqal to 0, continue the loop
;wait a bit more (11 cycles to get exactly 100uS of delay
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
ret ; return from branch
;delay x/10 ms (R22)
delay:
ldi r23,100 ; set delay to 100x100uS
loop1:
dec r23 ; decrement r23
cpi r23,0 ; compare r23 to 0
call subdelay; call subdelay routine
brne loop1 ; if r23 is not equal to 0, continue the loop
ret ; otherwise return from the delay branch
.global asmFunction ; makes asm function visible in other source files
asmFunction: ; Start of asmfunc_calledfrom_c subroutine
call initialize ; call initialize branch
while: ; main loop
;turn output high
ldi r24,0xFF
out PORTD,r24
;delay 10mS
call delay
;turn output low
ldi r24,0x00
out PORTD,r24
;delay 10 ms
call delay
rjmp while ; jump to while (for loop to continue existing)
main.c:
#include "avr/io.h"
void asmFunction();
int main()
{
asmFunction();
return 0;
}
这里是反汇编的hex文件:
Atmega328p_test.elf: file format elf32-avr
Sections:
Idx Name Size VMA LMA File off Algn
0 .data 00000000 00800100 000000f4 00000168 2**0
CONTENTS, ALLOC, LOAD, DATA
1 .text 000000f4 00000000 00000000 00000074 2**1
CONTENTS, ALLOC, LOAD, READONLY, CODE
2 .comment 00000011 00000000 00000000 00000168 2**0
CONTENTS, READONLY
3 .note.gnu.avr.deviceinfo 00000040 00000000 00000000 0000017c 2**2
CONTENTS, READONLY
Disassembly of section .text:
00000000 <__vectors>:
0: 0c 94 34 00 jmp 0x68 ; 0x68 <__ctors_end>
4: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
8: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
10: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
14: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
18: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
1c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
20: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
24: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
28: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
2c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
30: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
34: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
38: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
3c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
40: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
44: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
48: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
4c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
50: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
54: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
58: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
5c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
60: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
64: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
00000068 <__ctors_end>:
68: 11 24 eor r1, r1
6a: 1f be out 0x3f, r1 ; 63
6c: cf ef ldi r28, 0xFF ; 255
6e: d8 e0 ldi r29, 0x08 ; 8
70: de bf out 0x3e, r29 ; 62
72: cd bf out 0x3d, r28 ; 61
74: 0e 94 73 00 call 0xe6 ; 0xe6 <main>
78: 0c 94 78 00 jmp 0xf0 ; 0xf0 <_exit>
0000007c <__bad_interrupt>:
7c: 0c 94 00 00 jmp 0 ; 0x0 <__vectors>
00000080 <initialize>:
80: 8f ef ldi r24, 0xFF ; 255
82: 8a b9 out 0x0a, r24 ; 10
84: 80 e0 ldi r24, 0x00 ; 0
86: 8b b9 out 0x0b, r24 ; 11
88: 08 95 ret
0000008a <subdelay>:
8a: 73 e6 ldi r23, 0x63 ; 99
0000008c <loop>:
8c: 7a 95 dec r23
8e: 70 30 cpi r23, 0x00 ; 0
...
a8: 89 f7 brne .-30 ; 0x8c <loop>
...
be: 00 00 nop
c0: 08 95 ret
000000c2 <delay>:
c2: 74 e6 ldi r23, 0x64 ; 100
000000c4 <loop1>:
c4: 7a 95 dec r23
c6: 70 30 cpi r23, 0x00 ; 0
c8: 0e 94 45 00 call 0x8a ; 0x8a <subdelay>
cc: d9 f7 brne .-10 ; 0xc4 <loop1>
ce: 08 95 ret
000000d0 <asmFunction>:
d0: 0e 94 40 00 call 0x80 ; 0x80 <initialize>
000000d4 <while>:
d4: 8f ef ldi r24, 0xFF ; 255
d6: 8b b9 out 0x0b, r24 ; 11
d8: 0e 94 61 00 call 0xc2 ; 0xc2 <delay>
dc: 80 e0 ldi r24, 0x00 ; 0
de: 8b b9 out 0x0b, r24 ; 11
e0: 0e 94 61 00 call 0xc2 ; 0xc2 <delay>
e4: f7 cf rjmp .-18 ; 0xd4 <while>
000000e6 <main>:
e6: 0e 94 68 00 call 0xd0 ; 0xd0 <asmFunction>
ea: 80 e0 ldi r24, 0x00 ; 0
ec: 90 e0 ldi r25, 0x00 ; 0
ee: 08 95 ret
000000f0 <_exit>:
f0: f8 94 cli
000000f2 <__stop_program>:
f2: ff cf rjmp .-2 ; 0xf2 <__stop_program>
问题在于,当我在atmega328p微控制器上运行此代码时,它会产生周期为200μS的信号。
似乎subdelay
子例程正常执行并产生100uS的延迟但由于某种原因loop1
delay
子例程内的subdelay
不起作用,导致turtle.bgpic("bkgrd.jpg")
子例程只执行
问题是:我做错了什么?
答案 0 :(得分:0)
在延迟和子延迟中使用r23。您需要在调用子延迟之前保存它的值,然后使用push和pop将其恢复,或者将其存储在特定的内存位置。