
6.6.2018
Karta komunikuje prostřednictvím SPI. Na obrázku níže je vidět připojení slotu karty - 7 vodičů zleva doprava jsou postupně: ChipSelect (CS), DataIn (DI), Zem, Napájení 3.3 V, SerialCLocK (SCLK), Zem, DataOut (DO).

Kartu mám propojenou s MCU PIC18F24J50, který pracuje na 8 MHz.

Inicializujeme nastavení SPI:
//remappable pins settings
EECON2=0x55;
EECON2=0xAA;
PPSCONbits.IOLOCK=0;
RPINR21=0b00000110; //SDI2 -> RP6 (RB3)
RPINR22=0b00000101; //SCK2in -> RP5 (RB2)
RPOR4=0b00001001; //SDO2 -> RP4 (RB1) (function number 9)
RPOR5=0b00001010; //SCK2out -> RP5 (RB2) (function number 10)
EECON2=0x55;
EECON2=0xAA;
PPSCONbits.IOLOCK=1;
//SPI settings (module 2)
TRISBbits.TRISB1=0;
TRISBbits.TRISB2=0;
TRISBbits.TRISB3=1;
SSP2STATbits.SMP=1;
SSP2STATbits.CKE=0;
SSP2CON1bits.CKP=1;
SSP2CON1bits.SSPM=0b0010;
SSP2CON1bits.SSPEN=1;
Funkce pro čtení a zápis SPI:
BYTE status;
void spiWriteSD(BYTE data)
{
SSP2BUF=data;
while (!SSP2STATbits.BF)
;
status=SSP2BUF;
}
BYTE spiReadSD(void)
{
spiWriteSD(0xFF);
return(status);
}
Informativní data budeme odesílat po seriové lince. Nastavíme příslušné registry:
//UART1 settings
TRISCbits.TRISC6=0;
SPBRG1=12; //12.02 -> 38400
TXSTA1bits.BRGH=0;
BAUDCON1bits.BRG16=1;
TXSTA1bits.SYNC=0;
RCSTA1bits.SPEN=1;
TXSTA1bits.TX9=0;
TXSTA1bits.TXEN=1;
Funkce pro odeslání textu:
void sendSerialString(char *s)
{
while ((*s)!='\0')
{
TXREG1=*(s++);
while (!TRMT1)
;
}
}
Komunikaci s kartou lze rozdělit do několika částí. První je inicializace, kdy se karta jednak uvede do režimu, kdy bude komunikovat prostřednictvím SPI, a dále se pomocí příkazů zjistí jakého je karta typu (případně je možné vyčíst další informace o kartě z jejích vnitřních registrů). Následně je možné pomocí příkazů z karty data číst nebo na ní data zapisovat.
Příkaz pro manipulaci s kartou je tvořen šesti byty. První byte je číslo příkazu, další 4 byty představují argument předávaný kartě (například adresa v paměti) a poslední byte je CRC (Cyclic Redundancy Check).
Funkce pro odeslání příkazu kartě prostřednictvím SPI:
BYTE status;
BYTE sendCommandSD(BYTE cmd,unsigned long arg)
{
spiWriteSD(0xFF);
spiWriteSD(cmd|0x40);
spiWriteSD((BYTE) (arg››24));
spiWriteSD((BYTE) (arg››16));
spiWriteSD((BYTE) (arg››8));
spiWriteSD((BYTE) arg);
BYTE crc=0xFF;
switch (cmd)
{
case CMD0:crc=0x95;break;
case CMD8:crc=0x87;break;
}
spiWriteSD(crc);
while ((status=spiReadSD()) & 0x80)
;
return status;
}
Ve funkci se nejprve odešle tzv. dummy byte. Následně se odešle číslo příkazu, přičemž je třeba zajistit, aby nejvyšší bit byl nula a druhý nejvyšší bit jednička. Dále se postupně odešlou 4 byty argumentu - nejvýznamnější byte jako první. Nakonec se odesílá byte s CRC. Ten se odesílá vždy, ale pouze na začátku inicializace je třeba, aby byl platný. Následně již karta CRC nekontroluje, pokud ji "výslovně neřekneme", aby tak činila, tudíž je možné zasílat libovolnou hodnotu. V ukázce jsou pevně stanoveny hodnoty CRC pro příkazy 0 a 8, v ostatních případech se odesílá 0xFF.
Po odeslání posledního bytu příkazu se čeká, až karta odešle odpověď ve formě jednoho bytu, který má nejvyšší bit nulový. Další bity v odpovědi indikují jednak různé chybové stavy nebo stav, kdy je karta připravena pro další příkazy. Funkce nakonec vrátí tento stavový byte.
Funkce sendACommandSD kartě nejprve odešle příkaz číslo 55 s nulovým argumentem a hned v zápětí požadovaný příkaz.
BYTE sendACommandSD(BYTE cmd,unsigned long arg)
{
sendCommandSD(CMD55,0);
return(sendCommandSD(cmd,arg));
}