Boujour
J'aimerais savoir quel est le vecteur d'interruption généré lorsque le flag ICF1 (de TIRF1) passe a '1', c'est-a-dire lorsque le compteur TCNT1 atteind la valeur du registre ICR1, dans le mode 'CTC to ICR1'.
J'ai evidemment configuré TMSK1 = (1<<ICIE1).
Est-ce ISR(TIMER1_CAPT_vect)?
Ou peut-etre ISR(TIMER1_TOV1_vect)?
La documentation que j'ai trouve ne précise pas ce détail.
Merci
peut-être que cet article Locoduino peut vous aider ?
Désolé pour ceux qui n'ont pas été lire le charabia du timer1, la suite va leur paraître écrit dans une autre langue (et pourtant c'est du C++).
Locoduino n'utilise pas le mode CTC avec comparaison ICF, mais le mode avec comparaison COMPA ou COMPB. Cela ne nous fait pas avancer...
J'ai voulu faire la même chose, utiliser le mode CTC avec ICF et pas COMPA ou COMPB. J'ai buté sur le même problème. Du coup je me suis rabattu sur les infos de Locoduimo. Je n'ai pas pu faire les test sur ICF, je n'avais rien qui fonctionnait. Maintenant, je le peux.
------------ Avant ---------------
Mon programme tourne actuellement en utilisant CTC / ICF. Voici les lignes de codes concernant le timer1:
// INITIALISATIONS
TIMSK1 = 0b00000000; // Pas d'interruption du timer pour l'instant
TCCR1A = 0b00000000; // Pas de comparaisons, mode CTC
TCCR1B = 0b00001010; // Mode CTC-COMPA, prescaler à /8
// Pour faire partir la temporisation
TCNT1 = 0; // Remettre le compteur à 0 pour que la première tempo soit bonne
TIMSK1 = 0b00000010; // Autoriser les interruptions COMPA
OCR1A = Temps; // Mettre le temps
// Programme d'interruption
ISR(TIMER1_COMPB_vect)
{
...
if (...) TIMSK1 = 0; // Arrêter les inters du timer 1
...
}
------------ Pour tester CTC avec ICF ---------------
Comme le programme fonctionne la base est bonne, si je passe de COMPA à ICF, je peux tester. Voici ce que j'ai mis au départ, en me basant sur ce que j'ai compris (mais venant de "Fast PWM Mode, Timing Diagram"):
The Timer/Counter Overflow Flag (TOV1) is set each time the counter reaches TOP. In addition the OC1A or ICF1 Flag is set at the same timer clock cycle as TOV1 is set when either OCR1A or ICR1 is used for defining the TOP value.
// INITIALISATIONS
TIMSK1 = 0b00000000; // Pas d'interruption du timer pour l'instant
TCCR1A = 0b00000000; // Pas de comparaisons, mode CTC
TCCR1B = 0b00011010; // Mode CTC-ICF, prescaler à /8
// Pour faire partir la temporisation
TCNT1 = 0; // Remettre le compteur à 0 pour que la première tempo soit bonne
TIMSK1 = 0b00000001; // Autoriser les interruptions OVF
ICR1 = Temps; // Mettre le temps
// Programme d'interruption
ISR(TIMER1_OVF_vect)
{
...
if (...) TIMSK1 = 0; // Arrêter les inters du timer 1
...
}
Évidemment cela n'a pas marché. Par contre (après essais!!!) ceci fonctionne:
// INITIALISATIONS
TIMSK1 = 0b00000000; // Pas d'interruption du timer pour l'instant
TCCR1A = 0b00000000; // Pas de comparaisons, mode CTC
TCCR1B = 0b00011010; // Mode CTC-ICF, prescaler à /8
// Pour faire partir la temporisation
TCNT1 = 0; // Remettre le compteur à 0 pour que la première tempo soit bonne
TIMSK1 = 0b00000010; // Autoriser les interruptions COMPA
ICR1 = Temps; // Mettre le temps
// Programme d'interruption
ISR(TIMER1_COMPA_vect)
{
...
if (...) TIMSK1 = 0; // Arrêter les inters du timer 1
...
}
Et si je remplace COMPA par COMPB, cela fonctionne aussi:
TIMSK1 = 0b00000100; // Autoriser les interruptions COMPA
...
ISR(TIMER1_COMPB_vect)
J'en déduis, chose surprenante que le vecteur d'interruption CTC-ICR est au choix TIMER1_COMPA_vect ou TIMER1_COMPB_vect
Ces tests ont été faite sur une carte Mega... à l'aide de la documentation de la Uno (en fait c'est le même timer)
Merci à sdaniel qui m'a obligé à me replonger dans mon code pour que je m'aperçoive que ma première durée pendant laquelle je ne fait rien à une durée indéterminée.
Bonsoir, ce n'est pas tout à fait ça.
L'ISR(...OVF...) ne peut se déclencher que s'il se produit un OVERFLOW : comme tu remets le timer à zéro avant (en arrivant à la valeur contenue dans ICR1), l' overflow n'a pas lieu et l'interruption ne se déclenche pas (ou plutôt n'est pas demandée).
Dans tes deux essais avec ISR(...COMPA/COMPB...), comme OCR1A/B sont à zéro, tu as l'impression que ça fonctionne, mais l'INT a lieu dès le début (quand le timer est à zéro) ou au mieux la première fois qu'il y revient.
En fait, l'ISR qui correspond à ICF est bien ISR(...CAPT...), qui est la même que pour le mode capture.
(non testé, mais ça doit fonctionner, c'est ce qu'indique Atmel dans sa doc)
5_cylindre, t'es un dieu!
// INITIALISATIONS
TIMSK1 = 0b00000000; // Pas d'interruption du timer pour l'instant
TCCR1A = 0b00000000; // Pas de comparaisons, mode CTC
TCCR1B = 0b00011010; // Mode CTC-ICF, prescaler à /8
// Pour faire partir la temporisation
TCNT1 = 0; // Remettre le compteur à 0 pour que la première tempo soit bonne
TIMSK1 = 0b00100000; // Autoriser les interruptions OVF
ICR1 = Temps; // Mettre le temps
// Programme d'interruption
ISR(TIMER1_CAPT_vect)
{
...
if (...) TIMSK1 = 0; // Arrêter les inters du timer 1
...
}
Fonctionne.
Ce qui m'a induit en erreur, c'est le schéma du timer 1:
Sur ce schéma, ICF ne peut provenir que de l'extérieur, alors que TOV dépend de la boite noire "Control logic". Du coup, je n'ai pas cherché vers CAPT.
C'est vrai aussi que CAPT, c'est pas plus logique que TOV
Effectivement, ISR(TIMER1_CAPT_vect) fonctionne pour le mode CTC to ICR1, je viens de verifier. Ceci me libere OCR1A et OCR1B en sortie.
Merci beaucoup a tous en particulier a 5_cylindres.
Ceci me libere OCR1A et OCR1B en sortie.
J'ai eu la même réflexion, c'est pour cela que je voulais utiliser ICR. Mais maintenant, je me demande si on peut utiliser les sorties. J'ai l'impression que l'on ne peut plus utiliser le PWM (en plus comme je fais varier la période, il faudrait ajuster COMPA. Et si c'est pour utiliser les sorties en mode I/O, que l'on utilise ou pas COMPA ne change rien.