C code für Uhrenquarz

OP #859661
Lesenswert?
• ▲
▼
Hallo!

Ich bin relativ unerfahren mit Mikrocontroller und dessen 
Programmierung.. Paar Sachen kann ich schon aber naja..

Mein Problem:
Ich hab einen Uhrenquarz an den TOSC1 und TOSC2 von einem AtMega128 
angeschlossen.. soweit so gut, nur habe ich jetzt absolut keinen Plan 
wie ich davon was nützliches kriege mit C, z.B. ein Sekundenzähler oder 
sowas ähnliches

Wäre sehr dankbar, wenn sich wer kurz Zeit nimmt und ein Beispiel Code 
machen könnte, damit sogar ich mal kapiere ;)

Danke!
Moderator Persönliche Seite #860100
Lesenswert?
• ▲
▼
Falls man einen Timer im Async-Mode verwenden will, also getrieben vom 
32kHz Quarz an TOSCx, kann man sich im Beispielcode zum AVR Butterfly 
die erforderlichen Schritte zur Initialierung und für die 
Interrupt-Routine abschauen. Code zum BF ist für ATmega169, sind also 
ein paar kleinere Änderungen für ATmega128 erforderlich, aber kein 
Hexenwerk, Prinzip ist gleich. Datenblatt gibt eine 
"Schitt-für-Schritt-Liste", wie man den Async-Mode aktiviert.
OP #861850
Lesenswert?
• ▲
▼
Also ich hab mich mal versucht durch das Datenblatt zu hangeln und auch 
im Netz recheriert...

Ich bin jetzt mal zu folgenden Schlüssen gekommen:

also, ich will/hab:
-ATmega128
-ein 32768khz quarz auf TOSC1/TOSC2 mit dem ich die Uhr steuern will

Was ich jetzt, denke ich, machen soll damit ich jede Sekunde einen 
Interrupt habe:

-ASSR: AS0 auf 1 damit die Frequenz vom externen Quarz übernommen wird
-TCCR0: CS02 auf 1, CS01 auf 0, CS00 auf 1, damit der Vorteiler auf 128 
ist
-TCNT0: auf 0x00, also Startwert auf 0
-OCR0: auf 0xFF, Vergleichswert auf 255
-TIMSK: OCIE0 auf 1 vergleicht OCR0 und macht Interrupt sobald 255 
erreicht ist

Vorallem beim letzten Punkt bin ich nicht sicher ob ich das richtig 
verstanden habe.. also das es einen Interrupt gibt sobald der 255 
erreicht hat oder auf 0 zurück setzt...

Auch weiss ich nicht wie ich denn Interrupt konkret in C umsetze.. also 
Pseudocode: if Interrupt mach sekundenzähler 1 hoch

Könnt ihr mir kurz sagen wie ich das in echtes C übersetze?

Danke!
Moderator Persönliche Seite #861944
Lesenswert?
• ▲
▼
Hax Sowieso wrote:

> -ASSR: AS0 auf 1 damit die Frequenz vom externen Quarz übernommen wird

OK.

> -TCCR0: CS02 auf 1, CS01 auf 0, CS00 auf 1, damit der Vorteiler auf 128
> ist

OK, das gibt einen Takt von 256 Hz.

> -TCNT0: auf 0x00, also Startwert auf 0

Ist die Voreinstellung, ist aber auch egal: nur der erste Tick
ändert sich damit.  Da der Quarz ja sowieso ,,irgendwann'' losläuft,
hat das keine wirkliche Relevanz.

> -OCR0: auf 0xFF, Vergleichswert auf 255
> -TIMSK: OCIE0 auf 1 vergleicht OCR0 und macht Interrupt sobald 255
> erreicht ist

Damit teilst du die 256 Hz durch 255.  Du willst aber durch 256
teilen, damit du 1 Hz bekommst.  Nichts einfacher als das: lass den
Zähler ganz normal durchlaufen und benutze den Overflow-Interrupt.
OP #861957
Lesenswert?
• ▲
▼
Vielen Dank!
>
>> -TCNT0: auf 0x00, also Startwert auf 0
>
> Ist die Voreinstellung, ist aber auch egal: nur der erste Tick
> ändert sich damit.  Da der Quarz ja sowieso ,,irgendwann'' losläuft,
> hat das keine wirkliche Relevanz.

also könnt ich die Zeile einfach weglassen?


>> -OCR0: auf 0xFF, Vergleichswert auf 255
>> -TIMSK: OCIE0 auf 1 vergleicht OCR0 und macht Interrupt sobald 255
>> erreicht ist
>
> Damit teilst du die 256 Hz durch 255.  Du willst aber durch 256
> teilen, damit du 1 Hz bekommst.  Nichts einfacher als das: lass den
> Zähler ganz normal durchlaufen und benutze den Overflow-Interrupt.

Das heisst bei TIMSK TOIE0 auf 1 zu ändern? Und OCIE0 auch einfach 
weglassen?

Juhu ich komm der Sache immer näher =)
Moderator Persönliche Seite #862004
Lesenswert?
• ▲
▼
Hax Sowieso wrote:

[TCNT0 auf 0 setzen]
> also könnt ich die Zeile einfach weglassen?

Ja.

> Das heisst bei TIMSK TOIE0 auf 1 zu ändern?

Ja, und natürlich die zugehörige ISR schreiben.  Ungefähr so:
1
#include <stdbool.h>
2

3
#include <avr/io.h>
4
#include <avr/interrupt.h>
5

6
volatile bool ticked_1Hz;
7

8
ISR(TIMER0_OVF_vect)
9
{
10
  ticked_1Hz = true;
11
}
12
...
Gast #862103
Lesenswert?
• ▲
▼
Kleiner Tip:
So sparst du Rechenzeit, da ja die Sekundenazeige nur bei Änderung 
aktualisiert werden muss:
1
volatile uint08_t seconds;  // 8Bit reichen für 0..59Sekunden
2

3
void main (void)
4
{
5
  uint8_t  _u8SecLast = 255;
6
  ...
7

8

9
  while (1)
10
  {
11
    if ( _u8SecLast != seconds )
12
    {
13
      _u8SecLast = seconds;
14
      LCD_Print("Nichts los....", 1, 60, 1, 1, 1, white, black);
15
      sprintf(str,"sekunde %d ",(int) seconds);
16
      LCD_Print(str, 0, 20, 1, 1, 1, white, black);
17
    }
18
  }
19
}

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 18 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.