www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Langzeit Timer mit ATtiny11 Kleine Steuerungsaufgabe


Autor: Jan Purrucker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich bin absoluter MikroController-Einsteiger und möchte nun meine erste 
kleine Steuerungsaufgabe lösen:

PB0 soll für ca. 1 Stunde auf "logisch 1" sein, dann für ca. 15 Sekunden 
auf "logisch 0" sein, dann wieder für ca. 1 Stunde auf "logisch 1" und 
sofort (periodisch fortgesetzt). Dazu brauche ich irgendwie einen Timer 
für 1 Stunde und für 15 Sekunden, alles +- 20%, also nur ungefähr.
Als Quarz nehme ich den internen mit 1MHz.
Kann mir jemand einen Assembler Code-Schnipsel mit

- Timer Initialisierung
- Schleifen für die zwei Zeiten

kurz schreiben? Im AVR Tutorial und im Netz hab ich mich schon 
erkundigt, jedoch nichts brauchbares für dieses (ich denke) einfache 
Problem gefunden.
Ich wäre wirklich riesig erfreut, wenn jemand einen 
Assembler-Code-Schnipsel (ohne drum herum) schreiben könnte, oder mir 
einen Link sagen könnte.
Vielen Dank schon einmal für unterstützende Hilfen.

Gruß
Jan Purrucker
(aus dem Schwaben-Ländle)

Autor: Tim (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zwar kein vollständiger Code aber ein parr tipps (ohne Gewähr):
; Timer 0: Overflow IRQ alle CLK/1024/256 Ticks -> 0.262144 Sec
  ldi  r16, 0b00000101    ;clk/1024 -> 1,024mSec Periode
  out  TCCR0, r16
  ldi  r16, 0b00000010    ; enable overflow irq
  out  TIMSK, r16
  clr  r16      ; reset counter
  out  TCNT0, r16
Damit kommt der Overflow Irq alle 0.262144 Sec.
Dann must du im IRQ nur noch feststellen welcher der beiden
Zeiten laufen soll und dementsprechend von
0 bis 3600Sec/0.262144 Sec = 13733 oder
0 bis 15Sec/0.262144 Sec = 57 zählen.

Wenn der zähler seinen wert erreicht hat zurücksetzen, port
umschalten und in einem Register speichern das jetzt der andere
Zähler dran ist.

als Hauptprogramm braucht du dann nur noch eine endlosschleife, ggf
mit einem sleep befehl drin

btw: die internen Taktgeneratoren der AVRs sind keine Quarze sondern 
RC-glieder! Du solltest dir also mal die sache mit dem OSCCAL ansehen...

Autor: Jan Purrucker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Hilfe!

Du hast Recht, es ist ein RC Glied der interne Takt. Der ist relative 
ungenau. Aber ich brauche die Zeiten wie gesagt nur ungefähr so genau, 
daher brauche ich auch kein OSCCAL, sondern muß nur die Fuse-Bits 
entsprechend auf den internen Oszillator einstellen.
Die Entscheidung, ob ich bis 57 oder 13733 zähle mache ich dann, indem 
ich den Status des PB0 abfrage.
Ich versuch mich mal demnächst, und frage hier wieder, sollte was nicht 
funktionieren.
Vielen Dank nochmals für die Hilfe.

Gruß
Jan

Autor: kurfa (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Warum ATtiny11? Wäre nich ATtiny12, oder ATtiny13 besser? (tiny11 kann 
man nur mit assembler programieren...)

Autor: sechseinssechs (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Problem ist genuegend trivial um mit ASM geloest zu werden.

Autor: sechseinssechs (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ob Zaehler0 oder Zaehler1 laeuft sollte man sich in einer Variablen und 
nicht in einem Portbit merken.

Autor: AVRFan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist sehr einfach zu machen. Du brauchst nur zwei ineinander 
verschachtelte Software-Teiler.  Der eine teilt durch 57 (von 0.262144 s 
auf 14.9422 s), der zweite von 14.9422 s auf ca. 1 h).  Nach dem 
Zählerstand des zweiten schaltest Du den Portpin: "High" wenn 
Zählerstand = 0, "Low" wenn Zählerstand = 1, 2, 3 ... 239.  Das ist 
alles.
TOOverflowInterrupt:

// wird alle 0.262144 s durchlaufen

inc k
IF (k=57) 
    {
    // wird alle 57*0.262144 s = 14.9422 s durchlaufen

    k = 0
 
    inc i
    IF (i=240) 
        {
        i = 0
        }

    PortState = 0
    IF (i=0) PortState = 1

    [PortState auf gewuenschten Portpin ausgeben]
    }

Autor: Jan Purrucker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo AVRFan,

vielen Dank für die nette Erklärung. Nur möchte ich jetzt erst einmal 
Assembler lernen. Könntest du (oder irgendwer hier) mir deshalb bitte 
diese Schleife in Assembler kurz schreiben. Kann nämlich mit C nicht 
viel anfangen. Hab auch schon überlegt wie ich es in Assembler mache, 
aber bin nicht drauf gekommen. Also wenn mir hier jemand weiterhelfen 
könnte wäre ich wirklich riesig dankbar.

Gruß
Jan Purrucker

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

Bewertung
0 lesenswert
nicht lesenswert
Ohne Garantie ;)
.def state=r19
.def counter_k=r20
.def counter_i=r21

.
.
.
.

timerint:
 inc counter_k
 ;counter >= 57 ?
 cpi counter_k, 57
 brlo int_ende
  ;Counter auf 0
  ldi counter_k=0
  inc counter_i
  ;counter = 240 ?
  cpi counter_i, 240
  brne weiter
   ;counter auf 0
   ldi counter_i, 0
   ;state = 1
   ldi state, 1
   rjmp int_ende
  weiter:
   ;state = 2
   ldi state, 2
int_ende:
 reti

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.