Ich versuche, eine 32-GB-microSD-Karte über SPI-Kommunikation mit PIC32MX795F512L zu verbinden . Die SPI-Kommunikation funktioniert einwandfrei, da ich sie getestet habe, indem ich die Dateneingangs- und -ausgangsleitung kurzgeschlossen und die von mir gesendeten Daten zurückerhalten habe. Ich folge den Beispielen in Lucio de Jasios Buch Programming 32-bit Microcontrollers in C .
Folgende Aufgaben übernehme ich:
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)
Aber das Problem ist, dass ich keine R1
Antwort von der Karte erhalte, sondern die 0xFF
. Nachfolgend der Code:
#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);
}
Hier ist das Schema :
Ich erhalte keine R1
Antwort. Es bleibt bei step4 in hängen initSD()
.
Kann ich nach dem Senden von 80 Taktimpulsen feststellen, ob die Karte aufgewacht ist oder nicht? Nach 80 Taktimpulsen lautet die Antwort der Karte 0xFF
.
Muss ich die Taktfrequenz reduzieren? Derzeit sind es 250 kHz.
Warum wird die Karte nicht initialisiert? Wie kann ich es reparieren?
Ich sehe keinen Code, um den MISO-Pin zu einem Eingangs-Pin zu machen oder den SCK-Pin-Ausgang zu machen. Da Sie die SPI-Bibliothek in nicht verwenden plib
, müssen Sie die gesamte Pin-Initialisierung selbst durchführen. Erhöhen Sie außerdem nach dem Senden CMD0
die Anzahl der Iterationen (in Ihrer for
Schleife) von 8 auf 20 (ich verwende 100), um genügend Spielraum zu haben. Verwenden Sie stattdessen auch diesen Vergleich:
if ((r & 0x80) == 0)
break;
return r;
r
Machen Sie auch unsigned char
überall.
if ((r & 0x80) == 0)
. Können Sie ein bisschen erklären.uint8_t
wäre besser als unsigned char
.Sieht oberflächlich nach einem elektrischen Problem aus
Zu einem späteren Zeitpunkt müssen Sie möglicherweise Folgendes überprüfen - keine bestimmte Reihenfolge.
https://www.sdcard.org/downloads/pls/simplified_specs/archive/part1_110.pdf
Seite 47 sagt, dass Sie das Gerät abfragen müssen, bis die Karte bereit ist. Tun Sie das?
Check the 'endianness'
, kannst du es mir bitte kurz erklären
David
ChrisR
Benutzer3629249
Benutzer007
Benutzer3629249
SoreDakeNoKoto