PWM avec ATmega8

Pour toutes vos questions sur WinAVR, AVR-GCC et la programmation en C en général

Modérateur: Modérateur

PWM avec ATmega8

Messagede Truc le 22 Fév 2006 18:34

Salut,
J'ai un problème pour utiliser le Timer2 de l'atmega8 en PWM.
Voici le code C que j'utilise:

Code: Tout sélectionner
#include <avr/io.h>
#include <avr/interrupt.h>

uint8_t val;

ISR(TIMER2_OVF_vect)
{
   val=1;
}

int main(void)
{
   val = 0;
   DDRB = _BV(PB3);
   TCCR2 = _BV(WGM20) | _BV(COM21) | _BV(CS20);
   TCNT2 = 0;
   TIMSK = _BV(TOIE2);

   sei();

   while (1) {};
   return 0;
}


Le problème c'est que l'interruption ne déclenche jamais. Lorsque je débug je vois bien le compteur TCNT2 evolué, le problème c'est qu'il compte de 2 en 2 ??!! et ne repasse jamais à 0 donc l'interruption ne déclenche pas.
Si vous avez des explications...
Truc
 

Messagede JP le 23 Fév 2006 1:01

Bonjour Truc,

C'est la non prédivision de la clock qui pose problème, si tu fais un test avec /8 (CS21=1) tu n'auras plus ce problème.

Pourquoi ? Je n'en sais rien ... à 1h du matin j'ai un peu de mal à réfléchir ...

a+
JP
Ca clignote !!!!
Avatar de l’utilisateur
JP
Administrateur
Administrateur
 
Messages: 2325
Inscription: 23 Sep 2003 18:14
Localisation: Strasbourg

Messagede Truc le 23 Fév 2006 10:35

Merci JP. C'est vrai qu'avec un prédivision de 8 le compteur compte bien de 1 en 1. Le problème c'est que je rentre jamais dans ma routine d'interruption. :evil:
Pourtant, dans le datasheet il est bien spécifié que l'interruption de débordement est déclenché à chaque fois que le compteur se met à incrémenter/décrémenter. :?
J'ai du oublier un truc mais quoi ?
Truc
 

Messagede JP le 23 Fév 2006 16:44

J'ai essayé de le refaire avec un exemple "tout fait" trouvé sur le net, ce qui me donne :

Code: Tout sélectionner
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>

uint8_t led;

SIGNAL (SIG_OVERFLOW2)
{
led=1;
}

int main( void )
{
  DDRB=0xFF;
  TIMSK=0x40;
  TCNT2=0x00;
  TCCR2=0x62;
  led = 0;
  sei();
  for (;;){}
}


mais j'ai exactement le même problème, pas d'interruption :cpu:
Ca clignote !!!!
Avatar de l’utilisateur
JP
Administrateur
Administrateur
 
Messages: 2325
Inscription: 23 Sep 2003 18:14
Localisation: Strasbourg

Messagede vincevg le 23 Fév 2006 17:06

un exemple avec le timer 1. J'utilise la fonction
Code: Tout sélectionner
timer_enable_int (_BV (OCIE1A));
pour valider l'interruption.

Code: Tout sélectionner
/********************************************
Projet :
Commentaires :
Date    :
Heure :
Auteur  : Frank SAURET
Compagnie: Lycée Aristide BRIAND - St Nazaire -

Micro Contrôleur     : AT MEGA 8535
*********************************************/
#include <sup_avr/Maquette_AVR_V2.h>// Déclare l'utilisation de la structure de la maquette AVR.
#include <avr/io.h>

#include <avr/signal.h>
#include <avr/interrupt.h>
volatile char UneLED;
unsigned int LaTempo;

int main(void)
   {
      //Direction du port B
      DDRB=0xF0; // Direction du port B 0, 1, 2, 3 en entrée et 4, 5, 6, 7 en sortie
      PORTB=0x00;// Pas de pull-up sur les entrées et les sorties à NL0
      // Initialisation du Timer 1
      TCCR1A=0;//Mode normal
      TCCR1B=0x05; // Prédivision par 1024
      TCNT1=0; // Initialisation du compteur 1 à 0
      OCR1A=(0.5*F_CPU)/1024;//0,5 est la durée en seconde avant interruption
      SFIOR=0x00;
      timer_enable_int (_BV (OCIE1A)); // Valide l'interruption de comparaison du timer 1A
      sei (); //Valide toutes les interruptions

      UneLED=0;
      while(1);
   }

INTERRUPT(SIG_OUTPUT_COMPARE1A) // Interruption généré quand TCNT1 = OCR1A
   {
      if  (UneLED) AllumeLED(1) ;// Si le Switch Ref est appuyé Allume la LED Ref
            else EteindLED(1);//Sinon l'éteind
            UneLED=!UneLED;
      TCNT1=0;//Relance le comptage
   }
Vince
http://anyedit.free.fr/
http://electropol.free.fr/

Les amis, ça va, ça vient, mais les ennemis, ça s’accumule.
Avatar de l’utilisateur
vincevg
ACCRO
ACCRO
 
Messages: 802
Inscription: 05 Mar 2005 16:58
Localisation: SMalville

Messagede Truc le 24 Fév 2006 12:33

Merci Vince, mais l'interruption fonctionne tres bien en mode "normal", le problème c'est en mode PWM.
Attention à ton programme Vince, il risque de ne plus fonctionner avec gcc > 1.4 car la fonction Interrupt ne sera plus supporté ainsi que les anciens nom d'interruptions.
Utilise plutot ISR.
Truc
 

Messagede Truc le 07 Avr 2006 11:29

Coucou,
Bon, alors pour le problème de l'interruption qui déclenche pas, il semblerait que le simulateur d'AVRStudio gère tres mal le PWM en mode "correct". Car l'interruption déclenche tres bien en mode "Fast".
Pour le coup du compteur qui compte de 1 en 1 (normal quoi) avec predivision, et de 2 en 2 sans prédivision, il semblerais que cela vienne de ma boucle do {} while(1).
Le code équivalent en assembleur serait un simple rjump qui prend 2 clock cycle, pendant se temps, le compteur s'incrémente 2 fois (1 fois par cycle, logique). Et le rafraichissement du compteur dans le simulateur se fait une fois par instruction (le saut, ici). Donc l'histoire du compteur qui évolue de 2 en 2 c'est normal.
J'ai pas trouver ça tout seul, je me suis fais aider ( :oops: ) car c'est vraiment subtil comme truc...
A bientot pour de nouvelles aventures :)
Truc
 


Retourner vers WinAVR-AVR GCC

Qui est en ligne

Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 0 invités

cron