Go Down

Topic: Fréquence max des GPIO (Read 811 times) previous topic - next topic

Vaarai

Bonjour à tous,

j'ai besoin de générer un carré de 500KHz en TTL pour piloter un composant.
J'ai fait ça avec le TIMER1 mais ma fréquence plafonne à 180KHz, je n'ai pas eu le temps de tester plus
mais avant de chercher un problème, quelle est la limite en fréquence des GPIO d'un UNO/NANO ?

Merci d'avance.

J-M-L

#1
Jul 05, 2016, 12:55 pm Last Edit: Jul 05, 2016, 01:01 pm by J-M-L
le processeur tourne à 16MHz

suivant ce que vous faites ou ne faites pas, vous pouvez monter au moins jusqu'à plus de 1MHz sans pb mais bien sûr votre arduino n'aura pas le temps de faire grand chose d'autre si c'est vous qui générez ce signal.

lisez cela aussi, ça peut aider

personnellement je regarderai plus à faire ça en hardware séparément avec un NE555 - en configuration monostable  qui permet de générer une impulsion d'une durée définie seulement à l'aide d'une résistance et d'un condensateur et déclencher par impulsion d'un front descendant à l'entrée du circuit (TRIG)
Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

Vaarai

Le composant est commandé par une horloge front montant (500K) et une data que je changerais sur les fronts descendants (pour tenir les Tsetup et Thold assez égaux).
Donc si je prend un 555 cela m'oblige à prendre aussi un shift register pour envoyer octet par octet...
Ce n'est pas très compliqué mais c'est ça de plus sur la carte ^^

kamill

Bonjour,

Je ne vois pas pourquoi le timer 1 plafonnerait à 180kHz
En mode ctc on peut sortir un signal jusqu'à 8MHz (avec une horloge 16MHz)

J-M-L

effectivement ça dépend du nombre de pin qu'on est prêt à sacrifier et des librairies utilisées

Sur un Uno:

- timer0 est utilisé pour delay(), millis() and micros() ==> donc si on change son comportement on change la gestion du temps

- timer1 est utilisé pour la servo library

- timer2 est utilisé pour la fonction tone() (qui pourrait vous être utile d'ailleurs pour fabriquer votre signal)


Si vous jouez avec le PWM et les modes

sur un UNO on a 3 timers mais 6 pins PWM, donc jouer avec 1 timer impacte plusieurs Pins.

- timer0  = Pins 5, 6
- timer1  = Pins 9, 10
- timer2 = Pins 11, 3


Sinon il y a un bon article à lire sur le CTC en anglais

Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

Vaarai

#5
Jul 05, 2016, 02:51 pm Last Edit: Jul 05, 2016, 03:28 pm by Vaarai
Voici le code que j'avais fait pour tester si je pouvais monter à 500KHz:

Code: [Select]
#define pin_clk 0b01000000  // Sur les registres B c'est la pin 12
#define Load 0              // Préchargement du compteur

void setup()
{
  // Mise en sortie et à 0 de la pin pour l'horloge du composants
  DDRB |= pin_clk;
  PORTB &= ~pin_clk;
  // Activation des interruptions
  SREG |= 0x80;
  // Mode normale du timer
  TIMSK2 |= 1;      // Mode comptage
  // Paramétrage du timer2
  TCCR2A = 0;       // RAS
  TCCR2B = 0x03;    // Division d'horloge par 32
  //TCNT2 =  Load;  // Aucun besoin de Load car 16M / 32 = 500k
}

void loop()
{}

ISR(TIMER2_OVF_vect)
{
  PORTB ^= pin_clk;
  //TCNT2 = Load;
}

kamill

Je comprends mieux, je pensais que tu utilisais le timer pour générer directement le signal, mais en fait tu génère le signal par soft sur interruption.
Je ne pense pas que tu puisses atteindre 500kHz par interruption. Ca fait 2 µs pour sauvegarder le contexte, faire le traitement et restaurer le contexte.

Soit tu génère le signal directement par la sortie du timer, soit tu le génère par une boucle en écrivant directement dans les registres comme tu l'a fait dans ton it.
Si tu veux savoir si tu atteint 500khz le mieux c'est d'essayer et de mesurer la fréquence de sortie avec un oscillo (ou d'utiliser un timer pour mesurer le temps d'exécution du programme).

Vaarai

Je n'avais absolument pas pensé à la sauvegarde du contexte merci beaucoup, mon problème viens donc de là :D
Pour ce qui est de l'oscillo c'est ce que je faisais déjà.
Ensuite je vais devoir faire bouger ma sortie de data en opposition de phase avec mon horloge.

68tjs

Avec ta méthode il serait bon que tu contrôle le rapport cyclique du signal de sortie car il se dégrade quand on s'approche des limites du micro.

J'ai réalisé quelques test il ya deux ans et j'avais trouvé les résultats suivant ( je cite de mémoire de retraité) :
basculement d'une sortie
avec digitalWrite environ 80 cycles horloge -> dépend de la sortie -> n'importe quoi !
avec les registres ( comme tu as fait) 8 cycles horloge.

J'avais pu monter jusquà environ 730 kHz mais avec un rapport cyclique pourri.
En ajoutant des " nop()" on obtient un peu plus de 500 kHz avec un rapport cyclique 40/60 mais on bloque le micro.

Je pense qu'actuellement avec 500 kHz non compensé tu rique de ne pas avoir un bon rapport cyclique.

Je dis moi aussi que a solution passe par le timer en mode CTC.
Un timer en mode CTC donnera toujours un rapport cyclique 50/50 et ne consommera pas de tempcs CPU parce que le gros avantage des modules en "électronique câblée" comme les timers , l'UART, le SPI, l'I2C c'est qu'une fois configurés il vivent leur vie de façon totalement autonome.

Pour lancer le signal ou l'arrêter il suffit d'écrire 3 bits dans un seul registre du timer

aligote

#9
Jul 05, 2016, 06:02 pm Last Edit: Jul 05, 2016, 06:04 pm by aligote
Avec ta méthode il serait bon que tu contrôle le rapport cyclique du signal de sortie car il se dégrade quand on s'approche des limites du micro.

J'ai réalisé quelques test il ya deux ans et j'avais trouvé les résultats suivant ( je cite de mémoire de retraité) :
basculement d'une sortie
avec digitalWrite environ 80 cycles horloge -> dépend de la sortie -> n'importe quoi !
avec les registres ( comme tu as fait) 8 cycles horloge.

J'avais pu monter jusquà environ 730 kHz mais avec un rapport cyclique pourri.
En ajoutant des " nop()" on obtient un peu plus de 500 kHz avec un rapport cyclique 40/60 mais on bloque le micro.

Je pense qu'actuellement avec 500 kHz non compensé tu rique de ne pas avoir un bon rapport cyclique.

.................

Bonsoir,

je confirme totalement : (j'avais moi aussi effectué ce genre de comparaison et visualisé à l'oscillo)

De mémoire (volatile certes) j'avais obtenu un peu plus de 4µs avec digitalWrite et 10 fois mieux en écrivant directement dans le port (Arduino Uno) .... ce qui fait sensiblement la même chose que toi.

Effectivement en poussant la vitesse le temps de montée et le rapport cyclique s'étaient beaucoup dégradés sauf à "charger comme une bourrique" la sortie digitale avec une faible résistance..... et encore.

Serge .D


Go Up