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:.
#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_ */
#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
}
// 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
}
#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_ */