Microchip, C18, variable folle

Bonjour,
Je suis en train de faire un afficheur pour afficher les horaires de bus de Rennes dans mon appart, j'ai déjà réalisé avec succès ce projet sur un arduino. J'ai cependant besoin de libérer mon arduino pour un autre projet.
J'ai donc sortit un 18f2580 pour l'occasion. Je travaille avec mplabX et C18.

J'ai un problème qui me semble défier les lois de la programmation, je vous explique :


var = 38%10;//Récupérer '8'
printCar(var+48); //+48 pour la conversion en ascii, et afficher '8'
// --> mon écran affiche '8', pas de problème!
Maintenant voilà quelque chose de plus utile, mais qui tourne pas :

autreVar = 38;
var = autreVar%10;//Récupérer '8'
printCar(var+48); //l'afficher '8'
// --> mon écran affiche '0' peut importe la valeur de "autreVar"

J'hésite entre passer le karcher sur le pic ou mon ordi...

Merci de votre analyse, j'attend patiemment une réponse, voir solution?

Titus.

32 réponses

Résumé de la discussion

Le problème porte sur l'affichage sur un afficheur LCD via un PIC18F2580 lorsque var=autreVar%10 et que printCar(var+48) affiche correctement '8', mais que var = autreVar%10 affiche systématiquement '0'. Des échanges soulignent que des variables déclarées char ou int, des décalages mémoire et des interruptions cycliques peuvent fausser l'affichage et orienter le résultat vers zéro. Plusieurs suggestions visent à tester des affichages consécutifs, à revoir la conversion ASCII (utiliser '0' plutôt que 48), à vérifier la fonction d'envoi ecr_data et les réglages LCD et ports. En cas de doute, il peut être utile d'exposer le code entier et de tester sur une configuration minimale afin d'isoler si l'anomalie provient du format des variables ou du flux d'horloge.

Bobot (l’IA à votre service)
  1. Pour ce dernier point, je devrais pouvoir t'aider.
    Dans les PIC, les bus d'adresse programme et de données, ainsi que les mémoires correspondantes, sont totalement séparés.
    Il existe des pointeurs RAM et des pointeurs ROM. Ces deux types sont totalement incompatibles : une adresse de la mémoire programme n'a absolument rien qui lui correspond dans la mémoire vive, et lycée de Versailles.
    Quand tu définis :
    char var[] = "bonjour";
    

    Tu définis une variable (initialisée) en RAM et ta fonction "ecrire" attend un pointeur de type ram : ça tombe bien.
    Quand tu appelles directement ecrire("bonjour"); "bonjour" n'est pas affecté à une variable, il est "logé" en mémoire non volatile, donc la mémoire programme. donc tu essayes de passer à ecrire un pointeur de type rom : je suppose que le compilateur refuse.

    Ré-écris une autre version, copie quasi-conforme de "ecrire", mais avec un paramètre rom char * et ça devrait marcher.
    Tu peux toujours garder tes messages prédéfinis sous la forme
    const rom char var[] = "bonjour";

    comme ça ton texte "bonjour" est et reste en mémoire programme, alors que tel que tu le définis actuellement, il est défini dans la mémoire vive, ce qui oblige à en avoir une copie dans la mémoire programme (recopiée vers la RAM au lancement du programme).
    1. Oui, effectivement il y avait bien un problème, j'avais pas remarqué.
      C'est des vraies 10 secondes maintenant, merci!

      J'aimerai également faire quelques chose pour mon drivers LCD :
      ecrire("bonjour");


      au lieu de :
      char var[] = "bonjour";
      ecrire(var);


      J'ai essayé quelques truc mais rien de s'affiche, il doit y avoir une solution?
      J'ai pensé à faire un prototype dans ce genre :
      void ecrire(const char p*);

      Mais rien!
      1. Hors sujet, après vérification, ça concerne les pointeurs sur le code.
        J'ai horreur de l'avouer, mais je sèche...
        Sinon, peux-tu confirmer que ton comptage de secondes a bien un problème de comptage ?
        1. Alors là, je suis perdu! J'ai jamais entendu parler de ça!
          Peux-tu m'en dire plus?
          1. Encore une idée : n'as-tu pas mélangé les modèles (small et large) dans ton projet ? Utilises-tu bien la bonne bibliothèque ? Il me semble (je n'ai pas de doc où je suis) qu' il y a plusieurs façons de gérer la mémoire et il faut bien utiliser à l'édition de liens la bibliothèque compatible avec le modèle choisi.
            1. Pour :
              testT = 17 affichage de 'T'
              testT = 18 affichage de 'T'
              testT = 19 affichage de 'T'
              testT = 0 affichage de 'T'
              Bon... Visiblement il s'en fou de ma variable.

              Une autre piste? Je n'utilise pas de picKit ou ICD. Je suis dans le non-officiel avec cette chose : https://login.aliexpress.com/?from=sm&return_url=http://www.aliexpress.com/item/536517358.html

              Ça marche plutôt bien, seul inconvénient, il faut régler les fuses à chaque fois dans le logiciel fourni avec. Je pense les avoirs bien réglés.
              Je t'envoie un screenshot de mes réglages.
              1. Le sl++ se fait en interruption
                Effectivement, j'aurais dû le voir. Mais ça n'est pas logique : elle devrait être incrémentée dans time() comme les autres variables de comptage de temps. Et il faudra que tu m'expliques comment tu fais pour avoir un affichage correct du temps alors que tu n'incrémentes les dizaines que toutes les 11 secondes ! Pendant la dernière de chaque 11 secondes, tu dois afficher : (deux points) qui est le code ASCII qui suit '9'.

                Personnellement, j'ai fait tourner des applications écrites avec C18 sur des 18F, j'utilise l'opérateur modulo et je n'ai jamais rien remarqué.

                Aux dernières nouvelles, ça affiche un 'T' avec testT=17 : peux-tu essayer d'autres valeurs pour essayer de dégager une loi ?
                1. Cet affichage marche très bien! L'heure est correcte et s'affiche bien.

                  J'ai en effet remi mon drivers en question, et il marche aussi comme ça.
                  Pas de changement sur mon résultat de modulo.

                  Passer sur un pic 16F ou un autre compilateur tel que HITECH (je doute de la prise en charge des 18F) résoudrait peut etre le problème.
                  J'essayerai demain. ca m'embete d'arreter le projet sur un problème comme celui là.

                  Le sl++ se fait en interruption
                  1. Je vois que le code a encore changé : tu as ajouté des remises à 0 des sorties après chaque impulsion : tu remets ton driver LCD en cause, finalement ?
                    Et tes variables ont changé de banque. Je ne peux malheureusement pas compiler ni désassembler, je n'ai pas MPLABX à la maison et je n'ai pas envie de l'installer.
                    Mais je vois que tu es supposé afficher l'heure sur la première ligne. Mis à part que tu oublies, il me semble, de faire sl++ au début et que ton test if (sl > 10) est incorrect (il faudrait >=), est-ce que cet affichage-là marche ?

                    Ceci étant dit, j'avoue que je ne trouve toujours pas d'explication
                    1. J'ai deux fois le caractère T, j'ai remis ma variable en char.

                      Je zip le tout ce soir et te l'envoie.
                      1. Heureusement que quand je t'avais fait remarquer qu'une de tes variables était un int, tu m'avais confirmé que c'était un char. Maintenant, tu te rends compte que c'est un int. Passons encore, mais essaye de donner des réponses exactes.
                        As-tu fait l'essai que je t'avais demandé de faire deux affichages consécutifs :
                           
                          ecr_data(tmp + '0');
                          ecr_data(tmp + '0');

                        Pour l'envoi du code, zippe tout en un seul fichier et utilise le site cjoint.com ou un autre si tu as une préférence.
                      2. Rectification, en sortie avec :
                           testT = 17;
                           tmp = testT%10;
                           ecr_data(tmp + '0');
                        


                        J'ai 'T'.
                        Soit 84-48=36

                        36?
                        17%10=36 d'après mon pic
                        1. Effectivement je l'avais laissée en int pour mes tests...

                          Je peux t'envoyer le programme, par mail? Peux-tu m'envoyer une adresse mail?
                          1. J'étais INSAlien de 1974 à 1979 et c'était déjà la ligne 3 :)

                            ta ligne
                            0538  6B7A     CLRF 0x7A, BANKED
                            montre que ta variable testT est en fait un int. J'ai fait l'essai, quand on déclare un char, il n'essaye pas de mettre à 0 le poids fort d'un char, il ne le fait que pour un int. Mais passons.

                            Deux questions :

                            Est-il possible d'avoir le programme en entier ? (via cjoint.com ou autre)
                            Peux -tu afficher deux fois consécutives le chiffre :
                            ecr_data(tmp + '0');
                            ecr_data(tmp + '0');
                            1. 
                              0532  0E11     MOVLW 0x11
                              0534  0100     MOVLB 0x0
                              0536  6F79     MOVWF testT, BANKED
                              0538  6B7A     CLRF 0x7A, BANKED
                              
                              


                              Quelque chose qui va pas ici me semble t'il...
                              On déplace 0x11 vers W, on sélectionne la banque 0x0 pour mettre mon 0x11 ?
                              Et on efface la banque 0x7A ?

                              Ca fait longtemps que j'ai pas fait d'assembleur, je dois pas être loin de la vérité
                              1. Et on efface la banque 0x7A ?
                                Non, on efface l'adresse 0x7A, qui est le poids fort de l'adresse 0x79 qui contient testT.
                                testT est défini comme un char ou un int ?

                                Je ne vois rien de choquant.

                                Par contre, tu ne m'as pas répondu : Quand tu dis qu'il n'y a aucun problème avec le simulateur, qu'est-ce que ça veut dire ?
                                Tu mets un point d'arrêt et tu observes les valeurs de variables ?

                                Et quand tu fais le test en réel, tu as un programme qui tourne en boucle je suppose : As-tu laissé tourner le simulateur pour que lui aussi fasse plusieurs boucles avent de vérifier l'état des variables ?
                              2. Question subsidiaire et hors sujet : avec un nom de variable comme hourNextL3, tu ne serais pas étudiant du côté du campus de Beaulieu ?
                              3. Bravo, si effectivement je suis à Beaulieu! J'ai la ligne 1 à faire aussi!

                                Sur simulation mon modulo se fait bien! Toutes mes variables sont en char!
                                Je met un point d'arrêt juste avant de commencer le code qui m'intéresse et je fais du pas à pas pour observer les variations de mes variables.

                                Le programme tourne quelques minutes oui, donc pas de doute ça marche pas.
                            2. 48:               cursor(0,1);
                              0516  6EE6     MOVWF POSTINC1, ACCESS
                              0518  6AE6     CLRF POSTINC1, ACCESS
                              051A  EC8E     CALL 0x31C, 0
                              051C  F001     NOP
                              051E  52E5     MOVF POSTDEC1, F, ACCESS
                              0520  52E5     MOVF POSTDEC1, F, ACCESS
                              49:               ecr_string(next3);
                              0522  0EB6     MOVLW 0xB6
                              0524  6EE6     MOVWF POSTINC1, ACCESS
                              0526  0E01     MOVLW 0x1
                              0528  6EE6     MOVWF POSTINC1, ACCESS
                              052A  EC6F     CALL 0x2DE, 0
                              052C  F001     NOP
                              052E  52E5     MOVF POSTDEC1, F, ACCESS
                              0530  52E5     MOVF POSTDEC1, F, ACCESS
                              50:               testT = 17;
                              0532  0E11     MOVLW 0x11
                              0534  0100     MOVLB 0x0
                              0536  6F79     MOVWF testT, BANKED
                              0538  6B7A     CLRF 0x7A, BANKED
                              51:               tmp = testT%10;
                              053A  C079     MOVFF testT, __tmp_0
                              053C  F010     NOP
                              053E  C07A     MOVFF 0x7A, 0x11
                              0540  F011     NOP
                              0542  0E0A     MOVLW 0xA
                              0544  6E0D     MOVWF 0xD, ACCESS
                              0546  6A0E     CLRF 0xE, ACCESS
                              0548  C010     MOVFF __tmp_0, 0x8
                              054A  F008     NOP
                              054C  C011     MOVFF 0x11, 0x9
                              054E  F009     NOP
                              0550  ECB8     CALL 0x570, 0
                              0552  F002     NOP
                              0554  C004     MOVFF 0x4, __tmp_0
                              0556  F010     NOP
                              0558  C005     MOVFF 0x5, 0x11
                              055A  F011     NOP
                              055C  C010     MOVFF __tmp_0, tmp
                              055E  F078     NOP
                              52:               ecr_data(tmp + '0');
                              0560  0E30     MOVLW 0x30
                              0562  0100     MOVLB 0x0
                              0564  2578     ADDWF tmp, W, BANKED
                              0566  6EE6     MOVWF POSTINC1, ACCESS
                              0568  EC0F     CALL 0x21E, 0
                              056A  F001     NOP
                              056C  52E5     MOVF POSTDEC1, F, ACCESS
                              
                              1. Pas facile de te suivre : ton code change à chaque fois, ainsi que les noms de tes fonctions et de tes variables... Et tu n'as pas répondu à l'essai que je t'avais demandé.

                                Quand tu dis qu'il n'y a aucun problème avec le simulateur, qu'est-ce que ça veut dire ? Le simulateur n'a pas d'afficheur ! Et quand tu simules, exécutes-tu tout bien depuis le reset du PIC ?

                                Est-il possible d'avoir le programme complet ?
                                1. Pour afficher l'assembleur, si c'est comme avec MPLAB, tu fais un make de ton projet, puis tu fais menu View, commande Disassembly listing
                              2. Ouaip,
                                Le code en C :
                                   cursor(0,1);
                                   ecr_string(next3);
                                   testT = 17;
                                   tmp = testT%10;
                                   ecr_data(tmp + '0');
                                


                                Et en asm j'arrive pas à mettre la main sur le .asm, y'a un moyen particulier sur mplabX ?

                                J'ai testé avec le simulateur intégré et aucun problème
                                • 1
                                • 2