mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Timer-Tutorial ATMega644


Autor: slimb0y (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich versuche das Programmbeispiel AVR-Tutorial: Timer auf meinem 
ATMega644 zum Laufen zu bekommen. Offenbar muss ich die Bezeichnungen 
für die Timer ändern, da der 644 3 davon hat, TIMSK0-2. Ebenso muss wohl 
auf TTCR0B zugegriffen werden, da TTCR0A andere Aufgaben hat und kein 
CS00 Flag hat.

Geändert habe ich also TCCR0 in TCCR1 und TIMSK in TIMSK0.

Build gibt mir aus, dass ihm der Operand (1<<TOIE0) nicht in TIMSK0 
passt.
Laut Datasheet besitzt dieses Register aber diesen Flag.
Fehlermeldung ist: Operand 1 out of Range.

Die Fehlerzeile:
         ldi     temp, (1<<TOIE0)      ; TOIE0: Interrupt bei Timer Overflow
->        out     TIMSK0, temp

Hier die Beschreibung vom fraglichen Flag von TIMSK0:

Bit 0 - TOIE0: Timer/Counter0 Overflow Interrupt Enable
When the TOIE0 bit is written to one, and the I-bit in the Status 
Register is set, the Timer/Counter0 Overflow interrupt is enabled. The 
corresponding interrupt is executed if an overflow in Timer/Counter0 
occurs, i.e., when the TOV0 bit is set in the Timer/Counter 0 Inter-
rupt Flag Register - TIFR0.

Muss ich das I-Bit manuell setzen? Ich denke, dass wird von SEI 
erledigt.

Ich hoffe, ich hab das Problem richtig rübergebracht, Vielen Dank im 
voraus für Lösungsansätze.

Autor: slimb0y (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Korrektur: statt TCCR0 habe ich TCCR0B benutzt (Prescaler), im 
Originalcode TCCR0.

Hier noch einmal main: komplett.
main:
        ldi     temp, LOW(RAMEND)     ; Stackpointer initialisieren
        out     SPL, temp
        ldi     temp, HIGH(RAMEND)
        out     SPH, temp
  
        ldi     temp, 0xFF            ; Port B auf Ausgang
        out     DDRC, temp
 
        ldi     leds, 0xFF
     
        ldi     temp, (1<<CS00)       ; CS00 setzen: Teiler 1
        out     TCCR0B, temp
 
        ldi     temp, (1<<TOIE0)      ; TOIE0: Interrupt bei Timer Overflow
        out     TIMSK0, temp
 
        sei

Autor: Stefan B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Offensichtliches Problem: Die Endlosschleife am Ende von main fehlt!

  sei          ; Ende deines Codes

endlos:        ; neuer Code
  RJMP endlos  ; neuer Code


Die zum Timer0-Overflow-Interrupt gehörende Interrupt Service Routine 
(ISR) gibt es auch? Und die ist an der richtigen Vektorposition 
eingetragen (.org xxx)?

Autor: Stefan B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>        ldi     temp, 0xFF            ; Port B auf Ausgang
>        out     DDRC, temp

Gehört fast schon ins Kapitel "Superkommentare" ;-)

Autor: slimb0y (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Kommentar ist vom Original kopiert. :-)
DDRC ist für mich schon korrekt, da dort die LED sitzt.

Zum Vektor: Ich bin nicht sicher, ich fuchtel zum ersten Mal mit 
Interrupts rum. :-)

Im Datasheet kann ich nichts zu OVF0addr finden, in der m644def steht es 
aber drin:
.equ  OVF0addr  = 0x0024  ; Timer/Counter0 Overflow


Zur Schleife: Im Original ist die nächste Zeile
loop:   rjmp    loop

Hätte wohl den kompletten Code einfügen sollen, bin noch nicht erfahren, 
wie ihr das am Liebsten habt. :-)

Also hier einmal komplett, ist ja nicht so gross:
.include "m644def.inc"

.def temp = r16
.def leds = r17
 
.org 0x0000
        rjmp    main                  ; Reset Handler
.org OVF0addr
        rjmp    timer0_overflow       ; Timer Overflow Handler
 
main:
        ldi     temp, LOW(RAMEND)     ; Stackpointer initialisieren
        out     SPL, temp
        ldi     temp, HIGH(RAMEND)
        out     SPH, temp
  
        ldi     temp, 0xFF            ; Port B auf Ausgang
        out     DDRC, temp
 
        ldi     leds, 0xFF
     
        ldi     temp, (1<<CS00)       ; CS00 setzen: Teiler 1
        out     TCCR0B, temp
 
        ldi     temp, (1<<TOIE0)      ; TOIE0: Interrupt bei Timer Overflow
        out     TIMSK0, temp
 
        sei
 
loop:   rjmp    loop
 
timer0_overflow:                      ; Timer 0 Overflow Handler
        out     PORTC, leds
        com     leds
        reti

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>timer0_overflow:                      ; Timer 0 Overflow Handler
>        out     PORTC, leds
>        com     leds
>        reti

Spielt in dem Programm noch keine Rolle, aber du solltest dir angewöhnen 
in der Interruptroutine SREG und die die verwendeten Register zu 
sichern.

timer0_overflow:                      ; Timer 0 Overflow Handler
        push temp
        in temp,SREG
        push temp

        out     PORTC, leds
        com     leds

        pop temp
        out SREG,temp
        pop temp
        reti

MfG Spess

Autor: Stefan B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Funktioniert, wenn du

        out     TIMSK0, temp

in

        STS     TIMSK0, temp

änderst. TIMSK0 ist beim Atmega644 memory-mapped und du kommst da mit 
OUT nichtdran (Build Meldung im Assembler2 beachten).

Deine ISR wird alle 255 µs aufgerufen, wenn der Atmega644 mit 1 MHz 
läuft (Stopwatch im Simulator).

Autor: Stefan B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
255 µs LED schalten ist fürs Auge viel zu schnell. Ich würde den 
Prescaler 1024 benutzen. 261 ms LED Blinken ist sichtbar.

Autor: slimb0y (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke an euch Beiden, läuft nun.

Der Prescaler war in dem Tutorial absichtlich erstmal ungeteilt für die 
Simulation. Die Fehlermeldung "error: Operand 1 out of range: 0x6e" hat 
mir nicht gerade weitergeholfen.
Wo hätte ich denn nachlesen können, das dieses Flag nicht per OUT 
gesetzt werden kann?

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Wo hätte ich denn nachlesen können, das dieses Flag nicht per OUT
>gesetzt werden kann?

Im Datenblatt ist relativ weit hinten eine Tabelle mit den IO-Registern 
('Register Summary'. Die Register bis zu den Adressen 0x3F (0x5F) lassen 
sich per in/out ansprechen.

MfG Spess

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.