Bienvenue aux nouveaux arrivants sur FantasPic !

- Pensez à lire les règles durant votre visite, il n'y en a pas beaucoup, mais encore faut-il les respecter .
- N’hésitez pas à faire des remarques et/ou suggestions sur le Forum, dans le but de l'améliorer et de rendre vos prochaines visites plus agréables.
- Vous pouvez regarder votre "panneau de l'utilisateur" afin de configurer vos préférences.
- Un passage par "l'utilisation du forum" est recommandé pour connaître les fonctionnalités du forum.

--- L’équipe FantasPic ---
Forum général sur le langage C !

Modérateur : Jérémy

Trouvez l'erreur ? interruption ou timer ?
Jérémy
Administrateur du site
Administrateur du site
Messages : 2723
Âge : 45
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#1 Message par Jérémy » sam. 22 août 2015 23:58

Bonsoir à tous ,

Après mon Tuto sur les interruptions , j'ai fais celui des timer .

Mais le HIC c'est que mon programme ne fonctionne pas, et je ne sais pas pourquoi .

Quand j'essaye de faire un debug, mes valeurs de timer ne change jamais . TMR0L et TMR0H ?

Si vous trouvez l'erreur je pourrais publier mon tuto , ce qui serait sympa . Voila une erreur que j'essaye alors un œil neuf serait le bienvenue .

PIC 18F45K22 oscillateur à 8Mhz compilé avec MikroC

Code : Tout sélectionner

//#################################       DECLARATION      #########################################

 char compteur = 0;          // Déclaration de la variable compteur en char ( 0 à 255) et on l'initialise à 0 en même temps
 
//#################################        FONCTION       #########################################

void interrupt() {           // Ici c'est notre fonction d'interruption

                             // On regarde quel drapeau a été mis à 1, pour connaitre la source de l’interruption
  if (INTCON.TMR0IF)         // Ici le bit TMR0IF (bit2) du registre INTCON est testé
  {
   ++compteur;               // On incrémente notre compteur sur une interruption
   TMR0H = 0;
   TMR0L = 0;
   INTCON.TMR0IF = 0;        // IMPORTANT !!! On ré-arme notre drapeau en le remettant à 0
  }
}

//#########################     FONCTION PRINCIPALE ET CONFIGURATION    #################################

void main() {                // ceci contiendra notre programme, c'est la fonction principale(main) et elle est obligatoire.

     ANSELC = 0;             // Met le PORT C en numérique

     PORTC = 0;              // Affecte 0 au PORT C

     TRISC = 0b00000000;     // Place le PORT C en sortie pour afficher les leds
     
     T0CON 
: 0b11000111 ;    // Configuration du TIMER0
     TMR0L = 0;              // chargement de la valeur 0 dans le TIMER
     TMR0H = 0;
     
     INTCON 
= 0b10100000;    // Configuration de l'interruption

 //#################################     Boucle infinie    #########################################

 while(1)                 // Ici c'est notre boucle sans fin.
 {
      if (compteur == 31) // Si notre compteur d'interruption à atteint la valeur calculée de 31
         {
          PORTC = ~PORTC; // alors on inverse nos sorties
          compteur = 0;   // On remet à 0 notre compteur pour une nouvelle tempo
         }

  }
 }                        // Fin de notre fonction principale, la boucle est bouclée   


Par avance Merci
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Trouvrez l'erreur ? interruption ou timer ?
Jérémy
Administrateur du site
Administrateur du site
Messages : 2723
Âge : 45
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#2 Message par Jérémy » dim. 23 août 2015 09:50

Comme quoi la nuit porte conseil .

Je regarde mon code ce matin et voila ce que je remarque .

Code : Tout sélectionner

T0CON 0b11000111 ;    // Configuration du TIMER0 


Forcement ca fonctionne moins bien avec ":" à la place de "=" .

Tout est rentré dans l'ordre, c'est ca d'avoir la tête dans le guidon des fois !
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Trouvez l'erreur ? interruption ou timer ?
HULK28
Avatar de l’utilisateur
Amateur
Amateur
Messages : 106
Enregistré en : août 2015
Localisation : IdF

#3 Message par HULK28 » ven. 18 sept. 2015 03:37

Bonsoir,

quand tu utilises une variable dans une interruption qui peut être modifiée ailleurs, comme ici remise à 0 dans le main() il est conseillé de la déclarer en volatile et de l'initialisée au préalable (comme tu l'as fait) sans quoi tu auras des soucis dans un code plus important et selon les accès mémoire que tu seras amené à faire, ou les taches que le µC traitera il y aura des écrasements de variables.

Mon conseil également est de ne pas escompter que:

Code : Tout sélectionner

if (compteur == 31)


fonctionne dans un programme plus conséquent ou plus rapide.
L'usage est de lever un drapeau dans l'interruption quand l'évènement est acté puis de libérer les action à faire dans le programme principal organisé par exemple avec des switch.
Il faudra qu'on parle de gestion en multitâches un jour, seule manière propre de faire un programme plus solide, car dans un exemple simple comme ici ça fonctionnera mais quand il y aura du monde à gérer et des milliers de lignes de code ça deviendra mission impossible et de multiples bugs vont apparaitre inopinément.
C'est donc une meilleure habitude de penser dès le départ un code qui devra être maintenu (modifié) et qui s'inscrira dans un processus plus lourd.

Parmi les tutaux utiles à faire:

-gestion de la mémoire (allocation, directives de linker) et usage propre des variables
-usage des fichiers header pour apprendre à rendre un programme lisible et réexploitable
-usage de pointeurs pour alléger le code
-associer l'assembleur et le C pour optimiser les fonctions bas niveau et les temps de traitements.
-RTOS simplifié, méthode et usage pour que le code fasse ce qu'on veut et pas le contraire (réservé à ceux qui maitrisent déjà bien le reste).

Si je trouve du temps comme je te l'ai promis je ferai ces papiers ici avec des exemples concrets.
"Pour la carotte, le lapin est la parfaite incarnation du mal" -Robert Shecley-

Trouvez l'erreur ? interruption ou timer ?
Jérémy
Administrateur du site
Administrateur du site
Messages : 2723
Âge : 45
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#4 Message par Jérémy » ven. 18 sept. 2015 09:13

Hello HULK28,

Ravi de te voir sur le forum , et bienvenue à toi.

J'ai essayé de comprendre ton conseil, mais j'avoue "tiquer" un peu !.

Pour toi il est préférable de lever un flag dans l’interruption , et d’incrémenter mon compteur dans le MAIN c'est bien ça ?
ce qui me turlupine c'est le déroulement du programme en fait :
détection du débordement TMR, donc mis à 1 d'un flag ( TMOIF) . dans l’interruption je lève un autre flag, je reviens dans le MAIN , dans le MAIN si mon deuxième flag est levé j’incrémente mon compteur une fois à 31 j’effectue mon action

J'ai la sensation que cela fait interruption sur interruption en quelques sortes, et qu'il y a redondance. Mais ce n'est que mon impression !Je pense par ailleurs qu'il serait aussi préférable d'écrire

Code : Tout sélectionner

if (compteur >= 31
non ?
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Trouvez l'erreur ? interruption ou timer ?
HULK28
Avatar de l’utilisateur
Amateur
Amateur
Messages : 106
Enregistré en : août 2015
Localisation : IdF

#5 Message par HULK28 » sam. 19 sept. 2015 10:33

Non, l'incrémentation est toujours faite en interruption.
Lorsque la valeur est atteinte le drapeau est levé pour autoriser l'exécution dans le main.
"Pour la carotte, le lapin est la parfaite incarnation du mal" -Robert Shecley-

Trouvez l'erreur ? interruption ou timer ?
HULK28
Avatar de l’utilisateur
Amateur
Amateur
Messages : 106
Enregistré en : août 2015
Localisation : IdF

#6 Message par HULK28 » sam. 19 sept. 2015 10:51

Code : Tout sélectionner

volatile char compteur = 0, flag_action = 0;

void interrupt()
 {           // Ici c'est la routine d'interruption, on regarde quel drapeau a été mis à 1, pour connaitre la source de l’interruption
  if (INTCON.TMR0IF == 1     // Ici le bit TMR0IF (bit2) du registre INTCON qui indique un débordement du timer0
    {
    INTCON.TMR0IF = 0; // IMPORTANT !!! On réautorise l'interruption en remettant ce flag à 0 [u]aussitôt[/u]
    if(flag_action == 0) // on teste flag_action pour savoir si on doit incrémenter (si à 0), ou si une action est déjà en cours dans le main() -> donc à 1
      {
      ++compteur;  // On incrémente notre compteur
      if(compteur == 31) flag_action = 1; // flag_action activé, on autorise dans le main l'action à accomplir, flag_action sera remis à 0 dans le main() après l'action réalisée
      }
     
    TMR0H = 0;  // on remet le compteur à 0
    TMR0L = 0;
    }
}

......

main()
{
....
        while(1)    // Ici c'est notre boucle sans fin qui débute.
        {
        if (flag_action == 1) // Si notre compteur d'interruption à atteint la valeur calculée de 31, flag_action à 1 autorise ici l'action à réaliser
           {
           LATC = ~LATC; // alors on inverse nos sorties du PORTC (comme ce sont des sorties on utilise [u]toujours[/u] la commande LAT et non pas PORT)
           compteur = 0;
           flag_action = 0;   // On remet à 0 flag_action pour autoriser un nouvel évènement
           }
          ......
        }
}


"Pour la carotte, le lapin est la parfaite incarnation du mal" -Robert Shecley-

Trouvez l'erreur ? interruption ou timer ?
Guest
Confirmé
Confirmé
Messages : 800
Enregistré en : mars 2017

#7 Message par Guest » dim. 20 sept. 2015 10:13

Bonjour

il y a pas mal d'erreur ou incompréhension pour ma part:
jeremy tu utilises le timer0 en mode 8bits ( bit6 de T0CON a 1 ) donc pourquoi TMR0H TMR0L qui sont pour le mode 16 bits. Si tu es en 8bits TRM0L uniquement.
Tu es en 8 ou 16 bits? pour clarifier les choses.

HULK28: pourquoi utiliser une 2eme variable qui pourra tout autant être modifié dans le main et ne résout pas ce problème voir le double.A utiliser une seconde variable, autant utiliser une structure de bits plus rapide a gérer dans le main,et plus difficile a modifier (0 ou 1).
Autre problème si pour X raisons compteur est >31 on ne valide jamais le flag action faire plutôt un test if(compteur >= 31)
je ne comprend cela:
TMR0H = 0; // on remet le compteur à 0
TMR0L = 0;
Alors que l'int se déclenche sur passage du compteur FFFF-> 0000 mode (16bits) donc ils sont foncement a zero on réinitialise c'est registres si leurs valeur est différent de 0.
et enfin pourquoi faire un test du flag action?dans int? si action pas terminer c'est qui y a un problème de timing cela risque de bousculer au portion probleme a revoir AMHA

j'ai peut-être perso raté quelque chose, dans ce cas merci de l’éclairer

A+
Modifié en dernier par Anonymous le dim. 20 sept. 2015 16:41, modifié 1 fois.

Trouvez l'erreur ? interruption ou timer ?
Jérémy
Administrateur du site
Administrateur du site
Messages : 2723
Âge : 45
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#8 Message par Jérémy » dim. 20 sept. 2015 14:18

jeremy tu utilises le timer0 en mode 8bits ( bit6 de T0CON a 1 ) donc pourquoi TMR0H TMR0L qui sont pour le mode 16 bits. Si tu es en 8bits TRM0L uniquement.
Tu es en 8 ou 16 bits? pour clarifier les choses.

Je me suis posé la même question et j'ai cherché un moment. Je n'ai pas d'explication, car je suis encore un newbie . Même avec le compteur en 8 bit il faut utiliser TMR0H et TMR0L , sinon ça fonctionne pas !(Je ne me souviens plus si ca compilait ou non). J'ai été surpris moi aussi, et j'ai mis du temps a trouver qu'il fallait faire comme ça .

Peut être qu'un expert à une explication .
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Trouvez l'erreur ? interruption ou timer ?
Guest
Confirmé
Confirmé
Messages : 800
Enregistré en : mars 2017

#9 Message par Guest » dim. 20 sept. 2015 16:15

re bonjour
En mode 8 bits on peut charger le registre TRM0 OUPS désolé (je revendique le droit a l'erreur :-)
En mode 16bits c'est les registres TRM0H et TRM0L. j'utilise rarement le TRM0 en 8bits

Donc inutile de faire dans ton code si tu es en 8bits
TMR0H = 0;
TMR0L = 0;
Le problème de ton complilo c'est quoi?

As-tu essayé de passer en mode 16bits, pour diminuer la valeur de compteur cela sera plus rapide moins d' accès a l'int

je ne connais pas ton compilateur sur XC8 il faut déterminer le niveau de priorité des int (2 niveaux prioritaire adresse 0X8 non prioritaire adresse 0X18)
A+

Trouvez l'erreur ? interruption ou timer ?
Jérémy
Administrateur du site
Administrateur du site
Messages : 2723
Âge : 45
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#10 Message par Jérémy » dim. 20 sept. 2015 16:27

En mode 8 bits on peut charger le registre TRM0

D’après mes souvenirs, justement ça ne fonctionnait pas ; Il fallait obligatoirement passé par TMR0H et TMR0L même en 8bits.
est-ce la faute de MikroC, du PIC , ou bien de moi (le plus probable) :D

A mon grand désespoir , pour le moment j'ai trop le temps de refaire un essai, mais si j'y pense je te confirmerai cela . Je m'efforce de fignoler le Forum, le plus vite possible ; j'y passe mes journées, mes soirées et une partie des nuits ! lol .

Vivement que ce soit fini que je puisse vous embêter avec mes questions, et faire de la programmation pour lequel j'ai créer ce forum.
C'est en faisant des erreurs, que l'on apprend le mieux !!!


Retourner vers « Langage C »

Qui est en ligne

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