IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Embarqué Discussion :

Compteur LCD sur µC PIC16F876


Sujet :

Embarqué

  1. #1
    Membre à l'essai
    Homme Profil pro
    Ingénieur validation
    Inscrit en
    Novembre 2015
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur validation

    Informations forums :
    Inscription : Novembre 2015
    Messages : 25
    Points : 16
    Points
    16
    Par défaut Compteur LCD sur µC PIC16F876
    Bonjour,

    Dans le cadre d'un TP je dois réaliser un programme permettant d'afficher des caractères sur un afficheur LCD de type 16*2.

    Plus précisément il faut qu'au début le LCD affiche en alternance BONJOUR/Appuyez sur une touche, puis on a 2 boutons:
    -Le premier qui permet de passer à la suite du programme, si on appuie dessus le LCD va afficher TOUCHE OK pendant 3 secondes puis il va afficher NBR DE VISITEURS (sur la 1ère ligne) et Nbr : (sur la 2ème).

    C'est là qu'intervient le second bouton, en fait quand on appuie dessus le nombre de visiteurs va augmenter (ex : j'appuie 5 fois dessus le LCD va afficher Nbr : 5).
    En fait il faut donc faire un compteur mais je ne sais pas trop par où commencer.

    De plus j'ai un autre petit problème, je suis obligé de mettre un long délai ( genre 999999999 ms) pour que le LCD affiche un message longtemps, j'imagine que mettre un délai pareil ce n'est pas la solution (surtout si on veut mettre des conditions après !).

    Et maintenant voici le code + un screen de mon schéma Proteus
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
                            //////////Programme permettant d'afficher du texte sur un afficheur LCD\\\\\\\\\\
    ////////////////////////////////////////////////////////////////////////////////
    //Fonctions
    void init(); // Prodédure d'initialisation du PIC
    void affichage(); // Procédure qui gère l'affichage
    void impulsion_E(); // Procédure qui gère l'impulsion E
    void touche_ok(); // Procédure qui affiche "TOUCHE OK" sur le LCD
    ////////////////////////////////////////////////////////////////////////////////
    //Constantes
    #define LCD PORTB
    #define RS PORTC.F3
    #define E PORTC.F4
    #define LED PORTC.F7
    #define TOUCHE_OK PORTC.F6
    #define NBR_VISITEURS PORTC.F5
    #define EFFACER 0x01
    #define LIGNE_BAS 0xC0
    ////////////////////////////////////////////////////////////////////////////////
    //Fonction principale
    void main()
    {
         init(); // appel de la procédure "init"
                 while(1)
                 {
                       affichage(); // appel de la procédure "affichage"
                       while ( TOUCHE_OK == 0)
                       {
                          touche_ok(); // appel de la procédure "touche_ok"
                       }
                 }
    }
    ////////////////////////////////////////////////////////////////////////////////
    void init() //Sous programme qui gère l'initialisation
    {
     // Définition des ports en entrée ou sortie
     trisc.F3 = 0;
     trisc.F4 = 0;
     trisc.F7 = 0;
     trisc.F6 = 1;
     trisc.F5 = 1;
     trisb = 0x00;
    
     RS = 0;
     // Config du LCD
     LCD = 0x38;
     impulsion_E();
    
     LCD = 0x10;
     impulsion_E();
    
     LCD = 0x0C;
     impulsion_E();
    
     LCD = 0x06;
     impulsion_E();
    
     LCD = 0x01;
     impulsion_E();
    
    }
    ////////////////////////////////////////////////////////////////////////////////
    void affichage() // Sous programme qui gère l'affichage sur le LCD
    {
         int boucle;
         char message1[] = "BONJOUR"; // On initialise la variable "message1"
         char message2[] = "Appuyez sur une"; // On initialise la variable "message2"
         char message3[] = "touche"; // On initialise la variable "message3"
         RS = 1; // Permet d'écrire des caractères sur le LCD
    
                        for ( boucle = 0; boucle < 7; boucle ++) // Boucle qui va afficher "BONJOUR"
                        {
                            LCD = message1[boucle]; // Affiche "Appuyez sur une" sur le LCD
                            impulsion_E(); // appel de la procédure "impulsion_E"
                        }
                        delay_ms(1000); // Pendant 1 sec
                        RS = 0;
                        LCD = EFFACER; // Efface le LCD
                        impulsion_E(); // appel de la procédure "impulsion_E"
                        RS = 1;
    
                           for ( boucle = 0; boucle < 15; boucle ++) // Boucle qui affiche "Appuyez sur une touche"
                           {
                               LCD = message2[boucle]; // Affiche "Appuyez sur une" sur le LCD
                               impulsion_E(); // appel de la procédure "impulsion_E"
                           }
                           RS = 0;
                           LCD = LIGNE_BAS; // Affiche sur la deuxième ligne le prochain texte
                           impulsion_E(); // appel de la procédure "impulsion_E"
                           RS = 1;
    
                                for (boucle = 0; boucle < 6; boucle ++) // Boucle qui permet d'afficher la suite de "Appuyez sur une touche"
                                {
                                    LCD = message3[boucle]; // Affiche "touche" sur le LCD
                                    impulsion_E(); // appel de la procédure "impulsion_E"
                                }
                                delay_ms(1000);
                                RS = 0;
                                LCD = EFFACER; // Efface le texte sur le LCD
                                impulsion_E(); // appel de la procédure "impulsion_E"
    
    }
    ////////////////////////////////////////////////////////////////////////////////
    void impulsion_E() // Sous programme qui gère l'impulsion sur E
    {
         E = 1;
         delay_ms(2); //Tempo 2 ms
         E = 0;
    }
    ////////////////////////////////////////////////////////////////////////////////
    void touche_ok() // Sous programme qui gère l'affichage de "TOUCHE OK" sur le LCD
    {
         int boucle;
         char message4[] = "TOUCHE OK"; // On initialise la variable "message4"
         char message5[] = "NBR DE VISITEURS"; // On initialise la variable "message5"
         char message6[] = "Nbr :"; // On initialise la variable "message6"
         RS = 0;
         LCD = EFFACER; // Efface le texte sur le LCD
         impulsion_E(); // appel de la procédure "impulsion_E"
         RS = 1;
    
                     for (boucle = 0; boucle < 9; boucle ++)  // Boucle qui va affiche "TOUCHE OK"
                     {
                         LCD = message4[boucle]; // Affiche "TOUCHE OK" sur le LCD
                         impulsion_E(); // appel de la procédure "impulsion_E"
                     }
                     delay_ms(3000); // Pendant 3 sec
                     RS = 0;
                     LCD = EFFACER; // Efface le texte sur le LCD
                     impulsion_E(); // appel de la procédure "impulsion_E"
                     RS = 1;
    
                          for (boucle = 0; boucle < 16; boucle ++) // Boucle qui affiche "NBR DE VISITEURS"
                          {
                              LCD = message5[boucle]; // Affiche "NBR DE VISITEURS" sur le LCD
                              impulsion_E(); // appel de la procédure "impulsion_E"
                          }
                          RS = 0;
                          LCD = LIGNE_BAS; // Affiche le prochain texte sur la 2ème ligne
                          impulsion_E(); // appel de la procédure "impulsion_E"
                          RS = 1;
    
                             for (boucle = 0; boucle < 5; boucle ++) // Boucle qui affiche "Nbr :"
                             {
                                 LCD = message6[boucle]; // Affiche "Nbr :" sur le LCD
                                 impulsion_E(); // appel de la procédure "impulsion_E"
                             }
                                 delay_ms(999999); // Délai élevé pour que le LCD affiche longtemps le message
    
     }
    Nom : Schem proteurs.png
Affichages : 6974
Taille : 22,7 Ko

    Merci

  2. #2
    Modérateur

    Avatar de Vincent PETIT
    Homme Profil pro
    Consultant en Systèmes Embarqués
    Inscrit en
    Avril 2002
    Messages
    3 189
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Consultant en Systèmes Embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 189
    Points : 11 571
    Points
    11 571
    Par défaut
    Salut,
    Tu y es presque, il ne te manque plus que la gymnastique d'esprit avec les interruptions !

    Je vais résumer le cahier des charges :
    Citation Envoyé par Caenem
    Il faut qu'au début le LCD affiche en alternance "BONJOUR" et "Appuyez sur une touche"
    Bouton 1 fait afficher "TOUCHE OK" pendant 3 secondes puis il va afficher NBR DE VISITEURS (sur la 1ère ligne) et une variable NBR : (sur la 2ème).
    Bouton 2 fait augmenter le nombre de visiteurs (ex : j'appuie 5 fois dessus le LCD va afficher Nbr : 5), donc la variable NBR.

    Citation Envoyé par Caenem
    En fait il faut donc faire un compteur mais je ne sais pas trop par où commencer.
    De plus j'ai un autre petit problème, je suis obligé de mettre un long délai ( genre 999999999 ms) pour que le LCD affiche un message longtemps, j'imagine que mettre un délai pareil ce n'est pas la solution (surtout si on veut mettre des conditions après !).
    En effet, il faut un compteur et ton micro a un TIMER qui sert à ça.
    Les délais inséraient dans le code vont bloquer l'exécution du programme principal. Là aussi, ton micro possède ce qu'il faut : les programmes d'interruptions, qui stop ton programme principal le temps s'exécuter puis ils redonnent la main au programme principal.

    Ton algorithme peut ressembler à ça :
    - encadré en pointiller (programme d'interruption)
    Nom : Diagramme1.png
Affichages : 5578
Taille : 105,7 Ko

    Dans un premier temps et avant d'aller plus loin, arrives tu a comprendre les grandes lignes de cet algorithme ?
    La science ne nous apprend rien : c'est l'expérience qui nous apprend quelque chose.
    Richard Feynman

  3. #3
    Membre à l'essai
    Homme Profil pro
    Ingénieur validation
    Inscrit en
    Novembre 2015
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur validation

    Informations forums :
    Inscription : Novembre 2015
    Messages : 25
    Points : 16
    Points
    16
    Par défaut
    Tiens, il y a des trucs que je ne connais pas comme "Timer overflow" et Indéfiniment ( c'est un délai ?), sinon le reste de l'algo je comprends.
    Mais si tu as fais des "morceaux" d'algo, ça veut dire qu'il faudra les mettre dans des fonctions à part ?

  4. #4
    Modérateur

    Avatar de Vincent PETIT
    Homme Profil pro
    Consultant en Systèmes Embarqués
    Inscrit en
    Avril 2002
    Messages
    3 189
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Consultant en Systèmes Embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 189
    Points : 11 571
    Points
    11 571
    Par défaut
    Demain, je t'expliquerai comment tout ça fonctionne.
    Mais oui c'est bien ça : morceau d'algo = fonction d'interruption.

    Lorsque tu vois une fonction d'interruption dans un programme, tu te dis que c'est bizarre car le programme principal n'appelle jamais cette fonction. En réalité, c'est le hardware qui lance la fonction.

    Si tu créais une fonction d'interruption TIMER, à chaque fois que le TIMER du PIC va déborder (overflow), ton programme principal va se stopper net et c'est la fonction d'interruption qui va s'exécuter. Des que la fonction d'interruption a fait ce que tu voulais qu'elle fasse alors le programme principal reprend à l'endroit où il a été interrompu.

    Si tu regardes l'organigramme, l'idée est de faire une fonction d'interruption qui va incrémenter une variable à chaque débordement du TIMER du PIC. Au préalable il faut régler le TIMER du PIC pour qu'il déborde toutes les secondes. Cette variable va s'incrémenter, va donc toutes les secondes au travers de la fonction d'interruption et cela même si ton programme principal est dans une boucle infinie ou un délai genre 999999999 ms (aucun soucis dans la mesure ou le programme principal va être stoppé, de toute manière, par la fonction d'interruption, qui est prioritaire !)
    La science ne nous apprend rien : c'est l'expérience qui nous apprend quelque chose.
    Richard Feynman

  5. #5
    Membre à l'essai
    Homme Profil pro
    Ingénieur validation
    Inscrit en
    Novembre 2015
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur validation

    Informations forums :
    Inscription : Novembre 2015
    Messages : 25
    Points : 16
    Points
    16
    Par défaut
    Je comprends mieux maintenant, à demain.

  6. #6
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Hello,

    Pourquoi utiliser des interruptions pour les 2 boutons ?
    On utilise des interruptions pour simuler du multithreading, pour être notifié d'un évènement extérieur (sans polling) ou pour exécuter du code à intervalle régulier sans avoir à compter les cycles (c'est le cas du timer ici).

    On peut faire du polling sur les boutons sans problèmes (je crois ?). Il y a un avantage à utiliser des interruptions ?

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    bool btn1 = false;
    bool btn2 = false;
     
    typedef enum { ST_HELLO, ST_DELAY_HELLO /*...*/, ST_WAIT_BTN1 } state_t;
    state_t st = ST_HELLO;
     
    while(1) {
       btn1 |= readBtn1State();
       btn2 |= readBtn2State();
     
       switch(st) {
       case ST_HELLO:
          print("Bonjour");
          st = ST_DELAY_HELLO;
       // ...
       case ST_WAIT_BTN1:
          if(btn1) {
             btn1 = false;
             st = // ...
           }
       }
    }

    (Au passage, c'est quoi ton soft pour faire ces beaux schémas ? Ça à l'air vachement plus pratique que paint *_*).

  7. #7
    Membre à l'essai
    Homme Profil pro
    Ingénieur validation
    Inscrit en
    Novembre 2015
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur validation

    Informations forums :
    Inscription : Novembre 2015
    Messages : 25
    Points : 16
    Points
    16
    Par défaut
    Le logiciel c'est Isis, il fait partie de la suite de logiciel Proteus.
    Sinon pour les explications, c'est compliqué pour moi car on ne m'en demande pas autant, on utilise les conditions, les boucles, les délais ... Mais pas ça quand même (C'est un TP de 1ère STI2D).

  8. #8
    Modérateur

    Avatar de Vincent PETIT
    Homme Profil pro
    Consultant en Systèmes Embarqués
    Inscrit en
    Avril 2002
    Messages
    3 189
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Consultant en Systèmes Embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 189
    Points : 11 571
    Points
    11 571
    Par défaut
    Citation Envoyé par Iradrille Voir le message
    Pourquoi utiliser des interruptions pour les 2 boutons ?
    On utilise des interruptions pour simuler du multithreading, pour être notifié d'un évènement extérieur (sans polling) ou pour exécuter du code à intervalle régulier sans avoir à compter les cycles (c'est le cas du timer ici).
    On peut faire du polling sur les boutons sans problèmes (je crois ?). Il y a un avantage à utiliser des interruptions ?
    Le problème du polling, c'est que tu peux rater l'info qui est, justement, sensée te faire sortir du polling.

    Ici dans l'exemple, on doit :
    1) Afficher "Bonjour" pendant 1 seconde c'est un minimum pour que l'utilisateur puisse lire.
    2) Afficher "Appuyer sur une touche"
    3) Polling sur le Bouton 1 pendant 1 seconde c'est un minimum pour que l'utilisateur puisse lire le message du 3).
    4) recommencer 1)

    L'appui sur une touche est complètement aléatoire et dépend de l'utilisateur. Certain appuierons longtemps dessus et le polling fonctionnera, et d'autre appuierons tellement rapidement qu'il y aura plus de chance qu'on soit hors polling que dans le polling. Lorsque tu écris avec un téléphone portable tactile je suis quasi sur que la durée d'appuie sur une touche est entre 50ms et 100ms (en considérant qu'il n'y a pas de rebond évidemment). Si j'ai le temps ce week en je vais essayer pour voir ce timing si j'appuie rapidement sur un interrupteur.

    Bien sur on pourrait modifier l'ago ci dessous comme ça :
    1) Afficher "Bonjour"
    2) Polling sur le Bouton 1 pendant 1 seconde c'est un minimum pour que l'utilisateur puisse lire le message du 1).
    3) Afficher "Appuyer sur une touche"
    4) Polling sur le Bouton 1 pendant 1 seconde c'est un minimum pour que l'utilisateur puisse lire le message du 2).
    5) recommencer 1)

    Avec cette algo on a étendu la plage de détection de l'appui sur Bouton 1 mais est ce suffisant ? Pour le dire, il faut regarder combien de temps dure 1) et 2) car lorsqu'on est dans ces fonctions qui gèrent l'afficheur, on est pas entrain de faire du polling et on peut potentiellement rater l'appuie sur la Bouton 1. Ensuite, statistiquement et pour qu'il y ait plus de chance de "voir" l'appui d'une touche que de la "rater", il faudrait que tout ce qui se passe entre 2 pollings dure 10x mois longtemps que la durée minimal moyenne de l'appuie d'une touche par un utilisateur. En partant de ce principe, polling 10x plus rapide que l'appuie de l'interrupteur on peut dire qu'il y a 90% de chances que l'appuie soit détecté.

    Du polling ça implique de calculer beaucoup de chose et en plus dans le cas de Caenem, ce qui est embêtant c'est qu'il doit faire des choses entre temps (alterner sur l'afficheur "Bonjour" et "Appuyer sur une touche"), il ne peut donc pas faire un polling constant dans une boucle while par exemple.


    Citation Envoyé par Caenem Voir le message
    Le logiciel c'est Isis, il fait partie de la suite de logiciel Proteus.
    Sinon pour les explications, c'est compliqué pour moi car on ne m'en demande pas autant, on utilise les conditions, les boucles, les délais ... Mais pas ça quand même (C'est un TP de 1ère STI2D).
    J'utilise aussi Proteus http://www.labcenter.com/index.cfm et il fonctionne parfaitement bien sur mon Linux.

    Par contre !!! Je vois que tu est en 1ère... as tu vu en cours tout le mécanisme des interruptions des micros ? Ou est ce là que le prof veut t'emmener ?
    D'après toi ?

    Je demande ça car si les interruptions font parties du programme scolaire des années suivantes alors le prof attend une solution polling, comme le suggère Iradrille, et quitte à accepter que certain appuie soit loupé.

    Qu'est ce que tu en penses ?
    A ce soir.
    La science ne nous apprend rien : c'est l'expérience qui nous apprend quelque chose.
    Richard Feynman

  9. #9
    Membre à l'essai
    Homme Profil pro
    Ingénieur validation
    Inscrit en
    Novembre 2015
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur validation

    Informations forums :
    Inscription : Novembre 2015
    Messages : 25
    Points : 16
    Points
    16
    Par défaut
    Non on a pas encore vu cela, pour info certains de ma classe avaient fini ce programme et ils n'étaient pas allés aussi loin, juste des if, des while,for etc... Mais ça faisait 300 lignes leur code à peu près.

  10. #10
    Modérateur

    Avatar de Vincent PETIT
    Homme Profil pro
    Consultant en Systèmes Embarqués
    Inscrit en
    Avril 2002
    Messages
    3 189
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Consultant en Systèmes Embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 189
    Points : 11 571
    Points
    11 571
    Par défaut
    Bon, alors dans ce cas faisons du polling.

    Tu verras dans la suite de ton cursus que les interruptions sont, de loin, la meilleure solution car elles permettent de ne pas rater un événement.
    La gestion des événements extérieurs (souris, clavier, trigger sur un signal, action d'un périphérique, action de l'utilisateur, ...) est souvent très compliqué car on ne peut pas toujours se permettre de les rater. Tu imagines si ton polling ne fonctionne pas sur un bouton "Arrêt d'urgence" même si il y a 1 chance sur 100 que ça merdouille, dans ce cas précis ce n'était pas acceptable.

    Une solution élégante et je pense que les OS gèrent ça de cette manière :
    Les événements clavier/souris sont interceptés non pas par polling mais par interruptions. Les événements sont stockés immédiatement dans une pile et la main est rendu à l'OS (les fonctions d'interruption sont donc très courtes). Dans la liste des tâches qu'exécute l'OS il y en a une qui a pour rôle de traiter la pile d'interruption. Je n'ai jamais mis les doigts dans le kernel Linux mais je pense que c'est comme ça qu'il fonctionne (du moins c'est comme ça que je ferai pour être sur et certain de ne rater aucun événement.)

    Bref, ton programme pourrait ressembler à ça au final (pas testé car pas de compilateur Microchip sous la main) :
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    //////////Programme permettant d'afficher du texte sur un afficheur LCD
    ////////////////////////////////////////////////////////////////////////////////
    //Fonctions
    void init(void); 
    void affichage(char *message, int longeur_message);
    void effacer(void);
    void ligne_bas(void);
    char *itoa (int value, char *string, int radix);
    ////////////////////////////////////////////////////////////////////////////////
    //Constantes
    #define LCD PORTB
    #define RS PORTC.F3
    #define E PORTC.F4
    #define LED PORTC.F7
    #define TOUCHE_OK PORTC.F6
    #define NBR_VISITEURS PORTC.F5
    #define EFFACER 0x01
    #define LIGNE_BAS 0xC0
    ////////////////////////////////////////////////////////////////////////////////
    char *itoa (int value, char *string, int radix) // fonction qui convertie un entier en chaîne de caractères, dans n'importe quelle base 
    {
      char tmp[32];
      char *tp = tmp;
      int i;
      unsigned v;
      int sign;
      char *sp;
     
      if (radix > 36 || radix <= 1)
        return 0;
     
      sign = (radix == 10 && value < 0);
     
      if (sign)
        v = -value;
      else
        v = (unsigned)value;
     
      while (v || tp == tmp)
      {
        i = v % radix;
        v = v / radix;
     
        if (i < 10)
          *tp++ = i+'0';
        else
          *tp++ = i + 'A' - 10;
      }
     
      sp = string;
     
      if (sign)
        *sp++ = '-';
     
      while (tp > tmp)
        *sp++ = *--tp;
     
      *sp = 0;
     
      return string;
    }
     
    ////////////////////////////////////////////////////////////////////////////////
    void init() //Sous programme qui gère l'initialisation
    {
     // Définition des ports en entrée ou sortie
     trisc.F3 = 0;
     trisc.F4 = 0;
     trisc.F7 = 0;
     trisc.F6 = 1;
     trisc.F5 = 1;
     trisb = 0x00;
     
     RS = 0;
     // Config du LCD
     LCD = 0x38;
     impulsion_E();
     
     LCD = 0x10;
     impulsion_E();
     
     LCD = 0x0C;
     impulsion_E();
     
     LCD = 0x06;
     impulsion_E();
     
     LCD = 0x01;
     impulsion_E();
     
    }
    ////////////////////////////////////////////////////////////////////////////////
    void affichage(char *message, int longeur_message) // Sous programme qui gère l'affichage sur le LCD
    {
         int boucle;
     
         RS = 1; // Permet d'écrire des caractères sur le LCD
     
         for ( boucle = 0; boucle < longeur_message; boucle ++) // Boucle qui va afficher "BONJOUR"
         {
         	LCD = message[boucle]; // Affiche "Appuyez sur une" sur le LCD
     
    // tempo évitant de gérer le Handshaking possible avec l'afficheur.
         	E = 1;
            delay_ms(2); //Tempo 2 ms
            E = 0;
         }
    }
    ////////////////////////////////////////////////////////////////////////////////
    void effacer(void)
    {
    	RS = 0;
    	LCD = EFFACER; // Efface le texte sur le LCD
     
    // tempo évitant de gérer le Handshaking possible avec l'afficheur.
         	E = 1;
            delay_ms(2); //Tempo 2 ms
            E = 0;
    }
    ////////////////////////////////////////////////////////////////////////////////
    void ligne_bas(void)
    {
    	RS = 0;
    	LCD = LIGNE_BAS; // Affiche le prochain texte sur la 2ème ligne
     
    // tempo évitant de gérer le Handshaking possible avec l'afficheur.
         	E = 1;
            delay_ms(2); //Tempo 2 ms
            E = 0;
    }
    ////////////////////////////////////////////////////////////////////////////////
    //Fonction principale
    void main()
    {
         char nb[16];
         unsigned int visiteur = 0;
         init(); // appel de la procédure "init"
     
    	do
    	{
    		affichage("BONJOUR", 7);
    		delay_ms(1000);
    		effacer();
    		affichage("Appuyez sur une", 15);
    		delay_ms(1000);
    		effacer();
    		affichage("touche", 6);
    		delay_ms(1000);
    		effacer();
     
    	}while(TOUCHE_OK != 0);
     
    	affichage("TOUCHE OK", 9);
    	delay_ms(3000);
    	effacer();
    	affichage("NBR VISITEURS", 13);
    	ligne_bas();
     
     
     
    	while (1) // indéfiniment
    	{
    		if(NBR_VISITEURS == 0)
    		{
    			visiteur++;
    			affichage(itoa(visiteur, nb, 10));
    			effacer();
    			ligne_bas();
     
    		}	
    	}
    }

    la fonction itoa, que tu peux voir en cliquant au dessus de mon avatar, permet de convertir un entier en chaîne de caractères et dans n'importe quelle base (base 10 = décimal, base 2 = binaire, base 16 = hexa, etc...) Ton afficheur reçoit des caractères ASCII mais le soucis est que tu dois convertir le nombre d'appui sur le bouton 2 en caractères ASCII (ex : 10 -> '1' '0', 51 -> '5' '1'). L'exercice est plus compliqué qu'il n'y paraît.
    Si le code fonctionne, je t'invite a recréer ta propre fonction itoa mais plus simple car tu n'as pas besoin d'une fonction sachant faire toutes les bases
    La science ne nous apprend rien : c'est l'expérience qui nous apprend quelque chose.
    Richard Feynman

  11. #11
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    @Vincent, vu ton dernier code, je vois le problème : on a des itérations longues (l'affichage, avec les delay); et dans ce cas le polling va soit rater les appuis courts, soit il va falloir compter les cycles pour continuer le polling pendant le delay avec un truc (chiant) genre

    (syntaxe très approximative)
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    // return 1 si bouton pressé pendant le delay, 0 sinon.
    int delay(int ms) {
       int const iter_by_ms = (20000000 / 1000) / 5;
       int const total_iter = iter_by_ms * ms;
     
       __asm {
         xor eax, eax // eax = 0
         xor ecx, ecx // ecx = 0
         loop_start: // 5 cycles par itération
            inc ecx
            mov ebx, BTN_VAL // polling: ebx = btn
            or eax, ebx // eax |= ebx
            cmp ecx, total_iter
            jne loop_start
         loop_end:
            push eax // return eax
            ret
       };
    }

    Citation Envoyé par Vincent PETIT Voir le message
    En partant de ce principe, polling 10x plus rapide que l'appuie de l'interrupteur on peut dire qu'il y a 90% de chances que l'appuie soit détecté.
    Je dérive un peu le sujet, mais on a pas 100% de chance de détecter l'appui avec une fréquence de polling au moins 2 fois supérieure à la fréquence de changement d'état du bouton ?



    (Disons fréquence de polling 4 fois supérieure à la fréquence du bouton pour éviter le polling sur les fronts montants / descendants).

    Mais sinon, oui, les interruptions simplifient le code, et nous assurent que ça marche dans tous les cas.

  12. #12
    Membre actif
    Homme Profil pro
    Technicien Layout
    Inscrit en
    Août 2015
    Messages
    275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Technicien Layout

    Informations forums :
    Inscription : Août 2015
    Messages : 275
    Points : 292
    Points
    292
    Par défaut
    Citation Envoyé par Vincent PETIT Voir le message
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    //////////Programme permettant d'afficher du texte sur un afficheur LCD
    ////////////////////////////////////////////////////////////////////////////////
    //Fonctions
    void init(void); 
    void affichage(char *message, int longeur_message);
    void effacer(void);
    void ligne_bas(void);
    char *itoa (int value, char *string, int radix);
    ////////////////////////////////////////////////////////////////////////////////
    //Constantes
    #define LCD PORTB
    #define RS PORTC.F3
    #define E PORTC.F4
    #define LED PORTC.F7
    #define TOUCHE_OK PORTC.F6
    #define NBR_VISITEURS PORTC.F5
    #define EFFACER 0x01
    #define LIGNE_BAS 0xC0
    ////////////////////////////////////////////////////////////////////////////////
    char *itoa (int value, char *string, int radix) // fonction qui convertie un entier en chaîne de caractères, dans n'importe quelle base 
    {
      char tmp[32];
      char *tp = tmp;
      int i;
      unsigned v;
      int sign;
      char *sp;
     
      if (radix > 36 || radix <= 1)
        return 0;
     
      sign = (radix == 10 && value < 0);
     
      if (sign)
        v = -value;
      else
        v = (unsigned)value;
     
      while (v || tp == tmp)
      {
        i = v % radix;
        v = v / radix;
     
        if (i < 10)
          *tp++ = i+'0';
        else
          *tp++ = i + 'A' - 10;
      }
     
      sp = string;
     
      if (sign)
        *sp++ = '-';
     
      while (tp > tmp)
        *sp++ = *--tp;
     
      *sp = 0;
     
      return string;
    }
     
    ////////////////////////////////////////////////////////////////////////////////
    void init() //Sous programme qui gère l'initialisation
    {
     // Définition des ports en entrée ou sortie
     trisc.F3 = 0;
     trisc.F4 = 0;
     trisc.F7 = 0;
     trisc.F6 = 1;
     trisc.F5 = 1;
     trisb = 0x00;
     
     RS = 0;
     // Config du LCD
     LCD = 0x38;
     impulsion_E();
     
     LCD = 0x10;
     impulsion_E();
     
     LCD = 0x0C;
     impulsion_E();
     
     LCD = 0x06;
     impulsion_E();
     
     LCD = 0x01;
     impulsion_E();
     
    }
    ////////////////////////////////////////////////////////////////////////////////
    void affichage(char *message, int longeur_message) // Sous programme qui gère l'affichage sur le LCD
    {
         int boucle;
     
         RS = 1; // Permet d'écrire des caractères sur le LCD
     
         for ( boucle = 0; boucle < longeur_message; boucle ++) // Boucle qui va afficher "BONJOUR"
         {
         	LCD = message[boucle]; // Affiche "Appuyez sur une" sur le LCD
     
    // tempo évitant de gérer le Handshaking possible avec l'afficheur.
         	E = 1;
            delay_ms(2); //Tempo 2 ms
            E = 0;
         }
    }
    ////////////////////////////////////////////////////////////////////////////////
    void effacer(void)
    {
    	RS = 0;
    	LCD = EFFACER; // Efface le texte sur le LCD
     
    // tempo évitant de gérer le Handshaking possible avec l'afficheur.
         	E = 1;
            delay_ms(2); //Tempo 2 ms
            E = 0;
    }
    ////////////////////////////////////////////////////////////////////////////////
    void ligne_bas(void)
    {
    	RS = 0;
    	LCD = LIGNE_BAS; // Affiche le prochain texte sur la 2ème ligne
     
    // tempo évitant de gérer le Handshaking possible avec l'afficheur.
         	E = 1;
            delay_ms(2); //Tempo 2 ms
            E = 0;
    }
    ////////////////////////////////////////////////////////////////////////////////
    //Fonction principale
    void main()
    {
         char nb[16];
         unsigned int visiteur = 0;
         init(); // appel de la procédure "init"
     
    	do
    	{
    		affichage("BONJOUR", 7);
    		delay_ms(1000);
    		effacer();
    		affichage("Appuyez sur une", 15);
    		delay_ms(1000);
    		effacer();
    		affichage("touche", 6);
    		delay_ms(1000);
    		effacer();
     
    	}while(TOUCHE_OK != 0);
     
    	affichage("TOUCHE OK", 9);
    	delay_ms(3000);
    	effacer();
    	affichage("NBR VISITEURS", 13);
    	ligne_bas();
     
     
     
    	while (1) // indéfiniment
    	{
    		if(NBR_VISITEURS == 0)
    		{
    			visiteur++;
    			affichage(itoa(visiteur, nb, 10));
    			effacer();
    			ligne_bas();
     
    		}	
    	}
    }

    la fonction itoa, que tu peux voir en cliquant au dessus de mon avatar, permet de convertir un entier en chaîne de caractères et dans n'importe quelle base (base 10 = décimal, base 2 = binaire, base 16 = hexa, etc...) Ton afficheur reçoit des caractères ASCII mais le soucis est que tu dois convertir le nombre d'appui sur le bouton 2 en caractères ASCII (ex : 10 -> '1' '0', 51 -> '5' '1'). L'exercice est plus compliqué qu'il n'y paraît.
    Si le code fonctionne, je t'invite a recréer ta propre fonction itoa mais plus simple car tu n'as pas besoin d'une fonction sachant faire toutes les bases
    Peut etre que je dis une betise mais a la ligne 166, ne manque t-il pas un argument pour la fonction affichage "longeur de chaine" itoa renvoi seulement une chaine de caractère? par contre la longueur varie en fonction de l'incrémentation visiteur ?
    L’art est une activité humaine, le produit de cette activité ou l'idée que l'on s'en fait s'adressant délibérément aux sens, aux émotions, aux intuitions et à l'intellect. www.elise-galerie.com

  13. #13
    Modérateur

    Avatar de Vincent PETIT
    Homme Profil pro
    Consultant en Systèmes Embarqués
    Inscrit en
    Avril 2002
    Messages
    3 189
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Consultant en Systèmes Embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 189
    Points : 11 571
    Points
    11 571
    Par défaut
    Citation Envoyé par Iradrille Voir le message
    @Vincent, vu ton dernier code, je vois le problème : on a des itérations longues (l'affichage, avec les delay); et dans ce cas le polling va soit rater les appuis courts, soit il va falloir compter les cycles pour continuer le polling pendant le delay avec un truc (chiant) genre
    [...]
    Oui, je vois l'astuce et ça fonctionnerait beaucoup mieux car la tempo est réaliser par une boucle de polling.

    Citation Envoyé par Iradrille Voir le message
    Je dérive un peu le sujet, mais on a pas 100% de chance de détecter l'appui avec une fréquence de polling au moins 2 fois supérieure à la fréquence de changement d'état du bouton ?
    (Disons fréquence de polling 4 fois supérieure à la fréquence du bouton pour éviter le polling sur les fronts montants / descendants).
    Alors oui mais ... Je m'explique.

    Oui... parce que :
    Si on aborde les notions du traitement du signal, on voit que le théorème de Nyquist-Shannon dit, effectivement : l'échantillonnage (ici par du polling) d'un signal (ici le bouton 1) doit être effectué régulièrement à une fréquence au moins 2x supérieure. Si on est en dessous de cette fréquence, on perd des informations et on a des effets d'aliasing dans le spectre (hyper gênant) @Julien => Voici a quoi sert la décimation https://fr.wikipedia.org/wiki/Sous-%...la_chrominance c'est du sous échantillonnage volontaire, ce je ne connaissais pas !

    Donc ce théorème dit que pour échantillonner, via du polling, sans perdre d'infos dans le signal, ici le bouton, il faut que le polling aille au moins 2x plus vite.

    Mais... parce que :
    Il y a donc des problèmes à lever :
    Faire du polling très régulier => Comme tu viens de le démontrer, en écrivant en assembleur on contrôle le temps des instructions et on peut faire de l'échantillonnage de type polling.
    Connaître précisément la fréquence d'appuie sur le bouton => Beaucoup plus compliquer mais possible en prenant un temps d'appuie très très court.

    **********************************************************************

    Maintenant, quel boulot ça demande d'implémenter ça ? Pour rappel, ici on devait afficher "Bonjour" un instant, afficher "Appuyer sur une touche" un instant, faire du polling et recommencer le tout tant que personne n'appuie sur le bouton.

    Il faut connaitre parfaitement :
    Le temps que met l'afficheur LCD a gérer ses données, combien de temps il met a faire "clear", passer le curseur à la ligne du bas, afficher les données. Est ce que toutes les données prennent le même temps ?
    Maîtriser entièrement le code assembleur du programme dans le micro, de cette boucle quitte à ajouter des NOP (Not Operation) pour assurer un polling "régulier" et "d'une fréquence au moins 2x supérieure à l'appuie sur le bouton", contrôler le temps si il y a des appels de fonction dans d'autres fonctions et dans tous les cas de figures car peut être que le timing dans un if n'est pas le même que dans un else. Faut gérer ça aussi !

    Si je résume, faire du polling aussi fiable qu'une interruption donc avec une fréquence de polling 2x > à la fréquence de l'appuie sur le bouton nécessite ;
    De passer beaucoup de temps en calcul.
    De dégrader le code en ajoutant des NOP afin d'assurer un timing dans chaque cas de figure.
    Et le programme est dans une situation de blocage (boucle) ce qui implique que dans un programme digne de ce nom, il faudra mettre à jour le Watchdog pour ne pas qu'il croit que le soft est planté (et aussi revoir les timings en fonction de ça)
    A la fin on peut aussi s’apercevoir qu'on tourne en rond, ou que tous les temps cumulés nous font arriver à une fréquence de polling complètement déconnante et supérieur à ce que le micro peut faire ....
    Ça fait beaucoup d'inconvénients pour quasiment pas d'avantages face aux interruptions qui t'épargnent tout ça

    Je ne te raconte pas si il y avait eu des calculs mathématiques en plus de la gestion de l'afficheur dans la boucle de polling En assembleur on aurait des conditions dans tous les sens et il aurait fallut tout calculer, dans tous les cas de figures...... En réalité, le polling est une bonne solution dans très très peu de cas de figures (et que tu peux contourner avec des interruptions)


    @Julien,
    Bien vu mon gars
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    affichage(itoa(visiteur, nb, 10), 16);
    Après j'ai pas pu essayer, j'ai encore quelques PIC chez moi mais je ne les utilise plus et j'ai pas envie de réinstaller toute l'artillerie

    A+
    La science ne nous apprend rien : c'est l'expérience qui nous apprend quelque chose.
    Richard Feynman

  14. #14
    Membre à l'essai
    Homme Profil pro
    Ingénieur validation
    Inscrit en
    Novembre 2015
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur validation

    Informations forums :
    Inscription : Novembre 2015
    Messages : 25
    Points : 16
    Points
    16
    Par défaut
    Bon après un bon moment j'ai quasiment réussi à faire mon compteur, mais il demeure encore un problème, enfait le compteur doit s'incrémenter à chaque appui de bouton mais le problème c'est que quand je le maintiens enfoncé ça défile. Or ce qu'il faut que ça fasse c'est tant que le bouton n'est pas relaché le compteur ne bouge pas.

    J'ai fait une vidéo pour montrer clairement le problème
    https://youtu.be/vqX5slorWHg

    Et bien sur voici le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
                            //////////Programme permettant d'afficher du texte sur un afficheur LCD\\\\\\\\\\
    ////////////////////////////////////////////////////////////////////////////////
    //Fonctions
    void init(); // Prodédure d'initialisation du PIC
    void affichage(); // Procédure qui gère l'affichage
    void impulsion_E(); // Procédure qui gère l'impulsion E
    void touche_ok(); // Procédure qui affiche "TOUCHE OK" sur le LCD
    ////////////////////////////////////////////////////////////////////////////////
    //Constantes
    #define LCD PORTB
    #define RS PORTC.F3
    #define E PORTC.F4
    #define LED PORTC.F7
    #define TOUCHE_OK PORTC.F6
    #define NBR_VISITEURS PORTC.F5
    #define EFFACER 0x01
    #define LIGNE_BAS 0xC0
    ////////////////////////////////////////////////////////////////////////////////
    //Fonction principale
    void main()
    {
         init(); // appel de la procédure "init"
                 while(1)
                 {
                       affichage(); // appel de la procédure "affichage"
                       while ( TOUCHE_OK == 0)
                       {
                          touche_ok(); // appel de la procédure "touche_ok"
                       }
                 }
    }
    ////////////////////////////////////////////////////////////////////////////////
    void init() //Sous programme qui gère l'initialisation
    {
     // Définition des ports en entrée ou sortie
     trisc.F3 = 0;
     trisc.F4 = 0;
     trisc.F7 = 0;
     trisc.F6 = 1;
     trisc.F5 = 1;
     trisb = 0x00;
     portb = 0x00;
     portc = 0x00;
     
    
     RS = 0;
     // Config du LCD
     LCD = 0x38;
     impulsion_E();
    
     LCD = 0x10;
     impulsion_E();
    
     LCD = 0x0C;
     impulsion_E();
    
     LCD = 0x06;
     impulsion_E();
    
     LCD = 0x01;
     impulsion_E();
    
    }
    ////////////////////////////////////////////////////////////////////////////////
    void affichage() // Sous programme qui gère l'affichage sur le LCD
    {
         int boucle;
         char message1[] = "BONJOUR"; // On initialise la variable "message1"
         char message2[] = "Appuyez sur une"; // On initialise la variable "message2"
         char message3[] = "touche"; // On initialise la variable "message3"
         RS = 1; // Permet d'écrire des caractères sur le LCD
    
                        for ( boucle = 0; boucle < 7; boucle ++) // Boucle qui va afficher "BONJOUR"
                        {
                            LCD = message1[boucle]; // Affiche "Appuyez sur une" sur le LCD
                            impulsion_E(); // appel de la procédure "impulsion_E"
                        }
                        delay_ms(1000); // Pendant 1 sec
                        RS = 0;
                        LCD = EFFACER; // Efface le LCD
                        impulsion_E(); // appel de la procédure "impulsion_E"
                        RS = 1;
    
                           for ( boucle = 0; boucle < 15; boucle ++) // Boucle qui affiche "Appuyez sur une touche"
                           {
                               LCD = message2[boucle]; // Affiche "Appuyez sur une" sur le LCD
                               impulsion_E(); // appel de la procédure "impulsion_E"
                           }
                           RS = 0;
                           LCD = LIGNE_BAS; // Affiche sur la deuxième ligne le prochain texte
                           impulsion_E(); // appel de la procédure "impulsion_E"
                           RS = 1;
    
                                for (boucle = 0; boucle < 6; boucle ++) // Boucle qui permet d'afficher la suite de "Appuyez sur une touche"
                                {
                                    LCD = message3[boucle]; // Affiche "touche" sur le LCD
                                    impulsion_E(); // appel de la procédure "impulsion_E"
                                }
                                delay_ms(1000);
                                RS = 0;
                                LCD = EFFACER; // Efface le texte sur le LCD
                                impulsion_E(); // appel de la procédure "impulsion_E"
    
    }
    ////////////////////////////////////////////////////////////////////////////////
    void impulsion_E() // Sous programme qui gère l'impulsion sur E
    {
         E = 1;
         delay_ms(2); //Tempo 2 ms
         E = 0;
    }
    ////////////////////////////////////////////////////////////////////////////////
    void touche_ok() // Sous programme qui gère l'affichage de "TOUCHE OK" sur le LCD
    {
         int boucle;
         int centaine;
         int dizaine;
         int unite;
         char message4[] = "TOUCHE OK"; // On initialise la variable "message4"
         char message5[] = "NBR DE VISITEURS"; // On initialise la variable "message5"
         char message6[] = "Nbr :"; // On initialise la variable "message6"
         RS = 0;
         LCD = EFFACER; // Efface le texte sur le LCD
         impulsion_E(); // appel de la procédure "impulsion_E"
         RS = 1;
         centaine = 48; // centaine = 0 en ASCII
         dizaine = 48; // dizaine = 0 en ASCII
         unite = 48; // unite = 0 en ASCII
                     for (boucle = 0; boucle < 9; boucle ++)  // Boucle qui va affiche "TOUCHE OK"
                     {
                         LCD = message4[boucle]; // Affiche "TOUCHE OK" sur le LCD
                         impulsion_E(); // appel de la procédure "impulsion_E"
                     }
                     delay_ms(3000); // Pendant 3 sec
                     RS = 0;
                     LCD = EFFACER; // Efface le texte sur le LCD
                     impulsion_E(); // appel de la procédure "impulsion_E"
                     RS = 1;
    
                          for (boucle = 0; boucle < 16; boucle ++) // Boucle qui affiche "NBR DE VISITEURS"
                          {
                              LCD = message5[boucle]; // Affiche "NBR DE VISITEURS" sur le LCD
                              impulsion_E(); // appel de la procédure "impulsion_E"
                          }
                          RS = 0;
                          LCD = LIGNE_BAS; // Affiche le prochain texte sur la 2ème ligne
                          impulsion_E(); // appel de la procédure "impulsion_E"
                          RS = 1;
    
                             for (boucle = 0; boucle < 5; boucle ++) // Boucle qui affiche "Nbr :"
                             {
                                 LCD = message6[boucle]; // Affiche "Nbr :" sur le LCD
                                 impulsion_E(); // appel de la procédure "impulsion_E"
                             }
                             
                                 while (1)                               // Ce morceau de programme gère le compteur du nombre de visiteurs
                                 {
                                       RS = 0;                   //{ Ici on va afficher 000 sur la 2ème ligne du LCD
                                       LCD = LIGNE_BAS;
                                       LCD = 0xC9;
                                       impulsion_E();
                                       RS = 1;
                                       LCD = centaine;
                                       impulsion_E();
                             
                                       RS = 0;
                                       LCD = 0xCA;
                                       impulsion_E();
                                       RS = 1;
                                       LCD = dizaine;
                                       impulsion_E();
                             
                                       RS = 0;
                                       LCD = 0xCB;
                                       impulsion_E();
                                       RS = 1;
                                       LCD = unite;
                                       impulsion_E();           // }
    
                                       delay_ms(150);
                                 
                                         if ( NBR_VISITEURS == 0) // Si on appuie sur le bouton Nombre visiteurs
                                         {
                                            unite ++; // On incrémente "unite" pour faire défiler le compteur
                                         }
                                            if ( unite > 57)  // Si "unite" est > à "9" ( 57 pour le LCD)
                                            {
                                               dizaine ++;    // La variable "dizaine" va s'incrémenter et
                                               RS = 0;        // "unite" va repasser à 0
                                               LCD = 0xCA;
                                               impulsion_E();
                                               RS = 1;
                                               LCD = dizaine;
                                               impulsion_E();
                                               unite = 48;
                                               RS = 0;
                                               LCD = 0xCB;
                                               impulsion_E();
                                               RS = 1;
                                               LCD = unite;
                                               impulsion_E();
                                            }
                                            
                                               if ( dizaine > 57) // Si "dizaine" est > à "9"
                                               {
                                                  centaine ++;    // "centaine" va s'incrémenter et
                                                  RS = 0;         // "dizaine" va repasser à 0
                                                  LCD = 0xC9;
                                                  impulsion_E();
                                                  RS = 1;
                                                  LCD = centaine;
                                                  impulsion_E();
                                                  dizaine = 48;
                                                  RS = 0;
                                                  LCD = 0xCA;
                                                  impulsion_E();
                                                  RS = 1;
                                                  LCD = dizaine;
                                                  impulsion_E();
                                               }
    
                                                  if ( centaine > 57) // Si "centaine" est > à "9"
                                                  {
                                                     centaine = 57;   // "centaine", "dizaine" et "unite" restent à "9"
                                                     dizaine = 57;
                                                     unite = 57;
                                                     RS = 0;
                                                     LCD = 0xC9;
                                                     impulsion_E();
                                                     RS = 1;
                                                     LCD = centaine;
                                                     impulsion_E();
                                                     RS = 0;
                                                     LCD = 0xCA;
                                                     impulsion_E();
                                                     RS = 1;
                                                     LCD = dizaine;
                                                     impulsion_E();
                                                     RS = 0;
                                                     LCD = 0xCB;
                                                     impulsion_E();
                                                     RS = 1;
                                                     LCD = unite;
                                                     impulsion_E();
                                                  }
                                 }
     }

  15. #15
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Au lieu de seulement vérifier que le bouton est appuyé, vérifie que le bouton change d'état (et est appuyé aussi)

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    bool oldBtnState = false;
    bool newBtnState;
     
    while(1) {
       newBtnState = getBtnState();
     
       // le bouton était pressé à l'itération précédente, mais ne l'est plus
       if(oldBtnState && !newBtnState) {
          // bouton qui vient d'être relaché
       }
     
       // l'inverse
       else if(!oldBtnState && newBtnState) {
          // bouton qui vient d'être pressé
       }
       oldBtnState = newBtnState;
    }

  16. #16
    Membre à l'essai
    Homme Profil pro
    Ingénieur validation
    Inscrit en
    Novembre 2015
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur validation

    Informations forums :
    Inscription : Novembre 2015
    Messages : 25
    Points : 16
    Points
    16
    Par défaut
    Ok j'essaierai, mais existe-t-il une autre façon de faire ça ? Car je suis pas sensé connaitre ce que tu m'as dit (A mon niveau).

  17. #17
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Comment ça, pas censé connaitre ça ?

    C'est de la simple logique :
    Si tu vérifie que le bouton est appuyé, alors en restant appuyé tu entrera toujours dans la condition.
    Si tu vérifie que le bouton vient d'être relâché, alors tu n'entre dans la condition qu'en relâchant le bouton (donc rester appuyé n'a pas d'effet).

    Et "vient d'être relâché" c'est équivalent à "était pressé, mais ne l'est plus".

    (Mais non, je vois pas d'autre façon de faire).

  18. #18
    Membre à l'essai
    Homme Profil pro
    Ingénieur validation
    Inscrit en
    Novembre 2015
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur validation

    Informations forums :
    Inscription : Novembre 2015
    Messages : 25
    Points : 16
    Points
    16
    Par défaut
    Ok très bien merci

  19. #19
    Membre à l'essai
    Homme Profil pro
    Ingénieur validation
    Inscrit en
    Novembre 2015
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur validation

    Informations forums :
    Inscription : Novembre 2015
    Messages : 25
    Points : 16
    Points
    16
    Par défaut
    Ça ne marche pas, du moins c'est ce que dit le débogueur.
    Je crois que les bool n'existent pas sur MikroC.

  20. #20
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Citation Envoyé par Caenem Voir le message
    Ça ne marche pas, du moins c'est ce que dit le débogueur.
    Je crois que les bool n'existent pas sur MikroC.
    Si ça compile, c'est que les [c]bool[c] existent.

    (Si jamais c'est le compilo qui gueule, tu peux "créer" le type bool avec des #define; ou utiliser des int à la place)
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    #define bool int
    #define true (1)
    #define false (0)

    Qu'est ce que te dit le débogueur ?

Discussions similaires

  1. Compteur windows sur la mémoire utilisée par w3wp.exe
    Par maxagaz dans le forum Visual Studio
    Réponses: 2
    Dernier message: 23/01/2008, 20h56
  2. compteur dynamique sur action utilisateur
    Par Goldorak2 dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 18/07/2007, 14h26
  3. [Cookies] un compteur basé sur les cookies
    Par kuja2053 dans le forum Langage
    Réponses: 5
    Dernier message: 12/03/2007, 17h28
  4. Réponses: 11
    Dernier message: 27/06/2006, 16h42

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo