Lecture de carte SD par liaison SPI
Répondre à la discussion
Affichage des résultats 1 à 5 sur 5

Lecture de carte SD par liaison SPI



  1. #1
    invite24eebdfe

    Question Lecture de carte SD par liaison SPI


    ------

    Salut à tous,

    Voila mon problème : j'aimerais lire des données d'une carte SD à une adresse précise à l'aide d'un PIC16F876 et envoyer ces données sur l'USART mais je n'y arrive pas ! Le PIC ne lit pas les données. Pourtant, j'arrive à écrire sans problème !

    Voici un bout de mon code (fonction sensé lire sur la carte SD) :

    bit sendmmc()
    {
    char i;
    // read-mode
    if (Command(0x51,6,0,0xFF) !=0) {
    SerString("MMC: read error 1 ");
    return 1;
    }
    while(SPI(0xFF) != 0xFE); // Attend 0xFE (Démarrage d'une transmission)
    for(i=0; i < 63; i++)
    {
    TXREG = SPI(0xFF);
    // Envoie l'octet MMC via l'USART
    }
    serialterminate();
    SPI(0xFF); // at the end, send 2 dummy bytes
    SPI(0xFF);
    return 0;
    }




    -----

  2. #2
    invite24eebdfe

    Re : Lecture de carte SD par liaison SPI

    Personne ne peut m'aider ? je ne m'en sors vraiment pas et je n'ai plus d'idées.

  3. #3
    invite8f8ffe44

    Re : Lecture de carte SD par liaison SPI

    Salut!

    Je ne sais pas si cela pourra t'aider, je me suis mis récemment sur le bus SPI mais avec un PIC24HJ12GP202. Je n'ai encore jamais travaillé sur du 16F.

    En revanche, es-tu sûr d'envoyer les bonnes instructions sur ta carte SD? Car de mon côté, j'avais fait un test sur une EEPROM et il était important d'envoyer plusieurs instructions déffirentes, mais précises, les unes après les autres, avant de pouvoir recevoir la réponse attendue.
    Sinon, je ne sais pas si ton PIC fonctionne de la même façon, mais as-tu bien déclaré tes pins du bus SPI en entrée et sortie? As-tu bien configuré ton PIC en maitre?
    As-tu déclaré tes pins en numérique et non analogique?
    Mets-tu bien SSx/ à 0 lorsque tu communiques? Et continues tu à envoyer des infos bidons à la suite de ton premier message pour recevoir la réponse?

    Lorsque tu communique sur le bus SPI, tu émets en même temps que tu reçois. Et comme il s'agit d'une communication maitre/esclave (l'esclave ne parle pas tant que le maitre ne lui donne pas la parole), tu ne pourras pas avoir de réponse si tu ne lui parle pas en même temps. Par ailleurs, puisque les deux se parlent en même temps, si ton maitre envoit une question(instruction) à l'esclave, l'info que le maitre va récupérer immédiatement ne sera pas la réponse puisque l'esclave l'aura envoyé en même temps qu'il recevait la question. C'est seulement au coup d'après qu'il aura eu le temps de préparer une réponse et de l'envoyer au maitre lorsque celui-ci lui parlera de nouveau.

    A mon avis, tu dois être au courant de pas mal de chose dans ce que je t'ai dis, voir au courant de tout, mais si toutefois ce n'est pas le cas, j'espère que cela pourra t'aider. Je sais que c'est frustrant d'avoir un problème électronique et de ne pas trouver de réponse dans un forum pourtant fait pour ça!

    Cordialement,

    Crepuscule3

  4. #4
    invite24eebdfe

    Re : Lecture de carte SD par liaison SPI

    Merci pour ta réponse Crepuscule3. En effet, je connais tous ces éléments. J'ai quand meme vérifié tout ce que tu as dit et je semble avoir tout juste : malheureusement ça ne fonctionne pas. Je te file mon code, peux-tu me dire ce que tu en penses stp ?

    /* PIC MMC Interface */
    #include"INT16CXX.H"
    #pragma chip pic16F876 // Appel du header du pic

    #define CP_off |= 0x3F30
    #define LVP |= 128
    #pragma config CP_off,PWRTE=on,WDTE=off,FOSC= HS,BODEN=on,LVP

    #pragma bit CS @ PORTC.2 // Chip Select (MMC) : selection de la puce

    #pragma origin 4 // force interrupt service routine at address 4

    interrupt myInterrupt(void) // ISR
    {
    int_save_registers
    char rec;
    if (RCIF) // Interruption USART ?
    {
    while(!TXIF) { // wait for serial register to be sent,
    // if there is still something in there
    nop();
    }
    rec = RCREG; // Get the received character
    TXREG = rec; // write to serial register -> start transmission
    RCIF = 0; // clear USART int flag
    }
    int_restore_registers
    }

    void InitUSART()
    {
    PORTA = 0b.0000.0000;
    PORTB = 0b.0000.0000;
    PORTC = 0b.0000.0000;

    BRGH = 1; // Mode high speed
    SPBRG = 25; // Etablit 9600 bauds pour 4 MHz oscillator
    SYNC = 0; // Mode asynchrone
    SPEN = 1; // Set serial port enable
    TX9 = 0; // 8-bit transmissions
    TXEN = 1; // Permet la transmission
    RCIE = 1; // Active les interruptions Rx
    RX9 = 0; // 8-bit receptions
    CREN = 1; // Permet la réception
    }

    void initint() // initialisation des interruptions
    {
    GIE = 1; // Set Global Interrupt Enable
    PEIE = 1; // Set Peripheral Interrupt Enable
    }

    char SPI(char d) // Envoie un caractère sur le SPI
    {
    SSPBUF = d; // Envoie du caractère
    // Synchronous Serial Port Receive Buffer/Transmit Register
    while (!BF); // Attendre jusque envoi accompli
    // BF=1 : octet reçu ; BF=0 : buffer vide
    // BF=1 indique que le buffer de réception (SSPBUF)
    // contient un octet complet reçu via SDI.
    return SSPBUF; // Retourne le caractère reçu
    }

    char Command(char befF,uns16 AdrH,uns16 AdrL,char befH )
    { // Envoie une commande à la carte SD
    char a;
    SPI(0xFF);
    SPI(befF);
    SPI(AdrH.high8);
    SPI(AdrH.low8);
    SPI(AdrL.high8);
    SPI(AdrL.low8);
    SPI(befH);
    SPI(0xFF);
    return SPI(0xFF); // Retourne le dernier caractère reçu
    }

    bit MMC_Init() // initialisation SPI
    {
    /* ****************************** ****************************** ******* */
    /* ****** LES REGISTRES SSPSTAT ET SSPCON COMMANDENT LE MODE SPI ***** */
    /* ****************************** ****************************** ******* */
    // ********** Configuration du registre SSPSTAT en mode maître *********
    SMP = 0; // input is valid in the middle of clock
    // Capture du bit présent sur SDI au milieu de l'horloge
    CKE = 0; // rising edge is data capture
    // CKE détermine quel sens de transistion de l'horloge
    // accompagne le placement du bit sur la ligne SDO
    // ********** Configuration du registre SSPCON en mode SPI master ******
    CKP = 1; // donne le niveau de l'état de repos.
    // détermine la polarité du signal d'horloge
    SSPM1 = 1; // speed f/64(312kHz), Master
    SSPEN = 1; // Mise en service du module SSP
    // ****************************** ****************************** *********
    CS = 1; // CS : Chip Select. disable MMC


    char i;
    // Démarre la MMC en mode SPI
    // Power ON (Insersion)
    // After supply voltage reached 2.2 volts,
    // wait for a millisecond at least,
    // set DI and CS high and apply more than 74 pulses to SCLK
    // and the card will able to accept a native command.


    for(i=0; i < 10; i++)SPI(0xFF); // Envoie 10*8=80 coups d'horloge
    CS=0; // MMC en place

    if (Command(0x40,0,0,0x95) !=1) goto mmcerror; // Remise à zéro de la MMC

    st: // si il n'y a pas de carte SD, le programme fait une boucle
    if (Command(0x41,0,0,0xFF) !=0) goto st;

    return 1;
    mmcerror:
    return 0;
    }

    void serialterminate() { // terminate sent string!!!
    while(!TXIF);
    TXREG = 0x0d;
    while(!TXIF);
    TXREG = 0x0a;
    }

    // Envoie des chaines de caractères vers l'ordinateur
    void SerString(const char *str)
    {
    char ps;
    ps = *str; // pointer of start of string into ps
    while(ps>0) // Teste si la fin de la chaine est atteinte
    {
    str++; // Mettre le pointeur au caractère suivant
    if (ps== 0) break; // Teste si la fin de la chaine est atteinte
    while(!TXIF); // Teste si le registre TXREG est vide
    TXREG = ps ; // Envoie le caractère
    ps = *str; // content of pointer into ps
    }
    serialterminate();
    }


    bit sendmmc() // Envoie 512 octets de la MMC
    {
    uns16 i;
    // 512 byte-read-mode
    if (Command(0x51,6,512,0xFF) !=0) {
    SerString("MMC: read error 1 ");
    return 1;
    }
    while(SPI(0xFF) != 0xFE); // Attend 0xFE (Démarrage d'une transmission)
    for(i=0; i < 512; i++)
    {
    while(!TXIF);
    TXREG = SPI(0xFF);
    // Envoie l'octet MMC
    }
    serialterminate();
    SPI(0xFF); // at the end, send 2 dummy bytes
    SPI(0xFF);
    return 0;
    }

    void main(void)
    {
    char i;
    InitUSART(); // initialisation port série
    initint(); // initialize interrupts

    ADCON1=0x6; // PortA Digital
    // Entrées PORTA numériques

    // Configuration des PORTS E/S
    TRISC = 0b.1101.0011; // sck rc3-0, sdo rc5-0, CS rc2-0.
    /* SCK (RC3) est la pin d’horloge, donc définie en sortie sur notre
    SDI (RC4) es l’entrée des données, donc définie en entrée
    SDO (RC5) est la sortie des données. */

    TRISB = 0b.0000.0010; // RB2>TX, RB1>RX

    SerString("PPPPPPPP"); // start message
    // SerString(0x00); // start message

    // Initialise la MMC et envoie le message si ok
    MMC_Init();
    if (MMC_Init()) SerString("AAAAAAAA");
    CS = 0;
    sendmmc(); // Envoie 512 octets de la MMC via le port série

    while(1){
    }
    }

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

    Re : Lecture de carte SD par liaison SPI

    A chaud comme ça, en un petit coup d'oeil, il y a deux choses qui me viennent à l'esprit. Ca m'étonnerait que ça soit ça, mais l'erreur est toujours là où on ne l'attend pas.

    A la ligne:
    for(i=0; i < 10; i++)SPI(0xFF); // Envoie 10*8=80 coups d'horloge
    tu dis que tu envois 80 coups d'horloge. Or de i = 0 à i = 10, tu envois à chaque fois 0xFF, soit que des 1 : 1111 1111. Donc si je ne me trompe pas (car j'utilise le compilateur C30 dont la syntaxe ne ressemble pas trop à la tienne), tu n'envois pas d'horloge mais juste un état haut.
    Par ailleurs, dans mon cas, j'avais déclaré CS comme pin de sortie par défaut. Je ne laissais pas le bus SPI la contrôler. L'as tu bien déclaré en sortie?

    Pour finir, vérifie s'il n'y aurait pas des résistances de pull-up qui t'empêcheraient de recevoir les données. On ne sait jamais, c'est le truc con, mais qui arrive parfois.

    Comme ça, à chaud, c'est tout ce qui me vient pour l'instant.

    Crepuscule3

Discussions similaires

  1. Lecture sur le port spi
    Par invite91a05f0b dans le forum Électronique
    Réponses: 6
    Dernier message: 08/04/2009, 22h33
  2. PIC 16F87X et liaison SPI
    Par chrisric dans le forum Électronique
    Réponses: 2
    Dernier message: 06/03/2008, 20h18
  3. liaison SPI et bus I2C
    Par invite5a645688 dans le forum Électronique
    Réponses: 1
    Dernier message: 27/02/2008, 13h55
  4. Problème lecture signal SPI
    Par invite58fd6b21 dans le forum Électronique
    Réponses: 5
    Dernier message: 16/08/2007, 14h44
Dans la rubrique Tech de Futura, découvrez nos comparatifs produits sur l'informatique et les technologies : imprimantes laser couleur, casques audio, chaises gamer...