Error al iniciar la tarjeta microSD en modo SPI

1

Estoy intentando conectar una tarjeta microSD de 32 GB con PIC32MX795F512L utilizando la comunicación SPI. La comunicación SPI está funcionando bien, ya que la he probado cortocircuitando la línea de Entrada y Salida de Datos y recuperando los datos que envié. Sigo los ejemplos proporcionados en el el libro de Lucio de Jasio, Programación de microcontroladores de 32 bits en C .

Las siguientes son las tareas que estoy realizando:

1. Initializing the SPI Communication in initSPI(), setting the baudrate=76 (250 kHz)
2. Initializing the SD card
   -> CS = 1
   -> Sending 80 clock cycles to wake the card
   -> CS = 0
   -> Sending CMD0 command (0x40, 0x00, 0x00, 0x00, 0x00, 0x95)

Pero el problema es que no estoy recibiendo la respuesta R1 de la tarjeta, en cambio estoy recibiendo el 0xFF . El siguiente es el código:

#define FCY 77000000UL
#define FPB (FCY/2)
#define BAUDRATE    9600
#pragma config POSCMOD=HS,FNOSC=PRIPLL
#pragma config FPLLIDIV=DIV_3, FPLLMUL=MUL_21, FPLLODIV=DIV_1
#pragma config FPBDIV=DIV_2, FWDTEN=OFF

#include <stdio.h>
#include <stdlib.h>
#include <plib.h>
#include <stdbool.h>

#define SDI  _RC4
#define SDCS _RA9
#define enableSD()    SDCS = 0
#define disableSD()   SDCS = 1
#define readSPI() writeSPI(0xFF)

int main(int argc, char** argv)
{
    TRISAbits.TRISA9 = 0;   // CS as output
    TRISCbits.TRISC4 = 1;   // SDI as input
    TRISDbits.TRISD0 = 0;   // SDO as output
    TRISDbits.TRISD10 = 0;  // SCK as output
    AD1PCFG = 0xFFFF;
    DDPCONbits.JTAGEN = 0;
    OpenUART1( UART_EN | UART_NO_PAR_8BIT | UART_1STOPBIT, UART_RX_ENABLE | UART_TX_ENABLE, (FPB/16/BAUDRATE)-1 );
    disableSD(); //CS PIN INITIALLY HIGH TO DISABLE CARD
    initSPI();
    initSD();

    while(1)
    {

    }
    return (EXIT_SUCCESS);
}

void initSPI( void)
{
    SPI1BRG = 76; // FPB/154=250KHZ; (76+1)*2 = 154, so brg = 76
    SPI1CONbits.MSTEN = 1; // MasterEnable
    SPI1CONbits.CKE = 1;   // CKE on
    SPI1CONbits.ON = 1;    // SPI Module ON
}

unsigned char writeSPI(unsigned int b)
{
    SPI1BUF=b; // Write to buffer for TX
    while( !SPI1STATbits.SPIRBF)
        ; // Wait transfer complete
    return(SPI1BUF);
}

int initSD(void)
{
    int i,r,rx;
    int data;

    // Step1: Disable SD card
    disableSD();

    // Step2: Send 80 clock cycles to wake up the card
    for(i=0; i<=9; i++)
    {
        data = writeSPI(0xFF);
    }

    // Step3: Enable SD card
    enableSD();

    // Step4: Send CMD0 command to RESET
    r = sendCMD0();
    disableSD();
    if(r!=1)
    {
        putsUART1("CMD reject\n");
    }
}

int sendCMD0()
{
    int i,r;
    enableSD();

    writeSPI(0x40);
    writeSPI(0x00);
    writeSPI(0x00);
    writeSPI(0x00);
    writeSPI(0x00);
    writeSPI(0x95); //CMD0 Command

    for( i=0; i<100; i++)
    {
        r = readSPI();
        if ((r & 0x80) == 0)
            break;
    }
    return ( r);
}

Aquí está el esquema :

No estoy recibiendo la respuesta R1 . Está atascado en el paso 4 en initSD() .

¿Hay alguna manera de saber si la tarjeta se ha despertado o no después de enviar 80 pulsos de reloj? Después de 80 pulsos de reloj, la respuesta de la tarjeta es 0xFF .

¿Necesito reducir la frecuencia del reloj? Actualmente es de 250 kHz.

¿Por qué la tarjeta no se está inicializando? ¿Cómo puedo solucionarlo?

    
pregunta user007

2 respuestas

1

No veo ningún código para hacer que el pin MISO sea un pin de entrada o para hacer la salida del pin SCK. Dado que no está utilizando la biblioteca SPI en plib , debe hacer usted mismo toda la inicialización del pin. Además, después de enviar CMD0 , aumente el número de iteraciones (en su bucle for ) de 8 a 20 (uso 100), para proporcionar suficiente margen de maniobra. También usa esta comparación en su lugar:

if ((r & 0x80) == 0) 
   break;
return r;

También crea r y unsigned char en todas partes.

    
respondido por el TisteAndii
1

Aparece en la superficie como un problema eléctrico

  • Intente una velocidad más lenta para comenzar; puede tener una capacidad excesiva en sus líneas o una tarjeta SD de baja velocidad.
  • ¿Está realizando una votación hasta que la tarjeta esté lista (ver más abajo)?
  • ¿Puede poner un alcance en él para verificar los tiempos, estos son críticos?
  • Pruebe una tarjeta SD diferente, o la misma tarjeta en un dispositivo que funcione
  • ¿Puede transmitir y recibir a un puerto diferente en el mismo dispositivo?
  • ¿Puede transmitir y recibir a una placa diferente utilizando el mismo dispositivo PIC?
  • ¿Está utilizando controladores de microchip / bibliotecas de software?
  • ¿Tienes MISO / MOSI correctamente conectado?
  • ¿Se cumplen los requisitos de alimentación: tapas de desacoplamiento, etc.? 10uF + // 100nF (algunas personas usan 100uF !!)
  • ¿Sus pines de salida y entrada están configurados correctamente?

En una etapa posterior, es posible que deba verificar lo siguiente, no un orden en particular.

  • Verifique la "endianidad" de su SPI
  • Revise su CRC
  • revisa tu protocolo

enlace

La página 47 dice que debes sondear el dispositivo hasta que la tarjeta esté lista. ¿Estás haciendo esto?

    
respondido por el ChrisR

Lea otras preguntas en las etiquetas