- LiTime Speicher und Akkus         
Ergebnis 1 bis 10 von 10

Thema: ret springt nicht nach rcall befehl

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    25.11.2004
    Beiträge
    17

    ret springt nicht nach rcall befehl

    Anzeige

    LiFePo4 Akku selber bauen - Video
    hallo!

    bin noch anfänger in sachen assembler. habe ein beispiel prog fürs übertragen über RS232 gefunden.

    hier:

    Code:
    .NOLIST
    .INCLUDE "D:\m32def.inc"
    .LIST
    
    .equ fck = 4000000
    .equ baudrate = 4800
    
    .equ baudconst = (fck / (baudrate * 16)) - 1
    
    .def w = R19				; Arbeitsregister
    .def wi = R20				; Interrupt-Arbeitsregister
    .def rs_buf = R21			; Buffer für empfangenes Byte
    .def a_flag = R25			; Flagregister
    
    .equ rs_recv = 0			; 1 = Byte empfangen - 0 = kein Byte empfangen
    
    
    ; Interrupt-Adressen
    .cseg
    .org $0000
    	rjmp main
    
    .org $0007					; RS232 Empfangsinterrupt
    	rjmp rs232_recv			; RS232 Behandlungsroutinge wenn etwas empfangen wird
    
    
    
    ; I/O-Port Initialisierung:
    hdw_init:
    	ldi w, 0b11111111
    	out PORTD, w			; alle Pins am Port D auf 1 setzen
    	ldi w, 0b11111110
    	out DDRD, w				; Datenrichtung am Port D festlegen: 1 = Ausgang; 0 = Eingang
    							; Pin 1 am Port D Empfangen (= 1) RX
    							; Pin 2 am Port D Senden (= 0) TX
    
    	
    	ldi w, 0b11111111
    	out PORTB, w
    	ldi w, 0b11111111
    	out DDRB, w
    
    	
    	; UART Initialisierung:
    uart_init:
    	ldi w, baudconst
    	out UBRRL, w			; UBRR = USART Baud Rate Register
    	ldi w, 0
    	out UBRRH, w
    	ldi w, 0b00011000
    	out UCSRB, w			; RXEN und TXEN setzen
    	sbi UCSRB, RXCIE		; RS232 Interrupt freigeben
    
    
    ; PWM Initialisierung:
    pwm_init:
    	ldi w, 0b10000001
    	out TCCR1A, w
    	ldi w, 0
    	out OCR1AH, w
    	ldi w, 1
    	out OCR1AL, w
    	ldi w, 0b00000001
    	out TCCR1B, w
    
    	sei						; gibt alle Interrups frei
    	ret
    
    
    ; Behandlung für empfangene Bytes:
    rs_rec_up:
    	cbr a_flag, 1 << rs_recv; durch '1<<' wird eine '1' n-mal nach links geschoben
    							; für rs_recv = 0: 0b00000001
    							; für rs_recv = 1: 0b00000010
    							; --> das erste bzw zweite Bit in a_flag wird somit gelöscht
    
    	mov w, rs_buf			; empfangenes Byte in w
    	out PORTB, w			; an Port B ausgeben ?(kein PWM)?
    	out OCR1AL, w
    	rcall rs_send
    	ret
    
    
    rs_send:
    	sbis UCSRA, UDRE		; überprüft, ob UDRE im Register UCSRA gesetzt ist, wenn ja (UDRE=1) überspringen
    							; UDRE = 1 Sender frei, UDRE = 0 Sender besetzt
    	rjmp rs_send
    	out UDR, w
    	ret
    
    
    ; Interruptroutine wenn Bytes empfangen werden:
    rs232_recv:
    	in wi, SREG				; CPU-Status
    	push wi					; wi in Stackpointer
    	
    	in wi, UDR				; Byte vom Empfänger laden
    	mov rs_buf, wi			; zwischenspeichern
    	sbr a_flag, 1<<rs_recv	; durch '1<<' wird eine '1' n-mal nach links geschoben
    							; für rs_recv = 0: 0b00000001
    							; für rs_recv = 1: 0b00000010
    							; --> das erste bzw zweite Bit in a_flag wird somit gesetzt
    
    	pop wi					; Stackpointer zurück in wi
    	out SREG, wi			; zurück zur CPU
    	
    	reti					; Return from Interrupt
    
    
    main:
    	ldi w, RAMEND			; RAMEND: Speicherende des Chips
    	out SPL, w				; in Stackpointer schreiben
    	clr a_flag
    	rcall hdw_init			; Hardware Initialisierung
    
    endlos:
    	sbrc a_flag, rs_recv
    	rcall rs_rec_up			; wenn was empfangen wurde dann...
    	rjmp endlos				; sonst warten
    die komentare sind von mir. können also auch falsch sein

    geht man das prog schritt für schritt durch, springt er hier 'rcall hdw_init' in den initialisierungsteil. am ende von 'pwm_init:' steht ein 'ret'. an dieser stelle springt er aber dann nicht zurück zum 'rcall hdw_init' bzw in die endlosschleife, sondern springt ganz an den anfang zu: '.org $0000 rjmp main'

    woran liegt das?

    wird in 'main:' der stackpointer falsch beschrieben? was genau bedeutet denn RAMEND?

    danke mal für eure geduld wenn ihr bis zum schluss gelesen habt! \/

    freddy0815

  2. #2
    RN-Premium User Begeisterter Techniker
    Registriert seit
    30.04.2004
    Alter
    46
    Beiträge
    245
    Hallo,

    ich vermute, du liegst schon mal nicht schlecht.
    m32def.inc ist ein ATMEGA32 oder irre ich mich? Dieser hat sicher mehr als 255 Bytes Ram. Deswegen muss nicht nur spl sondern auch sph gesetzt werden.
    RamEnd ist eine Konstante die die Speichergröße enthält. Du kannst ja mal die m32def.inc aufmachen, da solltest du es finden. Der Stackpointer wird normalerweise immer auf das Ende des Rams gesetzt, da er decrementiert.
    Ich habe leider meine Tools nicht bei mir sonst könnte ichs dir jetzt genauer sagen.

    lg

    Alex

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    25.11.2004
    Beiträge
    17
    vielen dank für der tipp!!

    jetzt gehts. habe den sph auch gesetzt:

    ldi w, HIGH(RAMEND)
    out SPH, w
    ldi w, LOW(RAMEND)
    out SPL, w

    und ich bin in meiner schleife drin

    danke
    freddy

  4. #4
    Neuer Benutzer Öfters hier
    Registriert seit
    25.11.2004
    Beiträge
    17
    aber eins vielleicht noch. wie kann ich im debugg-modus manuell n interrupt auslösen?
    in meinem fall isses n zeichen im UART-empfangspuffer.

    freddy

  5. #5
    RN-Premium User Begeisterter Techniker
    Registriert seit
    30.04.2004
    Alter
    46
    Beiträge
    245
    Du musst einfach das entsprechende Flag setzen. Lad dir das PDF vom ATMEGA32 oder was auch immer runter. Da steht drinnen, welches bit in welchem Register für das Auslösen der Interruptroutine verantwortlich ist.
    Das entsprechende Bit setzt du dann einfach im Debugmodus, und die Interrupt Routine wird ausgelöst.

    lg
    Alex

  6. #6
    Neuer Benutzer Öfters hier
    Registriert seit
    25.11.2004
    Beiträge
    17
    wenn ichs richtig gefunden habe, isses das RXC bit im UCSRA register. wenn ich in meinem prog in der endlosschleife bin und das rxc setze, springt er zwar woanders hin, aber nicht in die eigentlich interrupt-routine.

    genaugesagt springt er in die 'pwm_init:' unterfunktion in die zeile 'out OCR1AH, w'

    weiss aber nicht warum. stöber mal durch die atmega32-pdfs. vielleicht wartet mich da ja die erlösung...

    freddy0815

  7. #7
    RN-Premium User Begeisterter Techniker
    Registriert seit
    30.04.2004
    Alter
    46
    Beiträge
    245
    Hm, wollt mir grad die Doku zum Mega 32 runterladen, aber atmel.com scheint für mich nicht erreichbar zu sein. Nur so ein Verdacht ins blaue hinein: Hast du kontrolliert, ob $0007 wirklich der Interrupt einsprungpunkt ist? Mir scheint, das das daran liegt. Ich bin mir jetzt auch nicht ganz sicher, aber vermutlich legt der Compiler das Programm dann ab $0008 rein. Dadruch kann es eben zu diesen lustigen effekten kommen.
    Mein Vorschlag: Setz einfach mal alle Interrupteinsprungpunkte mit reti.
    Dann siehst du besser, wo er landet. Keine Ahnung wieviele Interrupt Quellen es beim Mega 32 gibt.

    .cseg
    .org $0000
    rjmp main
    reti ; Kommt an Adr. 1
    reti ; Kommt an Adr. 2
    reti ; Kommt an Adr. 3
    reti ; etc
    reti
    reti
    reti
    reti
    reti
    reti
    reti
    reti
    reti
    reti
    reti
    reti
    reti
    reti
    reti
    reti
    reti
    reti
    reti
    reti
    reti ; Ich hab nur soviele gemacht, weil ich nicht weiß, was es beim mega32 alles gibt. Dadurch deckst du sicher den ganzen einsprungraum ab.
    main:

    Alles klar?

    lg

    Alex

  8. #8
    RN-Premium User Begeisterter Techniker
    Registriert seit
    30.04.2004
    Alter
    46
    Beiträge
    245
    Kleine Frage noch nebenbei: War das Beispiel mit dem Mega 32 oder hast du selbst probiert es zu portieren? (Sph fehlte, Einsprungpunkt vermutlich falsch...). Dann tu ich mir auch gleich leichter, zu erkennen, woran du eventuell scheiterst...

    lg

    Alex

  9. #9
    Gast
    also ich hab nen atmega32. aber das programm is von nem kleineren kopiert. deswegen fehlte zb sph. kann dir jetzt leider nicht sagen welcher, da ich nicht mehr im labor bin. das mit reti werd ich versuchen. und mich dann spätestens nächste woche wieder melden! (wenn ichs dann ausprobiert hab)

    mfg
    freddy

    und danke für deine mühe!!

  10. #10
    Neuer Benutzer Öfters hier
    Registriert seit
    25.11.2004
    Beiträge
    17
    es lag an der interrupt adresse. hatte noch $0007 drin statt $01A.
    war auch noch n relikt ausm alten prog, das übrigens für ein at90s2313 geschrieben war.

    gruß
    freddy

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

LiFePO4 Speicher Test