Besoin d'aide pour comprendre la sortie miroir AVR ATMEGA / ATTINY timer


10

J'essaie d'utiliser Timer1 du microcontrôleur Atmel AVR, soit AtMega328 tel qu'utilisé dans l'Arduino, ou ATTiny85, pour émettre deux signaux d'horloge qui sont des images miroir l'un de l'autre. La fréquence que j'essaie de générer est une variable de 1 MHz à 2 MHz ou plus qui est trop élevée pour le faire en utilisant du code pour basculer les broches de sortie, sauf si je ne veux presque rien faire d'autre dans le contrôleur. Je veux donc utiliser la sortie du minuteur directement sur les broches associées. J'utilise la chaîne d'outils GCC donc pas limitée par les bibliothèques ou le langage Arduino.

Timer1 dans l'Atmega328 a deux broches associées et je peux en obtenir deux signaux identiques de 1 MHz à 2 MHz. Bien que la fiche technique semble dire que je peux obtenir une forme d'onde inversée, cela me porte à confusion. Je peux également obtenir deux signaux qui sont des cycles d'utilisation différents à 1 MHz, en utilisant les paramètres PWM avec Timer1, mais les deux signaux montent en même temps, le plus court devient bas plus tôt. Cela ne sert pas mon projet. Je n'ai même pas besoin de la variation de largeur d'impulsion PWM, j'ai juste besoin de deux signaux identiques de type "horloge" de phase opposée, c'est tout.

Je ne demande à personne d'écrire du code pour que je le fasse, j'ai juste besoin que quelqu'un me dise quel mode / drapeaux de la minuterie devrait me donner une forme d'onde inversée simple sur l'une des deux broches associées à la minuterie. Si possible, je veux éviter d'utiliser un circuit inverseur externe pour l'une des sorties, sauf si c'est la seule option.

Si cela est possible dans ATTiny, ce sera encore mieux. L'ATTiny a également 2 broches associées à une minuterie, mais je ne suis pas sûr qu'il ait les mêmes options que l'ATMega.

J'ai déjà un cristal de 20 MHz et des condensateurs connectés sur le PCB et une horloge de 20 MHz fonctionne de manière fiable sur l'ATMega328. Sur ATTiny85 PCB, j'ai un cristal de 8 MHz et cela fonctionne également de manière fiable.

Veuillez aider. Je vous remercie.


MISE À JOUR : Il y a des hypothèses non valides dans les réponses et commentaires jusqu'à présent, alors je devrais peut-être clarifier: Notez que dans mon message d'origine, j'ai déclaré que j'utilise une horloge de 20 MHz, pas de 8 MHz , et que je n'ai pas besoin de PWM .

Le seul mode qui donne une fréquence de sortie suffisamment élevée semble être le mode CTC car les modes PWM ne fonctionnent pas pour une sortie à 2 MHz. Existe-t-il un moyen d'inverser la sortie A du temporisateur 1 ou la sortie B en mode CTC?

Je suis maintenant passé à un Arduino Uno standard (ATMega328, 16 MHz) au lieu de ma propre carte de 20 MHz pour vérifier mon code, et c'est mon code pour une belle horloge constante de 2 MHz en mode CTC à partir des broches 9 et 10, le minuteur 1 broches de sortie:

#define tick 9
#define tock 10

void setup() {
  pinMode(tick, OUTPUT);  
  pinMode(tock, OUTPUT); 

  TCCR1A = _BV(COM1A0) | _BV(COM1B0) ;   // activate both output pins 
  TCCR1B = _BV(WGM12)| 1;                // set CTC mode, prescaler mode 1

  // various frustrating attempts to invert OC1B failed. What do I put here?

  OCR1A = 3;                             // set the counter max for 2 MHz

}

void loop() {
}

Les traces de l'oscilloscope pour les deux broches sont identiques et synchronisées, comment puis-je inverser l'un des deux signaux? Le mode inverser dans la feuille de données semble ne rien faire en mode CTC. Suis-je en train de lire la fiche technique de manière incorrecte, ou serai-je obligé d'utiliser une fréquence inférieure et un mode PWM après tout?

Pour ajouter une question "prime" spécifique à ma requête d'origine:
quels changements dois-je apporter à mon code ci-dessus, pour qu'il donne des signaux parfaitement inversés aux broches 9 et 11 à la fréquence la plus élevée possible pour une horloge de 16 MHz , que ce soit c'est 2 MHz ou pas?

Je vais m'en tenir à un Arduino Uno standard pour l'instant, afin qu'il n'y ait pas de mode d'erreur introduit par ma carte homespun, et pour que toute personne ayant un arduino puisse essayer mon code ci-dessus et confirmer qu'il fonctionne comme je l'ai mentionné et non comme je l'ai dit. avoir besoin!


1
En regardant la page 97-98 de la fiche technique atmega8L , il y a un tableau des modes de fonctionnement. La page 108 indique "Les bits COM21: 0 contrôlent si la sortie PWM générée doit être inversée ou non (PWM inversé ou non inversé)". Tenez-nous au courant de votre réussite!
Vorac

Pourquoi ne pas utiliser un simple transistor inverseur pour les sorties miroir rouge?
Jonny B Good

Réponses:


10

De la fiche technique ATtiny85:

Le mode de fonctionnement, c'est-à-dire le comportement du temporisateur / compteur et des broches de comparaison de sortie, est défini par la combinaison du mode de génération de forme d'onde (WGM0 [2: 0]) et du mode de comparaison de sortie (COM0x [1: 0]). morceaux. Les bits du mode de comparaison de sortie n'affectent pas la séquence de comptage, contrairement aux bits du mode de génération de forme d'onde. Les bits COM0x [1: 0] contrôlent si la sortie PWM générée doit être inversée ou non (PWM inversé ou non inversé ).

Le tableau 11-5 montre comment définir le mode.

Mode   WGM  WGM  WGM  Timer/Counter Mode    TOP      Update of    TOV Flag
c0     02   01   00   of Operation                   OCRx at      Set on
==========================================================================
0      0    0    0    Normal                0xFF     Immediate    MAX(1)
1      0    0    1    PWM, Phase Correct    0xFF     TOP          BOTTOM
2      0    1    0    CTC                   OCRA     Immediate    MAX
3      0    1    1    Fast PWM              0xFF     BOTTOM       MAX
4      1    0    0    Reserved                                  
5      1    0    1    PWM, Phase Correct    OCRA     TOP          BOTTOM
6      1    1    0    Reserved                                  
7      1    1    1    Fast PWM              OCRA     BOTTOM       TOP

Vous voulez un mode PWM rapide (donc soit le mode 3 ou le mode 7). Si vous souhaitez faire varier le rapport cyclique et que cela vous ressemble, vous voulez le mode 7 et faire varier le rapport cyclique en définissant OCRA.

Le tableau 11-3 montre comment définir le mode de sortie de comparaison pour le mode PWM rapide.

COM0A1/   COM0A0/
COM0B1    COM0B0     Description
===============================================================================
0         0          Normal port operation, OC0A/OC0B disconnected.
0         1          Reserved
1         0          Clear OC0A/OC0B on Compare Match, set OC0A/OC0B at BOTTOM
                     (non-inverting mode)
1         1          Set OC0A/OC0B on Compare Match, clear OC0A/OC0B at BOTTOM
                     (inverting mode)

Autrement dit, vous pouvez régler la sortie OC0A pour qu'elle soit basse lorsque la valeur du temporisateur == OCR0A et élevée lorsque la valeur du temporisateur == 0x00 en définissant COM0A1: COM0A0 = 0b10. Ou vice versa en réglant COM0A1: COM0A0 = 0b11. Et de même pour OC0B, OCR0B, COM0B0, COM0B1.

La fréquence PWM est déterminée par l'horloge d'E / S (8 MHz, cela ressemble à vous) et le réglage de votre prédécaleur de minuterie. Et l'équation est donnée comme f_clk_IO / (N * 256) pour le mode PWM rapide.

Vous pouvez donc utiliser OC0A pour une polarité "normale" et OC0B pour une polarité "inversée" en définissant OCR0A et OCR0B sur la même valeur et en définissant COM0A1: COM0A0 = 0b10 et COM0B1: COM0B0 à 0b11.

METTRE À JOUR

Étant donné que vous souhaitez basculer la sortie aussi rapidement que possible et que vous utilisez le Mega328 fonctionnant à 16 MHz, le mode de fonctionnement CTC vous permettra d'obtenir une fréquence de commutation de:

f_OCnA = f_clk_IO / (2 * N * [1 + OCRnA) = 16e6 / (2 * 1 * [1 + 1]) = 4 MHz

Le mode Fast PWM vous permettra de basculer la broche à:

f_OCnxPWM = f_clk_IO / (N * [1 + TOP]) = 16e6 / (1 * [1 + 1]) = 8 MHz

Donc je pense toujours que vous voulez un mode PWM rapide. Plus précisément, le mode 3 avec OCR0A = OCR0B = 0x80 pour un rapport cyclique de 50%. Et définissez les bits COM0A sur 0x3 et les bits COM0B sur 0x2 pour créer les deux formes d'onde sur les inversions OC0A et OC0B l'une de l'autre.

Mise à jour # 2 Plus le Mega328 Essayez ce code Arduino:

#define tick 9
#define tock 10

void setup(){

  pinMode(tick, OUTPUT);  
  pinMode(tock, OUTPUT); 

  // Setup Waveform Generation Mode 15
  // OC1A Compare Output Mode = inverting mode
  // OC1B Compare Output Mode = non-inverting mode
  // Timer Prescaler = 1
  // TOP = OCR1A = 1

  //COM1A[1:0] = 0b11, COM1B[1:0] = 0b10, WGM1[1:0] = 0b11
  TCCR1A = _BV(COM1A1) | _BV(COM1A0) | _BV(COM1B1) | _BV(WGM11) | _BV(WGM10);

  //WGM1[3:2] = 0b11, CS1[2:0] = 0b001
  TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10);

  OCR1A = 0x0001;
  OCR1B = 0x0001;
}

void loop(){

}

Laissez-moi mâcher un peu et voir si cela fonctionne. Merci.
ExcitingProjects

Après avoir relu votre réponse pour l'essayer aujourd'hui, je vois quelques hypothèses invalides: j'ai spécifié une horloge de 20 MHz (et maintenant je suis passé à 16 MHz), pas "(8MHz ça sonne pour vous)" . J'ai également spécifié que je n'avais pas besoin de variation de largeur d'impulsion PWM, donc je ne sais pas où vous avez supposé "Si vous voulez faire varier le rapport cyclique, et cela ressemble à vous" .
ExcitingProjects

@ExcitingProjects Je saisissais votre déclaration "Sur ATTiny85 PCB, j'ai un cristal de 8 MHz et cela fonctionne également de manière fiable." et ma réponse se réfère à l'ATtiny85. Je vais essayer de mettre à jour ma réponse en réponse à votre question mise à jour.
vicatcu

@vicateu Merci. J'ai mis à jour la question, car le mode inversé semble n'avoir aucun effet en mode CTC, sauf si je manque une étape.
ExcitingProjects

@ExcitingProjects de la fiche technique ATmega328: "Pour les modes non PWM, les bits COM0x1: 0 contrôlent si la sortie doit être définie, effacée ou basculée lors d'une comparaison"
vicatcu

1

La famille ATtinyX5 a PLL à l'intérieur, utilisez-le grand garçon.

J'utilise également la PLL interne pour alimenter l'horloge du processeur et j'ai 16 MHz sans XTAL. C'est précieux car vous n'avez que 5 broches. (Je ne compte pas la broche de réinitialisation). Un PWM PLL (OCR1B) fonctionne également sur les broches XTAL avec sa sortie complémentaire en option. Vous avez juste besoin d'ajuster les fusibles pour 16Mhz Xtalless ATtiny ... Ou tout simplement laisser le CPU fonctionner en 8Mhz mais exécuter PWM avec une horloge 64Mhz sans changer les fusibles ..

Vous pouvez avoir jusqu'à 64 Mhz d'horloge PWM (mais une résolution de 1 bit). Ou une résolution de 125 kHz à 8 bits. Vous pouvez réduire la résolution PWM et augmenter la vitesse en diminuant le registre OCR1C.

Pour 1 Mhz, vous devez définir OCR1C sur 63. Pour 2 Mhz, vous devez définir OCR1C sur 31. Pour 4 Mhz, vous devez définir OCR1C sur 15. ...

Activez simplement PLL avec ce code:

PLLCSR |= (1 << PLLE);           //Start PLL
while( !(PLLCSR & (1<<PLOCK)) ); //Wait for PLL lock
//PLLCSR |= (1<<LSM );           //Low Speed PLL that clocks 32Mhz, not 64Mhz
PLLCSR |= (1 << PCKE);           //Enable PLL

Vous avez maintenant une horloge de 64 MHz sur les PWM "OCR1B0 / OCR1A0".

De plus, vous pouvez régler OCR1 [A / B] 0 et XOCR1 [A / B] 0 pour la sortie miroir.

if(0){ //Synch mode
     //OCR1A & XOCR1A enable for Synch operation but not allow odd PWM values!
     TCCR1 |= (1 << PWM1A) | (0 << COM1A1) | (1 << COM1A0); 
     //Also ATtinyX5 has "Dead Time Generator", use it ;)
     DTPS1 = 3;   //8x Prescaler for dead time generator (maximum)
     DT1A = 0xff; //Clk dead on both channels (maximum)
     }
   else
     TCCR1 |= (1 << PWM1A) | (1 << COM1A1) | (0 << COM1A0);  //ONLY OCR1A enabled

Vous devez savoir que le générateur de temps mort mangera la sortie PWM si vous définissez OCR1A = 1. Vous avez besoin de valeurs plus élevées que le temps mort.

Cordialement,

Erdem

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.