Un delay bien curieux

Voici un truc rigolo, qui n'a aucun intérêt sauf mathématique.

Voici tout d'abord le petit programme test que j'utilise pour faire clignoter une led (je suis fainéant, je prends celle de la platine). Cela fonctionne sur une Uno ou sur une Mega (j'ai pas essayé d'autres platines). Période 1s:

void setup()
{
  // Initialisation led
  pinMode(LED_BUILTIN,OUTPUT);
}

void loop()
{
  digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); // Changer l'état de la led
  delay(500);
}

Dans un autre programme, les interruptions du timer de l'horloge me gênaient, j'ai donc arrêté ces interruptions, en mettant le masque d'interruption à 0:

  TIMSK0 = 0; // Arrêter les inters du timer 0

J'ai vérifié par ailleurs, je n'ai plus les 0,8% de perte de temps de l'horloge.


Je sais que si je désactive le timer 0, je ne peux plus utiliser millis(), micros() et delay(). Mais comme je suis bête et indiscipliné,j'ai repris mon programme de la led clignotante, et j'ai désactivé le timer 0:

void setup()
{
  TIMSK0 = 0; // Arrêter les inters du timer 0
  // Initialisation led
  pinMode(LED_BUILTIN,OUTPUT);
}

void loop()
{
  digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); // Changer l'état de la led
  delay(500);
}

Évidemment, comme je l'attendais, la led ne clignote plus (vous pouvez faire l'essai). J'ai pensé au début que comme l'horloge n'avançait plus, je n'atteindrai jamais les 500ms.
Erreur! ma led clignote toujours mais simplement plus vite, il suffit pour le voir de remplacer delay(500) par delay(100000) pour retrouver la période de 1s.

Est-ce que cela répond à "que faire pendant le confinement?"

Pas d’explication.

Immédiatement j’ai pensé que tu n’avais que le débordement du timer0 mais 4µs * 255 l’œil ne voit rien.

J’en profite pour signaler d’autres fonctions delay uniquement pour des micros avr.
Ce sont des fonctions Atmel de l’avr-libc qui n’utilisent pas de timer mais des propriété particulière du micro : quand on conçoit un micro on sait exactement ce qu’il y a dedans cela aide.

Detailed Description
#define F_CPU 1000000UL // 1 MHz
//#define F_CPU 14.7456E6
#include <util/delay.h>

Functions
void
void

Plus d’info :

https://www.nongnu.org/avr-libc/user-manual/group__util__delay.html

Pas d'explication.

Sur quoi faire pendant le confinement?

Sinon pour le delay si on supprime les interruptions, l'explication vient du code de delay:
(Arduino\hardware\arduino\avr\cores\arduino\wiring.c):

while (ms > 0)
{
   while ( ms > 0 && (micros() - start) >= 1000)
   {
      ms--;
      start += 1000;
   }
}

Si on bloque les interruptions micros retournera une partie haute fixe (plus remise à jour) et une partie basse qui évolue (TCNC). Du coup elle retourne une valeur entre N et N+1024. Micros() déborde donc toutes les ms. La première fois que micro déborde, ms diminue, start augmente de 1000 et sera donc toujours supérieur à micros(). La condition (micros() - start) >= 1000 est alors toujours vraie et le delay dure donc le temps des ms boucles.


_delay_us, _delay_ms et delayMicroseconds fonctionnent sensiblement pareil, il me semble. Dans les trois cas, on compte les boucles.