Go Down

Topic: Welcher Timer für was? (Read 14738 times) previous topic - next topic

Serenifly

Code: [Select]

(0 << COM1A1)

Das schiebt eine 0 x mal links. Das bewirkt einfach nichts. Auch wenn das Bit gesetzt ist. Letztlich ist das ein Oder mit 0. Ich habe schon mehrmals gesehen dass Leute denken so könnte man ein Bit löschen.

Doc_Arduino

#31
Jun 29, 2015, 07:36 pm Last Edit: Jun 29, 2015, 07:47 pm by Doc_Arduino
Hallo,

ich weis was das macht, keine Sorge, hatte es dennoch wie schon gesagt erstmal so getippt für den besseren Überblick im Code.

Damit sich Serenifly nicht weiter aufregt   :)   habe ich den Code in #27 nochmal geändert
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

Serenifly


Doc_Arduino

Hallo,

Dein Einwand ist / war ja formell richtig. Ich hatte den Code einfach zu zeitig veröffentlicht vor lauter Freude das er endlich funktioniert. Das war nur vorhin aus meiner Sicht anders, weil ich mehrere Tage am coden war und dann kommt einer und ...  ;)
Aber egal, ist ja wie gesagt alles korrekt so. Weiter machen ... Euer Ehren.
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

Doc_Arduino

#34
Jun 30, 2015, 03:07 pm Last Edit: Jun 30, 2015, 09:30 pm by Doc_Arduino
Hallo,

nochwas korrigiert. Direkt an den Timer Pins sind natürlich 8MHz möglich.
Durch bedingte Rundungsfehler sind keine 7, 6 oder 5MHz möglich.
Entweder ist der Wert im Compare Match Register 0 (8MHz) oder springt auf 1 (4MHz).
Kann man sich alles nochmal in der Excel anschauen mit den dazugehörigen Abweichungen.


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

Doc_Arduino

Hallo,

ich lese schon den ganzen Tag das Datenblatt und parallel im Netz.
Kann es sein, dass es nicht möglich ist, die Frequenz vom Timer 1 Toggle Pin von Kanal A und B unabhängig zu schalten?

ich schalte die Toggle Pin's ein
TCCR1A  |= (1 << COM1A0);  // set Toggle OCnA Pin on compare match > Pin 11 Mega2560
TCCR1A  |= (1 << COM1B0);  // set Toggle OCnB Pin on compare match > Pin 12 Mega2560

setzte beide Compare Match Register verschieden
OCR1A = 10;     
OCR1B = 20;

schalten den CTC Mode ein
TCCR1B |= (1 << WGM12);  // turn on CTC mode

setzte den Prescaler auf 64
TCCR1B |= (1 << CS11) | (1 << CS10);

und schalte den Timer Compare Match Interrupt ein für A und B
TIMSK1 |= (1 << OCIE1A); 
TIMSK1 |= (1 << OCIE1B); 

Effekt ist, Kanal A taktet und Kanal B überhaupt nicht.

lasse ich diese Zeile weg, takten A und B gleich
// OCR1B = 20;

Hab ich einen Denkfehler oder geht das wirklich nicht? Der Timeraufbau von 17.2 im Datenblatt suggeriert mir jedoch das man alle 3 Kanäle durch verschiedene CMR Werte an den Timer Pins unterschiedlich takten lassen könnte.

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

Serenifly

Dachte ich eigentlich auch. Schau dir mal 15.9.2 an. Da wird nur OCR1A als Vergleichsregister genannt. Bei PWM dagegen wird OCR1x genannt. Das scheint dann unabhängig zu sein. Etwas seltsam dass das bei CTC nicht geht. Habe ich ehrlich gesagt nie so ausprobiert.

Doc_Arduino

#37
Jul 01, 2015, 02:42 pm Last Edit: Jul 01, 2015, 02:43 pm by Doc_Arduino
Hallo,

habe jetzt die Timerbeschreibung laut Datenblatt fast auswendig drin.   :smiley-confuse:
Ich verstehe das auch so. Eigentlich kann jeder OCnx Pin mit seinem OCRnx unabhängig voneinander geschalten werden. Der Zähler im TCNTn läuft weiter.

Im CTC Modus allerdings, wird der Zähler im TCNTn mit dem OCRnA automatisch gelöscht. Was hat sich Atmel dabei nur gedacht. Es sind tausende Register vorhanden, da hätte eines mehr für die Config das Kraut auch nicht fetter gemacht.

Jetzt lasse ich das im Normal Mode laufen. Habe die OCR1x Werte immer verdoppelt.
Dadurch sehe ich 3 plausible Toggles an den OC1x Pins.
Allerdings gibts dazwischen noch ungeklärte Schalteffekte. Siehe Screenshot.
Hab mal reingemalt was ich denke und was ich nicht weis.

Jetzt war mein Plan, den TCNT1 selbst auf 0 zu setzen, wenn der langsamste Takt, in dem Fall Timer1.C, sein Interrupt Request/Flag bekommen hat.

Ich habe aber das Problem, sobald ich den ISR Code für C aktiviere, taktet alles nur noch im 32ms Takt.
ISR(TIMER1_COMPC_vect) {   // Timer 1.C Interrupt  
}


Code: [Select]
/*
01.07.2015

Arduino Mega2560

*/

// globale Variablen
boolean _toggle_T1 = LOW;
const byte _LED = 8;

// Funktionen deklarieren
void set_Timer1_CMR();

void setup() {
  Serial.begin(38400);
  pinMode(_LED, OUTPUT);  // max. 36 bzw. 170kHz
  pinMode(11, OUTPUT);    // Pin von OC1A > Pin 11 Mega2560 (max. 8MHz)
  pinMode(12, OUTPUT);    // Pin vom OC1B > Pin 12 Mega2560 (max. 8MHz)
                          // beim Uno sind das Pin 9 und 10
  pinMode(13, OUTPUT);    // Pin vom OC1C > Pin 13 Mega2560 (max. 8MHz)
                                      
  set_Timer1_CMR();  // gewünschte Taktfrequenz in Hz - bei Bedarf mit einer Kommastelle
                     // 0.2 bis 36kHz bzw. 170kHz bzw. 8MHz)

}  // Ende Setup

 
void loop() {
  // do other things here
    
}


// *** Funktionen *** ----------------------------------------------

void set_Timer1_CMR()  // Normal Mode, kein CTC
{  
  cli();  //stop interrupts

  // set Timer-1 Register
  TCCR1A = 0;      // Reset TCCR1A Register
  TCCR1B = 0;      // Reset TCCR1B Register
  TIMSK1 = 0;      // Reset TIMSK1 Register (disable Timer Compare Interrupts)
  TCNT1  = 0;      // initialize counter value to 0
  
  TCCR1A  |= (1 << COM1A0);  // set Toggle OCnA Pin on compare match > Pin 11 Mega2560
  TCCR1A  |= (1 << COM1B0);  // set Toggle OCnB Pin on compare match > Pin 12 Mega2560
  TCCR1A  |= (1 << COM1C0);  // set Toggle OCnC Pin on compare match > Pin 13 Mega2560
  
  OCR1A =   99;    // Compare Match Register A >> 10kHz (Precaler 8)
  OCR1B =  199;    // Compare Match Register B
  OCR1C =  399;    // Compare Match Register C
  //TCCR1B |= (1 << WGM12);  // turn on CTC mode
  
  TCCR1B |= (1 << CS11);    // set Prescaler 8
  TIMSK1 |= (1 << OCIE1A);  // enable Timer Compare Interrupt  A
  TIMSK1 |= (1 << OCIE1B);  // enable Timer Compare Interrupt  B
  TIMSK1 |= (1 << OCIE1C);  // enable Timer Compare Interrupt  C
      
  sei();  //allow interrupts
  
}  // end Funktion


ISR(TIMER1_COMPA_vect) {  // Timer 1.A Interrupt
  
}


ISR(TIMER1_COMPB_vect) {  // Timer 1.B Interrupt
  
}

/*
ISR(TIMER1_COMPC_vect) {  // Timer 1.C Interrupt
  
}
*/



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

Serenifly

Im CTC Modus allerdings, wird der Zähler im TCNTn mit dem OCRnA automatisch gelöscht. Was hat sich Atmel dabei nur gedacht.
Doh. Jetzt wo du es sagst. Das ist ja der ganze Sinn von CTC. Clear Timer on Compare Match. Dann ist es natürlich ein Problem mit mehreren Compare Registern zu arbeiten.

PWM funktioniert anders. Da läuft der Timer immer von BOTTOM nach TOP durch und beim Compare Match kann man was machen. Dadurch dass der Timer weiter läuft ist es dann kein Problem mehrere unabhängige Vergleichswerte zu haben.

Doc_Arduino

#39
Jul 01, 2015, 03:41 pm Last Edit: Jul 01, 2015, 04:01 pm by Doc_Arduino
Hallo,

ich dachte, weil jedes OCRnx noch sein eigenes OCFnx Interrupt/Flag hat, wäre es kein Problem alle Kanäle unabhängig zu betreiben. Allerdings muß ja der Zähler im TCNTn durch irgendwas genullt werden. Das ist nun einmal Kanal A im CTC Mode. Bei näherere Betrachtung doch wieder logisch. Man muß sich nur mit jemanden unterhalten. :)

Noch möchte ich keine PWM machen. Ich möchte nur erstmal den TCNT von Hand nullen oder ein Flag von A/B/C zurücksetzen ("set one"). Das klappt aber nicht. Muß ich da als Interrupt einen Capture Event verwenden?

Ich möchte Kanal A/B/C mit unterschiedlichen CMR Werten unterschiedlich takten lassen. Im Normal Mode.
Bsp. Kanal A mit 10kHz und Kanal B mit 5kHz. Ansatzweise funktioniert das ja schon, siehe Screenshot. Muß aber dabei dafür sorgen das Dings selbst zurückzusetzen. Sonst zählt TCNTn munter weiter bis zum Overflow.
Mir fehlt noch das kontrollierte zurücksetzen von ??? damit alle wieder bei 0 anfangen und nicht warten bis TCNT seinen Overflow hat.

Was an den mit ?? makierten Stellen passiert weist Du auch nicht zufällig im Timer-Diagramm?



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

Doc_Arduino

Hallo,

ich bekomme einfach keinen klaren neuen Anfang. Kanal C scheint auch noch was besonderes zu sein.
Ich lade die Compare Match Register von A/B/C unterschiedlich.
Bekomme die zeitlichen Unterschiede durch einmaliges Toogle an den OC1x Pins zu sehen.
Siehe Screenshot oben.
Aber egal was ich versuche, ich bekomme den Zähler nicht definiert vorzeitig zurückgesetzt.
Nullen kann ich den, aber dann haut gar nichts mehr hin.
Auch den TCNT1 Zähler auf 65535 (oder 65000 damit man eine Änderung sieht) hilft nicht.
Eigentlich müßte man nur im ISR Aufruf vom langsamsten Kanal den Zähler oder ein Flag zurücksetzen.
Ideen?
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

Doc_Arduino

Hallo,

so langsam verliere ich die Lust.
Der OCIE1x  (Timer Compare Interrupt) von A/B sind ausgeschalten. Normalerweise dürfte A/B gar nicht takten.
Tun sie aber laut Screenshot mit genau dem Code hier.

Nehme ich den ISR COMPC Vector dazu, takten alle 3 Kanäle gleich, leicht verschoben mit irgendeiner Frequenz ohne mein Einfluss.

Code: [Select]

/*
01.07.2015
Doc Arduino - german arduino.cc Forum

Arduino Mega2560

*/

// globale Variablen
boolean _toggle_T1 = LOW;
const byte _LED = 8;
long _CounterA;
long _CounterB;
long _CounterC;


// Funktionen deklarieren
void set_Timer1_CMR();

void setup() {
  Serial.begin(38400);
  pinMode(_LED, OUTPUT);  // max. 36 bzw. 170kHz
  pinMode(11, OUTPUT);    // Pin von OC1A > Pin 11 Mega2560 (max. 8MHz)
  pinMode(12, OUTPUT);    // Pin vom OC1B > Pin 12 Mega2560 (max. 8MHz)
                          // beim Uno sind das Pin 9 und 10
  pinMode(13, OUTPUT);    // Pin vom OC1C > Pin 13 Mega2560 (max. 8MHz)
                                       
  set_Timer1_CMR();  // gewünschte Taktfrequenz in Hz - bei Bedarf mit einer Kommastelle
                     // 0.2 bis 36kHz bzw. 170kHz bzw. 8MHz)

}  // Ende Setup

 
void loop() {
  // do other things here
}


// *** Funktionen *** ----------------------------------------------

void set_Timer1_CMR()  // Normal Mode, kein CTC
{   
  cli();  //stop interrupts

  // set Timer-1 Register
  TCCR1A = 0;      // Reset TCCR1A Register
  TCCR1B = 0;      // Reset TCCR1B Register
  TIMSK1 = 0;      // Reset TIMSK1 Register (disable Timer Compare Interrupts)
  TCNT1  = 0;      // initialize counter value to 0
 
  TCCR1A  |= (1 << COM1A0);  // set Toggle OCnA Pin on compare match > Pin 11 Mega2560
  TCCR1A  |= (1 << COM1B0);  // set Toggle OCnB Pin on compare match > Pin 12 Mega2560
  TCCR1A  |= (1 << COM1C0);  // set Toggle OCnC Pin on compare match > Pin 13 Mega2560
 
  OCR1A =  10000;    // Compare Match Register A
  OCR1B =  15000;    // Compare Match Register B
  OCR1C =  20000;    // Compare Match Register C
  //TCCR1B |= (1 << WGM12);  // turn on CTC mode
 
  TCCR1B |= (1 << CS11);    // set Prescaler 8
  //TIMSK1 |= (1 << OCIE1A);  // enable Timer Compare Interrupt  A
  //TIMSK1 |= (1 << OCIE1B);  // enable Timer Compare Interrupt  B
  TIMSK1 |= (1 << OCIE1C);  // enable Timer Compare Interrupt  C
     
  sei();  //allow interrupts
 
}  // end Funktion


/*
ISR(TIMER1_COMPC_vect) {  // Timer 1.C Interrupt
  TCNT1 = 65500;
}
*/
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

Doc_Arduino

Hallo,

sag mal Serenifly, wir hatten uns doch unterhalten das eine 0 um x Bits weiterschieben nichts bringt.
Es funktioniert aber. Die LED taktet. Was jetzt?  ;)

Code: [Select]
// globale Variablen
boolean _toggle_T1 = LOW;

void setup() {
  pinMode(8, OUTPUT); 

 
void loop() {
  _toggle_T1 =! _toggle_T1;
  PORTH = _toggle_T1 << 5;      // Pin 8 - Mega2560 auf Port.H.Bit.5
  delay(500);
}
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

Serenifly

Soll das jetzt eine Scherzfrage sein?

Doc_Arduino

Hallo,

ist ernst gemeint, siehe #30

Einmal wird eine 1 um 5 Stellen geschoben und dann wieder eine 0. Eine 0 soll ja nicht funktionieren.
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