[PIC] demande d'aide pour démarrer en c ou asm

demande d'aide pour démarrer en c ou asm [PIC] - Nano-ordinateur, microcontrôleurs, FPGA - Electronique, domotique, DIY

Marsh Posté le 22-08-2022 à 13:58:48    

Bonjour,
 
Je cherche de l'aide pour démarrer un projet en c ou assembleur, tous les tutos que je trouve sont pour des vieilles versions de mplab..
Pour un 16f88
 


---------------
Ce n'est pas parce que vous avez des certitudes que vous avez raison
Reply

Marsh Posté le 22-08-2022 à 13:58:48   

Reply

Marsh Posté le 22-08-2022 à 16:06:55    

C'est un exercice scolaire? :o
 
Tu as quel problème/... exactement?

Reply

Marsh Posté le 22-08-2022 à 23:54:48    

C'est en théorie tout simple :
Je souhaite faire avec le µC un compteur 3 digits avec boutons +/- et enregistrer 2 valeurs (High et Low) dans la mémoire non volatile, et rappeler ensuite ces 2 valeurs en fonction d'un bouton (Hi/Lo).
 
Mais je ne sais même pas comment démarrer correctement avec MPLABX, dès que j'essaye de compiler il y a toujours un problème avec des fichiers qu'on récupère un peu partout sur le net qui ne sont plus mis à jour pour d'anciennes versions de MPLab et j'avoue ça me décourage pas mal.


---------------
Ce n'est pas parce que vous avez des certitudes que vous avez raison
Reply

Marsh Posté le 23-08-2022 à 01:49:39    

Je ne connais pas MPLABX, mais je pense que ton problème est plutôt là:

iosys99 a écrit :

un problème avec des fichiers qu'on récupère un peu partout sur le net


On ne récupère pas des fichiers n'importe où mais - en supposant que tu parles des header pour ton PIC - directement chez le fabriquant du CI ou du compilateur/IDE/... Donc dans ton cas quelque part là bas je suppose: https://www.microchip.com/en-us/too [...] plab-x-ide
 
Et puis il faudrait être plus précis: Quel(s) fichier(s) récupéré(s) où exactement Quel problème exactement? ...

Reply

Marsh Posté le 06-11-2022 à 16:08:48    

J'y suis finalement arrivé.
J'ai commencé par installer une ancienne version de MPLABxIDE et suivi quelques tutoriels.
Et j'étais assez embeté avec un kit PICKIT v2 qui semble abandonné par tout le monde..
J'ai acheté un PICKIT v4 pour programmer en live mon montage, puis suivi quelques tutos plus récents.
J'ai finalement abouti à un programme complet qui fait presque ce que je veux mais j'en suis fier ^^
J'ai d'ailleurs découvert qu'il y a des fonctions intégrées dans le code qui évitent d'en coder et débuguer soi même par exemple pour stocker en RAM une variable on la déclare simplement, puis on l'utilise en faisant attention à la criticité de la rapidité du code (interruptions pendant un enregistrement en EEPROM), mais le compilateur gère ça tout seul apparemment :
 
// Variables declarations stored on EEPROM
unsigned char __eeprom iEEUnitsHi;
unsigned char __eeprom iEETensHi;
unsigned char __eeprom iEEHundredsHi;
unsigned char __eeprom iEEUnitsLo;
unsigned char __eeprom iEETensLo;
unsigned char __eeprom iEEHundredsLo;


Message édité par iosys99 le 06-11-2022 à 17:20:55

---------------
Ce n'est pas parce que vous avez des certitudes que vous avez raison
Reply

Marsh Posté le 06-11-2022 à 16:14:32    

Le schema :
 
https://img.super-h.fr/images/2022/11/06/c1b39aa3ad8ce29e40740e7a4edfca26.th.jpg
 
Le code:

Code :
  1. /* Main.c file generated by New Project wizard
  2. *
  3. * Created:   lun. oct. 17 2022
  4. * Processor: PIC16F882
  5. * Compiler:  MPLAB XC8
  6. */
  7. #include <xc.h>
  8. #include "Config16f882.h"
  9. #define _XTAL_FREQ 20000000
  10. #define PreLoad     65480
  11. #define SW1 PORTCbits.RC0 // Units up
  12. #define SW2 PORTCbits.RC1 // Tens up
  13. #define SW3 PORTCbits.RC2 // Hundreds up
  14. #define SW4 PORTCbits.RC3 // Hi/lo mode
  15. unsigned int iCurrent_Digit=0;
  16. const unsigned char iSegments_Code[11] = {
  17.     0b00111111, // 0
  18.     0b00000110, // 1
  19.     0b01011011, // 2
  20.     0b01001111, // 3
  21.     0b01100110, // 4
  22.     0b01101101, // 5
  23.     0b01111101, // 6
  24.     0b00000111, // 7
  25.     0b01111111, // 8
  26.     0b01101111, // 9
  27.     0b00000000, // 10 digit off
  28. };
  29. // Variables declarations stored on EEPROM
  30. unsigned char __eeprom iEEUnitsHi;
  31. unsigned char __eeprom iEETensHi;
  32. unsigned char __eeprom iEEHundredsHi;
  33. unsigned char __eeprom iEEUnitsLo;
  34. unsigned char __eeprom iEETensLo;
  35. unsigned char __eeprom iEEHundredsLo;
  36. // Because of the interrupt subroutine (ISR),
  37. // we working in main() AND in ISR with non EEPROM variables
  38. int iUnitsHi=0;
  39. int iTensHi=0;
  40. int iHundredsHi=0;
  41. int iUnitsLo=0;
  42. int iTensLo=0;
  43. int iHundredsLo=0;
  44. void TMR1_Init(void);
  45. void main(void) {
  46.     // Recall variables values from EEPROM
  47. iUnitsHi = iEEUnitsHi;
  48. iTensHi = iEETensHi;
  49. iHundredsHi = iEEHundredsHi;
  50. iUnitsLo = iEEUnitsLo;
  51. iTensLo = iEETensLo;
  52. iHundredsLo = iEEHundredsLo;
  53.     // In case EEPROM data is corrupted, display default 0 by corrupted digit
  54. if (iUnitsHi > 10) {iUnitsHi = 0;}
  55. if (iTensHi > 10) {iTensHi = 0;}
  56. if (iHundredsHi > 10) {iHundredsHi = 0;}
  57. if (iUnitsLo > 10) {iUnitsLo = 0;}
  58. if (iTensLo > 10) {iTensLo = 0;}
  59. if (iHundredsLo > 10) {iHundredsLo = 0;}
  60.     TMR1_Init();
  61.     TRISA = 0x00; // Segments on output
  62.     PORTA = iSegments_Code[0]; // All port A bits off
  63.     TRISB = 0x00; // Digit selection on output
  64.     PORTB = 0x00; // Digit selection on off
  65.     TRISC = 0b11111111; // Buttons on inputs, all port C
  66.     ADCON1 = 0x0F;
  67.    
  68.     while(1)
  69.     {
  70.         __delay_ms(2);
  71.    // First we check Hi / Lo mode
  72.     if(SW4==1)
  73.     {
  74.     // We are in High Mode
  75.         if(SW1==1)      //PRESSED SWITCH
  76.         {
  77.              while(SW1==1) // Waiting button release
  78.                 {
  79.                     NOP();
  80.                 }
  81.             // Increment Units
  82.             if (iUnitsHi < 10)
  83.             {
  84.              
  85.             iUnitsHi=iUnitsHi+1;
  86.             iEEUnitsHi=iUnitsHi ;
  87.             }
  88.     else
  89.     iUnitsHi=0;
  90.         iEEUnitsHi=iUnitsHi ;
  91.         }
  92.         if(SW2==1)      //PRESSED SWITCH
  93.         {
  94.             while(SW2==1) // Waiting button release
  95.                 {
  96.                     NOP();
  97.                 }
  98.             // Increment Tens
  99.             if (iTensHi < 10)
  100.             {
  101.                
  102.             iTensHi=iTensHi+1;
  103.             iEETensHi=iTensHi;
  104.             }
  105.     else
  106.     iTensHi=0;
  107.         iEETensHi=iTensHi;
  108.             }
  109.         if(SW3==1)      //PRESSED SWITCH
  110.         {
  111.             while(SW3==1) // Waiting button release
  112.                 {
  113.                     NOP();
  114.                 }
  115.             // Increment Hundreds
  116.             if (iHundredsHi < 10)
  117.             {
  118.                
  119.             iHundredsHi=iHundredsHi+1;
  120.             iEEHundredsHi=iHundredsHi;
  121.             }
  122.     else
  123.     iHundredsHi=0;
  124.         iEEHundredsHi=iHundredsHi;
  125.         }
  126.       }
  127.     else
  128.     {
  129.     // We are in Low mode
  130.         if(SW1==1)      //PRESSED SWITCH
  131.         {
  132.                while(SW1==1) // Waiting button release
  133.                 {
  134.                     NOP();
  135.                 }
  136.             // Increment Units
  137.             if (iUnitsLo < 10)
  138.             {
  139.            
  140.             iUnitsLo=iUnitsLo+1;
  141.             iEEUnitsLo=iUnitsLo;
  142.             }
  143.     else
  144.     iUnitsLo=0;
  145.         iEEUnitsLo=iUnitsLo;
  146.         }
  147.        
  148.         if(SW2==1)      //PRESSED SWITCH
  149.         {
  150.               while(SW2==1) // Waiting button release
  151.                 {
  152.                     NOP();
  153.                 }
  154.             // Increment Tens
  155.             if (iTensLo < 10)
  156.             {
  157.              
  158.             iTensLo=iTensLo+1;
  159.             iEETensLo=iTensLo;
  160.             }
  161.     else
  162.     iTensLo=0;
  163.         iEETensLo=iTensLo;
  164.             }
  165.        
  166.        
  167.         if(SW3==1)      //PRESSED SWITCH
  168.         {   
  169.             while(SW3==1) // Waiting button release
  170.                 {
  171.                     NOP();
  172.                 }
  173.             // Increment Hundreds
  174.             if (iHundredsLo < 10)
  175.             {
  176.          
  177.             iHundredsLo=iHundredsLo+1;
  178.             iEEHundredsLo=iHundredsLo;
  179.             }
  180.     else
  181.     iHundredsLo=0;
  182.         iEEHundredsLo=iHundredsLo;
  183.         }
  184.     }
  185.     }
  186.     return;
  187. }
  188. //===================================
  189. //--------------[ ISR ]--------------
  190. void __interrupt() ISR(void)
  191. {
  192.    if(TMR1IF)
  193.    {
  194.       //GIE=0;
  195.     __delay_ms(1);
  196.     // First we check Hi / Lo mode
  197.     if(SW4==1) // High Mode
  198.     {
  199.      if(iCurrent_Digit==0) // Units
  200.      {
  201.          // PORTA = iSegments_Code[10];
  202.  PORTA = iSegments_Code[iUnitsHi];
  203.          PORTB = 0b00000001;
  204.        
  205.      }
  206.      if(iCurrent_Digit==1) // Tens
  207.      {
  208.          //PORTA = iSegments_Code[10];
  209.  PORTA = iSegments_Code[iTensHi];
  210.  PORTB = 0b00000010;
  211.        
  212.      }
  213.      if(iCurrent_Digit==2) // Hundreds
  214.      {
  215.          //PORTA = iSegments_Code[10];
  216.  PORTA = iSegments_Code[iHundredsHi];
  217.          PORTB = 0b00000100;
  218.        
  219.      }
  220.       }
  221.       else // Low mode
  222.       {
  223.            if(iCurrent_Digit==0) // Units
  224.      {
  225.          // PORTA = iSegments_Code[10];
  226.  PORTA = iSegments_Code[iUnitsLo];
  227.          PORTB = 0b00000001;
  228.        
  229.      }
  230.      if(iCurrent_Digit==1) // Tens
  231.      {
  232.          //PORTA = iSegments_Code[10];
  233.  PORTA = iSegments_Code[iTensLo];
  234.  PORTB = 0b00000010;
  235.        
  236.      }
  237.      if(iCurrent_Digit==2) // Hundreds
  238.      {
  239.          //PORTA = iSegments_Code[10];
  240.  PORTA = iSegments_Code[iHundredsLo];
  241.          PORTB = 0b00000100;
  242.        
  243.      }
  244.       }
  245.      iCurrent_Digit++;
  246.      if(iCurrent_Digit==3)
  247.      {
  248.         iCurrent_Digit=0;
  249.       }
  250.      TMR1IF = 0;
  251.      TMR1 = PreLoad; // Preloading Timer1
  252.      //GIE=1;
  253.    }
  254. }
  255. //----------[ END OF ISR ]-----------
  256. //===================================
  257. // Functions' Definitions
  258. void TMR1_Init()
  259. {
  260.   // -- [[ Configure Timer1 To Operate In Timer Mode ]] --
  261.   // Preload TMR1 Register Pair
  262.   TMR1 = PreLoad;
  263.   // Choose the local clock source (timer mode)
  264.   TMR1CS = 0;
  265.   // Choose the desired prescaler ratio (1:8)
  266.   T1CKPS0 = 1;
  267.   T1CKPS1 = 1;
  268.   // Switch ON Timer1 Module!
  269.   TMR1ON = 1;
  270.   // Config TMR1 Interrupt
  271.   TMR1IE = 1;
  272.   TMR1IF = 0;
  273.   PEIE = 1;
  274.   GIE = 1;
  275. }


 
J'ai supprimé le le bouton STO inutile en fait et pas eu à gérer le code pour enregistrer en EEPROM le compilateur l'a fait pour moi  :love:
J'ai pour objectif de faire un speed display screen facile à programmer pour remplacer ceux des vieux PC années 80.
 
https://www.minuszerodegrees.net/le [...] isplay.htm
 
https://img.super-h.fr/images/2022/11/06/189df7c7886c8742bb680c8001001b46.th.jpg
 
Edit : J'ai oublié, j'ai un bug à résoudre, ça ne restore pas les zéros quand on boot le programme après extinction du courant...
Je fais une petite vidéo.
Edit : Optimisation de la gestion de l'appui du bouton, bug de la restauration des chiffres résolu, code mis à jour... Je vais refaire une vidéo de présentation non buguée ^^
 
Video : https://streamable.com/38pc2b


Message édité par iosys99 le 06-11-2022 à 17:21:06

---------------
Ce n'est pas parce que vous avez des certitudes que vous avez raison
Reply

Marsh Posté le 06-11-2022 à 17:48:31    

Bravo pour ta tenacité.
 
Quelque commentaires si tu veux bien:
-Il est très important d'avoir des résistances de tirage (pullup/down) sur les entrées, par contre il ne faut pas en mettre en série avec les boutons car tu fabriques un pont diviseur de tension. Selon les valeurs et les caractéristiques des entrées du PIC un appui risque de ne pas être enregistré (correctement). Aussi dans les AVR il y a des pullup intégrés qu'on peut activer, pour les PIC je ne sais pas.
-Tu devrais faire attention à la mise en page de ton code, ça évite les erreurs ou fait qu'on les trouve plus facilement et c'est plus facile à lire aussi.
-Le délai dans l'ISR c'est très moche, autant modifier la configuration du timer qui génère cette interruption.
-Tes variables globales ne sont pas _modifiés_ dans l'ISR, sinon il faudrait les déclarer "volatile".
-Pour l'EEPROM il faudrait voir si le code généré par le compilateur est suffisamment "intelligent" pour écrire l'EEPROM que quand une valeur change, car ce type de mémoire à un nombre de cycles limité.
 
A part ça le code est plutôt propre pour un débutant (ou pas débutant??). Après on peut toujours optimiser, genre utiliser switch() au lieu de tout ces if(), mais ce genre de choses c'est largement une question de goût aussi.
 

Reply

Marsh Posté le 06-11-2022 à 19:27:50    

J'ai fait de l'assembleur il y a 25 ans (HP 48 / Saturn) mais peu de C, et pas mal de Visual basic 6 debut 2000 (oui ça fait un grand écart !).
Pas totalement débutant mais après 20 ans, on va dire que pas loin du noob... !
 
en revanche certaines de tes explications sont un poil trop techniques pour moi ^^
 
- Les résistances pull-up/down :  
https://img.super-h.fr/images/2022/11/06/7becb787a75bb40016261b9a1d00b6bd.th.jpg
 
La je ne sais pas trop, j'ai des notions d'électronique (thevenin, norton, mailles, noeuds etc lol)
- Mise en page : alors là, je me base surtout sur l'indentation, si tu as un document sur la mise ne page de code... je prends :)
- Le délai dans l'ISR, là, totaly noob : J'ai pris un code à interrruption existant pour afficher un chiffre nombre sur un 3 segment LED Digit avec la persistance de la vision humaine ^^.
- Les variables alors j'ai de la chance, je ne les modifie pas dans l'interrruption... Mais je ne vois pas ce que signifie volatile dans un code C comme ça.
- Là je vais me renseigner chez microchip puisque j'utilise toute leur chaine de codage jusqu'au programmeur :)
 
Mais vraiment merci pour ta contribution !


Message édité par iosys99 le 06-11-2022 à 19:30:05

---------------
Ce n'est pas parce que vous avez des certitudes que vous avez raison
Reply

Marsh Posté le 08-11-2022 à 19:25:50    

Je ne connais pas les PIC, mais si j'interprête bien ce tableau il y a des pullup que sur le port B, or tes boutons sont branchés ailleurs. Pour quelque résistances autant laisser comme ça...
 
Pour l'indentation justement elle n'est pas cohérente dans ton code, mais c'est peut-être un soucis avec le forum. Il y a différents "styles" (et beaucoup de débats autour :o ), regarde simplement chez Wikipédia. Il y a des outils ("beautifier" ) pour automatiquement formater un code existant.
 
Le délai dans l'ISR: Comme je disais il faudrait modifier la configuration du Timer, mais je ne connais pas les PIC... Je laisse ma place à quelqu'un d'autre. De manière générale les interruption c'est pour des trucs critiques au niveau temps/délai/réactivité et on essaye de faire des interruptions les plus courtes possibles pour ne pas "bloquer" le processeur trop longtemps (sachant que l'interruption peut intervenir à n'importe quel moment et parfois - genre pour un timer - très souvent). Donc du délai dans une ISR c'est pas interdit et dans ton cas simple ça ne pose (probablement) pas de problème, mais c'est moche. :o  
 
Pour le "volatile", tu peux demander à ton moteur de recherche préféré ;). En bref ce mot clé indique au compilateur que la variable peut changer de valeur à n'importe quel moment (dans une ISR justement), du coup il faut récupérer la valeur "réelle" à chaque fois et ne pas utiliser une "copie" qu'on aurait stocké quelque part dans un registre du processeur ou similaire. Dans ce contexte il faut aussi faire attention au "atomic access" pour les variables >1 octet, je te laisse te renseigner si tu veux.

Reply

Marsh Posté le 08-11-2022 à 20:51:26    

[:onclecharlie:4]  
Je vais potasser tout cela car tu as a quand même des notions de coding bien avancées pour moi, mais comme je prends tout conseil et je me renseigne par la suite.
 
[:cyberad] Tu me montres le chemin, c'est à moi qu'il appartient de le suivre   [:apyrael:1]  
 
Merci beaucoup pour ton aide en tout cas !


Message édité par iosys99 le 08-11-2022 à 20:51:52

---------------
Ce n'est pas parce que vous avez des certitudes que vous avez raison
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed