www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Timer0 bei Bedarf


Autor: steffen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

sorry für diese Timer Frage, aber irgendwie versteh ich das nicht so 
richtig. Ich möchte einen Timer per Tastendruck einschalten und wenn die 
Zeit abgelaufen ist wieder ausschalten. Wie kann ich das per Assembler 
machen? Muss ich da einen Interrupt setzen?

Danke für die Hilfe.
Steffen

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit welchem Mikrocontroller möchtest du denn das machen?

Und wie lange soll der Timer0 denn laufen?

Und wie möchtest du erkennen, dass der Timer0 noch nicht läuft, gerade 
läuft oder abgelaufen ist?

Ich denke das Projekt ist noch nicht ganz durchdacht :)

Autor: Mh. M. (mhm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, dafür musst du einen Interrupt verwenden, denn anders den Timer 
abzufragen ist ziemlich aufwändig (falls es überhaupt möglich ist ohne 
Interrupt). Du könntest z.B. den Pin an dem der Taster hängt mit einem 
Timer pollen und sobald der Taster gedrückt wurde zählst du eben eine 
Variable hoch, bis die von dir gewünschte Zeit erreicht ist. Kannst 
natürlich auch den Tastaer irgendwie anders abfragen und dann den Timer 
starten bzw. stoppen, kommt drauf an wie dein Programm ist...

Autor: steffen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo und danke für die schnelle antwort.
na das soll mit einem mega8 laufen. das soll eine art nachlaufsteuerung 
werden. d.h. ich schalte per taster ein und wieder aus. wenn man nicht 
ausschaltet dann soll der Timer das nach x sekunden machen. was mir 
fehlt ist, wie schaltet man den timer ein und wieder aus?

danke & gruß steffen

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
steffen schrieb:
> Hallo zusammen,
>
> sorry für diese Timer Frage, aber irgendwie versteh ich das nicht so
> richtig. Ich möchte einen Timer per Tastendruck einschalten und wenn die
> Zeit abgelaufen ist wieder ausschalten.

Das Wort "Timer" kann verschiedene Bedeutungen haben. Timer0 ist eine 
Hardware-Einheit im AVR, die Takte zählt und Interrupts auslösen kann.

Du willst aber eine Art Eieruhr realisieren. Der Timer0 kann dazu 
hilfreich sein, ist aber alleine erstmal untauglich weil er zu schnell 
ist.

> Wie kann ich das per Assembler
> machen?

Da gibt es verschiedene Möglichkeiten. Im Prinzip macht man sich da 
einen geeigneten Zeittakt, in dem man eine Count-Down-Variable prüft und 
herunterzählt. Ist sie schon 0, dann lässt man sie in Ruhe, ist sie 
nicht 0, dann zählt man sie herunter. Wird sie dabei 0, dann schaltet 
man aus. Bei Tastendruck schaltet man ein und setzt die Zählvariable auf 
Startwert.

> Muss ich da einen Interrupt setzen?

Ein Timer-Interrupt ist zum Erzeugen des Zeitnormals (Zeittaktes) und 
zum Entprellen des Tasters sehr hilfreich. Ich würde es nicht ohne 
Timer-Interrupt machen wollen.

>
> Danke für die Hilfe.
> Steffen

...

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
steffen schrieb:
...
> was mir
> fehlt ist, wie schaltet man den timer ein und wieder aus?

Falsche Frage...

Du solltest Dich mehr dafür interessieren:
- Wie erzeuge ich mit einem Timer einen Zeittakt?
- Wie entprelle ich mit einem Timer Tasten?
- Wie reagiere ich auf Tastendruck?
- Wie programmiere ich einen Count-Down?

...

Autor: steffen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja genau da liegt mein problem. ich versteh nicht wie man den timer ein 
oder ausschalten kann. das mit der zeittberechnung und der dauer eines 
impulses versteh ich. nun fehlen mir nur noch die befehle wie ich den 
timer mit einer taste einschalte und wenn die zeit rum ist wieder aus. 
:-)

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>ich versteh nicht wie man den timer ein oder ausschalten kann.

Sieh dir mal im Datenblatt die Beschreibung der CS-Bits in TCCR0B an.

MfG Spess

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
steffen schrieb:
> ja genau da liegt mein problem. ich versteh nicht wie man den timer ein
> oder ausschalten kann. das mit der zeittberechnung und der dauer eines
> impulses versteh ich.

Das glaub' ich nicht, Du unterscheidest vermutlich noch nicht zwischen 
Timer und Timer (Timer als Hardware-Teil des Mega8 und Timer als 
Eieruhr).

> nun fehlen mir nur noch die befehle wie ich den
> timer mit einer taste einschalte

Die gibt es nicht, die musst Du Dir selbst basteln. Die Hardware-Einheit 
Timer0 hat einige "Schalter", mit denen sie bedient wird. Diese liegen 
als Register im I/O-Bereich des AVRs und können per Software bedient 
werden. Und diese Schalter sind im Datasheet des Mega8 (oder des 
betreffenden anderen AVRs) haarklein beschrieben. Also Datasheet 
besorgen (gibts kostenlos bei Atmel), lesen, verstehen und danach 
handeln.

> und wenn die zeit rum ist wieder aus.

Durch den Befehl CBI, wenn die Ausschaltbedingung erreicht ist.

...

Autor: steffen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja und das hab ich schon mehrfach und eineige dokus gelesen. nur leider 
startet der timer immer automatisch :-(

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Stefan Wimmer (wswbln)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
...Hannes hat in seiner Auflistung weiter oben noch zwei wichtige Punkte 
vergessen:

- wie erstelle ich eine Anforderungsspezifikation (und wenn's nur eine 
Stichpunktliste ist, was das Gerät genau machen soll) und
- wie erstelle ich einen Programmablaufplan (nach welcher "Religion" 
auch immer: Nasi-Schneider oder sonstwas).

Soll der "Timer" z.B. nachtriggerbar sein?

Autor: steffen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
genau da seh ich nicht druch. ich hab das jetzt so mal getestet. nur 
irgendwie passiert nix. die ausgänge sollten wenigstens blinken.
.include "m8def.inc"

.def temp = r16
.def leds = r17

rjmp main  ;reset
rjmp taste1  ;Int0
;reti    ;Int1
;reti    ;TC2 Compare
;reti    ;TC2 Overflow
;reti    ;TC1 Capture
;reti    ;TC1 Compare A
;reti    ;TC1 Compare B
;reti    ;TC1 Overflow
rjmp timer0_overflow    ;TC0 Overflow
;reti    ;Serial Transfer complete
;reti    ;UART Rx complete
;reti    ;UART Data Register
;reti    ;UART Tx complete
;reti    ;ADC
;reti    ;EEPROM Ready
;reti    ;Analog Comperator
;reti    ;2-wire Serial
;reti    ;SPM ready

main:
        ; Stackpointer initialisieren
        ldi     temp, HIGH(RAMEND)
        out     SPH, temp
        ldi     temp, LOW(RAMEND)     
        out     SPL, temp
  
        ldi     temp, 0xFF            ; Port D auf Ausgang
        out     DDRD, temp
 
        ldi     leds, 0xFF
     
    ldi temp, (1<<ISC01)  ; INT0 auf fallende Flanke konfigurieren
         out MCUCR, temp
 
         ldi temp, (1<<INT0)   ; INT0 aktivieren
         out GICR, temp


        ldi     temp, (1<<CS00)|(1<<CS02)       ;Teiler setzen
        out     TCCR0, temp

        sei
 
loop:   rjmp    loop

taste1:
    ldi     temp, (1<<TOIE0)      ; TOIE0: Interrupt bei Timer Overflow
        out     TIMSK, temp
    reti
 
timer0_overflow:                      ; Timer 0 Overflow Handler
        out     PORTD, leds
        com     leds
        reti

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
steffen schrieb:
> ja und das hab ich schon mehrfach und eineige dokus gelesen. nur leider
> startet der timer immer automatisch :-(

Wieso leider??

Also ich würde das Vorhaben so lösen:

- Mit einem Timer im CTC-Modus einen Zeittakt von 20 ms erzeugen. Es 
wird also alle 20 ms ein Interrupt ausgelöst, und das immer, also egal, 
ob die "Zeit läuft" oder ob das Ding in Bereitschaft ist.

- In diesem Interrupt würde ich die Tasten entprellen Entprellung 
und einen Vorteiler laufen lassen, der mir jede 50. Runde (alle 1,00 
Sekunde) eine Routine zum Bedienen des Count-Downs (des Software-Timers) 
aufruft.

- In dieser würde ich den Timeout-Zähler auf 0 prüfen. Ist er 0, bin ich 
fertig. Ist er nicht 0, würde ich ihn vermindern. Wird er dabei 0, dann 
würde ich mit CBI Schaltport,Schaltbit den Ausgang abschalten.

- In der Mainloop würde ich die Tastenflags prüfen, die von der 
Entprellroutine im Hintergrund bereitgestellt werden. Signalisiert ein 
Tastenflag einen neuen Tastendruck, dann wird die zugehörige Aufgabe 
erledigt. Bei der Starttaste ist das das Einschalten des Schaltports 
(mit SBI Schaltport,Schaltbit) und das Setzen des Count-Down-Zählers auf 
den Startwert (LDI CDZ,Startwert). Und natürlich noch das Entwerten 
(Rücksetzen) des Tastenflags, denn der Job ist ja erledigt. Den Rest der 
Mainloop würde ich den Mega8 bis zum nächsten Interrupt schlafen lassen.

- In der Initialisierung (Reset-Routine) würde ich den Stackpointer, die 
I/O-Ports und den Timer initialisieren, dazu noch ein paar Kleinigkeiten 
wie z.B Sleep-Mode IDLE.

Mit diesem Konzept hätte ich dann später alle Freiheiten, das Programm 
zu erweitern, ohne dass ich bereits realisierte Funktionalität wieder 
ändern muss.

...

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan Wimmer schrieb:
> ...Hannes hat in seiner Auflistung weiter oben noch zwei wichtige Punkte
> vergessen:
>
> - wie erstelle ich eine Anforderungsspezifikation (und wenn's nur eine
> Stichpunktliste ist, was das Gerät genau machen soll) und
> - wie erstelle ich einen Programmablaufplan (nach welcher "Religion"
> auch immer: Nasi-Schneider oder sonstwas).

Richtig, aber darauf hatte ich keinen Bock, da ich das erst in einem 
anderen Thread sehr deutlich getan habe:
Beitrag "Re: Verzweigungen"

>
> Soll der "Timer" z.B. nachtriggerbar sein?

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier ist ein Beispiel einer Eieruhr, das allerdings etwas umfangreicher 
ist (7-Segment-Anzeige, Tastenmatrix, Piepser). Da solltest Du Dir 
erstmal die Interrupt-Sprungtabelle ansehen:
http://www.mikrocontroller.net/attachment/23620/eieruhr1.asm
Deine kann nämlich nicht funktionieren, da sie auskommentiert ist.

Der zugehörige Thread (zum Nachlesen und Lernen) ist hier:
Beitrag "Re: 7 Segmentanzeige falsch eingekauft, reagiert nur auf low"

...

Autor: steffen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich seh da nicht durch. wenn ich über interrupt den timer nehme 
blockiert der das ich die tasten drücken kann. is mir bissel zu viel. 
ich nehm für meine schaltung einfach einen externen zeitbaustein. 
unabhängig vom atmega.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
steffen schrieb:
> ich seh da nicht durch.

Deine Vorstellungswelt ist falsch.

Du lebst in der Vorstellung, dass du den Timer startest und stoppst. 
Aber das tust du nicht! Der Timer läuft die ganze Zeit durch und 
generiert mit seinem Interrupt ein regelmässiges Signal.

Analogie:
Deine Stoppuhr am Handgelenk.
Die Feder im Inneren läuft die ganze Zeit und generiert ein 
Zehntel-Sekunden Signal. Drückst du den Startknopf, wird der Zeiger an 
die Uhrenmechanik gekoppelt und der Zeiger beginnt zu ticken. Drückst du 
den Stopp-Knopf, so wird der Zeiger von der Uhrenmechanik wieder 
entkoppelt und der Zeiger bleibt stehen. Aber die eigentliche 
Uhrenmechanik läuft die ganze Zeit weiter unabhängig davon, ob der 
Zeiger an der Mechanik hängt oder nicht.


Genauso kann man das programmierern. Der Timer Baustein in deinem 
Programm läuft die ganze Zeit durch. In der ISR wird eine Variable 
abgeprüft, ob sie 1 oder 0 ist. Ist sie 1, dann wird die Zeitvariable, 
die angibt wieviel Zeit noch verstreichen soll bis 0 erreicht ist, immer 
erniedrigt. Ist die Variable 0, dann passiert gar nichts (zumindest 
nicht mit deiner Zeitsteuerung)

Ein Tastendruck für Start setzt jetzt einfach die Variable auf 1 und 
koppelt so, bildlich gesprochen, den Zeiger ans Uhrwerk. Ein anderer 
Tastendruck setzt besagte Variable auf 0, und entkoppelt so den Zeiger 
wieder vom Uhrwerk. Anstelle eines 2.ten Tastendrucks kann sich 
natürlich auch die Zeitsteuerung selber den Takt abdrehen. Jeder der 
will kann besagte Variable auf 0 setzen und so die Eieruhr anhalten.

Aber der Timer läuft weiterhin durch und erzeugt regelmässige ISR 
Aufrufe. Der wird nie ausgeschaltet.

Autor: steffen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok, dann geht das bei mir nicht über interrupt, oder ich kann für die 
tast keinen interrupt nehmen. so lange der timer läuft blokiert er mir 
alles :-(
hier noch mal das komplette programm:
main:       ; hier beginnt das Hauptprogramm
 
         ldi temp, LOW(RAMEND)
         out SPL, temp
         ldi temp, HIGH(RAMEND)
         out SPH, temp     

         ldi temp, 0x00
         out DDRD, temp
 
         ldi temp, (1<<ISC01)  ; INT0 auf fallende Flanke konfigurieren
         out MCUCR, temp
 
         ldi temp, (1<<INT0)   ; INT0 aktivieren
         out GICR, temp
     
  ldi temp, (1<<CS02) | (1<<CS00)   ; Teiler 1024
         out TCCR0, temp
 
         clr SubCount
  
  ldi ZL,low(daten)     ; der Z-Zeiger wird hier exclusiv
  ldi ZH,high(daten)    ; für die Datenadressierung verwendet
     
     ldi r17, 0

         sei                   ; Interrupts allgemein aktivieren
 
loop:    rjmp loop             ; eine leere Endlosschleife
 
taste1:
     cpi r17, 1      ;R17 auf 1 prüfen
     breq aus        ;breq = gleich 1
         brne ein      ;brne = ungleich 1
         reti

ein:  
    ldi temp, 0xFF    ;als Ausgang setzten
        out DDRD, temp
    
    sbi PORTD, 5    ;PD 5 = ein

    ldi r17, 1      ;merken 1 = auf
    ldi temp, 1      
    
    rcall EEPROM_write  ;im EEprom speichern

    ldi temp, 1<<TOIE0     ; TOIE0: Interrupt bei Timer Overflow
        out TIMSK, temp

    reti 

aus:  
    ldi temp, 0   ; Timer aus
        out TCCR0, temp
    
    ldi temp, 0xFF
        out DDRD, temp
    
    cbi PORTD, 5
    cbi PORTD, 6

    ldi r17, 0
    
    reti

tc0_o:
        push    temp               ; temp 1 sichern
        in      temp,sreg          ; SREG sichern
        push    temp
 
        inc     SubCount            ; Wenn dies nicht der 15. Interrupt
        cpi     SubCount, 15        ; ist, dann passiert gar nichts
        brne    end_isr
 
        rcall aus

end_isr:
 
        pop     temp
        out     sreg,temp          ; sreg wieder herstellen
        pop     temp
        reti                       ; das wars. Interrupt ist fertig

Autor: Stefan Wimmer (wswbln)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aua aua!

Wenn das das komplette Programm ist, dann fangen wir mal ganz vorne an: 
Wo ist die Interruptvektortabelle?

Zum Rest werden sicher andere noch gebührend Stellung nehmen...

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> ok, dann geht das bei mir nicht über interrupt, oder ich kann für die
> tast keinen interrupt nehmen. so lange der timer läuft blokiert er mir
> alles :-(

Schau Dir nochmal die Interrupt-Sprungtabelle Deines ersten Listings an. 
Du hast alle unbenutzten Zeilen auskommentiert, wodurch die Platzhalter 
(reti) verloren gingen und die Sprünge nicht mehr zu den 
Interruptquellen passen. Daher landet Dein Timer-ISR-Sprung auf dem 
Platz des Ext-Int1. Da Dir dadurch 16 Platzhalter fehlen, beginnt Dein 
Programm bereits in dem Adressbereich, der für die Interrupt-Sprünge 
reserviert ist. Tritt nun das Ereignis für den Timer-Interrupt auf, so 
wird einfach mitten in den Initialisierungscode gesprungen, was 
natürlich in die Hose geht.

> hier noch mal das komplette programm:

Das ist nicht komplett, da fehlt der ganze Deklarationsbereich und die 
Interrupt-Sprungtabelle. Da man nicht sieht, ob Du die Fehler in der 
Sprungtabelle beseitigt hast, kann man auch nicht wissen, ob es 
funktionieren könnte.

Aber unabhängig davon:

Wenn ich Dein Programm sehe, muss ich davon ausgehen, dass Du keinen 
meiner oben genannten Links verfolgt, gelesen und verstanden hast.

Tasten fragt man nicht mit externen Interrupts ab, das macht man mit 
einer Entprellroutine im Timer-Interrupt. Da dieses Thema hier schon 
hunderte mal durchgekaut wurde, verweise ich auf das Wiki 
Entprellung. Dort gibt es weiterführende Links zu Beispielen und 
Diskussionen.

Da man zu diesem Zweck sowiso einen Timer braucht, lohnt es sich, seine 
Interrupt-Frequenz so zu wählen, dass sie zum Entprellen und zum 
Bedienen des Time-Outs (das Du cool "Timer" nennst) geeignet ist.

Alles Andere haben Karl-Heinz und ich oben bereits genannt. Lies diesen 
Thread einfach noch mal von vorn. Und lies diesmal gründlich und 
verfolge die Links.

Ehe Du einen weiteren (unsinnigen) Quelltext postest, solltest Du 
erstmal über das Konzept nachdenken.

...

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.