Go Down

Topic: CTC - Timer 2 - TCCR2A - gezielter Reset notwendig - Warum? (Read 711 times) previous topic - next topic

Doc_Arduino

Hallo,

bin gerade etwas ratlos warum das Timer 2 Register TCCR2A nicht richtig gesetzt wird und davon auch die serielle Ausgabe beeinträchtig ist.

Ich weise allen Timerregistern konkrete Werte zu. Ich verodere nichts. Sodass ich mir das vorherige notwendige Nullen sparen kann. Eigentlich! Setze ich TCCR2A nicht auf 0, dann stimmt die Frequenz nicht und die 2. serielle Ausgabe fehlt.
Alles hängt von Zeile 47 ab.
Kann das jemand nachvollziehen?
Sieht jemand irgendeinen Fehler den ich nicht sehe?

Code: [Select]

/*
 Arduino Mega2560
 Timer 2: CTC, Mode 2
 
 Pinouts  >>> http://www.pighixxx.net/pinoutspg/boards/
 Uno      >>> http://www.pighixxx.net/portfolio-items/uno/?portfolioID=314
 Mega2560 >>> http://www.pighixxx.net/portfolio-items/mega/?portfolioID=314
*/

const byte pin_T2 = 10;


void setup(void) {
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(pin_T2, OUTPUT);

  Serial.print("OCR2A");  Serial.print('\t'); formatiere_Byte (OCR2A);   
  Serial.print("OCR2B");  Serial.print('\t'); formatiere_Byte (OCR2B);
  Serial.print("TCCR2A"); Serial.print('\t'); formatiere_Byte (TCCR2A);
  Serial.print("TCCR2B"); Serial.print('\t'); formatiere_Byte (TCCR2B);
  Serial.print("TIMSK2"); Serial.print('\t'); formatiere_Byte (TIMSK2); 
  Serial.flush();
 
  set_Timer2();  
 
  Serial.println();
  Serial.print("OCR2A");  Serial.print('\t'); formatiere_Byte (OCR2A);   
  Serial.print("OCR2B");  Serial.print('\t'); formatiere_Byte (OCR2B);
  Serial.print("TCCR2A"); Serial.print('\t'); formatiere_Byte (TCCR2A);
  Serial.print("TCCR2B"); Serial.print('\t'); formatiere_Byte (TCCR2B);
  Serial.print("TIMSK2"); Serial.print('\t'); formatiere_Byte (TIMSK2);
 
}

void loop(void) {
 
}


// ****** Funktionen ******* //
   
void set_Timer2()         // CTC, Mode 2
{
  cli();                  // Interrupts ausschalten
  TCNT2 = 0;              // Reset Register                
  //TCCR2A = 0;           // Warum Nullen notwendig?
  OCR2A = 249;            // Compare
  TIMSK2 = (1<<OCIE2A);   // Compare Match A
  TCCR2A = (1<<WGM21);    // set Mode
  TCCR2B = (1<<CS22);     // Prescaler 64
  sei();                  // Interrupts einschalten



ISR(TIMER2_COMPA_vect)          // Timer 2 Interrupt

  static bool state = LOW;
  state = !state;
  digitalWrite(pin_T2, state);                   
}


void formatiere_Byte (unsigned int data)
{
  Serial.print(F("data: "));
  for (char i=7;i>=4;i--) {
    Serial.print( (data >> i) & 0x01);
  }
  Serial.print("'");
  for (char i=3;i>=0;i--) {
    Serial.print( (data >> i) & 0x01);
  }
  Serial.println();
}
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

combie

Quote
TCCR2A = 0;           // Warum Nullen notwendig?
Du musst an der Stelle nicht nullen.

Quote
TCCR2A = (1<<WGM21);
Den richtigen/beabsichtigten Modus setzen, wäre doch an der Stelle viel sinnvoller.

Warum, das aber stehen bleibt?
KA, vermute, dass du einen ungültigen inneren Zustand erzeugst.



> Das größte Problem, ist die Wahl der richtigen Gedanken <
Frei nach Dale Carnegie

Doc_Arduino

Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

combie

Natürlich!
Sogar ausprobiert.

Und meinen Vorschlag getestet!
Welcher sich als gangbar erwiesen hat.



Hast du meine Antwort gelesen?
Wenn ja, dann wohl nicht verstanden.


Aber ich kann dich ja nochmal deutlich was fragen:
Warum willst du unbedingt vorher den Timer in Modus 0 setzen und später dann in Modus 2, wenn du ihn AN DER STELLE genauso gut sofort in den gewünschtenModus bringen könntest?


Code: [Select]
void set_Timer2()         // CTC, Mode 2
{
  cli();                  // Interrupts ausschalten
  TCNT2 = 0;              // Reset Register                 
  TCCR2A = (1<<WGM21);           // hier setzen
  //TCCR2A = 0;           // Warum Nullen notwendig?
  OCR2A = 249;            // Compare
  TIMSK2 = (1<<OCIE2A);   // Compare Match A
 // TCCR2A = (1<<WGM21);    // set Mode
  TCCR2B = (1<<CS22);     // Prescaler 64
  sei();                  // Interrupts einschalten

EDIT: korrigiert
> Das größte Problem, ist die Wahl der richtigen Gedanken <
Frei nach Dale Carnegie

Doc_Arduino

Hallo,

du sagst mir doch nichts neues. Das weiß ich doch selbst. Steht im Text und im Sketch.
Die einzige Frage die mich beschäftigt ist warum das Register TCCR2B nur richtig gesetzt wird wenn man es vorher nullt?

Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

combie

Quote
Die einzige Frage die mich beschäftigt ist warum das Register TCCR2B nur richtig gesetzt wird wenn man es vorher nullt?
Das stimmt doch gar nicht!

Ich habe den Gegenbeweis hier bei mir laufen.

Ersetze deine Funktion durch diese, dann klappts auch bei dir ohne nullen.
Code: [Select]

void set_Timer2()         // CTC, Mode 2
{
  cli();                  // Interrupts ausschalten

  // erst die Control Register setzen
  TCCR2A = (1<<WGM21);    // Mode 2
  TCCR2B = (1<<CS22);     // Prescaler 64

  // dann die davon abhaengigen.
  OCR2A = 249;            // Compare
  TIMSK2 = (1<<OCIE2A);   // Compare Match A
  TCNT2 = 0;              // Reset Register   
               
  sei();                  // Interrupts einschalten

> Das größte Problem, ist die Wahl der richtigen Gedanken <
Frei nach Dale Carnegie

Doc_Arduino

Hallo,

du hast meine Eingangsfrage demnach nicht verstanden.

Das Einzigste was auffällig ist, das die Reihenfolge der Registeränderung Einfluss hat.
Das kann ich nun noch weniger nachvollziehen.
Wenn man TCCR2A vor OCR2A und vor TIMSK2 ändert, dann klappt alles ohne ordnungsgemäß.
Wenn man die Reihenfolge anders hat, wie zum Bsp. im Eingangspost gezeigt, muss man TCCR2A vorher nullen.
Damit entsteht die 2. Frage seit wann die Reihenfolge Einfluss auf die Settings haben?

das hier funktioniert wie es soll
Code: [Select]

void set_Timer2()         // CTC, Mode 2
{
  cli();                  // Interrupts ausschalten
  TCNT2 = 0;              // Reset Register          
  TCCR2A = (1<<WGM21);    // set Mode        
  OCR2A  = 249;           // Compare
  TIMSK2 = (1<<OCIE2A);   // Compare Match A
  TCCR2B = (1<<CS22);     // Prescaler 64
  sei();                  // Interrupts einschalten
}
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

combie

Quote
Damit entsteht die 2. Frage seit wann die Reihenfolge Einfluss auf die Settings haben?
Offensichtlich hat es einen Einfluss.

Das kann ich dir auch nicht mehr beantworten, als ich es schon getan habe!
> KA, vermute, dass du einen ungültigen inneren Zustand erzeugst.


PS:
Habe schon einiges mit den Timern gemacht,
Bin dabei aber noch nie auf deine Reihenfolge gekommen.

Habe IMMER erst die Controll Register gesetzt, und dann die anderen.
Nie damit auf deine Probleme/Fragen gestoßen


-----
Quote
du hast meine Eingangsfrage demnach nicht verstanden.
Damit endet diese Diskussion hier und jetzt für mich.
Ich wünsche dir einen erfolgreichen Kampf gegen die Windmühlen.




> Das größte Problem, ist die Wahl der richtigen Gedanken <
Frei nach Dale Carnegie

Doc_Arduino

Hallo,

du musst doch nicht immer gleich komisch tun, nur weil es keine Antworten auf gestellte Probleme gibt. Heute ist nichts weiter passiert als das ich die Reihenfolge zufällig geändert hatte und dabei auf besagtes Problem gestoßen bin. Deswegen stürzt die Welt nicht ein.

Wenn man es direkt macht funktioniert es. Demnach hat das Arduino Framework irgendeinen Einfluss.

Code: [Select]
int main(void) {

  DDRB = (1<<4);    // Pin 10
       
  set_Timer2();
 
  while(1) {           
                       
  }



void set_Timer2()         // CTC, Mode 2 (500Hz)
{
  cli();                  // Interrupts ausschalten
  TCNT2 = 0;              // Reset Register               
  OCR2A  = 249;           // Compare
  TIMSK2 = (1<<OCIE2A);   // Compare Match A
  TCCR2A = (1<<WGM21);    // set Mode 
  TCCR2B = (1<<CS22);     // Prescaler 64
  sei();                  // Interrupts einschalten



ISR(TIMER2_COMPA_vect)   // Timer 2 ISR

  PINB = _BV(PB4);                 
}
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

combie

Quote
Demnach hat das Arduino Framework irgendeinen Einfluss.
Natürlich!
Es setzt den Modus 1
(das sieht man doch auch an deinen Ausgaben)
> Das größte Problem, ist die Wahl der richtigen Gedanken <
Frei nach Dale Carnegie

Doc_Arduino

Hallo,

bei der Antwort bin ich mir wieder nicht sicher ob du das Problem im vollen Umfang erkannt hast.
Natürlich setzt das Framework erstmal seine Grundeinstellungen für alle Timer usw. Ist ja normal und auch richtig. Der Punkt ist das es danach eigene Einstellungen behindert und sogar die eigene Serielle lahm legt. An den seriellen Einstellungen fummel ich ja nicht rum. Da muss etwas unter der Haube völlig schief laufen.
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

combie

Quote
bei der Antwort bin ich mir wieder nicht sicher ob du das Problem im vollen Umfang erkannt hast.
Das sagst du mir jetzt zum dritten mal.
(habe ich richtig gezählt?)

Was soll das?
Willst du mich für blöd verkaufen?


Fakt ist ja wohl, dass ich häufiger mal eine andere Sicht auf die Dinge habe, als du.
Das "Problem" welches  du da aufbauscht, ist irrational, aus meiner Sicht.

Versagen, bei falscher Initialisierung von Hardwarekomponenten, ist keine Seltenheit.
Es gibt also keinen Grund so zu tun, als wäre das jetzt eine grausame Überraschung.


Quote
und sogar die eigene Serielle lahm legt.
Ich glaube, da bleibt noch mehr stehen!
Nicht nur die Serielle, sondern eher Alles.


Die Lösung für dein Problem ist: Richtige Initialisierungsreihenfolge einhalten.
Diese Lösung reicht dir nicht, nehme ich mal an...
Du möchtest das "Warum" erfahren.
Richtig?

Vermutlich wirst du dafür den Entwickler des ATMega2560 befragen müssen.
Denn der hält den inneren Aufbau des ATMega2560 vor mir verborgen.

Wobei ich vermute, dass der Entwickler dir nicht die Innereien offen legt, sondern dir nur sagen wird, was "wir" auch schon herausgefunden haben: Richtig Initialisieren, dann klappts auch.



Code: [Select]
#include <util/atomic.h>
#define AtomicSection ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
/*
 Arduino Mega2560
 Timer 2: CTC, Mode 2
 
 Pinouts  >>> http://www.pighixxx.net/pinoutspg/boards/
 Uno      >>> http://www.pighixxx.net/portfolio-items/uno/?portfolioID=314
 Mega2560 >>> http://www.pighixxx.net/portfolio-items/mega/?portfolioID=314
*/



//const byte pin_T2 = 10;
const byte pin_T2 = LED_BUILTIN;


void setup(void) {
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(pin_T2, OUTPUT);

  Serial.print("OCR2A");  Serial.print('\t'); formatiere_Byte (OCR2A);   
  Serial.print("OCR2B");  Serial.print('\t'); formatiere_Byte (OCR2B);
  Serial.print("TCCR2A"); Serial.print('\t'); formatiere_Byte (TCCR2A);
  Serial.print("TCCR2B"); Serial.print('\t'); formatiere_Byte (TCCR2B);
  Serial.print("TIMSK2"); Serial.print('\t'); formatiere_Byte (TIMSK2); 
  Serial.flush();
 
  set_Timer2();   
 
  Serial.println();
  Serial.print("OCR2A");  Serial.print('\t'); formatiere_Byte (OCR2A);   
  Serial.print("OCR2B");  Serial.print('\t'); formatiere_Byte (OCR2B);
  Serial.print("TCCR2A"); Serial.print('\t'); formatiere_Byte (TCCR2A);
  Serial.print("TCCR2B"); Serial.print('\t'); formatiere_Byte (TCCR2B);
  Serial.print("TIMSK2"); Serial.print('\t'); formatiere_Byte (TIMSK2);
 
}

void loop(void) {
 
}


// ****** Funktionen ******* //
   
void set_Timer2()         // CTC, Mode 2
{
  AtomicSection
  {
    // erst die Control Register setzen
    TCCR2A = (1<<WGM21);    // Mode 2
    TCCR2B = (1<<CS22);     // Prescaler 64
 
    // dann die davon abhaengigen.
    OCR2A = 249;            // Compare
    TIMSK2 = (1<<OCIE2A);   // Compare Match A
    TCNT2 = 0;              // Reset Counter Register   
  }             



ISR(TIMER2_COMPA_vect)          // Timer 2 Interrupt

  static bool state = LOW;
  state = !state;
  digitalWrite(pin_T2, state);                   
}


void formatiere_Byte (unsigned int data)
{
  Serial.print(F("data: "));
  for (char i=7;i>=4;i--) {
    Serial.print( (data >> i) & 0x01);
  }
  Serial.print("'");
  for (char i=3;i>=0;i--) {
    Serial.print( (data >> i) & 0x01);
  }
  Serial.println();
}
> Das größte Problem, ist die Wahl der richtigen Gedanken <
Frei nach Dale Carnegie

Doc_Arduino

Hallo,

zeige mir ein Dokument wo drin steht das man die Timer Register nach einer ganz bestimmten Reihenfolge bearbeiten muss.
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

combie

Und wieso muss ich dir das zeigen?
Wie kommst du auf diese absurde Idee?


Ist es nicht offensichtlich, in der Praxis nachgewiesen, dass eine Reihenfolge eingehalten werden muss?


> Das größte Problem, ist die Wahl der richtigen Gedanken <
Frei nach Dale Carnegie

Doc_Arduino

Hallo,

eben weil es keine amtlich festgelegte Reihenfolge gibt. Wäre ja auch nonsens. Manchmal möchte man zur Laufzeit Änderungen am Timer vornehmen. Erst die Gesamtkonfig ergibt die Timerfunktion. Du stützt dich alleine auf eine funktionierende Reihenfolge. Davon gibts hunderte, hab ich auch selber. Jedoch gibt es offensichtlich einen nicht logisch erklärbaren Abhängigkeitseffekt.
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Go Up