Estoy tratando de conectar una tarjeta microSD de 32 GB con PIC32MX795F512L mediante comunicación SPI. La comunicación SPI funciona bien, ya que la probé cortando la línea de entrada y salida de datos y recibiendo los datos que envié. Estoy siguiendo los ejemplos proporcionados en 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 recibo la R1
respuesta de la tarjeta, sino que recibo 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 R1
respuesta. 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 inicializa? ¿Cómo puedo arreglarlo?
No veo ningún código para hacer que el pin MISO sea un pin de entrada o para hacer que el pin SCK salga. Como no está utilizando la biblioteca SPI en plib
, debe realizar toda la inicialización del pin usted mismo. Además, después de enviar CMD0
, aumente el número de iteraciones (en su for
ciclo) de 8 a 20 (yo uso 100), para proporcionar suficiente margen de maniobra. También use esta comparación en su lugar:
if ((r & 0x80) == 0)
break;
return r;
También haz r
un unsigned char
por todas partes.
if ((r & 0x80) == 0)
. ¿Puedes explicar un poco?uint8_t
sería mejor que unsigned char
.Se ve en la superficie como un problema eléctrico
En una etapa posterior, es posible que deba verificar lo siguiente: ningún orden en particular.
https://www.sdcard.org/downloads/pls/simplified_specs/archive/part1_110.pdf
La página 47 dice que necesita sondear el dispositivo hasta que la tarjeta esté lista. ¿Está haciendo esto?
Check the 'endianness'
puedes explicar un poco
David
CrisR
usuario3629249
usuario007
usuario3629249
SoreDakeNoKoto