Problème "while" et "do while"
Bonjour,
je programme depuis 1976 dans divers langages et sur divers microprocesseurs ou micro contrôleurs.
j'ai commencé avec les cartes ARDUINO il 5 ou 6 ans et je n'ai jamais pu exploiter les instructions "while" ou "do while" que se soit sur UNO, MEGA ou DUE,
via 5 versions d'IDE (la dernière 2.0.1) et 3 PC différents avec différents OS, VISTA, ..........., WINDOWS10.
j'ai bien sûr consulté les forums et bien que me conformant aux exemples, ça ne marche pas, ecxepté pour le DUE ou je rajoute une instruction d'un cycle (inTerrups()) avant la boucle, ce qui n'est pas très satisfaisant, à croire que l'addresse de retour de boucle est décalée d'un cycle.
Code:
1 2 3 4 5 6
| inTerrupts();
while(condition)
{
// do something
} |
un exemple type sur UNO:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| void setup()
{
#include <arduino.h>
// timeout = 15000;
// b_timeout = false;
interrupts();
}
void loop()
{
timeout = 15000;
b_timeout = false;
while(!b_timeout)
{
cmpt++;
}
// if(b_timeout)
// {
noInterrupts();
// }
}
// interrupt routine basée sur un timer cadensé à 1ms
// ********************************
// timer_interrupts
// ********************************
ISR(TIMER1_COMPA_vect)
{
// 1ms
// 1s
if(tim_1s > 1)
{
tim_1s--;
}
else
{
b_1s = true;
digitalWrite (LED_BUILTIN, !digitalRead(LED_BUILTIN));
tim_1s = 500;
}
// 15s
if(timeout > 1)
{
timeout--;
}
else
{
b_timeout = true;
}
} |
On peut vérifier que le flag (boolean) b_timeout ainsi que la variable (unsigned int) timeout sont bien mis à jour en supprimant la boucle "while" et en validant le "if".
La LED clignotte 15 fois puis s'eteind avec le "if", clignotte indéfiniment avec le "while", boucle infinie.
Quelqun peut-il m'éclairer?
Grand merci d'avance
Le canard était toujours vivant...
Bonjour Artemus,
Citation:
Envoyé par
Artemus24
j'ai supprimé "volatile" mais ça n'a rien changé. Mon exemple fonctionne toujours...
Comme _Cptr n'est pas utilisée en dehors de l'interruption qui en modifie la valeur, il ne peut y avoir de problème (enfin pas de ce type, mettre des Serial.print dans l'interruption est jouable ici car l'interruption est déclenchée seulement toutes les secondes sinon c'est assez risqué car lent) . Les difficultés arrivent quand une partie d'un programme ne "voit" pas qu'une ou plusieurs autres parties peuvent modifier la valeur dans son dos (interruption, multitâche s'il existe).
Il n'y aurait pas non plus de problème si elle était utilisée une seule fois dans une partie du programme (entre autres pas dans une boucle) en dehors de l'interruption nonobstant la précaution de s'assurer que l'accès reste atomique ou la copier en section critique (ce qui fait disparaître de facto le problème impliquant la déclaration en volatile).
volatile empêche le compilateur d'utiliser les optimisations de réutilisation des valeurs en registres. Ici le gain devrait être nul sauf si, après l'incrémentation et enregistrement en mémoire de la nouvelle valeur, il recharge la valeur qu'il vient de calculer avant de la passer comme argument au println. Il pourrait y avoir 10 ns de différence (estimation d'expert appelée également "au doigts mouillé"). Gain nettement perceptible n'est-ce pas ? :mouarf:
Salut