2011-08-11 07:58 AM
I'm trying to comunicate with SD card with STM32F100RB controller via SPI.
I am able to erase blocks on card, and to read them. The problem is about writing blocks to card. I am able to write something to card, and i can read it, but i cant get correct response after writing bytes to card. Maybe anyone can tell me what i am doing wrong?
My code:
void SPI_SD_Init(void)
{
GPIO_InitTypeDef gpio;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
gpio.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
gpio.GPIO_Speed = GPIO_Speed_50MHz;
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &gpio);
gpio.GPIO_Pin = GPIO_Pin_4;
gpio.GPIO_Speed = GPIO_Speed_50MHz;
gpio.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &gpio);
SPI_SetSpeed(SD_SPEED_400KHZ);
}
void SPI_SetSpeed(SD_Speed_TypeDef speed)
{
SPI_InitTypeDef spi;
int prescaler = SPI_BaudRatePrescaler_64;
if(speed == SD_SPEED_400KHZ){
prescaler = SPI_BaudRatePrescaler_64;
}
else if (speed == SD_SPEED_25MHZ){
prescaler = SPI_BaudRatePrescaler_2;
}
// 6 mhz / 187khz ; 100<x<400khz, and <25mhz
SPI_Cmd(SPI_SD, DISABLE);
spi.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
spi.SPI_Mode = SPI_Mode_Master;
spi.SPI_DataSize = SPI_DataSize_8b;
spi.SPI_CPOL = SPI_CPOL_Low;
spi.SPI_CPHA = SPI_CPHA_1Edge;
spi.SPI_NSS = SPI_NSS_Soft;
spi.SPI_BaudRatePrescaler = prescaler;
spi.SPI_FirstBit = SPI_FirstBit_MSB;
spi.SPI_CRCPolynomial = 7;
SPI_Init(SPI_SD, &spi);
SPI_Cmd(SPI_SD, ENABLE);
}
unsigned char SPI_WriteByte(unsigned char data)
{
u8 Data = 0;
/* Wait until the transmit buffer is empty */
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
/* Send the byte */
SPI_I2S_SendData(SPI1, data);
/* Wait until a data is received */
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
/* Get the received data */
Data = SPI_I2S_ReceiveData(SPI1);
/* Return the shifted data */
return Data;
}
u8 SD_Init(void)
{
u8 retry;
u8 response=0;
u8 i;
retry = 0x00;
SD_CS_LOW();
do
{
for(i = 0; i < 10; i++)
{
SPI_WriteByte(0xff);
}
response = SD_sendCommand(GO_IDLE_STATE, 0); //send idle command
printf(''Idle cmd - '');
printfResponse(response);
retry++;
if(retry > 100)
{
printf(''SD init fail...\n\r'');
return 1; //time out
}
} while(response != 0x01);
SD_CS_HIGH();
SPI_WriteByte(0xff);
SPI_WriteByte(0xff);
retry = 0;
do
{
response = SD_sendCommand(SEND_OP_COND, 0); //activate card's initialization process
response = SD_sendCommand(SEND_OP_COND, 0); //same command sent again for compatibility with some cards
retry++;
if(retry > 100)
{
printf(''SD init fail..\n\r'');
return 1; //time out
}
}
while(response);
response = SD_sendCommand(CRC_ON_OFF, OFF); //disable CRC; deafault - CRC disabled in SPI mode
response = SD_sendCommand(SET_BLOCK_LEN, 512); //
SPI_SetSpeed(SD_SPEED_25MHZ);
return 0; //normal return
}
u8 SD_writeSingleBlock(u32 startBlock, u8* buffer)
{
u8 response = 0x04;
u8 retry = 0;
int i;
SD_CS_LOW();
response = SD_sendCommand(WRITE_SINGLE_BLOCK, startBlock<<9); //write a Block command
if(response != 0x00) //check for SD status: 0x00 - OK (No flags set)
return response;
response = SPI_WriteByte(0xfe); //Send start block token 0xfe (0x11111110)
for(i=0; i<512; i++) //send 512 bytes data
{
SPI_WriteByte(buffer[i]);
}
printf(''512 Bytes transfered!!\r\n'');
SPI_WriteByte(0xFF); //transmit dummy CRC (16-bit), CRC is ignored here
SPI_WriteByte(0xFF);
response = SPI_WriteByte(0xFF);
printf(''%#04x \r\n'',response);
if( (response & 0x1f) != 0x05) //response= 0xXXX0AAA1 ; AAA='010' - data accepted
{ //AAA='101'-data rejected due to CRC error
SD_CS_HIGH(); //AAA='110'-data rejected due to write error
printf(''BAD RESPONSE!!\r\n'');
return response;
}
printf(''GOOD!!\r\n'');
while(!SPI_WriteByte(0xff)) //wait for SD card to complete writing and get idle
{
if(retry++ > 0xfffe)
{
SD_CS_HIGH();
return 1;
}
}
SD_CS_HIGH();
SPI_WriteByte(0xff);
SD_CS_LOW();
while(!SPI_WriteByte(0xff)) //wait for SD card to complete writing and get idle
if(retry++ > 0xfffe)
{
SD_CS_HIGH();
return 1;
}
SD_CS_HIGH();
return 0;
}
int main(void)
{
u8 buf[512];
// HW configuration
RCC_Configuration();
GPIO_Configuration();
NVIC_Configuration();
// Peripherials configuration
USART_Configuration();
BLUE_LED_ON();
SPI_SD_Init();
SD_Init();
buf[0] = 0x99;
buf[1] = 0x99;
SD_writeSingleBlock(0, buf);
while(1);
}