pic16f ou 18f + mémoire externe!
Répondre à la discussion
Affichage des résultats 1 à 14 sur 14

pic16f ou 18f + mémoire externe!



  1. #1
    invite2c518e41

    pic16f ou 18f + mémoire externe!


    ------

    Bonjour à tous,

    J'ai un projet de réalisation d'une carte électronique à base de microcontrôleur qui doit récupérer des données avec l'uart et les stocker dans une mémoire externe. J'utilise le pic16f876. J'ai un problème pour le stockage des données parce que la taille totale des données est d'environ 1 Mo. J'ai cherché plusieurs solutions mais finalement j'ai pensé que ce serait mieux d'utiliser un pic 18f (je pense au pic18f4550) avec une carte SD/MMC puisqu'il y a déjà une librairie bien définie sur mikroC.
    Mais cela signifie acheter une carte de 2Go et utiliser moins d'1Mo.
    J'aimerais savoir si c'est une bonne idée ou bien s'il y a d'autres alternatives bien plus simples ou plus économiques.

    -----

  2. #2
    invitefa96bd8f

    Re : pic16f ou 18f + mémoire externe!

    Salut,

    Ca dépends: Si tu comptes gérer un système de fichiers ( j'entends par là, pouvoir lire tes données en mettant la carte dans un PC) : Alors tu n'as pas d'autre choix (à la limite une clé USB, mais ca complique encore plus les choses).

    sinon tu as la possibilité d'utiliser une mémoire flash, par exemple de ce type :
    AT45DB161D
    ca c'est une 16M, mais il y en a des plus petites aussi.

  3. #3
    invite2c518e41

    Re : pic16f ou 18f + mémoire externe!

    Merci pour ta réponse Terriblement.

    Je n'ai pas besoin de pouvoir lire après les données par un pc. Seul le microcontrôleur pic16F876 pourra écrire et lire dans la mémoire.
    Donc je pense que la mémoire flash me convient. Je pense au AT45DB011B ou au AT45DB021.
    Si tu as un bout de code sur la lecture et l'écriture dans ce type de mémoire, je te serai grée de me le passer. Juste pour démarrer plus vite.
    Sinon je me débrouillerai avec le datasheet.
    Merci encore.

  4. #4
    inviteb3c806f8

    Re : pic16f ou 18f + mémoire externe!

    Bonjour,

    Pour les bouts de code de lecture et d'écriture voir les application notes de microchip.

  5. A voir en vidéo sur Futura
  6. #5
    invitefa96bd8f

    Re : pic16f ou 18f + mémoire externe!

    J'avais commencé à bidouiller quelque chose, je sais plus si ca avait fonctionné ou pas, si il y avait des bugs, des optimsiations ou quoi...
    bref, ca peut etre bien comme ne rien valoir: Je sais plus.
    Mais voici ce que j'ai trouvé.
    extension du fichier à remettre en .c

    Pièce jointe 248990

  7. #6
    Philou67

    Re : pic16f ou 18f + mémoire externe!

    Pourquoi ne pas "zipper" le fichier main.c au lieu de changer son extension ?
    :'( Plus j'apprends, et plus je mesure mon ignorance

  8. #7
    invitefa96bd8f

    Re : pic16f ou 18f + mémoire externe!

    je savais pas que le zip était autorisé

  9. #8
    invitee05a3fcc

    Re : pic16f ou 18f + mémoire externe!

    Citation Envoyé par petitete Voir le message
    Donc je pense que la mémoire flash me convient.
    Attention, tu n'as le droit qu'a environ 100000 écritures ... et ça va vite avec un µC .

  10. #9
    gienas
    Modérateur

    Re : pic16f ou 18f + mémoire externe!

    Bonjour à tous

    Citation Envoyé par terriblement Voir le message
    ... extension du fichier à remettre en .c ..
    .c c'est, jusqu'à preuve du contraire, du texte en txt.

    J'essaye.

    et/ou dans le texte, comme suggéré par l'éditeur du forum.

    Code:
    #include "pic18f46k22.h"
    
    #pragma config IESO = OFF        //Oscillator Switchover mode disabled
    #pragma config FOSC = INTIO67    //Internal oscillator block
    #pragma config PRICLKEN = ON	 //Primary clock enabled
    #pragma config FCMEN = OFF       //Fail-Safe Clock Monitor disabled (Pas pour oscillateur interne)
    #pragma config PLLCFG = OFF       //Oscillator multiplied by 4 (Normalement pas besoin car oscillateur interne)
    #pragma config PWRTEN = ON       //Power up timer enabled
    #pragma config XINST = OFF       //Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
    #pragma config STVREN =	ON       //Stack full/underflow will not cause Reset
    
    //#pragma config P2BMX =  PORTB5   //P2B is on RB5
    #pragma config CCP2MX = PORTB3   //CCP2 input/output is multiplexed with RB3
    #pragma config PBADEN = OFF      //PORTB<5:0> pins are configured as digital I/O on Reset
    #pragma config CCP3MX = PORTB5   //P3A/CCP3 input/output is multiplexed with RB5
    #pragma config MCLRE = INTMCLR	 //RE3 input pin enabled; MCLR disabled
    #pragma config HFOFST = OFF      //HFINTOSC output and ready status are delayed by the oscillator stable status
    #pragma config T3CMX = PORTC0    //T3CKI is on RC0
    
    #pragma config BOREN = OFF       //Brown-out Reset disabled in hardware and software
    #pragma config BORV = 285        //VBOR set to 2.85 V nominal
    #pragma config WDTPS = 32768     //Watchdog Timer Postscale Select bits
    #pragma config WDTEN = OFF       //Watch dog timer is always disabled. SWDTEN has no effect.
    
    #define TRIS_SCK   TRISCbits.TRISC3
    #define TRIS_CS1   TRISCbits.TRISC2
    #define TRIS_SDO   TRISCbits.TRISC5
    #define TRIS_SDI   TRISCbits.TRISC4
    
    #define CS1 LATCbits.LATC2
    
    void ecrire_buffer(unsigned char numero_de_buffer,unsigned int adresse,unsigned char *tableau_donnee, unsigned char nombre_donnee);
    void lire_buffer(unsigned char numero_de_buffer,unsigned int adresse,unsigned char *tableau_donnee, unsigned char nombre_donnee);
    void envoyer_opcode(unsigned char opcode,unsigned char address_byte_1,unsigned char address_byte_2,unsigned char address_byte_3);
    void buffer_to_main_memory_page(unsigned char numero_de_buffer, unsigned int page_address, unsigned char erase);
    void main_memory_page_to_buffer(unsigned char numero_de_buffer, unsigned int page_address);
    unsigned char memoire_flash_busy();
    
    //Fonctions pour le PIC
    void initialisation(void);
    
    
    int main(int argc, char** argv)
    {
        unsigned char i = 0;
    
        unsigned char numero_de_buffer = 1;
        unsigned int adresse = 0;
        unsigned char tableau_donnee[5]={5,10,20,40,80};
        unsigned char nombre_donnee = 5;
        unsigned char tableau_test[5]={0};
    
        unsigned char status = 210;
    
        initialisation();
        
        TRIS_SCK = 0;
        TRIS_CS1 = 0;
        TRIS_SDO = 0;
        TRIS_SDI = 1;
    
        CS1 = 1;
    
        //A VERIFIER SI CKE ET CKP SONT BIEN CONFIGURE
        PIR1bits.SSP1IF = 0;        //Flag indiquant que la réception ou l'envoie sont terminés
        SSP1STATbits.CKE = 0;       //CKE doit etre à 0 avec CKP pour avoir le mode 3
        SSP1STATbits.SMP = 1;       //1 -> Input data sampled at end of data output time
        SSP1CON1 = 0b00110000;      //0bxx110000 -> SSP Enable = 1;CKP = 1 (mode3);0000 fosc/4
    
    
        //ecrire_buffer(numero_de_buffer,adresse,tableau_donnee,nombre_donnee);
        
        //buffer_to_main_memory_page(1,0,0);
        status = memoire_flash_busy();
        i++;
        main_memory_page_to_buffer(1,0);
    
        while(i<254)
        {
            i++;
        }
        status = memoire_flash_busy();
    
        //lire_buffer(numero_de_buffer,adresse,tableau_test,nombre_donnee);
        while(1)
        {
            adresse=0;
        }
    }
    
    unsigned char memoire_flash_busy()
    {
        unsigned char compteur = 0;
        unsigned char status = 0;
    
        CS1 = 0;
        SSP1BUF = 0xD7;
    
        while(compteur<2)
        {
            if(PIR1bits.SSP1IF == 1 && compteur == 0)
            {
                PIR1bits.SSP1IF = 0;
                SSP1BUF = 0;
                compteur++;
            }
            if(PIR1bits.SSP1IF == 1 && compteur == 1)
            {
                PIR1bits.SSP1IF = 0;
                status = SSP1BUF;
                compteur++;
            }
        }
    
        CS1 = 1;
        compteur = 0;
        return status;
        //return (((status) & (1 <<(7)))>>7);
    }
    
    
    void main_memory_page_to_buffer(unsigned char numero_de_buffer, unsigned int page_address)
    {
        unsigned char address_LSB = page_address;
        unsigned char address_MSB = page_address<8;
    
        if(numero_de_buffer == 1)
        {
            envoyer_opcode(0x53,address_MSB,address_LSB,0);
        }
        else
        {
            envoyer_opcode(0x55,address_MSB,address_LSB,0);
        }
        while(PIR1bits.SSP1IF == 0);
        CS1 = 1;
    }
    
    void buffer_to_main_memory_page(unsigned char numero_de_buffer, unsigned int page_address, unsigned char erase)
    {
        unsigned char address_LSB = page_address;
        unsigned char address_MSB = page_address<8;
    
        if(erase == 0)  //without built in erase
        {
            if(numero_de_buffer == 1)
            {
                envoyer_opcode(0x88,address_MSB,address_LSB,0);
            }
            else
            {
                envoyer_opcode(0x89,address_MSB,address_LSB,0);
            }
        }
        else            //with built in erase
        {
            if(numero_de_buffer == 1)
            {
                envoyer_opcode(0x83,address_MSB,address_LSB,0);
            }
            else
            {
                envoyer_opcode(0x86,address_MSB,address_LSB,0);
            }
        }
        CS1 = 1;
        while(PIR1bits.SSP1IF == 0);
    }
    
    /*********************************************************************
    * Fonction : void lire_buffer(unsigned char numero_de_buffer,unsigned int adresse,unsigned char *tableau_donnee, unsigned char nombre_donnee)
    *
    * Attends : le numero de buffer ou il faut lire, a quelle adresse,le pointeur sur tableau qui va contenir les donnees lues ainsi que le nombre d'octets à lire
    *
    * But: Lit x octets du buffer et les stock dans un tableau
    *
    * Note: Apres la fonction envoyer_opcode, on va attendre l'interrupt du SPI (dernier octet de l'adresse), et ensuite commencer a lire les données (il faut envoyer des 0 pour se faire)
    *
    * Note2: Le dernier while fait attendre la fin de reception des données (le dernier octet lu n'est pas demandé, on ne s'en préoccupe pas)
    *
    ********************************************************************/
    void lire_buffer(unsigned char numero_de_buffer,unsigned int adresse,unsigned char *tableau_donnee, unsigned char nombre_donnee)
    {
        unsigned char compteur = 0;
        unsigned char adresse_MSB = adresse>>8;
        unsigned char adresse_LSB = adresse;
        unsigned char opcode = 0;
    
        if(numero_de_buffer == 1)
        {
            opcode = 0xD4;
        }
        else
        {
            opcode = 0xD6;
        }
        envoyer_opcode(opcode,0,adresse_MSB,adresse_LSB);
    
        while(PIR1bits.SSP1IF == 0);
        SSP1BUF = 0;
        while(compteur<nombre_donnee)
        {
            if(PIR1bits.SSP1IF == 1)
            {
                PIR1bits.SSP1IF = 0;
                tableau_donnee[compteur] = SSP1BUF;
                SSP1BUF = 0;
                compteur++;
            }
        }
    
        while(PIR1bits.SSP1IF == 0);
    
        CS1 = 1;
        PIR1bits.SSP1IF = 0;
    }
    
    /*********************************************************************
    * Fonction : void envoyer_opcode(unsigned char opcode,unsigned char address_byte_1,unsigned char address_byte_2,unsigned char address_byte_3)
    *
    * Attends : le "opcode" et les 3 octets nommés "addresse byte" dans la datasheet (page 31)
    *
    * But: Envoyer une commande (lecture, ecriture, transfert de buffer a main etc) avec les données correspondantes (adresse...)
    *
    * Note: S'occupe automatiquement des "don't care bytes"
    *
    * Note2: Pour le dernier octet envoyé (que ce soit un don't care ou la dernière adresse), lance l'envoie, et quitte la fonction AVANT que l'envoie ne soit terminé, cad, un interrupt interviendra alors qu'on aura deja quitté la fonction
    *
    ********************************************************************/
    void envoyer_opcode(unsigned char opcode,unsigned char address_byte_1,unsigned char address_byte_2,unsigned char address_byte_3)
    {
        unsigned char compteur = 0;
        unsigned char additional_dont_care_bytes = 0;
        unsigned char nombre_octet_a_envoyer = 0;
    
        if(opcode == 0x0B || opcode == 0xD4 || opcode == 0xD6)
        {
            additional_dont_care_bytes = 1;
        }
        else if(opcode == 0xD2 || opcode == 0xE8)
        {
            additional_dont_care_bytes = 4;
        }
        nombre_octet_a_envoyer = 3+additional_dont_care_bytes;
    
        CS1 = 0;
        SSP1BUF = opcode;
    
        while(compteur<nombre_octet_a_envoyer)
        {
            if(PIR1bits.SSP1IF == 1 && compteur == 0)
            {
                PIR1bits.SSP1IF = 0;
                SSP1BUF = address_byte_1;
                compteur++;
            }
            if(PIR1bits.SSP1IF == 1 && compteur == 1)
            {
                PIR1bits.SSP1IF = 0;
                SSP1BUF = address_byte_2;
                compteur++;
            }
            if(PIR1bits.SSP1IF == 1 && compteur == 2)
            {
                PIR1bits.SSP1IF = 0;
                SSP1BUF = address_byte_3;
                compteur++;
            }
            if(PIR1bits.SSP1IF == 1 && additional_dont_care_bytes != 0 && compteur > 2)
            {
                PIR1bits.SSP1IF = 0;
                SSP1BUF = 0;
                compteur++;
            }
        }
    }
    
    /*********************************************************************
    * Fonction : void ecrire_buffer(unsigned char numero_de_buffer,unsigned int adresse,unsigned char *tableau_donnee, unsigned char nombre_donnee)
    *
    * Attends : le numero de buffer ou il faut ecrire, a quelle adersse,le pointeur sur tableau contenant les données ainsi que le nombre d'octets à écrire
    *
    * But: Stock le tableau de donnée dans le buffer de la memoire flash
    *
    * Note: Apres la fonction envoyer_opcode, on va attendre l'interrupt du SPI (dernier octet de l'adresse), et commencer a envoyer les données
    *
    * Note2: Le dernier while fait attendre la fin d'envoie des données
    *
    ********************************************************************/
    void ecrire_buffer(unsigned char numero_de_buffer,unsigned int adresse,unsigned char *tableau_donnee, unsigned char nombre_donnee)
    {
        unsigned char compteur = 0;
        unsigned char adresse_MSB = adresse>>8;
        unsigned char adresse_LSB = adresse;
        unsigned char opcode = 0;
    
        if(numero_de_buffer == 1)
        {
            opcode = 0x84;
        }
        else
        {
            opcode = 0x87;
        }
    
        envoyer_opcode(opcode,0,adresse_MSB,adresse_LSB);
    
        while(compteur<nombre_donnee)
        {
            if(PIR1bits.SSP1IF == 1)
            {
                PIR1bits.SSP1IF = 0;
                SSP1BUF = tableau_donnee[compteur];
                compteur++;
            }
        }
    
        while(PIR1bits.SSP1IF == 0);
    
        CS1 = 1;
        PIR1bits.SSP1IF = 0;
    
    }
    
    /*********************************************************************
    * Fonction : void initialisation(void)
    *
    * Attends : rien
    *
    * But: Régler la fréquence du PIC, initialiser les broches en Entrée/Sortie, paramètre le timer
    *
    * Renvoie : rien
    *
    ********************************************************************/
    void initialisation(void)
    {
        //Configuration oscillateur
        OSCCONbits.IRCF = 0b110;    //110 = HFINTOSC/2 ? (8 MHz)
        OSCCONbits.SCS = 0b00;      //00 = Primary clock (determined by FOSC<3:0> in CONFIG1H).
        OSCCON2bits.MFIOSEL = 0;    //0 = MFINTOSC is not used
        OSCTUNEbits.PLLEN = 0;      //1 = PLL enabled
    
        //Configuration des ports en digital
        ANSELA = 0;                 //PORTA : Digital input buffer enabled
        ANSELB = 0;                 //PORTB : Digital input buffer enabled
        ANSELC = 0;                 //PORTC : Digital input buffer enabled
        ANSELD = 0;                 //PORTD : Digital input buffer enabled
        ANSELE = 0;                 //PORTE : Digital input buffer enabled
    }
    
    /*
      //LECTURE BUFFER
        CS1 = 0;
        compteur = 0;
        SSP1BUF = 0xD4;
    
        while(compteur<10)
        {
            if(PIR1bits.SSP1IF == 1 && compteur ==0)
            {
                PIR1bits.SSP1IF = 0;
                compteur++;
                SSP1BUF = 0;
            }
            if(PIR1bits.SSP1IF == 1 && compteur ==1)
            {
                PIR1bits.SSP1IF = 0;
                compteur++;
                SSP1BUF = 0;
            }
             if(PIR1bits.SSP1IF == 1 && compteur ==2)
            {
                PIR1bits.SSP1IF = 0;
                compteur++;
                SSP1BUF = 0;
            }
            if(PIR1bits.SSP1IF == 1 && compteur ==3)
            {
                PIR1bits.SSP1IF = 0;
                compteur++;
                SSP1BUF = 0;
            }
            if(PIR1bits.SSP1IF == 1 && compteur ==4)
            {
                PIR1bits.SSP1IF = 0;
                compteur++;
                SSP1BUF = 0;
            }
            //
            if(PIR1bits.SSP1IF == 1 && compteur ==5)
            {
                PIR1bits.SSP1IF = 0;
                byte1 = SSP1BUF;
                compteur++;
                SSP1BUF = 0;
            }
            if(PIR1bits.SSP1IF == 1 && compteur ==6)
            {
                PIR1bits.SSP1IF = 0;
                byte2 = SSP1BUF;
                compteur++;
                SSP1BUF = 0;
            }
            if(PIR1bits.SSP1IF == 1 && compteur ==7)
            {
                PIR1bits.SSP1IF = 0;
                byte3 = SSP1BUF;
                compteur++;
                SSP1BUF = 0;
            }
            if(PIR1bits.SSP1IF == 1 && compteur ==8)
            {
                PIR1bits.SSP1IF = 0;
                byte4 = SSP1BUF;
                compteur++;
                SSP1BUF = 0;
            }
            if(PIR1bits.SSP1IF == 1 && compteur ==9)
            {
                PIR1bits.SSP1IF = 0;
                byte5 = SSP1BUF;
                compteur++;
                SSP1BUF = 0;
            }
        }
        //FIN LECTURE BUFFER
     */
    Fichiers attachés Fichiers attachés

  11. #10
    invite2c518e41

    Re : pic16f ou 18f + mémoire externe!

    Merci Terriblement pour ton code. Je prendrais le temps de l'étudier et de le modifier convenablement pour mon application et pour le pic16f876.


    DAUDET78

    Si je comprends bien, on ne peut plus écrire dans la mémoire flash après les 100000 écritures environ? càd qu'il faut prévoir de changer cette mémoire régulièrement?
    Selon mon application, il y a une machine qui fonctionne. Lorsqu'elle tombe en panne, je récupère alors les données de la mémoire de la machine à l'aide de la carte à microcontrôleur, je les stocke dans la mémoire flash. Lorsque j'ai fini de tout récupérer, je lis dans la mémoire et j'envoies les données à un serveur. Mais puisque la machine ne tombe pas régulièrement en panne (disons 1 fois par mois à tout casser), je suppose que je n'aurai pas à beaucoup écrire. Ou bien je me trompe?

  12. #11
    invitee05a3fcc

    Re : pic16f ou 18f + mémoire externe!

    Citation Envoyé par petitete Voir le message
    je suppose que je n'aurai pas à beaucoup écrire. Ou bien je me trompe?
    C'est à toi de faire le calcul du nombre d'écriture à la même adresse .
    Pour éviter ce problème (ou du moins l'atténuer). On peut utiliser une écriture circulaire. Les nouvelles données sont écrites à la suite des anciennes et, quand c'est plein, on continu au début en écrasant les plus anciennes.
    Par exemple, j'ai une caméra sur ma voiture qui filme en permanence ma conduite. Sur une 4Gb, on stocke deux heures. Avec cette écriture circulaire, on a statistiquement une carde SD HS au bout de 2*100000H soit un peu plus de deux ans de fonctionnement permanent..... la voiture sera H.S. avant !

  13. #12
    Philou67

    Re : pic16f ou 18f + mémoire externe!

    Citation Envoyé par DAUDET78 Voir le message
    2*100000H soit un peu plus de deux ans de fonctionnement permanent..... la voiture sera H.S. avant !
    22 ans j'aurais dit
    :'( Plus j'apprends, et plus je mesure mon ignorance

  14. #13
    invitee05a3fcc

    Re : pic16f ou 18f + mémoire externe!

    Citation Envoyé par Philou67 Voir le message
    22 ans j'aurais dit
    Exact (j'ai fait une erreur de virgule !) .....Donc la voiture est encore plus HS avant !

  15. #14
    invite2c518e41

    Re : pic16f ou 18f + mémoire externe!

    Merci DAUDET78
    En supposant que l'équipement sur lequel sera branché mon application tombe en panne une fois par jour, j'en ai pour plus de 270 ans. Je crois donc que la mémoire flash me convient bien. J'adopterai alors l'écriture circulaire.

Discussions similaires

  1. mémoire externe d'un PIC
    Par invite403d8201 dans le forum Électronique
    Réponses: 11
    Dernier message: 14/11/2011, 12h21
  2. Ajout d'une mémoire externe a un pic18f
    Par grd666 dans le forum Électronique
    Réponses: 9
    Dernier message: 05/07/2009, 22h45
  3. memoire externe sur dsPIC
    Par invite64eb49fc dans le forum Électronique
    Réponses: 0
    Dernier message: 27/02/2008, 15h38
  4. Adapter une mémoire EEPROM externe à un PICBASIC 3B
    Par invitea88e6ae4 dans le forum Électronique
    Réponses: 1
    Dernier message: 28/12/2006, 10h20
  5. sous-programmes 68HC11F1 et mémoire externe
    Par invited6b3423a dans le forum Électronique
    Réponses: 3
    Dernier message: 26/12/2006, 16h41
Dans la rubrique Tech de Futura, découvrez nos comparatifs produits sur l'informatique et les technologies : imprimantes laser couleur, casques audio, chaises gamer...