Wo steckt der Fehler? ASM Source

Gast #135730
Lesenswert?

Hallo,

ich verzweifel gerade etwas an einem kleinen ATmega8 evtl. hat hier
jemand einen Rat oder Tipp was ich falsch mache oder übersehe.
Schaltung wie hier im Tutorial mit folgendem Programm:

-----------------------------------------------------------
.include "m8def.inc"

.def temp = R16
.equ CLOCK = 3686411
.equ BAUD = 9600
.equ UBRRVAL = CLOCK/(BAUD*16)-1

.org 0x00
        rjmp main

.org URXCaddr                 ;Interruptvektor für UART-Empfang
        rjmp int_rxc

;Hauptprogramm
main:
        ldi temp, LOW(RAMEND)
        out SPL, temp
        ldi temp, HIGH(RAMEND)
        out SPH, temp

        ; Baudrate einstellen
        ldi temp, LOW(UBRRVAL)
        out UBRRL, temp
        ldi temp, HIGH(UBRRVAL)
        out UBRRH, temp

        ; Frame-Format: 8 Bit
        ldi temp, (1<<URSEL)|(3<<UCSZ0)
        out UCSRC, temp

        sbi UCSRB, RXCIE            ;Interrupt bei Empfang
        sbi UCSRB, RXEN             ;RX (Empfang) aktivieren
        sbi UCSRB, TXEN             ;TX (Senden) aktivieren

  ldi temp, 0x01       ;0x01 ins Arbeitsregister r16 laden
        out DDRC, temp       ;Inhalt von r16 ins IO-Register DDRC
ausgeben

  ldi temp, 0x01
        out PORTC, temp      ;PORTC auf 0x01 setzen -> Port PC0

        sei                  ;Interrupts global aktivieren

loop:
  cbi PINC, 0    ;An
  rcall wait    ;warten
  sbi PINC, 0    ;aus
  rcall wait    ;warten

        rjmp loop               ;Endlosschleife

;Interruptroutine: wird ausgeführt sobald ein Byte über das UART
empfangen wurde
int_rxc:
        push temp
        ldi temp, 'H'
        rcall serout
        ldi temp, 'a'
        rcall serout
        ldi temp, 'l'
        rcall serout
        ldi temp, 'l'
        rcall serout
        ldi temp, 'o'
        rcall serout
        ldi temp, 10
        rcall serout
  ldi temp, 13
        rcall serout
        pop temp                          ; temp wiederherstellen
        reti                              ; Interrupt beenden



serout:
        sbis UCSRA,UDRE           ;Warten bis UDR für das nächste
                                  ;Byte bereit ist
        rjmp serout
        out UDR, temp
        ret

wait:
; =============================
;    delay loop generator
;     18432000 cycles:
; -----------------------------
; delaying 18431985 cycles:
          ldi  R17, $A9
WGLOOP0:  ldi  R18, $92
WGLOOP1:  ldi  R19, $F8
WGLOOP2:  dec  R19
          brne WGLOOP2
          dec  R18
          brne WGLOOP1
          dec  R17
          brne WGLOOP0
; -----------------------------
; delaying 15 cycles:
          ldi  R17, $05
WGLOOP3:  dec  R17
          brne WGLOOP3
; =============================

  ret

------ENDE-------

Das Problem ist ich bekomme weder eine serielle Verbindung zum
Controller noch blinkt Port PC0. Der Controller lässt sich mit YAAP
einwandfrei beschreiben und auslesen.


Guten Rutsch
Reinhard
Gast #135731
Lesenswert?

Blinken wird's so sicher nicht. PINC und PORTC verwechselt.

Die Interrupt-Routine ist bemerkenswert - statt den Status zu retten,
ein konsequenter Verzicht auf alle Befehle die was dran ändern ;-).
Sieht man nicht oft.
Gast #135732
Lesenswert?

Hallo,

folgendermaßen würde ich die Interruptroutine noch abändern und wie
oben schon gesagt noch statt PINC PortC schreiben.

;Interruptroutine: wird ausgeführt sobald ein Byte über das UART
empfangen wurde
int_rxc:
        push temp
  in temp,SREG  ; Statusregister sichern
  push temp  ; dito
        ldi temp, 'H'
        rcall serout
        ldi temp, 'a'
        rcall serout
        ldi temp, 'l'
        rcall serout
        ldi temp, 'l'
        rcall serout
        ldi temp, 'o'
        rcall serout
        ldi temp, 10
        rcall serout
        ldi temp, 13
        rcall serout
        pop temp1    ; Statusregister vom Stack holen
  out SREG, temp1    ; dito
        pop temp               ; temp wiederherstellen
        reti

Gruß
#135733
Lesenswert?

Man sollte sich solche Art der schlechten Interruptprogrammierung
garnicht erst angewöhnen. Das verstößt nämlich gegen die ersten 3
Lehrsätze der Interruptprogramierung:

1. Halte Interrupts so kurz wie möglich
2. Halte Interrupts so kurz wie möglich
3. Halte Interrupts so kurz wie möglich

Und serielle Ausgabezeiten nutzlos zu verwarten, gulpt hier schon
stolze 19200 Zyklen kostbarer CPU-Zeit:

3686411 / 9600  10  5


Peter

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren