ADVERTISEMENT

SSP + SD card [18.06.2012 13.27].zip

Karta SD - suma kontrolna i odpowiedź R1 na komendę CMD0

Spróbuj linię: temp = sspWrite (0xFF); umieścić w pętli która wykonuje się przez jakiś czas lub określoną ilość razy, warunkiem opuszczenia pętli będzie koniec czasu (timeout) lub wartość temp inna niż 0xFF. W sdInitialize() linie: R1 = sdCommand (0, 0); // Send command CMD0; tell the card to reset and enter its idle state R1 = sdCommand (1, 0); // Send command CMD1; nie umieszczaj w pętli. CRC dla CMD1 chyba będzie już 0XFF. Mundi1970 i tak też zrobiłem. Dopisałem także prostą funkcję, która sprawdza jaką wartość ma bajt odczytany z linii SPIi. W zależności od tego czy bajt ten jest równy oczekiwanej wartości czy różny od oczekiwanej wartości, to mruga diodą LED - raz lub dwa razy. W załączniku przesyłam pliki źródłowe. Zmieniłem funkcję wysyłania komendy tak, aby można było ręcznie wpisywać wartość sumy kontrolnej CRC inną dla każdej komendy (po prostu są trzy argumenty zamiast dwóch). Niestety o ile po komendzie 0 (CMD0) otrzymuję wartość 0x01 (mrugnięcie diodą LED dwa razy), to po komendzie 1 (CMD1) już nie otrzymuję z powrotem wartości 0x00... :cry:.


Download file - link to post
  • SSP + SD card [18.06.2012 13.27].zip
    • sd.h
    • sd.c
    • ssp.c
    • ssp.h


SSP + SD card [18.06.2012 13.27].zip > sd.h

#ifndef SD_H_
#define SD_H_

uint32_t sdCommand (uint8_t CommandNumber, uint32_t CommandArgument, uint8_t CRC);
void sdInitialize (void);
uint8_t CheckErrorsR1 (uint8_t R1Response);

#endif /* SD_H_ */


SSP + SD card [18.06.2012 13.27].zip > sd.c

#include " lpc17xx.h "
#include " ssp.h "

// Function for check the returned value from the previous function
void CheckCondition_LED (uint8_t Condition, uint8_t Value)
{
uint32_t i = 0; // iteration variable
uint32_t delay = 700000;

if (Condition == Value)
{
LPC_GPIO0- & gt; FIOSET |= (1 & lt; & lt; 22);
for (i=0; i & lt; delay; i++) // loop of 1 ms delay
{
__ASM volatile ( " nop " );
}
LPC_GPIO0- & gt; FIOCLR|= (1 & lt; & lt; 22);
for (i=0; i & lt; delay; i++) // loop of 1 ms delay
{
__ASM volatile ( " nop " );
}
LPC_GPIO0- & gt; FIOSET |= (1 & lt; & lt; 22);
for (i=0; i & lt; delay; i++) // loop of 1 ms delay
{
__ASM volatile ( " nop " );
}
LPC_GPIO0- & gt; FIOCLR |= (1 & lt; & lt; 22);
for (i=0; i & lt; delay; i++) // loop of 1 ms delay
{
__ASM volatile ( " nop " );
}
}
else if (Condition != Value)
{
LPC_GPIO0- & gt; FIOSET |= (1 & lt; & lt; 22);
for (i=0; i & lt; delay; i++) // loop of 1 ms delay
{
__ASM volatile ( " nop " );
}
LPC_GPIO0- & gt; FIOCLR |= (1 & lt; & lt; 22);
for (i=0; i & lt; delay; i++) // loop of 1 ms delay
{
__ASM volatile ( " nop " );
}
}
}

// Function for send a command to the SD card in the SPI mode
// It can return 8- (R1 type),16- (R2 tpye) or 24-bits (R3 type) of the response from the SD card
uint32_t sdCommand (uint8_t CommandNumber, uint32_t CommandArgument, uint8_t CRC)
{
uint32_t temp = 0;

// Send the command frame into the SPI bus
sspWrite (CommandNumber|0x40); // First byte of the Frame with start bits ( " 01 " )
sspWrite ((CommandArgument & gt; & gt; 24) & 0xFF); // Second goes MSB 1 byte of the command into the SPI/SSP bus
sspWrite ((CommandArgument & gt; & gt; 16) & 0xFF); // Third goes ...
sspWrite ((CommandArgument & gt; & gt; 8) & 0xFF); // Fourth goes ...
sspWrite ((CommandArgument ) & 0xFF); // Fifth goes LSB 1 byte of the command into the SPI/SSP bus
sspWrite (CRC); // Sixth/last byte of the command frame with end bit set to the " 1 " , constant value 0x95 as the CRC

do {
temp = sspWrite (0xFF); // Few dummy bytes for generate 8-16 clocks signal until the SD card will response
} while (temp == 0xFF); // Send dummy bytes till the response is equal 0xFF

return temp;
}

// Function for the SD card initialization
void sdInitialize (void)
{
uint8_t R1 = 0; // response R1 type (It has only 1 byte length)
uint8_t i = 0; // iteration variable

sspInit (); // initialize the SSP interface in the low speed mode at 400 kHz as a default mode at the beginning

ssHi (); // set the !SS SSP line into the low logical level (high phisical level)
// Generate 16 clock cycles of the delay
for (i=0; i & lt; 2; i++)
{
sspWrite (0xFF);
}

ssLo (); // set the !SS SSP line into the high logical level (low phisical level)

// Generate 80 clock cycles
for (i=0; i & lt; 10; i++)
{
sspWrite (0xFF);
}

// Go into the SSP mode when !SS line is in the low level during the command 0
R1 = sdCommand (0, 0, 0x95); // Send command CMD0; tell the card to reset and enter its idle state
// Check if the response R1 at command 0 CMD0 is valid - 0x01 - bit 1 means In Idle State

for (i=0; i & lt; 2; i++)
{
sspWrite (0xFF);
}

// Send command 1 CMD1
R1 = sdCommand (1, 0, 0xFF); // Send command CMD1;
// Check if the response R1 at command 1 CMD1 is valid - 0x00 - bit 1 means no In Idle State

CheckCondition_LED (R1, 0x00);

// further part for the SD card initialization
// ... here come code with further initialization algorithm
// ... here come code with further initialization algorithm
// ... here come code with further initialization algorithm
}


SSP + SD card [18.06.2012 13.27].zip > ssp.c

// Serial Peripheral Interface initialization
// SSP frame format

#include " lpc17xx.h "

// negative Slave Select (!SS) to the low level
void ssLo (void)
{
LPC_GPIO0- & gt; FIOPIN & =~(1 & lt; & lt; 16); // GPIO pin P0.16 as a Slave Select (SS) pin is in the low level
}

// negative Slave Select (!SS) to the high level
void ssHi (void)
{
LPC_GPIO0- & gt; FIOPIN |= (1 & lt; & lt; 16); // GPIO pin P0.16 as a Slave Select (SS) pin is in the high level
}

// SSP initialization for working with the SD card (Secure Digital)
void sspInit (void)
{
// SSP pins settings
LPC_SC- & gt; PCONP |= (1 & lt; & lt; 21); // PCSSP0 The SSP0 interface power/clock control bit

LPC_SC- & gt; PCLKSEL1 |= (1 & lt; & lt; 10); // SSP_PCLK = CCLK (PCLK = Peripheral Clock; CCLK = Core Clock)
LPC_SC- & gt; PCLKSEL1 & =~(1 & lt; & lt; 11); // SSP_PCLK = CCLK (PCLK = Peripheral Clock; CCLK = Core Clock)

LPC_PINCON- & gt; PINSEL0 & =~(1 & lt; & lt; 30); // pin P0.15 as the SCK0 line (SSP Clock) pin in the SSP mode
LPC_PINCON- & gt; PINSEL0 |= (1 & lt; & lt; 31); // pin P0.15 as the SCK0 line (SSP Clock) pin in the SSP mode
LPC_GPIO0- & gt; FIODIR |= (1 & lt; & lt; 16); // pin P0.16 as the output GPIO
LPC_PINCON- & gt; PINSEL1 & =~(1 & lt; & lt; 0 )|(1 & lt; & lt; 1 ); // pin P0.16 as the GPIO, manual !SS line (negative Slave Select)
LPC_PINCON- & gt; PINSEL1 & =~(1 & lt; & lt; 2); // pin P0.17 as the MISO0 line (Master Input Slave Output)
LPC_PINCON- & gt; PINSEL1 |= (1 & lt; & lt; 3); // pin P0.17 as the MISO0 line (Master Input Slave Output)
LPC_PINCON- & gt; PINSEL1 & =~(1 & lt; & lt; 4); // pin P0.18 as the MOSI0 line (Master Output Slave Input) of the SSP
LPC_PINCON- & gt; PINSEL1 |= (1 & lt; & lt; 5); // pin P0.18 as the MOSI0 line (Master Output Slave Input) of the SSP

ssHi(); // pin P0.16 - Slave Select on the high level

// Set the Control Register 0
LPC_SSP0- & gt; CR0 |= (1 & lt; & lt; 2)|(1 & lt; & lt; 1)|(1 & lt; & lt; 0); // Data Size Select; 8-bit transfer
LPC_SSP0- & gt; CR0 & =~(1 & lt; & lt; 3); // Data Size Select; 8-bit transfer
LPC_SSP0- & gt; CR0 & =~(1 & lt; & lt; 5)|(1 & lt; & lt; 4); // Frame Format; SPI
LPC_SSP0- & gt; CR0 & =~(1 & lt; & lt; 6); // Clock Out Polarity; SSP controller maintains the bus clock low between frames
LPC_SSP0- & gt; CR0 & =~(1 & lt; & lt; 7); // Clock Out Phase; SSP controller captures serial data on the first clock transition of
// the frame, that is, the transition away from the inter-frame state of the clock line
LPC_SSP0- & gt; CR0 |= (0x7C & lt; & lt; 8); // Serial Clock Rate; frequency is PCLK / (CPSDVSR × [SCR+1]); 400 kHz

// Set the Control Register 1
LPC_SSP0- & gt; CR1 & =~(1 & lt; & lt; 0); // Loop Back Mode; During normal operation
LPC_SSP0- & gt; CR1 & =~(1 & lt; & lt; 2); // Master/Slave Mode; The SSP controller acts as a master on the bus, driving the
// SCLK, MOSI, and SSEL lines and receiving the MISO line

LPC_SSP0- & gt; CPSR = 2; // Clock Prescale Register; This even value between 2 and 254, by which SSP_PCLK is divided
// to yield the prescaler output clock

LPC_SSP0- & gt; CR1 |= (1 & lt; & lt; 1); // SSP Enable; The SSP controller will interact with other devices on the serial bus
}

// Write some data to the SSP0 bus
uint8_t sspWrite (uint8_t data)
{
uint8_t temp = 0; // temporary variable

LPC_SSP0- & gt; DR = data; // DR - Data Register
while((LPC_SSP0- & gt; SR & (1 & lt; & lt; 2)) == 0); // wait until byte is received
temp = LPC_SSP0- & gt; DR;
return temp;
}

// Go the SSP0 to the low speed mode (400 kHz)
void sspLoSpeed (void)
{
LPC_SSP0- & gt; CR1 & =~(1 & lt; & lt; 1); // SSP Enable; The SSP controller will interact with not other devices on the serial bus
LPC_SSP0- & gt; CR0 |= (124 & lt; & lt; 8); // Serial Clock Rate; frequency is PCLK / (CPSDVSR × [SCR+1]); 400 kHz
LPC_SSP0- & gt; CR1 |= (1 & lt; & lt; 1); // SSP Enable; The SSP controller will interact withother devices on the serial bus
}

// Go the SSP0 to the high speed mode (25 MHz)
void sspHiSpeed ()
{
LPC_SSP0- & gt; CR1 & =~(1 & lt; & lt; 1); // SSP Enable; The SSP controller will interact with not other devices on the serial bus
LPC_SSP0- & gt; CR0 |= (1 & lt; & lt; 8); // Serial Clock Rate; frequency is PCLK / (CPSDVSR × [SCR+1]); 25 MHz
LPC_SSP0- & gt; CR1 |= (1 & lt; & lt; 1); // SSP Enable; The SSP controller will interact withother devices on the serial bus
}


SSP + SD card [18.06.2012 13.27].zip > ssp.h

#include " lpc17xx.h "

#ifndef SSP_H_
#define SSP_H_

void ssLo (void);
void ssHi (void);
void sspInit (void);
uint8_t sspWrite (uint8_t data);
void sspSpeed (void);
void sspHiSpeed (void);

#endif /* SSP_H_ */