Forum: Mikrocontroller und Digitale Elektronik RTC-Timer2 - Binär Uhr


von Pierre G. (bqube)


Lesenswert?

Guten Abend,

Ich hatte mir mit Hilfe eines Atmega8 und ein paar Led's eine Binär Uhr 
gebaut, die mit dem TIMER0 (bis auf den ungenauen Sekundentakt) ganz gut 
funktioniert.

Nun wollte ich das ganze mit dem TIMER2 im Asynchron Mode verbesser aber 
AvrStudio schreibt mir immer diese Fehlermeldung.

1
Error  2  'GTCCR' undeclared (first use in this function)  
2
3
Message  3  each undeclared identifier is reported only once for each function it appears in  C:\Dokumente und Einstellungen\Bqube\Desktop\Wecker_V01_1\Wecker_01\Wecker_01\Wecker_01.c  14  3  Wecker_01
4
5
Error  4  'TSM' undeclared (first use in this function)  
6
Error  5  'PSRASY' undeclared (first use in this function)  
7
Error  6  'TCCR2A' undeclared (first use in this function)  
8
Error  7  'TCCR2B' undeclared (first use in this function)  
9
Error  8  'OCR2A' undeclared (first use in this function)  
10
Error  9  'TIMSK2' undeclared (first use in this function)  
11
Error  10  'OCIE2A' undeclared (first use in this function)  
12
13
Warning  11  'TIMER2_COMPA_vect' appears to be a misspelled signal handler [enabled by default]  C:\Dokumente und Einstellungen\Bqube\Desktop\Wecker_V01_1\Wecker_01\Wecker_01\Wecker_01.c  37  6  Wecker_01
14
15
Error  12  'TCCR2B' undeclared (first use in this function)  
16
Error  13  'OCR2AUB' undeclared (first use in this function)  
17
Error  14  'OCR2BUB' undeclared (first use in this function)  
18
Error  15  'TCR2AUB' undeclared (first use in this function)  
19
Error  16  'TCR2BUB' undeclared (first use in this function)

Das Programmbespiel ist aus dem Tutorial AVR-GCC-TIMER.

Ich hoffe mal ihr könnt mir weiter helfen.

von Dennis H. (c-logic) Benutzerseite


Lesenswert?

Gibt es die Register überhaupt beim Atmega8 ?

-> 
http://www.atmel.com/images/atmel-2486-8-bit-avr-microcontroller-atmega8_l_datasheet.pdf 
Seite 102.

Zeig mal den Kopf der Wecker_01.c und deren Headerfile

von Pierre G. (bqube)


Lesenswert?

Hier bitte,
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
//Variablen für die Zeit
5
volatile unsigned char sekunde;
6
volatile unsigned char minute;
7
volatile unsigned char stunde;
8
 
9
int main(void)
10
{
11
  // Timer 2 konfigurieren
12
  GTCCR |= (1 << TSM) | (1 << PSRASY);  //Timer anhalten, Prescaler Reset
13
  ASSR |= (1 << AS2);                   //Asynchron Mode einschalten
14
  TCCR2A = (1 << WGM21);                //CTC Modus
15
  TCCR2B |= (1 << CS22) | (1 << CS21);  //Prescaler 256
16
  // 32768 / 256 / 1 = 128                Intervall = 1s
17
  OCR2A = 128 - 1;
18
  TIMSK2 |= (1<<OCIE2A);                //Enable Compare Interrupt
19
  GTCCR &= ~(1 << TSM);                 //Timer starten
20
  sei();                                //Enable global Interrupts
21
 
22
  while(1)
23
  {
24
    /*Hier kann die aktuelle Zeit
25
      ausgeben werden*/
26
  }
27
}
28
 
29
/*
30
Der Compare Interrupt Handler 
31
wird aufgerufen, wenn 
32
TCNT2 = OCR2A = 128-1 
33
ist (128 Schritte), d.h. genau alle 1s
34
*/
35
ISR (TIMER2_COMPA_vect)
36
{
37
    TCCR2B = TCCR2B;              //Wird weiter unten im Text erklärt!
38
    sekunde++;
39
    if(sekunde == 60)
40
    {
41
      minute++;
42
      sekunde = 0;
43
    }
44
    if(minute == 60)
45
    {
46
      stunde++;
47
      minute = 0;
48
    }
49
    if(stunde == 24)
50
    {
51
      stunde = 0;
52
    }
53
    // Wird weiter unten im Text erklärt!
54
    while(ASSR & ((1<<TCN2UB) | (1<<OCR2AUB) | (1<<OCR2BUB) |
55
                  (1<<TCR2AUB) | (1<<TCR2BUB)));
56
}

von Thomas E. (thomase)


Lesenswert?

Pierre Gnauck schrieb:
> Das Programmbespiel ist aus dem Tutorial AVR-GCC-TIMER.

Das Beispiel ist für Atmega48..328.

Du musst an Hand der Datenbätter die Register vergleichen und es für den 
Atmega8 anpassen. Oder hast du endlich einen Grund dich, von der alten 
Gurke zu verabschieden.

mfg.

von Dennis H. (c-logic) Benutzerseite


Lesenswert?

Wie kommst du darauf das beim Atmega8 ein GTCCR existiert ?

Timer anhalten geht mit TCCR2 &= ~(0x07) 'Prescaler auf 0

Seite 116 aus dem PDF.

Das Konstrukt
1
    sekunde++;
2
    if(sekunde == 60)
3
    {
4
      minute++;
5
      sekunde = 0;
6
    }
7
    if(minute == 60)
8
    {
9
      stunde++;
10
      minute = 0;
11
    }
12
    if(stunde == 24)
13
    {
14
      stunde = 0;
15
    }
kann man sehr gut ineinander Schachteln
z.B. so
1
    sekunde++;
2
    if(sekunde == 60)
3
    {
4
      minute++;
5
      sekunde = 0;
6
      if(minute == 60)
7
      {
8
        stunde++;
9
        minute = 0;
10
        if(stunde == 24)
11
        {
12
          stunde = 0;
13
        }
14
      }
15
    }

von Pierre G. (bqube)


Lesenswert?

Thomas Eckmann schrieb:

> Das Beispiel ist für Atmega48..328.
>
> Du musst an Hand der Datenbätter die Register vergleichen und es für den
> Atmega8 anpassen. Oder hast du endlich einen Grund dich, von der alten
> Gurke zu verabschieden.
>
> mfg.

Was ist denn an dem atmega8 so falsch ?

Mfg Bqube

von Dennis H. (c-logic) Benutzerseite


Lesenswert?

Pierre Gnauck schrieb:
> Thomas Eckmann schrieb:
>
>> Das Beispiel ist für Atmega48..328.
>>
>> Du musst an Hand der Datenbätter die Register vergleichen und es für den
>> Atmega8 anpassen. Oder hast du endlich einen Grund dich, von der alten
>> Gurke zu verabschieden.
>>
>> mfg.
>
> Was ist denn an dem atmega8 so falsch ?
>
> Mfg Bqube

Der Atmega8 und der Atmega48/88 haben voneinander Unterschiedliche 
Registersätze betreffs der Timer.

Und offenbar benutzt du  Timerregister die es im Atmega8 so nicht gibt.
Lies das PDF.

von Dennis H. (c-logic) Benutzerseite


Lesenswert?

!GTCCR |= (1 << TSM) | (1 << PSRASY);  //Timer anhalten, Prescaler Reset
!TCCR2A = (1 << WGM21);                //CTC Modus
->TCCR2 = 0

ASSR |= (1 << AS2);                   //Asynchron Mode einschalten

Der Atmega8 hat nur ein Compare-Register im Timer2
  // 32768  256  1 = 128                Intervall = 1s
!OCR2A = 128 - 1;
->OCR2

!TIMSK2 |= (1<<OCIE2A);                //Enable Compare Interrupt
->TIMSK |= OCIE2

!TCCR2B |= (1 << CS22) | (1 << CS21);  //Prescaler 256
!GTCCR &= ~(1 << TSM);                 //Timer starten
->TCCR2 = (1 << CS22) | (1 << CS21) | (1 << WGM21)

Die Update-Schleife
while(ASSR & ((1<<TCN2UB) | (1<<OCR2AUB) | (1<<OCR2BUB) |
                  (1<<TCR2AUB) | (1<<TCR2BUB)));

braucht nur auf TCN2UB OCR2UB & TCR2UB zu warten.

von Pierre G. (bqube)


Lesenswert?

Ich hab es nun anhand des Datenblattes umgestellt aber nun passiert bei 
meiner Uhr garnix mehr ?


Für den TIMER
1
ASSR |= (1<<AS2);      //async operation
2
TCCR2 |= (1<< CS22) | (1<< CS20);  //Prescaler auf 128
3
TCNT2 = 0x00;        //Init counter
4
TIMSK |= (1<<TOIE2);      //Overflow Interrupt Enable 
5
sei();



Für den Interrupt
1
ISR (TIMER0_OVF_vect)
2
  {
3
    sek ++;
4
5
  }

Mfg

von Thomas E. (thomase)


Lesenswert?

Pierre Gnauck schrieb:
> ISR (TIMER0_OVF_vect)
            ^
            ^
            ^

mfg.

von Pierre G. (bqube)


Lesenswert?

Gut das hab ich übersehen aber selbst nach änderung auf Timer2 passiert 
nix.

den Quarz hab ich wie angegeben auf die Eingänge für einen externen 
Oszillator angeschlossen.

Mfg

von Dennis H. (c-logic) Benutzerseite


Lesenswert?

Pierre Gnauck schrieb:
> Gut das hab ich übersehen aber selbst nach änderung auf Timer2 passiert
> nix.
>
> den Quarz hab ich wie angegeben auf die Eingänge für einen externen
> Oszillator angeschlossen.
>
> Mfg

Hast du
TCCR2 = 0; //Timer Aus
ASSR |= (1 << AS2); //Asynch-Clock
OCR2 = 127; //Compare 128
TIMSK |= ( 1<<OCIE2 ); //Output Compare Interrupt vom Timer2
TCCR2 = (1 << CS22) | (1 << CS21) | (1 << WGM21); //CTC; Prescaler:256
sei(); //Interruptfreigabe
?
und

ISR (TIMER0_OVF_vect)
  {
    sek ++;
    while(ASSR & (1<<TCN2UB | 1<<OCR2UB | 1<<TCR2UB));
  }

von Pierre G. (bqube)


Lesenswert?

Guten Abend,

so nun hat es endlich funktioniert auch wenn es ein Flüchtigkeits Fehler 
war, ich hatte den Masseanschluss vergessen.

Aber was mich sehr verwundert ist als ich die Programzeilen von Dennis 
Heynlein (c-logic) ausprobiert hatte wurde meine Uhr immer nach einer 
Sekunde auf null gesetz.

Nun hab ich das Ganze mit meiner Code Variante ausprobiert und siehe da 
er zählt Sekundengenau.

Kann mir einer von euch vieleicht sagen was an der Variante von Dennis 
Heynlein dazu führte das nach jeder Sekunde mein Counter zurückgesetz 
wurde.

Mfg Bqube

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Pierre Gnauck schrieb:
> Kann mir einer von euch vieleicht sagen was an der Variante von Dennis
> Heynlein dazu führte das nach jeder Sekunde mein Counter zurückgesetz
> wurde.

Auch Dennis gibt den Interrupt für OC2A frei :
1
TIMSK |= ( 1<<OCIE2 ); //Output Compare Interrupt vom Timer2
behandelt aber den TIMER0_OVF.

Deswegen resetted der AVR jedesmal, wenn er den IRQ abarbeiten will.

von Pierre G. (bqube)


Lesenswert?

Matthias Sch. schrieb:
> Auch Dennis gibt den Interrupt für OC2A frei :TIMSK |= ( 1<<OCIE2 );
> //Output Compare Interrupt vom Timer2
> behandelt aber den TIMER0_OVF.
>
> Deswegen resetted der AVR jedesmal, wenn er den IRQ abarbeiten will.


Das hatte ich schon mitunter berücksichtig, dass man hier den TIMER2 
behandeln sollte und nicht den TIMER0.


Mal was anderes wie macht ihr einen Sekunden Abgleich wenn der TIMER zu 
schnell zählt?

Einfach eine Stoppuhr nehmen und nach 1 Stunde den unterschiede mittels 
delay ausgleichen oder gibt es da eine schönere Methode ausser DCF_77 
verarbeiten.

Mfg Bqube

von Karl H. (kbuchegg)


Lesenswert?


von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Für meinen Frequenzgenerator (Mega8515) habe ich die mitlaufende Uhr mit 
Trimmkondensatoren abgeglichen, damit stimmen auch die erzeugten 
Frequenzen sehr genau.
Wenn man nur eine genaue Uhr braucht, ist Karl-Heinz' Methode aber 
einfacher, da alles Software ist.

von Pierre G. (bqube)


Lesenswert?

Hallöchen,

mir ist ein Fehler im Zählalgorithmus aufgefallen, das ganze war so 
aufgebaut:
1
if(sek>=59)
2
 {
3
 sek=0;
4
 min++;
5
 }
6
      
7
  if(min>=59)
8
  {
9
  min=0;
10
  st++;
11
  }
12
        
13
   if(st>=23)
14
   {
15
   st=0;
16
   }

So Zählte meine Uhr nicht immer bis quasi 60sek / 60min sondern nur 
immer bis 59, somit fehlte mir immer eine Sekunde eine Minute und sogar 
eine Stunde.

Das ganze hab ich dann so verändert:
1
if(sek>59)
2
if(min>59)
3
if(st>=24)

Mfg Bqube

von Pierre G. (bqube)


Lesenswert?

Hallöchen,

ich hab bei meiner Binäruhr doch ein etwas größeres Problem was ich 
leider nicht beseitigt bekomm und zwar hängt sich meine Uhr ab und an 
mal auf,

z.b wenn ich die Zeit einstellen möchte dann nimmt sie keine 
Tastenbefehle mehr an aber das passiert nicht immer.

Desweiteren wenn ich sie eingestellt bekomme und laufen lasse dann 
bleibt sie irgendwann von jetzt auf gleich stehen und alle LED's 
leuchten,

wechsel ich den Modus von RUN auf PROG dann funktioniert wieder alles ?

Hat mein atmega8 einen Ram fehler ?

Mfg Bqube

von holger (Gast)


Lesenswert?

>Hat mein atmega8 einen Ram fehler ?

Ja, einen ProgRAMm Fehler;)

von Pierre G. (bqube)


Lesenswert?

Der ist gut Hilft nur dem Thema nicht weiter :)

von holger (Gast)


Lesenswert?

>Der ist gut Hilft nur dem Thema nicht weiter :)

Dein nicht sichtbares Programm hilft auch nicht weiter.
Vermutlich ist dein RAM voll. Es ist aber nur eine
Vermutung. Ohne deinen Programmcode zu sehen kann dir auch
keiner sagen was man tun könnte das Problem zu beheben.

von Pierre G. (bqube)


Angehängte Dateien:

Lesenswert?

Achso ja klar kein Problem ist in C geschrieben.

Ich hoffe mal es ist nicht all zu unübersichtlicht.

Mfg Bqube

von Pierre G. (bqube)


Lesenswert?

Guten Abend,
nun ich hab das ganze nochmal verfolgt und der fehler stellt sich circa 
zur selben Zeit ein und zwar bleibt der atmega8 nicht hängen sondern 
startet neu.

Mfg Bqube

von Pierre G. (bqube)


Lesenswert?

So ich hoffe mal es gibt jemanden dem auch schonmal sowas passiert ist,
mein Problem ist nun gefunden nur warum es entsteht kann ich nicht 
sagen.

Wenn von PortB und PortD jeweils 4 Ausgänge auf LOW liegen dann bleibt 
mein Programm stehen.

Hier ist der Abschnitt für die umsetzung von DEZ in BCD Code für die 
ausgabe über LED's
1
void show (void)    // Funktion zur Anzeige der Minuten / Stunden
2
{
3
  
4
  min_v=min;
5
  st_v=st;
6
  
7
  while(svar==0)    // Schleife zur Umsetzung DEZ in BCD für Minuten
8
  {
9
    if(min_v>9)
10
    {
11
      min_8=(min_8+0x10);
12
      min_v=(min_v-10);
13
    }
14
    
15
    if(min_v<=9)
16
    {
17
      min_8=(min_8+min_v);
18
      min_v=0;
19
      svar++;
20
    }
21
  }
22
  svar=0;
23
  
24
  while(svar==0)    // Schleife für Umsetung DEZ in BCD für Stunden
25
  {
26
    if(st_v>9)
27
    {
28
      st_8=(st_8+0x10);
29
      st_v=(st_v-10);
30
    }
31
    
32
    if(st_v<=9)
33
    {
34
      st_8=(st_8+st_v);
35
      st_v=0;
36
      svar++;
37
    }
38
  }
39
  svar=0;
40
  
41
  min_8=~(min_8);
42
  st_8=~(st_8);
43
  PORTB=st_8;
44
  PORTD=min_8;
45
  min_8=0;
46
  st_8=0;
47
  
48
  
49
}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.