Timers et comparaisons

Bonjour à tous.
Mon but est de comprendre les timers et les comparaisons.
j ai fait 2 programmes.
le premier utiliser le timer2 de l’UNO pour faire clignoter une led et une autre led dans le loop, tout est correct.
le second la même chose en utilisant le timer1, là le temps sur le timer1 est doublé, je ne comprend pas pour quel raison. (problème d’écriture ou je n’ai pas compris le fonctionnement des timers!)
Si l’un d’entre vous pouvez m’éclairer.
Merci.

//ARDUINO UNO TIMER 2

const byte Led = 13;
#define LedToggle digitalWrite (Led, !digitalRead(Led))
byte varCompteur = 0; // La variable compteur

void setup () 
{
  pinMode (Led, OUTPUT);
  Serial.begin(115200);

  //Configuration PORT
  DDRB |= (1<<4); // pin 12 en sortie
  PORTB &= ~(1<<4); // pin 12 LOW 
 

  cli(); // Désactive l'interruption globale
  // TIMER 2  8bit 
  // mode d'exploitation
  // | COM2A1 | COM2A0 | COM2B1 | COM2B0 | 0 | 0 | WGM21 | WGM20 |
  TCCR2A = B00000010;  // mode CTC
  // Horloge
  // | FOC2A | FOC2B | 0 | 0 | WGM22 | CS22 | CS21 | CS20 |
  //TCCR2B = B00000000; // Arrêt horloge
  //TCCR2B = B00000001;  // Horloge active prescalaire : 1 = 62.5ns / max : 15.94µs
  //TCCR2B = B00000010;  // Horloge active prescalaire : 8 = 500ns / max : 127.5µs
  //TCCR2B = B00000011;  // Horloge active prescalaire : 32 = 2µs / max : 510µs
  //TCCR2B = B00000100;  // Horloge active prescalaire : 64 = 4µs / max : 1.02ms
  //TCCR2B = B00000101;  // Horloge active prescalaire : 128 = 8µs / max : 2.04ms
  TCCR2B = B00000110;  // Horloge active prescalaire : 256 = 16µs / max : 4.08ms
  //TCCR2B = B00000111;  // Horloge active prescalaire : 1024 = 64µs / max : 16.32ms
  // interruption locale activées 
  // | 0 | 0 | 0 | 0 | 0 | OCIE2B | OCIE2A | TOIE2 |
  TIMSK2 = B00000010;    // Interruption Timer1 Quand TCNT2=OCR2A
  OCR2A = 250; //  max 255 Comparaison A
  sei(); // Active l'interruption globale
}
// Routine d'interruption
ISR(TIMER2_COMPA_vect) 
{
  if (varCompteur++ > 125) 
  { // 125 * 4 ms = 500 ms (demi-période)
    varCompteur = 0;
    PORTB ^= (1<<4); // pin 12 CHANGE état
  }
}
void loop () 
{
  LedToggle; // Temps du changement 10µs
  delay (500);
}
//ARDUINO UNO TIMER 1

const byte Led = 13;
#define LedToggle digitalWrite (Led, !digitalRead(Led))
byte varCompteur = 0; // La variable compteur

void setup () 
{
  pinMode (Led, OUTPUT);
  Serial.begin(115200);

  //Configuration PORT
  DDRB |= (1<<4); // pin 12 en sortie
  PORTB &= ~(1<<4); // pin 12 LOW 
 
  cli(); // Désactive l'interruption globale
  // TIMER 1  16bit 
  // mode d'exploitation
  // | COM1A1 | COM1A0 | COM1B1 | COM1B0 | 0 | 0 | WGM11 | WGM10 |
  TCCR1A = B00000010;  // mode CTC
  // Horloge
  // | ICNC1 | ICES1 | 0 | WGM13 | WGM12 | CS12 | CS11 | CS10 |
  //TCCR1B = B00000000; // Arrêt horloge
  //TCCR1B = B00000001;  // Horloge active prescalaire : 1 = 62.5ns / max : 4.10ms
  //TCCR1B = B00000010;  // Horloge active prescalaire : 8 = 500ns / max : 32.77mµs
  //TCCR1B = B00000011;  // Horloge active prescalaire : 64 = 4µs / max : 262.14ms
  TCCR1B = B00000100;  // Horloge active prescalaire : 256 = 16µs / max : 1048.56ms
  //TCCR1B = B00000101;  // Horloge active prescalaire : 1024 = 64µs / max : 4194.24ms
  // interruption locale activées 
  // | 0 | 0 | ICIE1 | 0 | 0 | OCIE1B | OCIE1A | TOIE1 |
  TIMSK1 = B00000010;    // Interruption Timer1 Quand TCNT1=OCR1A
  OCR1A = 250; //  max 65535 Comparaison A
  sei(); // Active l'interruption globale
}
// Routine d'interruption
ISR(TIMER1_COMPA_vect) 
{
  if (varCompteur++ > 125) 
  { // 125 * 4 ms = 500 ms (demi-période)
    varCompteur = 0;
    PORTB ^= (1<<4); // pin 12 CHANGE état
  }
}
void loop () 
{
  LedToggle; // Temps du changement 10µs
  delay (500);
}

Désolé une erreur dans la déclaration

"byte varCompteur = 0; // La variable compteur : (à remplacer par)
volatile byte varCompteur = 0; // La variable compteur"

Encore une fois désolé je viens de voir mon erreur sur la configuration du mode CTC pour le timer 1

| ICNC1 | ICES1 | 0 | WGM13 | WGM12 | CS12 | CS11 | CS10 |
TCCR1B = B00001000;
le 4eme bit doit être à 1 (WGM12) qui correspond au mode CTC.
Merci à tous, j'espère que ça pourra servir à d'autres.

Bonjour,
je te signale qu’il n’est pas nécessaire d’avoir recours à une interruption pour faire clignoter ta diode (ni d’ailleurs pour d’autres usages comme le pwm) :
tu configures juste ton étage de sortie sur “toggle on compare match”, et ça va tout seul

Bonjour QUINQUIN07

QUINQUIN07:
Encore une fois désolé je viens de voir mon erreur sur la configuration du mode CTC pour le timer 1

| ICNC1 | ICES1 | 0 | WGM13 | WGM12 | CS12 | CS11 | CS10 |
TCCR1B = B00001000;
le 4eme bit doit être à 1 (WGM12) qui correspond au mode CTC.

Oui, mais alors CS10, CS11, CS12 sont à 0 et le timer1 arrêté !
Et avec TCCR1A = B00000010 , vous n'êtes pas en mode CTC.

Cordialement,
bidouilleelec

Bonjour, je vous joins les modifications sur mes problème de timers.
pour “trimarco232”, j’ai précisé sur mon premier post que c’était pour comprendre le fonctionnement des timers, il est bien évident que pour faire clignoter une diode il y a d’autres moyen plus simple.

merci pour votre patience en espérant que cela puisse servir à d’autre.
Marc.

//ARDUINO UNO TIMER 2

const byte Led = 13;
#define LedToggle digitalWrite (Led, !digitalRead(Led))
volatile byte varCompteur = 0; // La variable compteur

void setup () 
{
  pinMode (Led, OUTPUT);
  Serial.begin(115200);

  //Configuration PORT
  DDRB |= (1<<4); // pin 12 en sortie
  PORTB &= ~(1<<4); // pin 12 LOW 
 

  cli(); // Désactive l'interruption globale
  // TIMER 2  8bit 
  // | COM2A1 | COM2A0 | COM2B1 | COM2B0 | 0 | 0 | WGM21 | WGM20 |
  TCCR2A = B00000010; // mode CTC sur OCR2A
  // Horloge
  // | FOC2A | FOC2B | 0 | 0 | WGM22 | CS22 | CS21 | CS20 |
  //TCCR2B = B00000000; // Arrêt horloge
  //TCCR2B = B00000001;  // Horloge active prescalaire : 1 = 62.5ns / max : 15.94µs
  //TCCR2B = B00000010;  // Horloge active prescalaire : 8 = 500ns / max : 127.5µs
  //TCCR2B = B00000011;  // Horloge active prescalaire : 32 = 2µs / max : 510µs
  //TCCR2B = B00000100;  // Horloge active prescalaire : 64 = 4µs / max : 1.02ms
  //TCCR2B = B00000101;  // Horloge active prescalaire : 128 = 8µs / max : 2.04ms
  TCCR2B = B00000110;  // Horloge active prescalaire : 256 = 16µs / max : 4.08ms
  //TCCR2B = B00000111;  // Horloge active prescalaire : 1024 = 64µs / max : 16.32ms
  // interruption locale activées 
  // | 0 | 0 | 0 | 0 | 0 | OCIE2B | OCIE2A | TOIE2 |
  TIMSK2 = B00000010;    // Interruption Timer1 Quand TCNT1=OCR1A
  OCR2A = 250; //  max 255 Comparaison A
  sei(); // Active l'interruption globale
}
// Routine d'interruption
ISR(TIMER2_COMPA_vect) 
{
  if (varCompteur++ > 125) 
  { // 125 * 4 ms = 500 ms (demi-période)
    varCompteur = 0;
    PORTB ^= (1<<4); // pin 12 LOW
  }
}
void loop () 
{
  LedToggle; // Temps du changement 10µs
  delay (500);
}

TIMER1

//ARDUINO UNO TIMER 1

const byte Led = 13;
#define LedToggle digitalWrite (Led, !digitalRead(Led))
volatile byte varCompteur = 0; // La variable compteur

void setup () 
{
  pinMode (Led, OUTPUT);
  Serial.begin(115200);

  //Configuration PORT
  DDRB |= (1<<4); // pin 12 en sortie
  PORTB &= ~(1<<4); // pin 12 LOW 
 
  cli(); // Désactive l'interruption globale
  // TIMER 1  16bit 
  // | COM1A1 | COM1A0 | COM1B1 | COM1B0 | 0 | 0 | WGM11 | WGM10 |
  TCCR1A = B00000000;
  // Horloge
  // | ICNC1 | ICES1 | 0 | WGM13 | WGM12 | CS12 | CS11 | CS10 |
  //TCCR1B = B00001000; // Arrêt horloge et mode CTC sur OCR1A
  //TCCR1B = B00001001;  // Horloge active prescalaire : 1 = 62.5ns / max : 4.10ms
  //TCCR1B = B00001010;  // Horloge active prescalaire : 8 = 500ns / max : 32.77mµs
  //TCCR1B = B00001011;  // Horloge active prescalaire : 64 = 4µs / max : 262.14ms
  TCCR1B = B00001100;  // Horloge active prescalaire : 256 = 16µs / max : 1048.56ms
  //TCCR1B = B00001101;  // Horloge active prescalaire : 1024 = 64µs / max : 4194.24ms
  // interruption locale activées 
  // | 0 | 0 | ICIE1 | 0 | 0 | OCIE1B | OCIE1A | TOIE1 |
  TIMSK1 = B00000010;    // Interruption Timer1 Quand TCNT1=OCR1A
  OCR1A = 250; //  max 65535 Comparaison A
  sei(); // Active l'interruption globale
}
// Routine d'interruption
ISR(TIMER1_COMPA_vect) 
{
  if (varCompteur++ > 125) 
  { // 125 * 4 ms = 500 ms (demi-période)
    varCompteur = 0;
    PORTB ^= (1<<4); // pin 12 LOW
  }
}
void loop () 
{
  LedToggle; // Temps du changement 10µs
  delay (500);
}

Bonjour QUINQUIN07

A noter que si on choisit (OCR1A étant sur 16 bits):

OCR1A = 31250;

on peut se passer du compteur varCompteur, ce qui simplifie la routine d’interruption, ce qui est toujours souhaitable.

Cordialement,
bidouilleelec

Bonjour ok pour le timer1, mais pas pour le 2, merci pour l'info.
Marc.

pour "trimarco232", j'ai précisé sur mon premier post que c'était pour comprendre le fonctionnement des timers, il est bien évident que pour faire clignoter une diode il y a d'autres moyen plus simple.

dans le sens où je l'entendais, ce n'est pas forcément plus simple dans un premier temps. Sauf qu'une fois le timer configuré, le clignotement (ctc) ou le pwm fonctionnent de manière autonome, cad. sans avoir recours à des interruptions donc en fichant la paix à la cpu et au programme

dans ta démarche d'apprentissage de la programmation "bare metal" des timers, je te suggère d'essayer cela, et pourquoi pas aussi le mode capture, qui est intéressant bien que peu utilisé par les arduinistes

bien entendu cette suggestion m'engage à t'apporter toute l'aide nécessaire le cas échéant