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

Optimisation du code
HVDifusion
Débutant
Débutant
Messages : 43
Enregistré en : décembre 2015

#1 Message par HVDifusion » lun. 21 déc. 2015 18:18

Bonjour a tous,

Nouveau sur le forum je vient poster un sujet pour demander des conseils au niveau optimisation de code.C'est a dire réduire au plus petit un code.

J'ai donc écrit un code de teste qui permet de faire clignoté une led sans devoir utilisé la fonction "Delay" qui vous le savez pendant son exécution le PIC ne peut rien faire d'autre.

J'utilise MikroC pour programmer.

Apprentissage :

-PIC utilisé : http://ww1.microchip.com/downloads/en/DeviceDoc/40044F.pdf

-Utilisation de variables

-Expérimentation des registres disponibles

-Créer un délais sans la fonction "delay_ms" (ici pour exemple 500ms)

-A l'aide du délais,faire clignoté une LED.

-Utilisation d'une LED témoin avant démarrage du programme principal.

-Expérimentation sur la création de fonctions et leurs appels.

-Routine d'interruption,le TMR0 et son calcule de débordement.

-Expérimentation de la condition "SI".


Voila dite moi si il est possible d'optimisé ce code et si vous avez des conseils.

Code : Tout sélectionner

#define led PORTA.B1 // masque pour le bit 1
#define led2 PORTB.B3 // masque pour le bit 3

unsigned int compteur; // variable pour stocker débordement TMR0
unsigned char bascule; // variable pour stocker débordement compteur

void interrupt() // routine interruption
{
 if (INTCON.T0IF == 1) // si débordement TMR0 a lieu,alors
 {
  INTCON.T0IF = 0; // init du flag a 0
  compteur++; // incrémentation de la variable
 }
}

void intled() // signalement avant le lancement du programme
{
 delay_ms(200);
 led2 = 1;
 delay_ms(200);
 led2 = 0;
 delay_ms(200);
 led2 = 1;
 delay_ms(200);
 led2 = 0;
 delay_ms(200);
 led2 = 1;
 return;
}

void main() // routine principale
{
 PORTA = 0; // init 0V
 PORTB = 0; // init 0V
 TRISA = 0; // init full sortie
 TRISB = 0; // init full sortie
 PCON = 0b00001000; // init OSC interne 4MHz
 INTCON = 0b10100000; // interrupt autorisé,TMR0 activé
 CMCON = 7; // désactivation comparateur PORTA
 OPTION_REG = 0b00000000; // init prescaler 1:2

 intled(); // appel de la fonction créer
 
 TMR0 
= 0; // init TMR0 a 0
 compteur = 0; // init variable a 0
 bascule = 0; // init variable a 0

 while(1)
 {
  if (compteur == 1953)
  {
   compteur = 0; // init compteur a 0
   bascule++;
  }
  
  if 
(bascule == 1)
  {
   led=~led; // changement état de la led
  }
  bascule = 0; // init bascule a 0
 }
}


Cordialement.
Modifié en dernier par HVDifusion le lun. 21 déc. 2015 23:48, modifié 1 fois.

Optimisation du code
Jérémy
Administrateur du site
Administrateur du site
Messages : 2722
Âge : 44
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#2 Message par Jérémy » lun. 21 déc. 2015 18:56

Hello HVDifusion,

Bienvenu sur le Forum FantasPIC . Je regarde ton code après mangé, mais je ne suis pas un spécialiste !. Il est de mise de bien débuter, je te propose d’éditer ton 1er post avec le petit crayon en haut à droite, et d'indiquer ton compilateur, ensuite suivre ce lien : Mettre un lien de sa data-sheet . Merci !

A+
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Optimisation du code
Jérémy
Administrateur du site
Administrateur du site
Messages : 2722
Âge : 44
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#3 Message par Jérémy » lun. 21 déc. 2015 19:44

Cette fonction :

Code : Tout sélectionner

void intled() // signalement avant le lancement du programme
{
 delay_ms(200);
 led2 = 1;
 delay_ms(200);
 led2 = 0;
 delay_ms(200);
 led2 = 1;
 delay_ms(200);
 led2 = 0;
 delay_ms(200);
 led2 = 1;
 return;


peut être remplacé par :

Code : Tout sélectionner


void intled
() // signalement avant le lancement du programme
{
 char i;
 for (i=0;i<=4;i++) // On fait 4 boucles à ajuster au besoin
   { 
      led2 
= ~led2;       // On inverse la sortie
      delays_ms(200); // pause de 200ms en chaque changement d'état
   }
}
 


Implicitement mais c'est moins clair quand on pas l'habitude on peut remplacer :

Code : Tout sélectionner

(INTCON.TMR0IF == 1)

par

Code : Tout sélectionner

(INTCON.TMR0IF)



* ==> Quand on traite une variable qui s’incrémente vite, ma maigre expérience me dit qu'il ne faut JAMAIS traiter celle-ci avec un ==, mais plutôt privilégié un <=ou >= . Si pour une raison X ou y on loupe le laps de temps très court ou la condition est vrai, ça bug. Je pense que les experts me contrediront pas !
Remplacé:
if (compteur == 1953)

PAR
if (compteur >= 1953)


La partie suivante est inutilement compliquée :

Si tu arrive a 1953 débordement du timer, tu actives un drapeau qui te dis de changer l'état de la led. Mais le fait d'arriver à 1953 débordements c'est ton drapeau, la bascule est inutile.
remplace :

Code : Tout sélectionner

if (compteur == 1953)
  {
   compteur = 0; // init compteur a 0
   bascule++;
  }
  
  if 
(bascule == 1)
  {
   led=~led; // changement état de la led
  }
  bascule = 0; // init bascule a 0
 }


Par

Code : Tout sélectionner

if (compteur >= 1953) // si la temp est écoulé
  {
   compteur = 0; // On raz la tempo
   led=~led; // On change l'état de la led
  }


Dans l’initialisation de tes INT, tu active déjà l'INT du TMR0 . mais le temps de faire tes fonctions l'INT est en route . Tu dois l'activer au dernier moment pour respecter les délais .
Donc tu ne l'active pas pendant l'initialisation, mais après juste avant ta boucle principale, donc remplace :

Code : Tout sélectionner

 INTCON = 0b10100000; // GIE interrupt global autorisé et TMR0 interupt activé    

Par

Code : Tout sélectionner

 INTCON = 0b10000000; // GIE interrupt global autorisé     


Juste avant ta boucle rajoute :

Code : Tout sélectionner

T0IE_bit = 1; // On active l'INT au dernier moment    




PS : je n'ai pas vérifier ton FOSC et les timings. Il reste certainement plein d'autres truc a vérifier, Voyons quelqu'un de plus expérimenté que moi .
Ce qui donne au final :

Code : Tout sélectionner

#define led2 PORTB.B3 // masque pour le bit 3

unsigned int compteur; // variable pour stocker débordement TMR0

void interrupt() // routine interruption
{
 if (INTCON.T0IF) // si débordement TMR0 a lieu,alors
 {
  INTCON.T0IF = 0; // init du flag a 0
  compteur++; // incrémentation de la variable
 }
}

void intled() // signalement avant le lancement du programme
{
 
char i;
 for (
i=0;i<=4;i++) // On fait 4 boucles à ajuster au besoin
   

      
led2 = ~led2;       // On inverse la sortie
      
delays_ms(200); // pause de 200ms en chaque changement d'état
   
}
}

void main() // routine principale
{
 PORTB = 0; // init 0V
 TRISB = 0; // init full sortie
 PCON = 0b00001000; // init OSC interne 4MHz
 INTCON = 0b10000000; // interrupt autorisé,TMR0 activé
 OPTION_REG = 0b00000000; // init prescaler 1:2
 CMCON = 7; // désactivation comparateur PORTA
 
intled
();
compteur = 0; // init variable a 0
TMR0 = 0; // init TMR0 a 0

T0IE_bit = 1; // On active l'INT au dernier moment

 while(1)
 {
  if (compteur >= 1953)
  {
     led=~led; // changement état de la led
    compteur = 0; // init compteur a 0
   }
}
 
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Optimisation du code
HVDifusion
Débutant
Débutant
Messages : 43
Enregistré en : décembre 2015

#4 Message par HVDifusion » mar. 22 déc. 2015 21:30

Salut,

Merci pour ta réponse,étant encore un débutant forcément je ne pense pas a tous.

Ce que tu dit ma parus logique,je me complique la vie mdr.

Je ne savais même pas que je pouvais appelée ou créer une variable en cours de programme.Ton raisonnement est plus que bon,le fait de mettre la boucle "for" limite le nombre de fonction "delay" utilisé ce qui diminue le nombre de phase pendant la quelle le PIC ne peut plus rien faire,et j'y avais pensé mais j'ai été bloqué par l'utilisation de la variable.

Et justement première question,quand ta créer la variable pour la boucle,reste elle présente quand on sort de la fonction ou elle s’efface?

Ensuite tu a eu la bonne idée de supprimer la bascule,ce qui me parais logique et j'y ai également pensé mais je ne sais pas pour quelle raison j'ai garder la bascule,va savoir.


A propos de la condition pour le FLAG du TMR0 ce que tu a mit est enrichissant.Effectivement tu m'apprend qu'il ne sert a rien de mettre un égal a 1 une valeur qui va forcément l'être quand le débordement va avoir lieu.

Donc mettre un T0IF == 1 que de toute façons il va prendre 1 est inutile.

Aucun doute,l'expérience est la.En tous cas je te remercie fortement pour c'est info.

Je bossais avant sur un programme de système d'alarme dont j'ai rencontré un bug majeur et tu ma ouvert les voies pour peut être le corrigé.

Franchement ce forum m'a l'air prometteur.Vous êtes sympas,et vos réponses son claire.J'ai jamais vu aussi clair.Ou c'est moi qui comprend mieux qu'avant mdr.

Une dernière chose,tu me dit de mettre la datasheet,je l'ai mit mais pas de la façons que tu voulais.Le problème étant que lorsque j'édit a nouveau le message je ne vois pas l’emplacement "DS" pour coller le lien d'une datasheet,tu sais pourquoi?

Cordialement.

Optimisation du code
Jérémy
Administrateur du site
Administrateur du site
Messages : 2722
Âge : 44
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#5 Message par Jérémy » mar. 22 déc. 2015 22:19

Merci pour ta réponse,étant encore un débutant forcément je ne pense pas a tous.

J'ai débuter il y a seulement quelques mois . réellement au mois d'Aout de cette année . J'ai vais fais quelques balbutiements avant . Mais j'a i beaucoup travailler et je compte encore beaucoup travailler car j'ai pris le Virus de la programmation .

Ton raisonnement est plus que bon,le fait de mettre la boucle "for" limite le nombre de fonction "delay" utilisé ce qui diminue le nombre de phase pendant la quelle le PIC ne peut plus rien faire,

Non, ce n'est pas ca. Le nombre de delay_ms sera le même . a chaque boucle correspond un delay_ms . 10 boucles= 10delays . Le pic sera bloqué autant de fois. C'est juste la manière qui est plus propre et plus courte mais le principe est le même que mettre toutes les fonction à la suite .

Il y a d'autres astuces si tu ne veux pas bloquer ton PIC pendant ces 200ms à chaque boucles. A la limite, dans ton cas ici ,ce n'est pas trop grave car c'est au début de ton programme qui ne fait encore rien , donc bon .
Mais au milieu du programme ça pourrait devenir gênant. Si ça avait été le cas , je t'aurais proposé de faire comme ceci .
Créer une INT tout les 100ms( à la place de toute les secondes) qui incrémente un compteur. Quand ce compteur arrive à 2, cela signifie que 200ms se sont écoulées , on inverse l'état de la led.
Et on compte jusqu’à 10 pour faire 1 seconde ( 10x100ms), pour le reste du programme ; en gros un chrono ajustable . ça c'est la bonne méthode .

Et justement première question,quand ta créer la variable pour la boucle,reste elle présente quand on sort de la fonction ou elle s’efface?

Une variable déclarée dans une fonction, je crois s’appelle unevariable locale, C'est à dire quelle n'est visible que par et dans cette fonction. cette variable est effacée , il me semble( à confirmer)
Elle n'est pas effacé en sortant de la boucle for, mais effacée en sortant de la fonction.

Franchement ce forum m'a l'air prometteur.Vous êtes sympas,et vos réponses son claire.J'ai jamais vu aussi clair.

Ça me fait vraiment plaisir ce que tu me dis la. J’espère qu'il sera prometteur, mais ce sont les membres qui font un forum non l'inverse .

Une dernière chose,tu me dit de mettre la datasheet,je l'ai mit mais pas de la façons que tu voulais.Le problème étant que lorsque j'édit a nouveau le message je ne vois pas l’emplacement "DS" pour coller le lien d'une datasheet,tu sais pourquoi?

Non ce n'est pas normal ??? je vais à la pêche aux infos , il faut corriger ce bug , merci de l'avoir signaler ;

tu me confirme que tu n'as pas ce qu'il y a dans l'ellipse rouge en faisant éditer ton premier message
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Optimisation du code
HVDifusion
Débutant
Débutant
Messages : 43
Enregistré en : décembre 2015

#6 Message par HVDifusion » mer. 23 déc. 2015 21:54

Salut,

J'ai débuter il y a seulement quelques mois . réellement au mois d'Aout de cette année . J'ai vais fais quelques balbutiements avant . Mais j'a i beaucoup travailler et je compte encore beaucoup travailler car j'ai pris le Virus de la programmation .


Ah bon d'accord,tu est peut être plus doué que moi.Moi le problème étant aussi que vu que je n'ai pas forcément toujours le temps pour étudier j'essaye surement d'aller trop vite et soit je ne retiens rien ou soit je saute des passages.

Comme on dit la programmation n'est pas si compliqué mais l'apprentissage est long.

Non, ce n'est pas ca. Le nombre de delay_ms sera le même . a chaque boucle correspond un delay_ms . 10 boucles= 10delays . Le pic sera bloqué autant de fois. C'est juste la manière qui est plus propre et plus courte mais le principe est le même que mettre toutes les fonction à la suite .


Oui effectivement vu comme ça c'est pas faux :).

Une variable déclarée dans une fonction, je crois s’appelle une variable locale, C'est à dire quelle n'est visible que par et dans cette fonction.


Ah,je n'ai appris ça nulle part,je me disais bien que celle ci n'allais pas influer dans la routine principal et c'est mieux qu'elle s'éfface.

Non ce n'est pas normal ??? je vais à la pêche aux infos , il faut corriger ce bug , merci de l'avoir signaler ;

tu me confirme que tu n'as pas ce qu'il y a dans l'ellipse rouge en faisant éditer ton premier message


Oui je te le confirme.

En lisant ton tutoriel très bien fait et très bien expliqué,on vois lors de la création d'un message un encadré DS pour y copier un lien DataSheet.

Cette espace n'est pas du tous affiché.Essaye de voir si celas se produis quand on craie un message ou seulement quand on édit a nouveau un message,ou les 2.

Cordialement.

Optimisation du code
HVDifusion
Débutant
Débutant
Messages : 43
Enregistré en : décembre 2015

#7 Message par HVDifusion » ven. 25 déc. 2015 00:27

Salut,

Me voila avec le code final qui marche.Comme on le vois j'ai banni la fonction delay_ms.La logiquement avec sa le PIC ne reste pas bloquer.

Code : Tout sélectionner

#define led PORTA.B1 // masque pour le bit 1
#define led2 PORTB.B3 // masque pour le bit 3

unsigned int compteur; // variable pour stocker debordement TMR0
unsigned int compteur2;
unsigned int time;

void interrupt() // routine interruption
{
 if (INTCON.T0IF) // si débordement TMR0 a lieu,alors
 {
  INTCON.T0IF = 0; // init du flag a 0
  compteur++;
  compteur2++;
  time++;
 }
}

void intled() // signalement preparation du programme
{
 time = 0;
 compteur2 = 0;
 while (time <=3906)
 {
    if (compteur2 >= 781)
    {
     led2=~led2;
     compteur2 = 0;
    }
  }
}

void main() // routine principale
{
 PORTA = 0; // init 0V
 PORTB = 0; // init 0V
 TRISA = 0; // init full sortie
 TRISB = 0; // init full sortie
 PCON = 0b00001000; // init OSC interne 4MHz
 INTCON = 0b10000000; // interrupt autorisé,TMR0 activé
 CMCON = 7; // désactivation comparateur PORTA
 OPTION_REG = 0b00000000; // init prescaler 256
 
 TMR0 
= 0; // init TMR0 a 0
 T0IE_bit = 1;
 intled(); // appel de la fonction creer
 compteur = 0; // init variable a 0

 while(1)
 {
  if (compteur >= 1953)
  {
   led=~led;
   compteur = 0;
  }
 }
}


Qu'en pensez-vous,d'autre suggestion?


Cordialement.


Retourner vers « Langage C »

Qui est en ligne

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