本帖最后由 flqcandy 于 2014-11-4 15:05 编辑 新手移植FatFs文件系统,利用STM32Cube,初始化SPI2,选择PB9作为片选信号,没用使用cube自带的fatfs文件系统;问题如标题所示,f_Open返回FR_NOT_READY,通过断点调试,发现在调用SD_Init()函数中,发送CMD0,让SD进入IDLE状态时,返回值不是0x01;调试了一周,也没找到问题所在。【系统时钟160MHz,SPI2所在的APBH1时钟为40MHz,SD卡为16G的SDHC卡】,跪求指导; 代码见楼下: |
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal.h"
#include "main.h"
#include "diskio.h"
/* Private variables ---------------------------------------------------------*/
SPI_HandleTypeDef hspi2;
/* USER CODE BEGIN 0 */
FATFS fs;// Work area (file system object) for logical drive
// DIR dir;
FIL fsrc, fdst; // file objects
FRESULT fr;// FatFs function common result code
/* USER CODE END 0 */
/* Private function prototypes -----------------------------------------------*/
static void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI2_Init(void);
int main(void)
{
/* USER CODE BEGIN 1 */
char buffer[100]; // file copy buffer
UINT br, bw; // File R/W count
// DSTATUS status;
unsigned char w_buffer[]="123456789123456789123456789123456789";//??????
/* USER CODE END 1 */
/* MCU Configuration----------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_SPI2_Init();
/* USER CODE BEGIN 2 */
// status = disk_initialize(0);
// if(status==0)
// {
// return RES_OK;
// }
fr=f_mount(0,&fs);
//fr=f_opendir(&dir,"");
fr = f_open(&fsrc,"0:/srcfile.txt",FA_CREATE_ALWAYS|FA_WRITE);
if(fr==FR_OK)
fr = f_write(&fsrc,w_buffer,strlen(w_buffer),&bw);
fr = f_close(&fsrc);
f_mount(0,NULL);
/* USER CODE END 2 */
/* USER CODE BEGIN 3 */
/* Infinite loop */
while (1)
{
}
/* USER CODE END 3 */
}
/** System Clock Configuration
*/
static void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;
__PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 15;
RCC_OscInitStruct.PLL.PLLN = 192;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1
|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
}
/* SPI2 init function */
void MX_SPI2_Init(void)
{
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_MASTER;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_HIGH;
hspi2.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLED;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_ENABLED;
hspi2.Init.CRCPolynomial = 7;
HAL_SPI_Init(&hspi2);
}
/** Configure pins as
* Analog
* Input
* Output
* EVENT_OUT
* EXTI
*/
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* GPIO Ports Clock Enable */
__GPIOH_CLK_ENABLE();
__GPIOC_CLK_ENABLE();
__GPIOB_CLK_ENABLE();
/*Configure GPIO pin : PB9 */
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_MEDIUM;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
/* Includes ------------------------------------------------------------------*/
#include "diskio.h"
#include "ffconf.h"
#include "Spi_SD_Driver.h"
#include <stdio.h>
/* Private variables ---------------------------------------------------------*/
//extern MSD_CARDINFO SD0_CardInfo;
DSTATUS disk_initialize (
BYTE drv /* Physical drive nmuber (0..) */
)
{
int Status;
Status = SD_Init();
if(Status==0)
{
return RES_OK;
}else{
return STA_NOINIT;
}
}
DSTATUS disk_status (
BYTE drv /* Physical drive nmuber (0..) */
)
{
return RES_OK;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
DRESULT disk_read (
BYTE drv, /* Physical drive nmuber (0..) */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address (LBA) */
BYTE count /* Number of sectors to read (1..255) */
)
{
int Status;
if( !count )
{
return RES_PARERR; /* count²»ÄܵÈÓÚ0£¬·ñÔò·µ»Ø²ÎÊý´íÎó */
}
if(count==1) /* 1¸ösectorµÄ¶Á²Ù×÷ */
{
Status = SD_ReadSingleBlock( sector ,buff );
if(Status == 0){
return RES_OK;
}else{
return RES_ERROR;
}
}
else /* ¶à¸ösectorµÄ¶Á²Ù×÷ */
{
Status = SD_ReadMultiBlock( sector , buff ,count);
if(Status == 0){
return RES_OK;
}else{
return RES_ERROR;
}
}
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
#if _READONLY == 0
DRESULT disk_write (
BYTE drv, /* Physical drive nmuber (0..) */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address (LBA) */
BYTE count /* Number of sectors to write (1..255) */
)
{
int Status;
if( !count )
{
return RES_PARERR; /* count²»ÄܵÈÓÚ0£¬·ñÔò·µ»Ø²ÎÊý´íÎó */
}
if(count==1) /* 1¸ösectorµÄд²Ù×÷ */
{
Status = SD_WriteSingleBlock( sector , (uint8_t *)(&buff[0]) );
if(Status == 0){
return RES_OK;
}else{
return RES_ERROR;
}
}
else /* ¶à¸ösectorµÄд²Ù×÷ */
{
Status = SD_WriteMultiBlock( sector , (uint8_t *)(&buff[0]) , count );
if(Status == 0){
return RES_OK;
}else{
return RES_ERROR;
}
}
}
#endif /* _READONLY */
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
//DRESULT disk_ioctl (
// BYTE drv, /* Physical drive nmuber (0..) */
// BYTE ctrl, /* Control code */
// void *buff /* Buffer to send/receive control data */
//)
//{
// //MSD0_GetCardInfo(&SD0_CardInfo);
// switch (ctrl)
// {
// case CTRL_SYNC :
// return RES_OK;
// case GET_SECTOR_COUNT :
// //*(DWORD*)buff = SD0_CardInfo.Capacity/SD0_CardInfo.BlockSize;
// return RES_OK;
// case GET_BLOCK_SIZE :
// //*(WORD*)buff = SD0_CardInfo.BlockSize;
// return RES_OK;
// case CTRL_POWER :
// break;
// case CTRL_LOCK :
// break;
// case CTRL_EJECT :
// break;
// /* MMC/SDC command */
// case MMC_GET_TYPE :
// break;
// case MMC_GET_CSD :
// break;
// case MMC_GET_CID :
// break;
// case MMC_GET_OCR :
// break;
// case MMC_GET_SDSTAT :
// break;
// }
//
//}
DRESULT disk_ioctl(BYTE drv, /* Physical drive nmuber (0..) */
BYTE ctrl, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
return RES_OK;
}
/* µÃµ½ÎļþCalendar¸ñʽµÄ½¨Á¢ÈÕÆÚ,ÊÇDWORD get_fattime (void) Äæ±ä»» */
/*-----------------------------------------------------------------------*/
/* User defined function to give a current time to fatfs module */
/* 31-25: Year(0-127 org.1980), 24-21: Month(1-12), 20-16: Day(1-31) */
/* 15-11: Hour(0-23), 10-5: Minute(0-59), 4-0: Second(0-29 *2) */
DWORD get_fattime (void)
{
return 0;
}
/* Includes ------------------------------------------------------------------*/
//#include "config.h"
#include "Spi_SD_Driver.h"
#include "stm32f4xx.h"
#include "main.h"
u8 SD_Type=0;
/* Private functions ---------------------------------------------------------*/
// ÒÔÏÂÊÇSPIÄ£¿éµÄ³õʼ»¯´úÂ룬ÅäÖóÉÖ÷»úģʽ£¬·ÃÎÊSD¿¨
/*******************************************************************************
* Function Name : SPI_SetSpeed
* Description : SPIÉèÖÃËÙ¶ÈΪ¸ßËÙ
* Input : u8 SpeedSet
* Èç¹ûËÙ¶ÈÉèÖÃÊäÈë0£¬ÔòµÍËÙģʽ£¬·Ç0Ôò¸ßËÙģʽ
* SPI_SPEED_HIGH 1
* SPI_SPEED_LOW 0
* Output : None
* Return : None
*******************************************************************************/
void SPI_SetSpeed(u8 SpeedSet)
{
hspi2.Instance=SPI2;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_HIGH;
hspi2.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLED;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_ENABLED;
hspi2.Init.CRCPolynomial = 7;
if(SpeedSet==SPI_SPEED_LOW)
{
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
}
else
{
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
}
HAL_SPI_Init(&hspi2);
}
/*******************************************************************************
* Function Name : SPI_ReadWriteByte
* Description : SPI¶Áдһ¸ö×Ö½Ú£¨·¢ËÍÍê³Éºó·µ»Ø±¾´ÎͨѶ¶ÁÈ¡µÄÊý¾Ý£©
* Input : u8 TxData ´ý·¢Ë͵ÄÊý
* Output : None
* Return : u8 RxData ÊÕµ½µÄÊý
*******************************************************************************/
u8 SPI_ReadWriteByte(u8 TxData)
{
u8 RxData;
HAL_SPI_TransmitReceive(&hspi2,&TxData,&RxData,1,1);
return RxData;
}
/*******************************************************************************
* Function Name : SD_WaitReady
* Description : µÈ´ýSD¿¨Ready
* Input : None
* Output : None
* Return : u8
* 0£º ³É¹¦
* other£ºÊ§°Ü
*******************************************************************************/
u8 SD_WaitReady(void)
{
u8 r1;
u16 retry;
retry = 0;
do
{
r1 = SPI_ReadWriteByte(0xFF);
if(retry==0xfffe)
{
return 1;
}
}while(r1!=0xFF);
return 0;
}
/*******************************************************************************
* Function Name : SD_SendCommand
* Description : ÏòSD¿¨·¢ËÍÒ»¸öÃüÁî
* Input : u8 cmd ÃüÁî
* u32 arg ÃüÁî²ÎÊý
* u8 crc crcУÑéÖµ
* Output : None
* Return : u8 r1 SD¿¨·µ»ØµÄÏìÓ¦
*******************************************************************************/
u8 SD_SendCommand(u8 cmd, u32 arg, u8 crc)
{
unsigned char r1;
unsigned char Retry = 0;
//????????
SPI_ReadWriteByte(0xff);
//Ƭѡ¶ËÖõͣ¬Ñ¡ÖÐSD¿¨
SD_CS_ENABLE();
//·¢ËÍ
SPI_ReadWriteByte(cmd | 0x40); //·Ö±ðдÈëÃüÁî
SPI_ReadWriteByte(arg >> 24);
SPI_ReadWriteByte(arg >> 16);
SPI_ReadWriteByte(arg >> 8);
SPI_ReadWriteByte(arg);
SPI_ReadWriteByte(crc);
//µÈ´ýÏìÓ¦£¬»ò³¬Ê±Í˳ö
while((r1 = SPI_ReadWriteByte(0xFF))==0xFF)
{
Retry++;
if(Retry > 200)
{
break;
}
}
//¹Ø±ÕƬѡ
SD_CS_DISABLE();
//ÔÚ×ÜÏßÉ϶îÍâÔö¼Ó8¸öʱÖÓ£¬ÈÃSD¿¨Íê³ÉÊ£ÏµĹ¤×÷
SPI_ReadWriteByte(0xFF);
//·µ»Ø״ֵ̬
return r1;
}
/*******************************************************************************
* Function Name : SD_SendCommand_NoDeassert
* Description : ÏòSD¿¨·¢ËÍÒ»¸öÃüÁî(½áÊøÊDz»Ê§ÄÜƬѡ£¬»¹ÓкóÐøÊý¾Ý´«À´£©
* Input : u8 cmd ÃüÁî
* u32 arg ÃüÁî²ÎÊý
* u8 crc crcУÑéÖµ
* Output : None
* Return : u8 r1 SD¿¨·µ»ØµÄÏìÓ¦
*******************************************************************************/
u8 SD_SendCommand_NoDeassert(u8 cmd, u32 arg, u8 crc)
{
unsigned char r1;
unsigned char Retry = 0;
//????????
SPI_ReadWriteByte(0xff);
//Ƭѡ¶ËÖõͣ¬Ñ¡ÖÐSD¿¨
SD_CS_ENABLE();
//·¢ËÍ
SPI_ReadWriteByte(cmd | 0x40); //·Ö±ðдÈëÃüÁî
SPI_ReadWriteByte(arg >> 24);
SPI_ReadWriteByte(arg >> 16);
SPI_ReadWriteByte(arg >> 8);
SPI_ReadWriteByte(arg);
SPI_ReadWriteByte(crc);
//µÈ´ýÏìÓ¦£¬»ò³¬Ê±Í˳ö
while((r1 = SPI_ReadWriteByte(0xFF))==0xFF)
{
Retry++;
if(Retry > 200)
{
break;
}
}
//·µ»ØÏìÓ¦Öµ
return r1;
}
/*******************************************************************************
* Function Name : SD_Init
* Description : ³õʼ»¯SD¿¨
* Input : None
* Output : None
* Return : u8
* 0£ºNO_ERR
* 1£ºTIME_OUT
* 99£ºNO_CARD
*******************************************************************************/
u8 SD_Init(void)
{
u16 i; // ÓÃÀ´Ñ»·¼ÆÊý
u8 r1; // ´æ·ÅSD¿¨µÄ·µ»ØÖµ
u16 retry; // ÓÃÀ´½øÐг¬Ê±¼ÆÊý
u8 buff[6];
//Èç¹ûûÓмì²âµ½¿¨²åÈ룬ֱ½ÓÍ˳ö£¬·µ»Ø´íÎó±êÖ¾
// if(!SD_DET())
// {
// //return 99;
// return STA_NODISK; // FatFS´íÎó±êÖ¾£ºÃ»ÓвåÈë´ÅÅÌ
// }
//SD¿¨Éϵç
// SD_PWR_ON();
// ´¿ÑÓʱ£¬µÈ´ýSD¿¨ÉϵçÍê³É
/*******************************************************
//Õâ¸öµØ·½Òª¼ÓÒ»¾ä,ÉèÖÃSPIËÙ¶ÈΪµÍËÙ¡£
//ΪʲôÓеĿ¨¿ÉÒÔÄØ£¿ÒòΪSPI³õʼ»¯Ê±ÊǵÍËٵģ¬SD¿¨³õʼ»¯
//Íê³ÉºóÉèÖÃΪ¸ßËÙ£¬ÓеĿ¨Ö»Òª³õʼ»¯Ò»´Î¾ÍÐУ¬³ÌÐò¾Íok£»
//µ«ÓеĿ¨ÐèÒª¶à´Î¸´Î»£¬ºÇºÇ£¬Õâ¸öµØ·½²îÕâÒ»¾ä£¬
//ÕâÖÖ¿¨¾ÍÓò»³É¿©£¡
*******************************************************/
SPI_SetSpeed(0); //ÉèÖÃSPIËÙ¶ÈΪµÍËÙ
//ÏȲúÉú>74¸öÂö³å£¬ÈÃSD¿¨×Ô¼º³õʼ»¯Íê³É
for(i=0;i<10;i++)
{
SPI_ReadWriteByte(0xFF);
}
//-----------------SD¿¨¸´Î»µ½idle¿ªÊ¼-----------------
//Ñ»·Á¬Ðø·¢ËÍCMD0£¬Ö±µ½SD¿¨·µ»Ø0x01,½øÈëIDLE״̬
//³¬Ê±ÔòÖ±½ÓÍ˳ö
SD_CS_ENABLE();
retry = 0;
do
{
//·¢ËÍCMD0£¬ÈÃSD¿¨½øÈëIDLE״̬
r1 = SD_SendCommand(CMD0, 0, 0x95);
retry++;
}while((r1 != 0x01) && (retry<200));
//Ìø³öÑ»·ºó£¬¼ì²éÔÒò£º³õʼ»¯³É¹¦£¿or ÖØÊÔ³¬Ê±£¿
if(retry==200)
{
return 1; //³¬Ê±·µ»Ø1
}
// retry=20;
// do
// {
// r1=SD_SendCommand(CMD0,0,0x95);
// }while((r1!=0x01)&&retry--);
// SD_Type=0;
//-----------------SD¿¨¸´Î»µ½idle½áÊø-----------------
//»ñÈ¡¿¨Æ¬µÄSD°æ±¾ÐÅÏ¢
r1 = SD_SendCommand_NoDeassert(8, 0x1aa, 0x87);
//Èç¹û¿¨Æ¬°æ±¾ÐÅÏ¢ÊÇv1.0°æ±¾µÄ£¬¼´r1=0x05£¬Ôò½øÐÐÒÔϳõʼ»¯
if(r1 == 0x05)
{
//ÉèÖÿ¨ÀàÐÍΪSDV1.0£¬Èç¹ûºóÃæ¼ì²âµ½ÎªMMC¿¨£¬ÔÙÐÞ¸ÄΪMMC
SD_Type = SD_TYPE_V1;
//Èç¹ûÊÇV1.0¿¨£¬CMD8Ö¸ÁîºóûÓкóÐøÊý¾Ý
//ƬѡÖøߣ¬½áÊø±¾´ÎÃüÁî
SD_CS_DISABLE();
//¶à·¢8¸öCLK£¬ÈÃSD½áÊøºóÐø²Ù×÷
SPI_ReadWriteByte(0xFF);
//-----------------SD¿¨¡¢MMC¿¨³õʼ»¯¿ªÊ¼-----------------
//·¢¿¨³õʼ»¯Ö¸ÁîCMD55+ACMD41
// Èç¹ûÓÐÓ¦´ð£¬ËµÃ÷ÊÇSD¿¨£¬ÇÒ³õʼ»¯Íê³É
// ûÓлØÓ¦£¬ËµÃ÷ÊÇMMC¿¨£¬¶îÍâ½øÐÐÏàÓ¦³õʼ»¯
retry = 0;
do
{
//ÏÈ·¢CMD55£¬Ó¦·µ»Ø0x01£»·ñÔò³ö´í
r1 = SD_SendCommand(CMD55, 0, 0);
if(r1 != 0x01)
{
return r1;
}
//µÃµ½ÕýÈ·ÏìÓ¦ºó£¬·¢ACMD41£¬Ó¦µÃµ½·µ»ØÖµ0x00£¬·ñÔòÖØÊÔ200´Î
r1 = SD_SendCommand(ACMD41, 0, 0);
retry++;
}while((r1!=0x00) && (retry<400));
// ÅжÏÊdz¬Ê±»¹Êǵõ½ÕýÈ·»ØÓ¦
// ÈôÓлØÓ¦£ºÊÇSD¿¨£»Ã»ÓлØÓ¦£ºÊÇMMC¿¨
//----------MMC¿¨¶îÍâ³õʼ»¯²Ù×÷¿ªÊ¼------------
if(retry==400)
{
retry = 0;
//·¢ËÍMMC¿¨³õʼ»¯ÃüÁûÓвâÊÔ£©
do
{
r1 = SD_SendCommand(1, 0, 0);
retry++;
}while((r1!=0x00)&& (retry<400));
if(retry==400)
{
return 1; //MMC¿¨³õʼ»¯³¬Ê±
}
//дÈ뿨ÀàÐÍ
SD_Type = SD_TYPE_MMC;
}
//----------MMC¿¨¶îÍâ³õʼ»¯²Ù×÷½áÊø------------
//ÉèÖÃSPIΪ¸ßËÙģʽ
SPI_SetSpeed(1);
SPI_ReadWriteByte(0xFF);
//½ûÖ¹CRCУÑé
/*
r1 = SD_SendCommand(CMD59, 0, 0x01);
if(r1 != 0x00)
{
return r1; //ÃüÁî´íÎ󣬷µ»Ør1
}
*/
//ÉèÖÃSector Size
r1 = SD_SendCommand(CMD16, 512, 0xff);
if(r1 != 0x00)
{
return r1; //ÃüÁî´íÎ󣬷µ»Ør1
}
//-----------------SD¿¨¡¢MMC¿¨³õʼ»¯½áÊø-----------------
}//SD¿¨ÎªV1.0°æ±¾µÄ³õʼ»¯½áÊø
//ÏÂÃæÊÇV2.0¿¨µÄ³õʼ»¯
//ÆäÖÐÐèÒª¶ÁÈ¡OCRÊý¾Ý£¬ÅжÏÊÇSD2.0»¹ÊÇSD2.0HC¿¨
else if( r1 == 0x01)
{
//V2.0µÄ¿¨£¬CMD8ÃüÁîºó»á´«»Ø4×Ö½ÚµÄÊý¾Ý£¬ÒªÌø¹ýÔÙ½áÊø±¾ÃüÁî
buff[0] = SPI_ReadWriteByte(0xFF); //should be 0x00
buff[1] = SPI_ReadWriteByte(0xFF); //should be 0x00
buff[2] = SPI_ReadWriteByte(0xFF); //should be 0x01
buff[3] = SPI_ReadWriteByte(0xFF); //should be 0xAA
SD_CS_DISABLE();
//the next 8 clocks
SPI_ReadWriteByte(0xFF);
//Åжϸÿ¨ÊÇ·ñÖ§³Ö2.7V-3.6VµÄµçѹ·¶Î§
if(buff[2]==0x01 && buff[3]==0xAA)
{
//Ö§³Öµçѹ·¶Î§£¬¿ÉÒÔ²Ù×÷
retry = 0;
//·¢¿¨³õʼ»¯Ö¸ÁîCMD55+ACMD41
do
{
r1 = SD_SendCommand(CMD55, 0, 0);
if(r1!=0x01)
{
return r1;
}
r1 = SD_SendCommand(ACMD41, 0x40000000, 0);
if(retry>200)
{
return r1; //³¬Ê±Ôò·µ»Ør1״̬
}
}while(r1!=0);
//³õʼ»¯Ö¸Áî·¢ËÍÍê³É£¬½ÓÏÂÀ´»ñÈ¡OCRÐÅÏ¢
//-----------¼ø±ðSD2.0¿¨°æ±¾¿ªÊ¼-----------
r1 = SD_SendCommand_NoDeassert(CMD58, 0, 0);
if(r1!=0x00)
{
return r1; //Èç¹ûÃüÁîûÓзµ»ØÕýÈ·Ó¦´ð£¬Ö±½ÓÍ˳ö£¬·µ»ØÓ¦´ð
}
//¶ÁOCRÖ¸Áî·¢³öºó£¬½ô½Ó×ÅÊÇ4×Ö½ÚµÄOCRÐÅÏ¢
buff[0] = SPI_ReadWriteByte(0xFF);
buff[1] = SPI_ReadWriteByte(0xFF);
buff[2] = SPI_ReadWriteByte(0xFF);
buff[3] = SPI_ReadWriteByte(0xFF);
//OCR½ÓÊÕÍê³É£¬Æ¬Ñ¡Öøß
SD_CS_DISABLE();
SPI_ReadWriteByte(0xFF);
//¼ì²é½ÓÊÕµ½µÄOCRÖеÄbit30루CCS£©£¬È·¶¨ÆäΪSD2.0»¹ÊÇSDHC
//Èç¹ûCCS=1£ºSDHC CCS=0£ºSD2.0
if(buff[0]&0x40) //¼ì²éCCS
{
SD_Type = SD_TYPE_V2HC;
}
else
{
SD_Type = SD_TYPE_V2;
}
//-----------¼ø±ðSD2.0¿¨°æ±¾½áÊø-----------
//ÉèÖÃSPIΪ¸ßËÙģʽ
SPI_SetSpeed(1);
}
}
return r1;
}
/*******************************************************************************
* Function Name : SD_ReceiveData
* Description : ´ÓSD¿¨ÖжÁ»ØÖ¸¶¨³¤¶ÈµÄÊý¾Ý£¬·ÅÖÃÔÚ¸ø¶¨Î»ÖÃ
* Input : u8 *data(´æ·Å¶Á»ØÊý¾ÝµÄÄÚ´æ>len)
* u16 len(Êý¾Ý³¤¶È£©
* u8 release(´«ÊäÍê³ÉºóÊÇ·ñÊÍ·Å×ÜÏßCSÖÃ¸ß 0£º²»ÊÍ·Å 1£ºÊÍ·Å£©
* Output : None
* Return : u8
* 0£ºNO_ERR
* other£º´íÎóÐÅÏ¢
*******************************************************************************/
u8 SD_ReceiveData(u8 *data, u16 len, u8 release)
{
u16 retry;
u8 r1;
// Æô¶¯Ò»´Î´«Êä
SD_CS_ENABLE();
//µÈ´ýSD¿¨·¢»ØÊý¾ÝÆðʼÁîÅÆ0xFE
retry = 0;
do
{
r1 = SPI_ReadWriteByte(0xFF);
retry++;
if(retry>2000) //2000´ÎµÈ´ýºóûÓÐÓ¦´ð£¬Í˳ö±¨´í
{
SD_CS_DISABLE();
return 1;
}
}while(r1 != 0xFE);
//¿ªÊ¼½ÓÊÕÊý¾Ý
while(len--)
{
*data = SPI_ReadWriteByte(0xFF);
data++;
}
//ÏÂÃæÊÇ2¸öαCRC£¨dummy CRC£©
SPI_ReadWriteByte(0xFF);
SPI_ReadWriteByte(0xFF);
//°´ÐèÊÍ·Å×ÜÏߣ¬½«CSÖøß
if(release == RELEASE)
{
//´«Êä½áÊø
SD_CS_DISABLE();
SPI_ReadWriteByte(0xFF);
}
return 0;
}
/*******************************************************************************
* Function Name : SD_GetCID
* Description : »ñÈ¡SD¿¨µÄCIDÐÅÏ¢£¬°üÀ¨ÖÆÔìÉÌÐÅÏ¢
* Input : u8 *cid_data(´æ·ÅCIDµÄÄڴ棬ÖÁÉÙ16Byte£©
* Output : None
* Return : u8
* 0£ºNO_ERR
* 1£ºTIME_OUT
* other£º´íÎóÐÅÏ¢
*******************************************************************************/
u8 SD_GetCID(u8 *cid_data)
{
u8 r1;
//·¢CMD10ÃüÁ¶ÁCID
r1 = SD_SendCommand(CMD10, 0, 0xFF);
if(r1 != 0x00)
{
return r1; //û·µ»ØÕýÈ·Ó¦´ð£¬ÔòÍ˳ö£¬±¨´í
}
//½ÓÊÕ16¸ö×Ö½ÚµÄÊý¾Ý
SD_ReceiveData(cid_data, 16, RELEASE);
return 0;
}
/*******************************************************************************
* Function Name : SD_GetCSD
* Description : »ñÈ¡SD¿¨µÄCSDÐÅÏ¢£¬°üÀ¨ÈÝÁ¿ºÍËÙ¶ÈÐÅÏ¢
* Input : u8 *cid_data(´æ·ÅCIDµÄÄڴ棬ÖÁÉÙ16Byte£©
* Output : None
* Return : u8
* 0£ºNO_ERR
* 1£ºTIME_OUT
* other£º´íÎóÐÅÏ¢
*******************************************************************************/
u8 SD_GetCSD(u8 *csd_data)
{
u8 r1;
//·¢CMD9ÃüÁ¶ÁCSD
r1 = SD_SendCommand(CMD9, 0, 0xFF);
if(r1 != 0x00)
{
return r1; //û·µ»ØÕýÈ·Ó¦´ð£¬ÔòÍ˳ö£¬±¨´í
}
//½ÓÊÕ16¸ö×Ö½ÚµÄÊý¾Ý
SD_ReceiveData(csd_data, 16, RELEASE);
return 0;
}
/*******************************************************************************
* Function Name : SD_GetCapacity
* Description : »ñÈ¡SD¿¨µÄÈÝÁ¿
* Input : None
* Output : None
* Return : u32 capacity
* 0£º È¡ÈÝÁ¿³ö´í
*******************************************************************************/
u32 SD_GetCapacity(void)
{
u8 csd[16];
u32 Capacity;
u8 r1;
u16 i;
u16 temp;
//È¡CSDÐÅÏ¢£¬Èç¹ûÆÚ¼ä³ö´í£¬·µ»Ø0
if(SD_GetCSD(csd)!=0)
{
return 0;
}
//Èç¹ûΪSDHC¿¨£¬°´ÕÕÏÂÃ淽ʽ¼ÆËã
if((csd[0]&0xC0)==0x40)
{
Capacity = (((u32)csd[8])<<8 + (u32)csd[9] +1)*(u32)1024;
}
else
{
//ÏÂÃæ´úÂëΪÍøÉÏ°æ±¾
////////////formula of the capacity///////////////
//
// memory capacity = BLOCKNR * BLOCK_LEN
//
// BLOCKNR = (C_SIZE + 1)* MULT
//
// C_SIZE_MULT+2
// MULT = 2
//
// READ_BL_LEN
// BLOCK_LEN = 2
/**********************************************/
//C_SIZE
i = csd[6]&0x03;
i<<=8;
i += csd[7];
i<<=2;
i += ((csd[8]&0xc0)>>6);
//C_SIZE_MULT
r1 = csd[9]&0x03;
r1<<=1;
r1 += ((csd[10]&0x80)>>7);
//BLOCKNR
r1+=2;
temp = 1;
while(r1)
{
temp*=2;
r1--;
}
Capacity = ((u32)(i+1))*((u32)temp);
// READ_BL_LEN
i = csd[5]&0x0f;
//BLOCK_LEN
temp = 1;
while(i)
{
temp*=2;
i--;
}
//The final result
Capacity *= (u32)temp;
//Capacity /= 512;
}
return (u32)Capacity;
}
/*******************************************************************************
* Function Name : SD_ReadSingleBlock
* Description : ¶ÁSD¿¨µÄÒ»¸öblock
* Input : u32 sector È¡µØÖ·£¨sectorÖµ£¬·ÇÎïÀíµØÖ·£©
* u8 *buffer Êý¾Ý´æ´¢µØÖ·£¨´óСÖÁÉÙ512byte£©
* Output : None
* Return : u8 r1
* 0£º ³É¹¦
* other£ºÊ§°Ü
*******************************************************************************/
u8 SD_ReadSingleBlock(u32 sector, u8 *buffer)
{
u8 r1;
//ÉèÖÃΪ¸ßËÙģʽ
SPI_SetSpeed(SPI_SPEED_LOW);
//Èç¹û²»ÊÇSDHC£¬½«sectorµØַת³ÉbyteµØÖ·
if(SD_Type!=SD_TYPE_V2HC)
{
sector = sector<<9;
}
r1 = SD_SendCommand(CMD17, sector, 0);//¶ÁÃüÁî
if(r1 != 0x00)
{
return r1;
}
r1 = SD_ReceiveData(buffer, 512, RELEASE);
if(r1 != 0)
{
return r1; //¶ÁÊý¾Ý³ö´í£¡
}
else
{
return 0;
}
}
/*******************************************************************************
* Function Name : SD_WriteSingleBlock
* Description : дÈëSD¿¨µÄÒ»¸öblock
* Input : u32 sector ÉÈÇøµØÖ·£¨sectorÖµ£¬·ÇÎïÀíµØÖ·£©
* u8 *buffer Êý¾Ý´æ´¢µØÖ·£¨´óСÖÁÉÙ512byte£©
* Output : None
* Return : u8 r1
* 0£º ³É¹¦
* other£ºÊ§°Ü
*******************************************************************************/
u8 SD_WriteSingleBlock(u32 sector, const u8 *data)
{
u8 r1;
u16 i;
u16 retry;
//ÉèÖÃΪ¸ßËÙģʽ
SPI_SetSpeed(SPI_SPEED_LOW);
//Èç¹û²»ÊÇSDHC£¬¸ø¶¨µÄÊÇsectorµØÖ·£¬½«Æäת»»³ÉbyteµØÖ·
if(SD_Type!=SD_TYPE_V2HC)
{
sector = sector<<9;
}
r1 = SD_SendCommand(CMD24, sector, 0x00);
if(r1 != 0x00)
{
return r1; //Ó¦´ð²»ÕýÈ·£¬Ö±½Ó·µ»Ø
}
//¿ªÊ¼×¼±¸Êý¾Ý´«Êä
SD_CS_ENABLE();
//ÏÈ·Å3¸ö¿ÕÊý¾Ý£¬µÈ´ýSD¿¨×¼±¸ºÃ
SPI_ReadWriteByte(0xff);
SPI_ReadWriteByte(0xff);
SPI_ReadWriteByte(0xff);
//·ÅÆðʼÁîÅÆ0xFE
SPI_ReadWriteByte(0xFE);
//·ÅÒ»¸ösectorµÄÊý¾Ý
for(i=0;i<512;i++)
{
SPI_ReadWriteByte(*data++);
}
//·¢2¸öByteµÄdummy CRC
SPI_ReadWriteByte(0xff);
SPI_ReadWriteByte(0xff);
//µÈ´ýSD¿¨Ó¦´ð
r1 = SPI_ReadWriteByte(0xff);
if((r1&0x1F)!=0x05)
{
SD_CS_DISABLE();
return r1;
}
//µÈ´ý²Ù×÷Íê³É
retry = 0;
while(!SPI_ReadWriteByte(0xff))
{
retry++;
if(retry>0xfffe) //Èç¹û³¤Ê±¼äдÈëûÓÐÍê³É£¬±¨´íÍ˳ö
{
SD_CS_DISABLE();
return 1; //дÈ볬ʱ·µ»Ø1
}
}
//дÈëÍê³É£¬Æ¬Ñ¡ÖÃ1
SD_CS_DISABLE();
SPI_ReadWriteByte(0xff);
return 0;
}
/*******************************************************************************
* Function Name : SD_ReadMultiBlock
* Description : ¶ÁSD¿¨µÄ¶à¸öblock
* Input : u32 sector È¡µØÖ·£¨sectorÖµ£¬·ÇÎïÀíµØÖ·£©
* u8 *buffer Êý¾Ý´æ´¢µØÖ·£¨´óСÖÁÉÙ512byte£©
* u8 count Á¬Ðø¶Ácount¸öblock
* Output : None
* Return : u8 r1
* 0£º ³É¹¦
* other£ºÊ§°Ü
*******************************************************************************/
u8 SD_ReadMultiBlock(u32 sector, u8 *buffer, u8 count)
{
u8 r1;
//ÉèÖÃΪ¸ßËÙģʽ
SPI_SetSpeed(SPI_SPEED_LOW);
//Èç¹û²»ÊÇSDHC£¬½«sectorµØַת³ÉbyteµØÖ·
if(SD_Type!=SD_TYPE_V2HC)
{
sector = sector<<9;
}
//SD_WaitReady();
//·¢¶Á¶à¿éÃüÁî
r1 = SD_SendCommand(CMD18, sector, 0);//¶ÁÃüÁî
if(r1 != 0x00)
{
return r1;
}
//¿ªÊ¼½ÓÊÕÊý¾Ý
do
{
if(SD_ReceiveData(buffer, 512, NO_RELEASE) != 0x00)
{
break;
}
buffer += 512;
} while(--count);
//È«²¿´«ÊäÍê±Ï£¬·¢ËÍÍ£Ö¹ÃüÁî
SD_SendCommand(CMD12, 0, 0);
//ÊÍ·Å×ÜÏß
SD_CS_DISABLE();
SPI_ReadWriteByte(0xFF);
if(count != 0)
{
return count; //Èç¹ûûÓд«Í꣬·µ»ØÊ£Óà¸öÊý
}
else
{
return 0;
}
}
/*******************************************************************************
* Function Name : SD_WriteMultiBlock
* Description : дÈëSD¿¨µÄN¸öblock
* Input : u32 sector ÉÈÇøµØÖ·£¨sectorÖµ£¬·ÇÎïÀíµØÖ·£©
* u8 *buffer Êý¾Ý´æ´¢µØÖ·£¨´óСÖÁÉÙ512byte£©
* u8 count дÈëµÄblockÊýÄ¿
* Output : None
* Return : u8 r1
* 0£º ³É¹¦
* other£ºÊ§°Ü
*******************************************************************************/
u8 SD_WriteMultiBlock(u32 sector, const u8 *data, u8 count)
{
u8 r1;
u16 i=0;
//ÉèÖÃΪ¸ßËÙģʽ
SPI_SetSpeed(SPI_SPEED_LOW);
//Èç¹û²»ÊÇSDHC£¬¸ø¶¨µÄÊÇsectorµØÖ·£¬½«Æäת»»³ÉbyteµØÖ·
if(SD_Type != SD_TYPE_V2HC)
{
sector = sector<<9;
}
//Èç¹ûÄ¿±ê¿¨²»ÊÇMMC¿¨£¬ÆôÓÃACMD23Ö¸ÁîʹÄÜÔ¤²Á³ý
if(SD_Type != SD_TYPE_MMC)
{
r1 = SD_SendCommand(ACMD23, count, 0x00);
}
//·¢¶à¿éдÈëÖ¸Áî
r1 = SD_SendCommand(CMD25, sector, 0x00);
if(r1 != 0x00)
{
return r1; //Ó¦´ð²»ÕýÈ·£¬Ö±½Ó·µ»Ø
}
//¿ªÊ¼×¼±¸Êý¾Ý´«Êä
SD_CS_ENABLE();
//ÏÈ·Å3¸ö¿ÕÊý¾Ý£¬µÈ´ýSD¿¨×¼±¸ºÃ
SPI_ReadWriteByte(0xff);
SPI_ReadWriteByte(0xff);
//--------ÏÂÃæÊÇN¸ösectorдÈëµÄÑ»·²¿·Ö
do
{
//·ÅÆðʼÁîÅÆ0xFC ±íÃ÷ÊǶà¿éдÈë
SPI_ReadWriteByte(0xFC);
//·ÅÒ»¸ösectorµÄÊý¾Ý
for(i=0;i<512;i++)
{
SPI_ReadWriteByte(*data++);
}
//·¢2¸öByteµÄdummy CRC
SPI_ReadWriteByte(0xff);
SPI_ReadWriteByte(0xff);
//µÈ´ýSD¿¨Ó¦´ð
r1 = SPI_ReadWriteByte(0xff);
if((r1&0x1F)!=0x05)
{
SD_CS_DISABLE(); //Èç¹ûÓ¦´ðΪ±¨´í£¬Ôò´ø´íÎó´úÂëÖ±½ÓÍ˳ö
return r1;
}
//µÈ´ýSD¿¨Ð´ÈëÍê³É
if(SD_WaitReady()==1)
{
SD_CS_DISABLE(); //µÈ´ýSD¿¨Ð´ÈëÍê³É³¬Ê±£¬Ö±½ÓÍ˳ö±¨´í
return 1;
}
//±¾sectorÊý¾Ý´«ÊäÍê³É
}while(--count);
//·¢½áÊø´«ÊäÁîÅÆ0xFD
r1 = SPI_ReadWriteByte(0xFD);
if(r1==0x00)
{
count = 0xfe;
}
if(SD_WaitReady())
{
while(1)
{
}
}
//дÈëÍê³É£¬Æ¬Ñ¡ÖÃ1
SD_CS_DISABLE();
SPI_ReadWriteByte(0xff);
return count; //·µ»ØcountÖµ£¬Èç¹ûдÍêÔòcount=0£¬·ñÔòcount=1
}
请问解决了嘛?