Sida 1 av 1

Subrutiner - AVR

Postat: 6 februari 2007, 22:50:48
av Limen
Hur använder man subrutiner i AVR (asm)?
Försöker med en liten testsnutt:

Kod: Markera allt

	RJMP	main

main:
	LDI	R16,0xFF
	OUT	DDRB,R16
loop:
	LDI	R16,0x00
	OUT	PORTB,R16
	RCALL	delay
	LDI	R16,0xFF
	OUT	PORTB,R16
	RCALL	delay
	RJMP	loop

delay:
	LDI	R17,0xFF
delay_2:
	SUBI	R17,0x01
	BRNE	delay_2
	RET
Men den återvänder inte från subrutinen utan hoppar istället tillbaka till "RJMP main". Vad har jag missat?

Postat: 6 februari 2007, 23:19:43
av oJsan
Förmodligen så har du glömt att initiera stacken. Återhoppsadressen från subrutinen sparas nämligen där. Kan inte på rak arm svara på hur du initierar den men det finns nog i många färdiga asm/AVR-exempel

Edit:

Kod: Markera allt

*Följande kod placerar stackpekaren längst ner i RAM.
	.include "m16def.inc" //Eller motsvarande...
	ldi	r16,low(RAMEND)
	out	SPL,r16
	ldi	r16,high(RAMEND)
	out	SPH,r16

Postat: 6 februari 2007, 23:21:49
av Limen
Aha måste den initieras manuellt. Ska man dedikera ett register till detta är det tänkt?

Postat: 7 februari 2007, 00:28:00
av Micke_s
Vid push och pop så flyttas den.
R16 används bara som temp lagring.
SPH och SPL är redan dedikerad i hårdvaran.

Postat: 7 februari 2007, 07:01:49
av Limen
Måste man ange R16 eller funkar det med vilket som? (16-31)

Postat: 7 februari 2007, 08:41:44
av oJsan
Det fungerar med vilken register som helst av samma typ. Operationen är ungefär samma som när du gör:

Kod: Markera allt

   LDI   R16,0xFF
   OUT   DDRB,R16
Först lägger man data (0xFF) till ett dataregister och sedan skriver man registret till ett specifikt hårdvaruregister (SPL/SPH/PORTB/DDRB/etc.).

Postat: 7 februari 2007, 09:03:48
av Limen
Aha då förstår jag. Tack för hjälpen!