Pour une application de conduite, j'ai besoin que le mode PWM soit correct en phase et que le prédécaleur soit 1. Le problème est que la carte avec laquelle je travaille a la charge reliée à une broche PWM dépendant de timer0. Le firmware fonctionnant sur cette carte utilise les fonctions delay ()
, delayMicroseconds ()
et millis ()
du câblage.c. Le but est de faire le changement de timer0, illustré ci-dessous, puis d'apporter de petites modifications là où le micrologiciel appelle les fonctions de synchronisation de câblage.c. Mon approche a été de trouver un facteur d'échelle à appliquer à l'appel de ces fonctions. Le facteur de mise à l'échelle auquel je suis arrivé était de 32,12549 , calculé en prenant le comportement du timer0 attendu de câblage.c: prescaler = 64 et TOV0 drapeau tous les 256 comptes , et en le comparant aux valeurs réelles après ma modification: prescaler = 1 et TOV0 marquent tous les 510 points
Calcul: 64 * 256/510 = 32.12549
Changement de Timer0:
// Réglez timer0 sur la phase correcte PWMTCCR0A = TCCR0A & 0b11111100 | 0x01; // Définit le prescaler pour timer0 sur 1TCCR0B = TCCR0B & 0b11111000 | 0x01;
Les autres temporisateurs sont tous configurés en mode PWM correct de phase, avec un prescaler de 1.
... Quand j'applique ce facteur de mise à l'échelle à une valeur retourné de millis () pour garder le temps ça marche bien. Par exemple, les deux morceaux de code ci-dessous se sont avérés équivalents grâce au changement de timer0:
Utilisation de millis ()
avant le changement de timer0:
// current timelong unsigned now = millis (); // délai pendant 1 seconde while (millis () - now < 1000) {}
Utiliser de millis ()
après le changement de timer0:
// current timelong unsigned now = millis (); // délai de 1 seconde, avec x32. 125 coefficient de mise à l'échelle pendant (millis () - maintenant < 32125) {}
Les deux extraits de code ci-dessus ont tous deux retardé pendant 1 seconde
Maintenant vient le problème: quand j'essaye d'appliquer ce même facteur de mise à l'échelle à delay ()
ou delayMicroseconds ()
il semble donner des délais déraisonnables ...
Utilisation de delayMicroseconds ()
avant le changement de timer0:
// attendez 1,5 ms pour que le multiplexeur change de délaiMicrosecondes (1500);
... cela retarde 1,5 ms
Utilisation de delayMicroseconds ()
après le changement de timer0:
// attendez 1,5 ms pour que le multiplexage change, avec mise à l'échelle x32.125 coefficientdelayMicrosecondes (48188);
... cela retarde d'environ 20 ms.
En supposant que cela reste linéairement évolutif: si 48188 -> 20ms, donc 1.5ms -> 3614
Mais quand le code suivant est utilisé ...
// attendez 1,5 ms pour que le multiplexage change, scaleddelayMicrosecondes (3614);
... cela retarde d'environ 4,5 ms
Pourquoi est-ce que delayMicroseconds ()
et delay ()
ne peuvent pas être mis à l'échelle linéairement pour tenir compte d'un changement de timer0? De plus, y a-t-il une modification simple de la façon dont ces fonctions sont appelées ou utilisées qui peuvent expliquer l'effet du changement de timer0?