📄 sd_cmd.c
字号:
uint8 resp;
int16 n;
sd_addr <<= 9;
if(blk_size == 0)
return((int8) EOF);
clear_sd_buff();
resp = 0xFF;
clear_sd_buff();
resp = 0xFF;
_SD_send_cmd(CMD25, sd_addr); /* Send Write Multi-Block Command */
for(n = 0; ((n < 30000) && (resp == 0xFF)); n++)
resp = _FF_spi(0xFF);
if(resp == 0)
{
#ifdef _DEBUG_MULTI_BLOCK_
_FF_printf(_FF_StartBlockWriteStr);
_BLOCK_ADDRESS_ = sd_addr;
#endif
SDBlockWriteBlockCnt = 0;
return(0);
}
SD_CS_OFF();
_FF_spi(0xFF);
#ifdef _DEBUG_MULTI_BLOCK_
_FF_printf(_FF_StartMultiErrStr, 4, resp);
#endif
return((uint8) EOF);
}
/****************************************************************************
**
** Function used to write 1 byte when block writing to the SD/MMC media.
**
** Parameters: sd_data, byte to write in block mode
**
** Returns: 0 - Byte written successfully
** -1 - An error occurred
**
****************************************************************************/
int8 SD_write_block_byte(uint8 sd_data)
{
uint8 resp, calc;
int16 n, i;
#ifdef _DEBUG_MULTIBLOCK_BYTE_
_FF_putchar(sd_data);
#endif
i = SDBlockWriteBlockCnt % 512;
if(i == 0)
{
_FF_spi(0xFF);
_FF_spi(SD_MULTI_START); /* Start Block Token */
#ifdef _DEBUG_MULTI_BLOCK_
_FF_printf(_FF_MultiWriteStr, _BLOCK_ADDRESS_);
_BLOCK_ADDRESS_ += 0x200;
#endif
}
_FF_spi(sd_data); /* Send the data */
SDBlockWriteBlockCnt++;
i++;
if(i == 512)
{
_FF_spi(0xFF); /* Send 2 blank CRC bytes */
_FF_spi(0xFF);
resp = _FF_spi(0xFF); /* Response should be 0bXXX00101 */
calc = resp | 0xE0;
if(calc == 0xE5)
{
n = 0;
do
{
/* Wait for not busy */
resp = _FF_spi(0xFF);
if(n++ > 30000)
resp = 0xFF; /* Response not received for too long, ignore*/
} while(resp == 0);
}
else
{
#ifdef _DEBUG_MULTI_BLOCK_
_FF_printf(_FF_Multi02Str, resp);
#endif
SD_CS_OFF();
_FF_spi(0xFF);
return((int8) EOF);
}
}
return(0);
}
/****************************************************************************
**
** Function called when block writing to the SD/MMC media is done
**
** Parameters: None
**
** Returns: 0 - Block ended successfully
** -1 - An error occurred
**
****************************************************************************/
int8 SD_write_block_end(void)
{
uint8 resp, calc;
int16 n, i;
i = SDBlockWriteBlockCnt % 512;
if(i)
{
while(i++ < 512)
_FF_spi(0xFF); /* Pad the rest of the block */
_FF_spi(0xFF); /* Send 2 blank CRC bytes */
_FF_spi(0xFF);
resp = _FF_spi(0xFF); /* Response should be 0bXXX00101 */
calc = resp | 0xE0;
if(calc == 0xE5)
{
n = 0;
do
{
/* Wait for not busy */
resp = _FF_spi(0xFF);
if(n++ > 30000)
{
#ifdef _DEBUG_MULTI_BLOCK_
_FF_printf(_FF_MultiEndStr, 1);
#endif
resp = 0xFF; /* Response not received for too long, ignore*/
}
} while(resp == 0);
}
else
{
SD_CS_OFF();
_FF_spi(0xFF);
#ifdef _DEBUG_MULTI_BLOCK_
_FF_printf(_FF_MultiEndStr, 2);
#endif
return((int8) EOF);
}
}
_FF_spi(0xFF);
_FF_spi(SD_STOP_TRANS); /* Stop Block Token */
n = 0;
do
{
/* Wait for not busy */
resp = _FF_spi(0xFF);
if(n++ > 30000)
resp = 0xFF; /* Response not received for too long, ignore*/
} while(resp == 0);
SD_CS_OFF();
_FF_spi(0xFF);
return(0);
}
#endif /*defined(_SD_BLOCK_WRITE_) && !defined(_READ_ONLY_)*/
/*****************************************************************************
**
** LOCAL FUNCTIONS
**
*****************************************************************************/
/****************************************************************************
**
** Initializes the SPI bus in the correct mode to use with the SD/MMC media.
**
** Parameters: None
**
** Returns: None
**
****************************************************************************/
void _FF_spi_init(void)
{
/* SPI BUS SETUP */
/* SPI initialization */
/* SPI Type: Master */
/* SPI Clock Rate: 921.600 kHz */
/* SPI Clock Phase: Cycle Half */
/* SPI Clock Polarity: Low */
/* SPI Data Order: MSB First */
#ifdef _MEGAAVRDEV_
DDRB = 0xB0 | DEMO_LED;
#else
DDRB |= 0x07; /* Set SS, SCK, and MOSI to Output (If not output, processor will be a slave) */
DDRB &= 0xF7; /* Set MISO to Input */
#endif
CS_DDR_SET(); /* Set CS to Output */
SPSR = 0x01;
SPCR = _FF_SPCR_SET; /* Initialize the SPI bus as a master */
}
/****************************************************************************
**
** Initializes all timers in the system. This call must be made before any
** time-dependent functions can be called. The application should not enable
** interrupts before TimeInit is called.
**
** Parameters: command, the command to send to the card
** argument, any data needed associated with the command
**
** Returns: None
**
****************************************************************************/
void _SD_send_cmd(uint8 command, uint32 argument)
{
HiLo32Union arg_temp;
SD_CS_ON(); /* select SD Card */
/* send the command */
_FF_spi(command);
arg_temp.uval32 = argument;
_FF_spi(arg_temp.uval8.hi);
_FF_spi(arg_temp.uval8.mh);
_FF_spi(arg_temp.uval8.ml);
_FF_spi(arg_temp.uval8.lo);
/* Send the CRC byte */
if(command == CMD0)
_FF_spi(0x95); /* CRC byte, don't care except for CMD0 = 0x95 */
else
_FF_spi(0xFF);
return;
}
/****************************************************************************
**
** Clears the SD/MMC's SPI bus so commands can be sent cleanly.
**
** Parameters: None
**
** Returns: None
**
****************************************************************************/
void clear_sd_buff(void)
{
int8 n;
SD_CS_OFF();
for(n = 0; n < 10; n++)
_FF_spi(0xFF);
}
/****************************************************************************
**
** Sends the "RESET" command to the SD/MMC media, the first command that has
** to be sent to the card when initally powered.
**
** Parameters: None
**
** Returns: 0 - Reset command successful
** -1 - Failed to reset the card
**
****************************************************************************/
int8 reset_sd(void)
{
int8 resp, c;
int16 n;
//**********************************************************************
#ifdef _DEBUG_INIT_SD_
_FF_printf(_FF_ResetCMDStr);
#endif
//**********************************************************************
for(c = 0; c < 10; c++) /* try reset command 3 times if needed */
{
clear_sd_buff(); /*dummy SPI */
_SD_send_cmd(CMD0, 0); /* idle COMMAND */
for(n = 0; n < 1000; n++)
{
resp = _FF_spi(0xFF);
if(resp == 0x1)
{
SD_CS_OFF(); // CS = 1
//***********************************************************
#ifdef _DEBUG_INIT_SD_
_FF_printf(_FF_OkStr);
#endif
//***********************************************************
_FF_spi(0xFF);
return(0);
}
}
//*******************************************************************
#ifdef _DEBUG_INIT_SD_
_FF_printf(_FF_Err02Str, resp);
#endif
//*******************************************************************
}
return((int8) EOF);
}
/****************************************************************************
**
** Sends the "RESET" command to the SD/MMC media, the first command that has
** to be sent to the card when initally powered.
**
** Parameters: None
**
** Returns: 0 - Reset command successful
** -1 - Failed to reset the card
**
****************************************************************************/
int8 init_sd(void)
{
uint8 resp;
int16 i, n;
clear_sd_buff();
//***********************************************************************
#ifdef _DEBUG_INIT_SD_
_FF_printf(_FF_InitStr);
#endif
//***********************************************************************
resp = 0xFF;
for(i = 0; ((i < 10000) && (resp != 0)); i++)
{
_SD_send_cmd(CMD1, 0);
for(n = 0; ((n < 200) && (resp != 0)); n++)
resp = _FF_spi(0xFF);
}
_FF_spi(0xFF);
SD_CS_OFF();
if(resp == 0)
{ //*********************************************************************
#ifdef _DEBUG_INIT_SD_
_FF_printf(_FF_OkStr);
#endif
//*********************************************************************
return(0);
}
else
{ //*********************************************************************
#ifdef _DEBUG_INIT_SD_
_FF_printf(_FF_Err02Str, resp);
#endif
//*********************************************************************
return((int8) EOF);
}
}
/*****************************************************************************
**
** EOF
**
*****************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -