mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Mega88: Mehrere Interupts? (NOP funktioniert nicht)


Autor: Silver69 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Frohes Neues an alle ;-)

Nachdem der UART nun läuft wollt ich (eigentlich noch vor dem essen :P) 
den Timer0 zum laufen bringen.

Hier mein Code:
.include "m88def.inc"
 
.org 0x0000
        rjmp main
 
.org URXCaddr                     ; Interruptvektor für UART-Empfang
        rjmp int_rxc
 
.org OVF0addr
       rjmp timer0_overflow       ; Timer Overflow Handler

 
; Hauptprogramm
 
main:
      nop
      nop
int_rxc:
reti
timer0_overflow:
reti



Die Fehlermeldung, beim compilieren lautet:

D:\Eigene Dateien\Mega88\Mega88ROMTest.asm(33): error: Overlap in .cseg: 
addr=0x12 conflicts with 0x12:0x13

Diese tritt übrigens beim zweiten NOP Befehl auf

Was mache ich nun schon wieder falsch?

Autor: Marius Wensing (mw1987)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So wird das ja auch nix.

Das ist kein lauffähiges Programm.

Füge mal nach dem zweiten nop nen rjmp main ein.

MfG
Marius

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

einmal siehe Marius Wensing (mw1987), ist aber nicht die Ursache für die 
Fehlermeldung.

Geh doch den Ablauf für den Assembler einfach mal "zu Fuß" durch:

.org 0x0000 -> assembliere an Adresse 0x0000
       rjmp main

.org URXCaddr -> assembliere ab Adresse 0x0012 ***
  rjmp int_rxc

.org OVF0addr -> asssembliere ab Adresse 0x0010
  rjmp timer0_overflow

-> der Assembler ist jetzt bei Adresse 0x0012 ***

ab hier soll er jetzt aber Deine main übersetzen, kann er aber nicht, 
weil Du ihm schon gesagt hast, daß dort der rjmp int_rxc hinsoll...

Siehe Vectorliste im Datenblatt.

Entweder die Vektoren in der Reihenfolge ihres Auftretens zuweisen, also
die Reihenfolge von

.org URXCaddr -> assembliere ab Adresse 0x0012 ***
  rjmp int_rxc
und
.org OVF0addr -> asssembliere ab Adresse 0x0010
  rjmp timer0_overflow

vertauschen oder
alle Vektoren in ihrer Reihenfolge eintragen

oder aber per .org vor der main festlegen, wo der Assembler weitermachen 
soll. Geht am Besten mit

.org INT_VECTORS_SIZE

vor main.

Ist in den AVR-includes definert auf die Länge der Vector-Liste.

Gruß aus Berlin
Michael

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>So wird das ja auch nix.
>Das ist kein lauffähiges Programm.

Quatsch. Das interessiert des Assembler herzlich wenig.

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

>.org OVF0addr
>       rjmp timer0_overflow       ; Timer Overflow Handler

Du kannst die .org nichr beliebig mischen

.org OVF0addr
       rjmp timer0_overflow       ; Timer Overflow Handler

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

OVF0addr ist kleiner als org URXCaddr. Damit platzierst du dein Main 
zwischen den beiden Adressen und dein Code überschneidet sich mit 'rjmp 
int_rxc'

Die Reihenfolge muss den Interruptvektoren entsprechen.

MfG Spess

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
spess53 wrote:
> Die Reihenfolge muss den Interruptvektoren entsprechen.
>
> MfG Spess
um dich mal zu zitieren:
> Quatsch. Das interessiert des Assembler herzlich wenig.
;)

Das einzige was man tun muß ist den Einsteigspunkt für die Main an die 
richtige stelle setzen nämlich INT_VECTORS_SIZE...

.org 0x0
        rjmp main
 
.org URXCaddr                     ; Interruptvektor für UART-Empfang
        rjmp int_rxc
 
.org OVF0addr
       rjmp timer0_overflow       ; Timer Overflow Handler

 
; Hauptprogramm
.org INT_VECTORS_SIZE
main:
rjmp main
int_rxc:
reti
timer0_overflow:
reti
Man kann die Vektoren dann belibig anordnen...

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

> MfG Spess
um dich mal zu zitieren:
> Quatsch. Das interessiert des Assembler herzlich wenig.

Dann sieh dir mal an, worauf sich das bezogen hat.

Ich weiss nicht, wer dieses .org-Gedödel erfunden hat (wahrscheinlich 
der Gleiche mit den 'tempxy'). Die Datenblattvariante wäre weniger 
irreführend gewesen.

MfG Spess

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

@spess53: ich finde das .org-Gedödel durchaus praktisch, auch die 
tempxy, allerdings heißen die bei mir TEMP_0 usw. ;-)
Warum soll ich x IRQ-Vectoren reinschreiben, wenn ich nur einen brauche?
Ja, man kann die kopieren, aber ich finde es lesbarer, wenn eben dann 
nur einer oder zwei dastehen.

Und seit Atmel netterweise INT_VECTORS_SIZE in den includes hat, erspart 
es selbst bei Änderungen auf eine andere CPU dann dort unnötige 
Korrekturen.

Gruß aus Berlin
Michael

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Warum soll ich x IRQ-Vectoren reinschreiben, wenn ich nur einen brauche?

Muss ich nicht. Ich kann mein Programmgerüst aus den XML-Dateien des 
AVR-Studios erzeugen.

> auch die tempxy, allerdings heißen die bei mir TEMP_0 usw. ;-)

Registerdefinitionen sind vielleicht bei kleinen Programmen hilfreich. 
Bei grösseren empfinde ich sie als störend. Wenn ein Register in einem 
Programm zig verschiedene Inhalte haben kann, muss ich entweder dauernd 
umdefinieren oder mit irrführenden Bezeichnungen leben. Beides ist für 
mich inakzeptabel.

MfG Spess

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Läubi Mail@laeubi.de wrote:

> Das einzige was man tun muß ist den Einsteigspunkt für die Main an die
> richtige stelle setzen nämlich INT_VECTORS_SIZE...

> Man kann die Vektoren dann beliebig anordnen...

Es geht sogar noch einfacher und übersichtlicher.
Man muß nicht umständlich alle Vektoren in ein File eintragen, sondern 
kann das auch erst direkt dort machen, wo man den Interrupthandler 
definiert.
Das geht am besten mit einem kleinen Macro:

.nolist
.include "m88def.inc"
.listmac
.list

.macro  INTHAND
        .set    _curr_addr = pc
        .org    @0
        rjmp    _curr_addr
        .org    _curr_addr
.endmacro


.org    0x0000
        rjmp main
.org    INT_VECTORS_SIZE
main:
;...
        rjmp    main
;...
        INTHAND URXCaddr
; handler code
        reti
;...
        INTHAND OVF0addr
; handler code
        reti

Das spart dann auch das Ausdenken eines Labels für den Handler.


Peter

Autor: spes53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Langsam dämmert es mir. Man muss also Assembler nur so unverständlich 
wie möglich zu machen, um den Einsatz sog. Hochsprachen zu 
rechtfertigen. Interessante Strategie.

MfG Spess

Autor: Sinusgeek (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Xundes Neues...

> Man muss also Assembler nur so unverständlich
> wie möglich zu machen, um den Einsatz sog. Hochsprachen zu
> rechtfertigen.

Hmmm... Da scheint was dran zu sein.

Das ist dann für mich ein Grund mehr, bei einfachem verständlichem 
überschaubarem Hobbybastler-ASM zu bleiben und wie bisher die komplette 
Interrupt-Vektorliste zu kopieren.

~

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
spes53 wrote:
> Langsam dämmert es mir. Man muss also Assembler nur so unverständlich
> wie möglich zu machen, um den Einsatz sog. Hochsprachen zu
> rechtfertigen. Interessante Strategie.

Ich vermute mal, Du bist ein Einzelkämpfer und hast daher weder die 
Notwendigkeit noch das Interesse, Deine Programme für andere besser 
lesbar und verstehbar zu machen.

Defines und Macros helfen aber nicht nur anderen, sondern auch einem 
selber, ältere Programme wieder schnell verstehen zu können.

Du hast natürlich recht, daß diese Hilfen ihren Ursprung in Hochsprachen 
haben.
Aber warum soll man denn nicht auch nützliche Dinge bei der 
Assemblerprogrammierung verwenden?

Assembler muß nicht automatisch spartsanisch und unübersichtlich sein.

Insbesondere, da ja neuere AVRs einige IO-Register im SRAM haben, ist 
ein Zugriffsmacro sinnvoll, welches automatisch IN/OUT bzw. LDS/STS 
benutzt.


Peter

Autor: Hmm... (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Peter:

Interessanter Ansatz. Einfach (wenn man den Preprozessor verstanden hat 
;) ) und effektiv. Das Makro dürfte vor allem wenn man für ein neues 
Feature in der Anwendung plötzlich doch noch ein paar Interrupts mehr 
benutzen möchte praktisch sein.

Danke für den Tip!


Für den Anfang bzw. zum lernen dürfte allerdings der Datenblatt-Ansatz 
günstiger sein, da man hier den Aufbau der Interrupt-Vektortabelle 
ständig vor Augen hat und sich nicht mit vom verwendeten Assembler 
abhängigen Konstrukten beschäftigen muss.
.org 0x00
    rjmp RESET        ; Reset Handler
    rjmp INT0         ; External Interrupt0 Handler
    rjmp INT1         ; External Interrupt1 Handler
    rjmp TIM1_CAPT    ; Timer1 Capture Handler
    rjmp TIM1_COMPA   ; Timer1 CompareA Handler
    rjmp TIM1_OVF     ; Timer1 Overflow Handler
    rjmp TIM0_OVF     ; Timer0 Overflow Handler
    rjmp USART0_RXC   ; USART0 RX Complete Handler
    rjmp USART0_DRE   ; USART0,UDR Empty Handler
    rjmp USART0_TXC   ; USART0 TX Complete Handler
    rjmp ANA_COMP     ; Analog Comparator Handler
    rjmp PCINT        ; Pin Change Interrupt
    rjmp TIMER1_COMPB ; Timer1 Compare B Handler
    rjmp TIMER0_COMPA ; Timer0 Compare A Handler
    rjmp TIMER0_COMPB ; Timer0 Compare B Handler
    rjmp USI_START    ; USI Start Handler
    rjmp USI_OVERFLOW ; USI Overflow Handler
    rjmp EE_READY     ; EEPROM Ready Handler
    rjmp WDT_OVERFLOW ; Watchdog Overflow Handler

main:
..

  rjmp main


Autor: Silver69 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Also es tut mir leid dass ich mich nicht für die Makro-Variante sondern 
für die einfache, die Adressen nach der Vektortabelle zu sortieren, 
entschieden habe... vielleicht später mal mit Makro ;-)

Eigentlich wollte ich jetzt nach so einer Interrupt-Vektortabelle 
fragen, ich habe die zwar irgendwo schon einmal gesehen, wusste aber 
nicht mehr wo. Nun, da ihr ja aber entweder Gedanken lesen könnt oder in 
die Zukunft sehen, habt ihr die Tabelle ja schon geposted bevor ich die 
Frage stellen konnte :-)

Der Timer läuft nun, Interrupt wird ausgelöst, trotzdem noch eine Frage:

Ich habe am Mega88 ein Quarzoszillator angeschlossen, 1.8 GHZ für RS232.
Der Timer0 läuft ohne Prescale. In der Interrupt Routine zähle ich dann 
noch ein Register hoch. Wenn dieses kleiner als 128 ist, schalte ich die 
LED an , andernfalls aus.

So etwa:

...
          ldi     r16, 0b00000001      ; Timer enable - Kein Prescale
          sts     TCCR0B, r16

          ldi     r16, 0b00000001      ; TOIE0: Interrupt bei Timer Overflow
          sts     TIMSK0, r16
 
          sei


...


timer0_overflow:
      lds r17, PWM

      lds R16, LED1
      cp r16, r17

      BRLO Led1AUS
      sbi PORTC,0    ;LED1 AN
      rjmp LED2Test
LED1AUS:  cbi PortC,0   ;LED1 AUS


LED2Test:

      inc R17
      sts PWM, R17
    

reti

...


OK, die "..." bedeuten, dass da noch mehr Code steht :-)
Das ich auch die Register R16 und R17 nicht sichere, ist mir auch 
bewusst (mach ich jetzt gleich).


Zur Frage:
Die LED sollte doch jetzt so schnell blinken, dass ich es mit dem Auge 
nicht sehen kann, oder? Aber aus irgendeinem Grund ist die Frequenz so 
niedrig, dass ich sie flackern sehe? Wieso?

Autor: Silver69 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
out     TCCR0B, r16

nicht

STS     TCCR0B, r16

muss es heißen ;-)

Autor: Silver69 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Meine letztes Posting könnte zur Verwirrung sorgen:

"out     TCCR0B, r16

nicht

STS     TCCR0B, r16

muss es heißen ;-)"

Bezieht sich auf einen COPY/Paste Fehler, der mir passiert ist, als ich 
den Code oben eingefügt habe. Soll aber NICHT heißen, dass das Problem 
"flackern" mit dieser Änderung gelöst ist....

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Aber aus irgendeinem Grund ist die Frequenz so
>niedrig, dass ich sie flackern sehe? Wieso?

CKDIV8 Fuse auf 1 gesetzt?

Autor: Gast (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
>Die LED sollte doch jetzt so schnell blinken, dass ich es mit dem Auge
>nicht sehen kann, oder?

Was für ein Ergebnis spuckt denn Deine Berechnung der Blinkfrequenz aus?

Ich komme auf 1843200 Hz : 256 : 256 = 28.125 Hz.

Eine mit dieser Frequenz bestromte LED wird nicht mehr als blinkend, 
sondern als dauerleuchtend, aber mit deutlichem Flimmern empfunden.

>Aber aus irgendeinem Grund ist die Frequenz so
>niedrig, dass ich sie flackern sehe? Wieso?

Wenn sich Deine LED eher schnell blinkend präsentiert, dann ist 
höchstwahrscheinlich die CKDIV8-Fuse enabled. Dann läuft Dein Controller 
nur mit 1843200/8 Hz und die LED mit ca. 3.5 Hz.

Hast Du eine Digitalkamera? Dann kannst Du die Frequenz leicht messen. 
Dazu darfst Du keinen Automatik-Modus verwenden, sondern musst die 
Verschlusszeit von Hand z. B. auf 1 Sekunde festsetzen. Dann die Kamera 
gleichmäßig während das Bild aufgenommen wird in größerem Abstand über 
die blinkende LED hinwegziehen. Sozusagen eine Luftaufnahme machen, mit 
Deinen Händen als "Flugzeug". Ergibt ein Bild wie im Anhang. Hier war 
die Verschlusszeit 1 s, und um die Blinkfrequenz der untersten LED zu 
bestimmen, musst Du nur die gelben Streifchen zählen. Sie hat mit 20 Hz 
geblinkt.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Silver69 wrote:
> Ich habe am Mega88 ein Quarzoszillator angeschlossen, 1.8 GHZ für RS232.

1,8GHz Quarzoszillator?

Autor: Silver69 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Das mit der Kamara ist eine gute Idee... das werde ich mal testen.
CKDIV8-Fuse ist nicht gesetzt. Wenn ich es setze, blinken die LEDs 
wirklich...

Zur Frequenzberechnung:

Ich dachte es wäre: 1843200 Hz : 256 : 2 =3600 HZ ?
Mit meinem Zähler (PWM = R17) teile ich doch nicht mehr durch 256 
sondern lediglich durch 2, oder?

Oder habe ich da einen Denkfehler drin?

Autor: Silver69 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist natürlich Quatsch... du hast Recht!
War ein Denkfehler von mir.
Ich muss den Zähler dann ja nur bis zb 128 zählen lassen, dann 
verdoppelt sich die Frequenz.

56 Hz müsste man dann nicht mehr blinken sehen können, denke ich mal...

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>56 Hz müsste man dann nicht mehr blinken sehen können

Nein, bei 40 Hz flirrt es noch ein ganz kleines bisschen, aber oberhalb 
ca. 50 Hz wirst Du das Leuchten als flimmerfrei wahrnehmen.

Die Kameramethode ist übrigens bis ca. 1 kHz praktikabel. Wenns mehr 
sein soll, braucht man dann doch einen Frequenzzähler ;-)

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Silver69 wrote:
> Also es tut mir leid dass ich mich nicht für die Makro-Variante sondern
> für die einfache, die Adressen nach der Vektortabelle zu sortieren,
> entschieden habe... vielleicht später mal mit Makro ;-)

Braucht Dir nicht leid zu tun, es gibt ja viele Wege, etwas zu tun.
Man sollte bloß nicht wie manch anderer sagen: "Alles was ich nicht 
benutzte, ist Mist", sondern auch mal andere Meinungen zulassen.

Der Grund, warum ich Macros bevorzuge, ist auch, daß ich viele 
verschiedene AVRs benutze und dann sind die Vektortabellen 
unterschiedlich.

Wenn Dir z.B. der Flash ausgeht und Du schnell mal auf den ATmega168 
upgraden willst, zeigt Deine Vektortabelle in den Wald.
Die .ORG-Anweisungen stimmen dagegen immer noch.


Peter

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.