Registres PWM & timer ATmega 328

Bonjour,
je souhaite connaitre les registres PWM de l’ATmega 328 pour obtenir une fréquence de découpage plus élevée qu’avec la fonction “analogWrite()” ( de l’orde de 10Khz ), les datasheets étant difficile à comprendre. Je pose la question car j’ai trouvé très peu d’informations sur la question …
Merci d’avance

salut, dans les projet fini tu peut trouver ça, http://arduino.cc/forum/index.php/topic,104058.0.html qui devrai largement répondre a ta question, tu a un code qui produit des PWM jusqu'à 8MHZ :)

Skizo !

Comme indiqué par Skywodd dans un autre post, il y a quelques articles sur le Wiki de Playground a ce sujet Voici ce que j'ai réussi à retrouver (parce que franchement, trouver des trucs précis dans le Playground, ça doit être un métier à part entière ;))

http://arduino.cc/playground/Main/TimerPWMCheatsheet http://arduino.cc/playground/Code/PwmFrequency

Merci beaucoup, parce que c'est vrai que trouver des infos précises sur le sujet est difficile ... Je vais regarder tout ça

Bonjour,

Si tu ne veut pas te casser la tête avec de l'anglais tu as aussi ce trés bonne article en français : http://sen.enst.fr/node/222

Et aussi celui (en anglais) qui détaille tout les mode de PWM possible : http://www.arcfn.com/2009/07/secrets-of-arduino-pwm.html

merci pour les liens. je me suis penché sur la question et j'ai réussie a obtenir la fréquence de découpage voulue (10Khz) mais il y a plusieurs petites choses que je ne comprend pas: j'ai utilisé le mode "fast pwm" du timer 2: TCCR2A = 0x23; TCCR2B = 0x0A; ====> pré-diviseur a 8 : 16Mhz/8=2Mhz OCR2A = 200; ====> registre pour la comparaison avant débordement: 2Mhz/200=10Khz OCR2B =100; ====> rapport cyclique = 100/200=50% Le problème est qu'il me faut 3 sorties pwm (à 10Khz de découpage) et qu'avec ce mode seul une sortie sur deux peux fonctionner (par timer) car l'autre sert de comparaison (ici seul la broche 3(oc2b)fonctionne et pas la 11(oc2a) ) ... Quelqu'un a-t-il une autre idée ?

j'ai enfin trouvé ce que je voulais mais a taton donc je ne serais pas trop expliquer pourquoi cette fréquence de 7.8khz:

void setup() { TCCR2A = 0b10100011; TCCR2B = 0b00000010; // mode fast pwm du timer 2 :: prediviseur 8

TCCR1A = 0b10100001; TCCR1B = 0b00001010; // mode fast pwm du timer 1 :: prediviseur 8

pinMode(9, OUTPUT); pinMode(10, OUTPUT); pinMode(11, OUTPUT);

OCR1A = x; // pin 9 OCR1B = x; // pin 10 OCR2A = x; // pin 11 // x rapport cyclique de 0 à 255 ( je crois que c'est de la que viens la deuxième division par 255 par défaut cf datasheet: 16Mhz/8=2Mhz/255 =7.8khz) }

voila si sa peux aider quelqu'un...

Re-bonjour tout le monde désolé de déterrer un peu le sujet mais c'est encore une question de registre que j'avais à poser: Voila mon (nouveau) problème : je ne sais pas comment lire les valeurs sur un port entier.. je pensais qu'en écrivant: int val; val = PORTC; cela marchais mais la valeur "val" obtenues prenait le valeur du portc mais rien ne ce passe,j'ai beau changer la valeur aux broches rien j'ai aussi essayé: int val; val = PORTC & 0b11111111; rien non plus.... comment faire ? le registre DDRC doit être à 0 ou à 1?

PORTC c'est pour la sortie PINC pour l'entrée et DDRC pour la direction

Voir le Users Manual de l'ATmega dispo sur le site Atmel

merci de répondre aussi vite!

Donc si je veux prendre la valeur de 4 broches du portc je doit mettre le registre DDRC à 0 pour les broches dont je veux lire l’état et utilisé le registre PIN pour lire les broches les unes après les autres ? J’avais crue comprendre que le registre PORTx était accessible en écriture et en lecture…
donc
val = Pin(14) | (pin(15)<<2) | (pin(16)<<3) ;
devrait fonctionner?

Salut,

Dans la documentation indiquée par Barburdor :

13.2.4 Reading the Pin Value Independent of the setting of Data Direction bit DDxn, the port pin can be read through the PINxn Register bit.

Donc pour lire la valeur du port C : - on se fiche de sa direction (DDRC) ; - on lit sa valeur en utilisant le registre PINC.

Donc

int val = PINC;

Il te reste juste à masquer PINC en fonction des broches dont tu veux lire la valeur.

A d’accord génial! Je viens de tester c’est ce que je voulais …
je croyais que le registre PIN ne lisait que la valeur de la broche choisie comme avec la fonction digitalRead()

Il faudrait vraiment faire une synthèse précise des registres au moins pour l’ATmega328 parce que je sais pas si il y a que moi mais je trouve la doc difficile à lire et a comprendre…et les références arduino sont parfois trop légères
en tout cas merci pour tout !

Tu peux aussi lire les entrées une à une, du genre PINC0, PINC1, etc ;)

PINC reflète toujours l'état des broches, que cet état soit imposé par l'extérieur si la broche est en entrée ou par l'intérieur si la broche est en sortie. Donc non on ne se fiche pas de DDRC.

PORTC permet de positionner les pin en sortie à 1 ou 0 mais aussi d'activer on non la résistance de pull-up interne sur les broches d'entrées.

Donc pour lire en 1 seul fois les broches C.0, C.1, C.2 et C.3 : DDRC &= ~0x0F; // met à 0 les 4 bits de poids faibles du registre de direction byte val = PINC & 0x0F;

SesechXP: Tu peux aussi lire les entrées une à une, du genre PINC0, PINC1, etc ;)

:astonished: C'est cool ça ! Je savais pas que avr/io.h avait les déclarations qui vont bien pour accéder aux broches séparément ... du coup ça me donne des idées $)

SesechXP:
Tu peux aussi lire les entrées une à une, du genre PINC0, PINC1, etc :wink:

Euh. Non. Tu ne peux lire que le port en entier.

#define PINB0 0
#define PINB1 1
#define PINB2 2
#define PINB3 3
#define PINB4 4
#define PINB5 5
#define PINB6 6
#define PINB7 7

A part faire un masque de bit, ce genre de macro ne sert pas à grand chose…

:blush: Autant pour moi, je n'ai pas regardé comment étaient définies ces macros et la doc de l'ATmega328 m'a induit en erreur : "the port pin can be read through the PINxn Register bit"

barbudor: PINC reflète toujours l'état des broches, que cet état soit imposé par l'extérieur si la broche est en entrée ou par l'intérieur si la broche est en sortie. Donc non on ne se fiche pas de DDRC.

Oui, c'est sûr que pour lire la valeur d'un port, ça fonctionne mieux si celui-ci est configuré en entrée... Je me suis mal exprimé, ce que j'avais en tête (et ce qu'indique la doc) c'est qu'on peut lire le registre PINC (et pas la valeur du port) quel que soit la valeur de DDRC...

Au fait quelqu'un utilise les résistances de pull-up intégrées à l'AVR ? ça fonctionne bien ? Car certains sont assez sceptiques...

Je savais pas que avr/io.h avait les déclarations qui vont bien pour accéder aux broches séparément

Tout est défini ici :
Pour Linux parce que win$ ??
/usr/lib/avr/io_nom_du_micro_.h
pour le 328p
/usr/lib/avr/iom328p.h

barbudor: Euh. Non. Tu ne peux lire que le port en entier.

A part faire un masque de bit, ce genre de macro ne sert pas à grand chose....

Bouuuououou =( encore une macro inutile ... J'aurai bien aimer avoir une vrai macro tout faite ^^ Tant pis ... ma macro fait maison va encore servir ^^

SesechXP: Au fait quelqu'un utilise les résistances de pull-up intégrées à l'AVR ? ça fonctionne bien ? Car certains sont assez sceptiques...

Je les utilisent trés souvent, c'est comme si tu avais une résistance de 20-30K externe dans ton circuit.