Probleme avec interruption ISR(TIMER1_COMPA_vect)

Bonjour,
je suis en train de créer des variations d'éclairage sur le PORTA avec une carte MEGA 2560
J'utilise un passage à 0 qui déclenche une interruption qui appelle "void passage à 0"
Une commande (action continue sur une bouton ) modifie une consigne de niveau d'éclairage de 1 à 25 . Cette consigne relie les retards de phase correspondant au niveau d'éclairage.

J'ai un souci avec l'interruption ISR.
Ci après le code épuré des 2 interruptions concernées

// paz et isr siimplifiés  pour l'essai de variation continue sut le bit 7 du PORTA
void passage_a_0 () {
  TCNT1 = 0;                           // initialisation de TNCT1
  if (variation_demandee == 128) {          // on est sur le bit 7
    PORTA &= ~variation_demandee;      // extinction du bit 7
    OCR1A = retard_phase[niv_ecl[7]];     // fixe la valeur de l'OCRIA 
    bitSet(TIMSK1, OCIE1A);                       // met le bit OCIE1A à 1  pour autoriser l'interruption de comparaison avec OCIE1A
  }
  n0++;                                                        // compte le nbre de passage dans cette interrup
}


ISR(TIMER1_COMPA_vect) {
  PORTA |= 128;                         // on agit immédiatement sur le port avec le bit concerné
  bitClear(TIMSK1, OCIE1A);    // met le bit OCIE1A à 0 pour interdire l'interruption de comparaison avec OCR1A
  n++;                                          // compte le nbre de passage dans cette interruption
}

Problème:
Avec cette instruction bitClear(TIMSK1, OCIE1A); dans l'ISR pourtant nécessaire
l'ISR est exécuté immédiatement comme si l'OCR1A était à 0 ??

Par contre si cette instruction est supprimée, la variation se produit correctement en prenant bien en compte les valeurs de l'OCR1A du retard de phase . MAIS, en fonction de la valeur de OCRIA , l'ISR est appelée plusieurs fois avant le passage à 0 suivant

Pourquoi l'ISR est déclenché immédiatement en présence du 'bitClear' ?
Est-ce une erreur de code ou de carte défectueuse ?
Votre avis sur ce point me serai bien utile.

Tu trouveras certainement la réponse en analysant le code .h ou .ccp de la bibliothèque tu appelles.

À mon avis, un bitClear() remet tout à zéro ... c'est - du moins - la fonction habituelle d'un xyzClear().

Je ne dis pas que c'est complètement impossible que le processeur ait une erreur, mais la probabilité est très faible. Par contre il y a de fortes chances, comme d'habitude, que se soit une erreur de code.

Tel que je comprends la doc:

Bit 1 – OCF1A: Timer/Counter1, Output Compare A Match Flag
This flag is set in the timer clock cycle after the counter (TCNTn value matches the Output Compare Register A (OCRnA).

Le flag OCF1A serait mis à 1 que l'on autorise ou pas les interruptions. Du coup comme il est à 1 depuis longtemps, le fait d'autoriser les interruptions la déclenche immédiatement, et la suivante devrait arriver au bon moment. Il faudrait faire le test en remettant ce bit à 0. Attention il y a une manip bizare:

OCFnA can be cleared by writing a logic one to its bit location.

il faut écrire un 1 pour le mettre à 0, contrairement à OCIE1A. Je suppose que bitSet(TIFR1, OCF1A); devrait faire l'affaire, mais personnellement j'écris TIFR1 |= 0b00000010;

bitClear(x, n) met à 0 le bit numéro n de la variable x. Le bit numéro 0 est le LSB, le plus à droite.

Les documents pour trouver le comportement des registres sont dans:
https://onlinedocs.microchip.com/
Find: All
Find in list: AVR Libc

Ils sont aussi dans la datasheet de l'ATMEGA2560, mais c'est pas la source qui est importante, c'est la compréhension que l'on en a.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.