Forum: Mikrocontroller und Digitale Elektronik Wo steckt der Fehler? ASM Source


von Reinhard (Gast)


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

von A.K. (Gast)


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.

von Chris (Gast)


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ß

von Peter D. (peda)


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

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.