Compter le temps qui s'écoule dans notre vie sans utiliser millis() et micros()

Salut, une question qui peut paraître stupide dans la vie de tous les jours, mais dans le loop d'arduino, c'est un peu le bordel.. (pour moi, abruti, qui écoute les playoff de la NFL).

En gros, je veux seulement adresser à des variables les temps suivants;

#1 le temps qui s'est écoulé pendant que digitalRead(13) recevait quelque chose (on).
#2 le temps qui s'est écoulé pendant que digitalRead(13) ne recevait rien (off).

Merci pour le temps passé à lire ce questionnement. :sweat_smile:

Jetez un œil éventuellement à pulseIn() sinon si ça bouge lentement et que la précision n’est pas au dizieme de millisecondes près enregistrez millis ou micros avant que la pin 13 ne commence à recevoir quelque chose et quand elle a terminée et faites la différence

Jetez un œil éventuellement à pulseIn()

Merci! Je n'avais pas connaissance de cette fonction.. Si on parle d'un temps de 15 minutes, j'ai fait un truc comme ça en m'inspirant d'un post précédent de kamill;

void setup () {
  Serial.begin(9600);
  pinMode(13, OUTPUT);
  pinMode(7, INPUT);
}

void loop () {
  static unsigned long temps=0;
  static unsigned long mSdebut=millis();
  static byte dR7=0;                                         

  if (digitalRead(7) == 1) { digitalWrite(13, 1); }
  if (digitalRead(7) == 0) { digitalWrite(13, 0); }
  
  if (digitalRead(7) == 1 && dR7 == 0) { mSdebut=millis(); } 
  else if (digitalRead(7) == 0 && dR7 == 1) { temps=millis()-mSdebut; }
  
  dR7=digitalRead(7);
  Serial.print("temps :");
  Serial.println(temps);
   
}

Ça semble fonctionner, mais il faut maintenant banker ces valeurs pour les utiliser plus tard, pour d'autres fonctions! Une piste?

Je le fais avec le registre compteur d'un timer.
Le timer0 est déconseillé car il est configuré pour les fonctions arduino.
N'importe quel autre timer convient. Le plus simple est de prendre un timer 8 bits puisque qu'avec un micro 8 bits un registre 16 bits se lit en deux temps ( 16 bits = 2 octets) et que la capacité de comptage d'un 8 bits est suffisant.

Tu règle le pré-diviseur du timer sur le rapport qui va bien pour ta mesure.
Un pré-diviseur de 1 permet de lire directement en cycles horloge.

Il suffit de lire le registre du compteur du timer avant et après l'opération à mesurer.

Pour éviter la gestion des débordement il suffit de mettre le compteur à zéro.
TCNT2 = 0 pour le timer 2.

TCCR2B = 1 ; //Timer 2 lancé avec diviseur = 1
TCNT2 = 0 ; // Raz du compteur
digitalWrite(13,1);
nombre_cycle = TCNT2 ;

Si le temps à mesurer est plus grand il suffit de modifier le pré-diviseur.
le Timer 2 accepte N=1, 8, 32, 64, 128, 256, 1024.
Les registres à modifier sont indiqués dans la datasheet du micro.

Je n'ai pas de source exemple immédiatement sous la main mais si la lecture de la datasheet te parait obscure je ferais des fouilles dans mon disque dur.

Bien, sauf que je ne vois pas comment je pourrais placer le timer2 pour compter le temps à l’intérieur du code...

si je fais un truc comme ça;

void loop () {
  unsigned long  temps=0;
  unsigned long  Timer_TCNT2_debut=0;
  unsigned long  Timer_TCNT2_fin=0;
  int dR7=0;

  TCCR2B = 1;
  TCNT2 = 0;
  
  if (digitalRead(7) == 1) { 
    digitalWrite(13, 1);
    Timer_TCNT2_debut=TCNT2;
    }
  if (digitalRead(7) == 0) { 
    digitalWrite(13, 0);
    Timer_TCNT2_fin=TCNT2;
    }

  temps=Timer_TCNT2_debut-Timer_TCNT2_fin;
  Serial.print("temps : ");
  Serial.println(temps);

J'ai seulement un résultat style 189, 124 tout le temps, peu importe le temps que la LED reste allumé.

Premièrement le timer 2 est un timer 8 bits soit un octet.
Utiliser un long pour le lire est une erreur. Les long c’est pour la fonction millis ou les fonctions qui utilisent millis.
Il faut utilser un type byte ou uint8_t c’est la même chose.

Deuxiemement il faut faire une raz du compteur avant chaque mesure :

TCNT2 = 0 ;
digitalWrite(13,1).
mesure_1 = TCNT2;
TCNT2=0 ;
resultat =digitalRead(13).
mesure_2 = TCNT2

On faisant ainsi j’“économise” :
une variable debut → comme TCNT2 est forcé à 0 je n’ai pas à enregistrer cette valeur
une soustraction → commme la valeur de départ est 0 la lecture est directe.
je n’ai pas à gérer le débordement du compteur (après la valeur 255 le registre passe à 0)

Capacité maximale de mesure :
Tout à une limite.
Un cycle horloge est égal à une période d’horloge soit T = 1/16MHz = 62,5 ns .
Un octet c’est 256 valeurs possibles.
Le prédiviseur max du timer 2 c’est 1024.
Capacité max = 256 *1024 cycles horloge → attention la valeur pour TCCR2B que j’ai donné est pour un diviseur de 1, pour avoir 1024 il faut changer cette valeur (voir datasheet du micro).

Le timer 8 bits est adapté à lamesure des temps courts.
Si les temps à mesurer dépassent sa capacité il est préférable d’utiliiser un timer 16 bits (la capacité de mesure sera multipliée par 256) → attention avec un registre16 bits il faut utiliser un unsigned int (ou uint16_t c’est la même chose).

Si les temps sont encore trop longs la méthode proposée par J-M-L sera la plus appropriée

Ok, ça fait environ 36 heures que j'apprends à gérer les timers. Oui, j'aurais pu m'en foutre et utiliser la commande millis()... Mais non. Je veux apprendre sur la vie des Timers. Ils sont peut-être vivants et ils méritent qu'on prenne le temps de s'en occuper. Peut-être qu'au paradis, ils seront là près de moi, en me remerciant d'avoir pensé à eux. Dans la vie, je prône la reconnaissance.

Le résultat est simple; compter les secondes qui s'écoulent quand on appuie sur un bouton. C'est simple à faire? Non.

Il fallait passer 36 heures pour comprendre comment on fait sans utiliser millis().

Je ne veux pas porter un commentaire négatif sur le conseil de 68tjs, pour ce qui est du calcul mathématique, c'est raisonnable, mais concernant cette piste de code;

 TCNT2 = 0 ;
digitalWrite(13,1).
mesure_1 = TCNT2;

Avec respect, ce n'est pas quelque chose qui m'a été utile de faire! Ce code prend la mesure de comptage pure du timer (avec surement un millier de "reset"). Ça ne sert absolument pas à mesurer quelque chose.

En fait, je me demandais dans quelle optique ce code pourrait servir??

Sinon, pour le résultat de mes recherches, j'ai réussi à faire ce que je voulais à la base, c'est à dire simplement compter les secondes en utilisant un des timers disponibles;

int Cycles = 0;                 // La variable qui compte les cycles  

void setup () {
  Serial.begin(9600);
  pinMode (13, OUTPUT);
  
  TCCR2A = 0b00000000;          // Configuration en mode normal
  TCCR2B = 0b00000110;          // Pprescaler 256
  TCNT2 = 6;                    // Chargement du timer à 6 (256-250).. aurait pu être à zéro, pas important??.
}

void loop () {
  if (digitalRead(7)==1){
    digitalWrite(13,1);
    if (TIFR2) {                // Si le flag TIFR2 (bit TOV2) est "ON" (à 1)
      TCNT2 = 6;                // Rechargement du timer à 6 pour qu'il recompte 250 coups.
      Cycles++;                 // Incrémentation du cycle de 1
    }
  }
  else digitalWrite(13,0);

  static long Seconde=0;
  Seconde=Cycles/250;           // (16Mhz /16) = 62 500Hz (coups de timer). 62 500 / 250 = 250Hz. Donc 250 / 250 = 1 pour 1Hz; une seconde.
  Serial.println(Seconde);      // Affiche les secondes qui ce sont écoulés pendant que digitalRead(7) recevait du courant.
}

Maintenant, si je fais un genre d'"Hello World" avec une superbe LED qui s'instille, tel mon coeur rempli de joie, en utilisant ce même timer2, configuré de la même façon que pour compter les secondes, je cherchais à comprendre un truc; à savoir pourquoi il faut remettre le flag à "1" au lieu de zéro dans un loop pour qu'il "reset" !!? Je ne comprends pas.

voir TIFR2=TIFR2;

int Cycles = 0;                 // La variable qui compte les cycles  

void setup ()
{
  Serial.begin(9600);
  pinMode (13, OUTPUT);
  
  TCCR2A = 0b00000000;          // Configuration en mode normal
  TCCR2B = 0b00000110;          // Prescaler 256
  TCNT2 = 6;                    // Chargement du timer à 6 (256-250).. aurait pu être à zéro, pas important??.
}
 


void loop () {
  
  
  if (TIFR2) {                  // Si le flag TIFR2 (bit TOV2) est "ON" (à 1)
    TCNT2 = 6;                  // Rechargement du timer à 6 pour qu'il recompte 250 coups.
    Cycles++;                   // Incrémentation du cycle de 1
    TIFR2=TIFR2;                // ?????????
      
    if (Cycles > 250) {
      Cycles = 0;               // Cycles remis à zéro.
      PINB |= 0x20;             // équivalent de digitalWrite (13, !digitalRead(13))
    }
  }
}

Avec respect, ce n'est pas quelque chose qui m'a été utile de faire! Ce code prend la mesure de comptage pure du timer (avec surement un millier de "reset"). Ça ne sert absolument pas à mesurer quelque chose.

En fait, je me demandais dans quelle optique ce code pourrait servir??

Comme je l’ai dit plus haut utiliser les timers directement pour mesurer un temps “long” ne presente aucun intérêt. La suggestion de 68tjs n’était là que parce qu’ils avait compris d’après le titre de votre post que vous souhaitiez mesurer le temps écoulé entre deux instructions un peu haut niveau au micro-processeur - genre voire combien de temps prends un digitalWrite(), un analogRead() ou un petit calcul mathématique par exemple.

Pour mesurer une externalité représentée sur une pin par une tension - comme je le dis plus haut - Si c’est fugace et qu’il faut être précis en quelques micro-secondes alors pulseIn() ou des interruptions et le timer système qui compte en microSecondes sont là pour cela, et si c’est du temps long (genre bouton appuyé par l’utilisateur et plusieurs dizaines ou centaines de millisecondes et pas besoin d’une précision micro-seconde) alors jouer juste avec millis() ou micros() est largement suffisant.

Faire autrement et prendre un second timer pour cela - alors qu’il y a déjà le timer0 qui compte pour vous et est prévu pour cela dans le système c’est un peu idiot à mon sens puisque ça fait double emploi...

Maintenant si c’est pour votre karma au paradis des programmeurs et des micros-contrôleurs alors c’est une autre histoire :slight_smile:

Si ce que je t'ai proposé ne te sert à rien et bien tu l'oublies.

Vu le flou pas artistique des temps que tu voulais mesurer il me semble bien avoir précisé que l'utilisation directe du compteur d'un timer était pour avoir de la précision avec des temps courts.
J'ai beau relire ton premier message il n'y est nulement fait mention de temps de l'ordre de la seconde.
C'est pourtant une information de première importance.
Donc quand on est pas précis il ne faut pas se plaindre de ne pas avoir une réponse adaptée.

Pour des temps plus long, la précision au cycle d'horloge près n'est pas necessaire et il existe d'autres méthodes dont millis() et celle que t'a proposé J-M-L.

J'ajouterai simplement que si tu avais ouvert le fichier qui contient le code de millis() tu aurai vu que millis utilise le compteur du timer 0. Millis ne fait en plus que gérer les débordements du compteur jusqu'à une certaine liimite, liée au type de variable que renvoie millis, après millis déborde lui même.
Donc utiliser un compteur de timer ou utiliser milli() c'est la même chose.

NB : Au depart du programme la configuration générale est effectuée par la fonction init().
Tel que configuré "en mode" arduino le timer 0 ne permet pas d'avoir une précision au cycle d'horloge prés.
Pour cela il faudrait modifier son prédiviseur. C'est pour cela que j'estime que quand un autre timer est disponible (pas de PWM active entre autre) autant ne pas modifier le timer 0.
C'est un choix personnel.
Dans tout les cas il est prudent de lire et de sauvegarder le registre concerné afin de le rétablir en configuration arduino à la fin de la phase de mesure.

Coup de Gueule ON !

Voila le cahier des charges du départ :

En gros, je veux seulement adresser à des variables les temps suivants;

#1 le temps qui s'est écoulé pendant que digitalRead(13) recevait quelque chose (on).
#2 le temps qui s'est écoulé pendant que digitalRead(13) ne recevait rien (off).

Voila la réponse pour remercier 68tjs et J-M-L du temps passé :

TTTTT:
.....
Ok, ça fait environ 36 heures que j'apprends à gérer les timers. Oui, j'aurais pu m'en foutre et utiliser la commande millis()... Mais non. Je veux apprendre sur la vie des Timers.
.....................
Je ne veux pas porter un commentaire négatif sur le conseil de 68tjs, pour ce qui est du calcul mathématique, c'est raisonnable, mais concernant cette piste de code;......

En ce qui me concerne, je considère que ce type de remerciement est une honte !
Coup de gueule off

Serge .D

J-M-L:
Mesurer le temps écoulé entre deux instructions un peu haut niveau au microprocesseur - genre voire combien de temps prends un digitalWrite(), un analogRead() ou un petit calcul mathématique par exemple.

68tjs:
J’ai beau relire ton premier message il n’y est nulement fait mention de temps de l’ordre de la seconde. C’est pourtant une information de première importance.

J’ai quand même spécifié pendant que digitalRead(13) recevait…, j’avoue que c’est difficile de faire un titre convenable, je voulais que ça soit simple. Pour quelle raison on pourrait avoir envie de savoir le temps que ça prend au microcontrôleur pour exécuter une fonction brute qui consiste à juste faire allumer une led? Surtout quand la vitesse est 16Mhz, on le sait que c’est hyper rapide. Je cherche à obtenir le temps durant laquelle la led est allumé et non l’action de le faire. Je croyais que c’était simple comme problématique… Je ne m’attendais pas à tout un charabia qui ne fonctionne même pas. :sob:

Mais ce n’est pas grave, parce qu’on est ici pour s’amuser, boire un bon café devant son écran d’ordinateur, aider les ignorants, passer le temps et se faire à croire (confirmer) qu’on est un bon programmeur Arduino.

J-M-L:
Faire autrement et prendre un second timer pour cela…

Une des raisons est que je ne veux pas seulement me fier aux librairies d’Arduino pour programmer un microcontrôleur, comprendre la gaffe et pouvoir le faire sur d’autres (qui ont des timers internes). Je veux aussi utiliser les timers pour avoir du PWM à une fréquence xyz et exécuter des tableaux à une vitesse xyz etc…

Je m’étais dit que de commencer par réussir à compter les secondes serait un bon début. En fait, si on pouvait changer le titre, ça serait “Compter le temps qui s’écoule dans notre vie sans utiliser millis() et micros()” soit en configurant soit même un timer pour le faire. 8)

pendant que digitalRead(13) recevait

Certes, mais ça ne veut absolument rien dire.... la pin 13 aura une valeur HIGH ou LOW en permanence - Elle « reçoit » tout le temps, de l’extérieur si elle est configurée en Input ou de l’interieur si Elle est configurée en OUTPUT (pas la meilleure pin vue la LED accrochée dessus sur votre arduino sans doute). De plus vous n’avez pas précisé si ça variait rapidement ou pas, d’où ma réponse #1 avec différentes options. [au passage adresser à des variables ça ne veut rien dire, on dit affecter une valeur à une variable]

Pour quelle raison on pourrait avoir envie de savoir le temps que ça prend au microcontrôleur pour exécuter une fonction brute qui consiste à juste faire allumer une led?

les membres du forum viennent ici avec toutes sortes de questions. Celle ci pourrait être de la curiosité intellectuelle ou cette pin pourrait être au bout d’une fibre optique de transmission de données et on pourrait vouloir affiner le timing, il peut y avoir 100 bonnes raisons

Surtout quand la vitesse est 16Mhz, on le sait que c'est hyper rapide.

Non c’est super lent par comparaison à l’utilisation directe des registres. tout dépend de votre besoin. Si vous devez mettre simultanément 2 pins à HIGH ou LOW avec cette digitalWrite() ou lire l’état de 2 pins simultanément avec digitalRead() - Il y aura plusieurs microSecondes d’ecart Entre les deux, ça peut créer des soucis de synchro avec un système lié par exemple.

Je cherche à obtenir le temps durant laquelle la led est allumé et non l'action de le faire. Je croyais que c'était simple comme problématique... Je ne m'attendais pas à tout un charabia qui ne fonctionne même pas. :sob:

tout ce qu’on vous a dit fonctionne - y compris ma réponse #1. Utilisez votre cerveau

Une des raisons est que je ne veux pas seulement me fier aux librairies d'Arduino pour programmer un microcontrôleur, comprendre la gaffe et pouvoir le faire sur d'autres (qui ont des timers internes). Je veux aussi utiliser les timers pour avoir du PWM à une fréquence xyz et exécuter des tableaux à une vitesse xyz etc...

pourquoi n’avez vous pas commencé par expliquer cela? Vous m’avez fait perdre mon temps alors en vous expliquant comment faire avec les services disponibles en standard...

Je m'étais dit que de commencer par réussir à compter les secondes serait un bon début. En fait, si on pouvait changer le titre, ça serait "Compter le temps qui s'écoule dans notre vie sans utiliser millis() et micros()" soit en configurant soit même un timer pour le faire. 8)

Il suffit de lire le code source de millis() et micros() et la doc et nombreux tutos sur les timers, ou d’une RTC... c’est ce qu’on vous aurait dit si vous aviez posé cette question... on vous aurait aussi dit que c’est tout à fait bien à titre de curiosité intellectuelle mais complètement idiot dans la majorité des cas de réinventer la roue puisque dans l'environnement Arduino - je rappelle que c’est le forum de programmation Arduino ici - ces services sont déjà implémentés pour vous, les ré-écrire ne ferait donc que double emploi et ralentirait un peu plus le système, tout en perdant un second timer qui peut être utile à autre chose, genre gérer un Servo... donc à moins d’avoir un besoin qui le justifie on vous aurait dit de ne pas aller dans cette direction...

Bref vous avez posé une question, la formulation était ce qu’elle était, vous avez eu des réponses précises pour cette question, avec des alternatives à explorer, de la part de bénévoles qui ont pris de leur temps et qui souhaitaient vous aider et vous ne semblez faire que peu de cas pour participer intellectuellement à une discussion suivie sur votre question...

Donc pour faire simple, je,quitte ce thread chronophage et inutile

Bien, mon but n’était pas que ça vire en chicane de programmeurs saouls…

Néanmoins, merci pour vos pistes (68tjs et J-M-L), ils ont quand même été utiles ;D

Pour conclure le thread, si jamais quelqu’un passe par là (c’est ça le but…), j’ai réussi à construire un code qui fait exactement ce que le titre dit. En bonus, j’ai aussi trouvé la façon de ne pas utiliser bitSet et bitRead;

TIFR2 >> 0 & 0x01 qui est l’équivalent de bitRead (TIFR2, 0) == 1)
C’est pour vérifier l’état du flag; s’il est on, le timer TCNT2 repart son décompte à 6.

TIFR2 |= (1 << 0); qui est l’équivalent de bitSet (TIFR2, 0);
Sers à faire redescendre le flag pour qu’il se relève un coup que le timer arrive à 255. Tout ça pour incrémenter la variable FlagCounter2 qui compte jusqu’à 250 le nombre de flags levés.

if (FlagCounter2 > 250)
250 flags levés est équivalent à une seconde, celle qui passe dans notre vie, placée dans la variable timer2 et ensuite affichée dans le Serial. Notez qu’un reset du Serial entraîne aussi un reset de la variable, c’est seulement pour visualiser que ça marche.

unsigned int FlagCounter2 = 0;

void setup ()
{
  Serial.begin(9600);
  pinMode (13, OUTPUT);
  
  cli();
  TCCR2A = 0b00000000;          // mode normal
  TCCR2B = 0b00000110;          // prescaler 256
  TIFR2 = 0b00000001;
  TCNT2 = 6;                    // 250 coups
  sei();
   
}

void loop () {
  
  static long timer2=0;
    
  if (TIFR2 >> 0 & 0x01) {      
    TCNT2 = 6;
    TIFR2 |= (1 << 0);     
    FlagCounter2++; 
      
      if (FlagCounter2 > 250) { 
        Serial.println(timer2); 
        FlagCounter2 = 0;       
        timer2++;          
      }
  }
}

Merci à Locoduino pour l’apprentissage des bases des timers, pas évident par contre. ::slight_smile:
http://www.locoduino.org/spip.php?article84

TIFR2 >> 0ça sert à quoi de décaler de 0 bit un octet??
TIFR2 |= (1 << 0); ça sert à quoi de décaler 1 de 0 bits ?

Notez qu’il y a un flag appelé OCF2A , qui est le bit 1 du registre TIFR2 (Timer/Counter 2 Interrupt Flag Register)

bien sûr comme millis et micros sont là, ce n’est pas la peine de réinventer la roue et on peut faire

const unsigned long uneSeconde = 1000000ul; // en microsecondes

void setup() {
  Serial.begin(115200);
}

void loop() {
  static unsigned long t0 = micros();
  static unsigned long n = 0;
  
  if (micros() - t0 >= uneSeconde) {
    t0 += uneSeconde;
    n++;
    Serial.print(n);
    Serial.println(F("s"));
  } 
}

Bien, mon but n’était pas que ça vire en chicane de programmeurs saouls…

:slight_smile: 8) :grin:

Je ne comprends pas exactement le pourquoi, mais j’essaie. Je me base sur le #define de bitRead et bitSet…

TIFR2 >> 0 & 0x01
C’est vérifier si le bit #0 de TIFR2 qui est à ‘1’, ça aurait pu juste être TIFR2==1 aussi, mais ça ne spécifie pas son bit exactement je crois. Sinon, c’est quoi le deal? Pourquoi ça marche? C’est quoi ça fait? Pouquoi? Dieu existe?

TIFR2 |= (1 << 0);
D’après ce que j’ai pu comprendre, c’est que tu set à ‘1’ le bit #0 du registre TIFR2. J’ai fait des tests, si tu fais le contraire, cad placer le bit à ‘0’, eh bien le flag reste levé en permanence.

En gros, c’étais juste de comprendre la mécanique de bitRead et bitSet;

#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))

OCF2A est le flag pour le mode CTC, en mode normal, il est désactivé.

se passer de la macro pour écrire à la main ce que le préprocesseur génère n'est pas très utile... autant conserver la macro dans ce cas là, surtout si vous ne comprenez pas ce que ça fait...

Un bon code serait ...(TIFR2 & B1)...etTIFR2 |= B1;

la notation B est une macro du monde arduino B1 c'est un octet avec le bit de poids faible alloué (bref c'est comme 1) on peut avoir B11001010 par exemple

sinon en C++ on noterait un littéral en binaire avec 0b au début par exemple 0b11001010

On pourrait donc aussi écrire

...(TIFR2 & 0b1)...
TIFR2 |= 0b1;

ou en décimal (car dans ce cas c'est lisible)

...(TIFR2 & 1)...
TIFR2 |= 1;

OCF2A est le flag pour le mode CTC, en mode normal, il est désactivé.

OCF2A est une constante qui sert de mask pour accéder un bit particulier d'un registre de contrôle

void setup() {
  Serial.begin(115200);
  Serial.println(OCF2A, BIN);
}

void loop() {}

va vous imprimer 1 sur la console série. il est défini quelque part dans un header ATMEGA comme #define OCF2A 1

Merci! Je vais analyser une autre façon de jouer avec les bits en faisant des tests ce soir avant de dormir. :smiley: Je vais en reparler.. Le mieux serait de juste pointer le registre et son bit, ensuite faire ==. Ça va être plus simple pour manœuvrer sans faire d'erreurs.

exemple; "registre" & "son bit" == 1?

Par contre je me demande encore pourquoi il faut mettre TIFR2 à 1 et pas à 0 pour le faire descendre? Ce qu'on veut, c'est faire descendre le flag parce qu'il est monté (donc à 1), lui envoyer l'instruction '1' me sembre avoir aucun sens.

TTTTT:
Merci! Je vais analyser une autre façon de jouer avec les bits en faisant des tests ce soir avant de dormir. :smiley: Je vais en reparler… Le mieux serait de juste pointer le registre et son bit, ensuite faire ==. Ça va être plus simple pour manœuvrer sans faire d’erreurs.

exemple; “registre” & “son bit” == 1?

dans l’absolu non…

Imaginez que le registre soit 1100[color=red]1[/color]010 et que vous vouliez le bit rouge.
Le masque à appliquer est donc 0000[color=blue]1[/color]000

Une fois le masque appliqué il reste 0000[color=red]1[/color]000 → la valeur calculée est 8(decimal) ==> si vous comparez avec 1 le test sera faux.

Dans votre cas comme vous testez sur le bit de poids faible ça fonctionnerait.

Dans le cas général soit il faut comparer à la valeur du masque, soit tout simplement écrire if (registre & mask) {...}car le compilateur traite toute valeur non nulle comme vraie.

TTTTT:
Par contre je me demande encore pourquoi il faut mettre TIFR2 à 1 et pas à 0 pour le faire descendre? Ce qu'on veut, c'est faire descendre le flag parce qu'il est monté (donc à 1), lui envoyer l'instruction '1' me sembre avoir aucun sens.

C’est contre intuitif effectivement mais bien documenté (et assez fréquent par exemple quand vous manipulez les ports écrire un 1 sur un des bit dans PIND va faire un toggle (bascule) de la valeur de ce bit -> pas besoin de le lire puis d’ecrire L’inverse c’est fait au niveau bas pour vous)

Extrait de la doc:

This is usually done by writing a logical 1 into this bit position. This seems to be illogical at first, the bit position already carries a logical 1 when reading it, so why does writing a logical 1 to it clear the interrupt bit?
The solution is simple: writing a logical 1 to it requires only a single OUT instruction, and it is clear that only this single interrupt request bit will be cleared. There is no need to perform a read-modify-write cycle (like, an SBI instruction), since all bits in these control registers are interrupt bits, and writing a logical 0 to the remaining bits (as it is done by the simple OUT instruction) will not alter them, so there is no risk of any race condition that might accidentally clear another interrupt request bit.

Merci, c’est ce que je me disais, ça confirme. :slight_smile: Je n’ai pas été capable d’être devant un ordinateur depuis 2 jours, mais j’ai hâte de m’installer et travailler sur des opérations qui vont manipuler les bits du registre.

Entre autre, si on a un octet style 0b10110111 et qu’on veut seulement manipuler le bits 0bX0X10111 (en random ou instruction quelconque) en n’utilisant pas de le bitwise shift << / >>… le contraire de &, donc !&?

exemple; 0b10110111 & 0b10010000 = 0b00100111?

L’idée serait de simplifier (visuellement) le code afin de mieux le comprendre, je ne veux pas utiliser les bitSet, bitWrite etc, ni de bitwise shift, parce que je risque d’avoir trop de manupulation dans un code et le fait de prendre l’octet au complet (avec son nom) facilitera ma façon de repère mes instructions. C’est une question de gout.

Ok, je suis le bois avec un iPhone 4S, je ne peux faire plus que ça :stuck_out_tongue: