BYTE SD_Init(){//SD卡初始化函数,成功返回0,失败则返回非0 BYTE i; BYTE cnt = 0; BYTE rtn = 0; Port_Init();//初始化引脚 SPI_SetSpeedLow();//SPI初始化,设定为低速 do{ for(i=0;i<10;i++) SPI_ByteRW(0xFF); rtn=SD_SendCommand(0,0);//发idle命令 if((cnt++)==0xFF) return 1;//超时退出 }while(rtn!=0x01); cnt=0;//清零重试计数器 do{ rtn=SD_SendCommand(1,0);//发active命令 if((cnt++)==0xFF) return 2;//超时退出 }while(rtn); SPI_SetSpeedHigh();//设定SPI到高速模式 SD_SendCommand(59,0);//禁用CRC SD_SendCommand(16,512);//设定扇区大小为512 return 0;//初始化成功 }
UINT8 SD_Init(void) { _SD_PRESENT=_IN; /* Check for SD */ if(SD_PRESENT) return(NO_SD_CARD); /* Initialize SPI Module */ SPI_Init(); /* Start SD card Init */ SPI_SS=ENABLE; SD_CLKDelay(10); // Send 80 clocks SPI_SS=DISABLE; gu8SD_Argument.lword=0; SD_CLKDelay(8); /* IDLE Command */ SPI_SS=ENABLE; if(SD_SendCommand(SD_CMD0|0x40,SD_IDLE)) { SPI_SS=DISABLE; return(INIT_FAILS); } SPI_SS=DISABLE; (void)SPI_Receive_byte(); // Dummy SPI cycle /* Initialize SD Command */ SPI_SS=ENABLE; while(SD_SendCommand(SD_CMD1|0x40,SD_OK)); SPI_SS=DISABLE; (void)SPI_Receive_byte(); // Dummy SPI cycle /* Block Length */ SPI_SS=ENABLE; gu8SD_Argument.lword=SD_BLOCK_SIZE; if(SD_SendCommand(SD_CMD16|0x40,SD_OK)) { SPI_SS=DISABLE; return(INIT_FAILS); } SPI_SS=DISABLE; SPI_High_rate(); SPI_Send_byte(0x00); SPI_Send_byte(0x00); return(OK); }
//写入SD卡的N个block(未实际测试过) //输入:u32 sector 扇区地址(sector值,非物理地址) // u8 *buffer 数据存储地址(大小至少512byte) // u8 count 写入的block数目 //返回值:0: 成功 // other:失败 u8 SD_WriteMultiBlock(u32 sector, const u8 *data, u8 count) { u8 r1; u16 i; //SPIx_SetSpeed(SPI_SPEED_HIGH);//设置为高速模式 if(SD_Type != SD_TYPE_V2HC)sector = sector<<9;//如果不是SDHC,给定的是sector地址,将其转换成byte地址 if(SD_Type != SD_TYPE_MMC) r1 = SD_SendCommand(ACMD23, count, 0x00);//如果目标卡不是MMC卡,启用ACMD23指令使能预擦除 r1 = SD_SendCommand(CMD25, sector, 0x00);//发多块写入指令 if(r1 != 0x00)return r1; //应答不正确,直接返回 SD_CS=0;//开始准备数据传输 SPIx_ReadWriteByte(0xff);//先放3个空数据,等待SD卡准备好 SPIx_ReadWriteByte(0xff); //--------下面是N个sector写入的循环部分 do { //放起始令牌0xFC 表明是多块写入 SPIx_ReadWriteByte(0xFC); //放一个sector的数据 for(i=0; i<512; i++) { SPIx_ReadWriteByte(*data++); } //发2个Byte的dummy CRC SPIx_ReadWriteByte(0xff); SPIx_ReadWriteByte(0xff); //等待SD卡应答 r1 = SPIx_ReadWriteByte(0xff); if((r1&0x1F)!=0x05) { SD_CS=1; //如果应答为报错,则带错误代码直接退出 return r1; } //等待SD卡写入完成 if(SD_WaitDataReady()==1) { SD_CS=1; //等待SD卡写入完成超时,直接退出报错 return 1; } } while(--count);//本sector数据传输完成 //发结束传输令牌0xFD r1 = SPIx_ReadWriteByte(0xFD); if(r1==0x00) { count = 0xfe; } if(SD_WaitDataReady()) //等待准备好 { SD_CS=1; return 1; } //写入完成,片选置1 SD_CS=1; SPIx_ReadWriteByte(0xff); return count; //返回count值,如果写完则count=0,否则count=1 }
/***************************************************************************** * ************* SD_Erase_Blocks *********** * * Description: Erase multiple sectors (blocks) no the SD card. * * Inputs: u32SD_Start_Block - the sector (block) number of the first * block to be erased. * u32SD_End_Block - the sector (block) number of the last * block to be erased. * *****************************************************************************/ UINT8 SD_Erase_Blocks(UINT32 u32SD_Start_Block, UINT32 u32SD_End_Block) { UINT8 res; UINT16 u16Counter; SPI_SS = ENABLE; /* Set the address of the first write block to be erased */ gu8SD_Argument.lword = u32SD_Start_Block; // Set ERASE_WR_BLK_START_ADDR // command argument gu8SD_Argument.lword = gu8SD_Argument.lword << SD_BLOCK_SHIFT; // Convert sector number to // byte address if (SD_SendCommand(SD_CMD32 | 0x40, SD_OK)) // ERASE_WR_BLK_START_ADDR command { SPI_SS = DISABLE; return (WRITE_COMMAND_FAILS); } SD_CLKDelay(1); // 8 dummy clocks /* Set the address of the last write block to be erased */ gu8SD_Argument.lword = u32SD_End_Block; // Set ERASE_WR_BLK_END_ADDR // command argument gu8SD_Argument.lword = gu8SD_Argument.lword << SD_BLOCK_SHIFT; // Convert sector number to // byte address if (SD_SendCommand(SD_CMD33 | 0x40, SD_OK)) // ERASE_WR_BLK_END_ADDR command { SPI_SS = DISABLE; return (WRITE_COMMAND_FAILS); } SD_CLKDelay(1); // 8 dummy clocks /* Send the erase command */ gu8SD_Argument.lword = 0x00000000; // stuff bits if (SD_SendCommand(SD_CMD38 | 0x40, SD_OK)) // ERASE command { SPI_SS = DISABLE; return (WRITE_COMMAND_FAILS); } /* Wait while card is busy. Indicated by reading 0x00 from SD Card */ u16Counter = 0; // Counter to see if it is doing something do { res = SPI_Receive_byte(); u16Counter++; } while (res == 0x00); // Wait while the card is busy SPI_SS = DISABLE; SD_CLKDelay(1); // 8 dummy clocks return (OK); }
uint_8 SD_ReadCSD(void) { #ifdef MCU_MKL25Z4 uint_8 i; SPI_set_SS(); if(SD_SendCommand(SD_CMD9|0x40,SD_OK)) { SPI_clr_SS() ; return(4); } while(i!=0xFE) i=SPI_Receive_byte(); for(i=0;i<16;i++) vSD_CSD[i]=SPI_Receive_byte(); (void)SPI_Receive_byte(); /* Dummy SPI cycle */ (void)SPI_Receive_byte(); /* Dummy SPI cycle */ SPI_clr_SS() ; (void)SPI_Receive_byte(); /* Dummy SPI cycle */ return(0); #else uint_8 i = 0; /*Body*/ if(SD_SendCommand(SD_CMD9|0x40,SD_OK)) { return(4); }/*EndIf*/ while(i!=0xFE) i=SPI_Receive_byte(); for(i=0;i<16;i++) vSD_CSD[i]=SPI_Receive_byte(); (void)SPI_Receive_byte(); (void)SPI_Receive_byte(); (void)SPI_Receive_byte(); return(0); #endif }/*EndBody*/
UINT8 SD_Read_Block(UINT32 u16SD_Block,UINT8 *pu8DataPointer) { UINT8 u8Temp=0; UINT16 u16Counter; T32_8 gu8SD_Argument; SD_ENABLE; gu8SD_Argument.lword=u16SD_Block; gu8SD_Argument.lword=gu8SD_Argument.lword<< SD_BLOCK_SHIFT; if(SD_SendCommand(SD_CMD17|0x40,gu8SD_Argument,SD_OK)) { SD_DISABLE; return(READ_COMMAND_FAILS); } while(u8Temp!=0xFE) u8Temp=ReadSPIByte(SDhandle); for(u16Counter=0;u16Counter<BLOCK_SIZE;u16Counter++) *pu8DataPointer++=ReadSPIByte(SDhandle); (void)ReadSPIByte(SDhandle); // Dummy SPI cycle (void)ReadSPIByte(SDhandle); SD_DISABLE; (void)ReadSPIByte(SDhandle); // Dummy SPI cycle return(OK); }
void SD_Write_Block(PTR_LBA_APP_STRUCT lba_data_ptr) { /* Body */ uint_32 u32Counter; SPI_set_SS(); gu8SD_Argument.lword = lba_data_ptr->offset; if(SD_SendCommand(SD_CMD24|0x40,SD_OK)) { SPI_clr_SS() ; return; /* Command IDLE fail */ } /* EndIf */ SPI_Send_byte(0xFE); for(u32Counter=0;u32Counter<lba_data_ptr->size;u32Counter++) { SPI_Send_byte(*(lba_data_ptr->buff_ptr + u32Counter)); } /* EndFor */ SPI_Send_byte(0xFF); /* checksum Bytes not needed */ SPI_Send_byte(0xFF); if((SPI_Receive_byte() & 0x0F) != 0x05) { SPI_clr_SS() ; return; /* Command fail */ } /* EndIf */ while(SPI_Receive_byte()==0x00) { __RESET_WATCHDOG(); /* Dummy SPI cycle */ } /* EndWhile */ SPI_clr_SS() ; return; } /* EndBody */
BYTE SD_WriteOneSector(DWORD sector,BYTE* buf){//写一个扇区(buf为512字节),成功返回0 BYTE rtn; WORD i,cnt=0; SPI_SetSpeedHigh();//设定SPI到高速模式 rtn=SD_SendCommand(24,sector<<9);//读命令 if(rtn!=0x00) return rtn; CS_LOW(); SPI_ByteRW(0xFF); SPI_ByteRW(0xFF); SPI_ByteRW(0xFF); SPI_ByteRW(0xFE);//发开始符 for(i=0;i<512;i++){//送512字节数据 SPI_ByteRW(*(buf++)); } SPI_ByteRW(0xFF);//dummy crc SPI_ByteRW(0xFF); rtn=SPI_ByteRW(0xFF); if((rtn & 0x1F)!=0x05){//等待是否成功 CS_HIGH(); return rtn; } //等待操作完 while(!SPI_ByteRW(0xFF)){ if((cnt++)==0xFFFF){ CS_HIGH(); return 1;//超时退出 } } CS_HIGH(); SPI_ByteRW(0xFF);//额外8个时钟周期 return 0; }
void SD_Read_Block(PTR_LBA_APP_STRUCT lba_data_ptr) { /* Body */ uint_8 u8Temp=0; uint_32 u32Counter; SPI_set_SS(); gu8SD_Argument.lword = lba_data_ptr->offset; if(SD_SendCommand(SD_CMD17|0x40,SD_OK)) { SPI_clr_SS() ; return; /* Command IDLE fail */ } /* EndIf */ while(u8Temp!=0xFE) { u8Temp = SPI_Receive_byte(); } /* EndWhile */ for(u32Counter=0;u32Counter<lba_data_ptr->size;u32Counter++) { *(lba_data_ptr->buff_ptr + u32Counter) = SPI_Receive_byte(); } /* EndFor */ (void)SPI_Receive_byte(); /* Dummy SPI cycle */ (void)SPI_Receive_byte(); /* Dummy SPI cycle */ SPI_clr_SS() ; (void)SPI_Receive_byte(); /* Dummy SPI cycle */ return; } /* EndBody */
/***************************************************************************** * * *** SD_Read_CSD *** * * Read the SD Card Card-Specific Data Register (CSD). * * The CSD is a 16 byte SD Card register that is read with the * CMD9 SEND_CSD command. * * Output: If read successful return OK with CSD register in gu8SD_CSD[0-16] * with MSB in gu8SD_CSD[0]. * Else return READ_COMMAND_FAILS. * * ******************************************************************************/ UINT8 SD_Read_CSD(void) { UINT8 u8Temp = 0, u8Counter; SPI_SS = ENABLE; gu8SD_Argument.lword = 0x00000000; if (SD_SendCommand(SD_CMD9 | 0x40, SD_OK)) { SPI_SS = DISABLE; return (READ_COMMAND_FAILS); } while (u8Temp != 0xFE) u8Temp = SPI_Receive_byte(); for (u8Counter = 0; u8Counter < 16; u8Counter++) gu8SD_CSD[u8Counter] = SPI_Receive_byte(); (void) ReadSPIByte(); // Dummy SPI cycle for CRC (void) ReadSPIByte(); SPI_SS = DISABLE; SD_CLKDelay(1); // 8 dummy clocks return (OK); }
UINT8 SD_Read_Block(UINT32 u16SD_Block,UINT8 *pu8DataPointer) { UINT8 u8Temp=0; UINT16 u16Counter; SPI_SS=ENABLE; gu8SD_Argument.lword=u16SD_Block; gu8SD_Argument.lword=gu8SD_Argument.lword<< SD_BLOCK_SHIFT; if(SD_SendCommand(SD_CMD17|0x40,SD_OK)) { SPI_SS=DISABLE; return(READ_COMMAND_FAILS); } while(u8Temp!=0xFE) u8Temp=SPI_Receive_byte(); for(u16Counter=0;u16Counter<BLOCK_SIZE;u16Counter++) *pu8DataPointer++=SPI_Receive_byte(); (void)SPI_Receive_byte(); // Dummy SPI cycle (void)SPI_Receive_byte(); SPI_SS=DISABLE; (void)SPI_Receive_byte(); // Dummy SPI cycle return(OK); }
UINT8 SD_ReadSector(UINT32 u32SD_Block,UINT8 pu8DataPointer[]) { volatile UINT8 u8Temp = 0; __RESET_WATCHDOG(); /* feeds the dog */ if (!gSDCard.SDHC) u32SD_Block <<= SD_BLOCK_SHIFT; SPI_SS = ENABLE; //Utilizo u8Temp para capturar respuesta de la tarjeta SD (fines depurativos) u8Temp = SD_SendCommand(SD_CMD17_READ_BLOCK, u32SD_Block, NULL, 0); if((u8Temp & SD_R1_ERROR_MASK) != SD_OK) { SPI_SS = DISABLE; return (SD_FAIL_READ); } while(u8Temp != 0xFE) u8Temp = SPI_ReceiveByte(); //La SD responde 0xFF...0xFF mientras accede al sector y 0xFE cuando esta lista. //Los datos que envía a continuación corresponden al sector solicitado. if (SD_ReadData(pu8DataPointer,SD_BLOCK_SIZE) != SD_OK) return (SD_FAIL_READ); SPI_SS = DISABLE; return (SD_OK); }
void SD_Read_Block(PTR_LBA_APP_STRUCT lba_data_ptr) { uint_8 u8Temp=0; uint_32 u32Counter; gu8SD_Argument.lword = lba_data_ptr->offset; if(SD_SendCommand(SD_CMD17|0x40,SD_OK)) { return; // Command IDLE fail } while(u8Temp!=0xFE) { u8Temp = SPI_Receive_byte(); } for(u32Counter=0;u32Counter<lba_data_ptr->size;u32Counter++) { *(lba_data_ptr->buff_ptr + u32Counter) = SPI_Receive_byte(); } (void)SPI_Receive_byte(); // Dummy SPI cycle (void)SPI_Receive_byte(); // Dummy SPI cycle (void)SPI_Receive_byte(); // Dummy SPI cycle return; }
//获取SD卡的CSD信息,包括容量和速度信息 //输入:u8 *cid_data(存放CID的内存,至少16Byte) //返回值:0:NO_ERR // 1:TIME_OUT // other:错误信息 u8 SD_GetCSD(u8 *csd_data) { u8 r1; r1=SD_SendCommand(CMD9,0,0xFF);//发CMD9命令,读CSD if(r1)return r1; //没返回正确应答,则退出,报错 SD_ReceiveData(csd_data, 16, RELEASE);//接收16个字节的数据 return 0; }
//获取SD卡的CID信息,包括制造商信息 //输入: u8 *cid_data(存放CID的内存,至少16Byte) //返回值: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; //没返回正确应答,则退出,报错 SD_ReceiveData(cid_data,16,RELEASE);//接收16个字节的数据 return 0; }
sd_result_t SD_DMA_SingleBlockRead(SD_Card *card, sd_block_t addr, SD_Data_Block *data) { uint8_t result; uint8_t args[4]; uint16_t i=0; if (card->State != SD_IDLE) { DBG_ERR_printf("SBR failed: Card not in idle state, state is 0x%02x", card->State); return SD_FAILED; } if (!card->SDHC) { addr = addr * card->BlockSize; } args[0] = (uint8_t)((addr >> 24) & 0xff); args[1] = (uint8_t)((addr >> 16) & 0xff); args[2] = (uint8_t)((addr >> 8) & 0xff); args[3] = (uint8_t)((addr >> 0) & 0xff); SD_SPI_Open(card); result = SD_SendCommand(card, SD_CMD_READ_SINGLE_BLOCK, args, 0x00); if (result != 0x00) { DBG_ERR_printf("SBR failed: Bad response to READ_SINGLE_BLOCK - got 0x%02x", result); SD_SPI_Terminate(card); SD_SPI_Close(card); return SD_PHY_ERR; } // wait for the start block token result = 0xff; while (result != SD_TOKEN_START_BLOCK && i < SD_BLOCK_TIMEOUT) { result = SD_SPI_Transfer(card, SD_DUMMY_BYTE); i++; } if (result != SD_TOKEN_START_BLOCK) { DBG_ERR_printf("SBR failed: Card did not send block, got 0x%02x", result); SD_SPI_Terminate(card); SD_SPI_Close(card); return SD_PHY_ERR; } data->StartOffset = 2; data->BlockLen = 514; SD_DMA_ReceiveBlock(card, data); SD_DMA_OnBlockRead(); card->State = SD_DMA_SBR; card->SubState = 0; return SD_BUSY; }
uint_8 SD_Init(void) { /* Body */ SPI_Init(); /* SPI Initialization */ SPI_set_SS(); SD_CLKDelay(10); /* Send 80 clocks */ SPI_clr_SS() ; gu8SD_Argument.lword = 0; SD_CLKDelay(8); /* IDLE Command */ SPI_set_SS(); if(SD_SendCommand(SD_CMD0|0x40,SD_IDLE)) { SPI_clr_SS() ; return(1); /* Command IDLE fail */ } /* EndIf */ SPI_clr_SS() ; (void)SPI_Receive_byte(); /* Dummy SPI cycle */ /* Initialize SD Command */ SPI_set_SS(); while(SD_SendCommand(SD_CMD1|0x40,SD_OK)) { __RESET_WATCHDOG(); } /* EndWhile */ SPI_clr_SS() ; (void)SPI_Receive_byte(); /* Dummy SPI cycle */ /* Block Length */ SPI_set_SS(); gu8SD_Argument.lword = SD_BLOCK_SIZE; if(SD_SendCommand(SD_CMD16|0x40,SD_OK)) { SPI_clr_SS() ; return(1); /* Command IDLE fail */ } /* EndIf */ SPI_clr_SS() ; SPI_High_rate(); SPI_Send_byte(0x00); SPI_Send_byte(0x00); return(0); } /* EndBody */
uint_8 SD_Init(void) { SPI_Init(); // SPI Initialization SD_CLKDelay(10); // Send 80 clocks gu8SD_Argument.lword = 0; SD_CLKDelay(8); /* IDLE Command */ if(SD_SendCommand(SD_CMD0|0x40,SD_IDLE)) { return(1); // Command IDLE fail } (void)SPI_Receive_byte(); // Dummy SPI cycle /* Initialize SD Command */ while(SD_SendCommand(SD_CMD1|0x40,SD_OK)) { Watchdog_Reset(); } (void)SPI_Receive_byte(); // Dummy SPI cycle /* Block Length */ gu8SD_Argument.lword = SD_BLOCK_SIZE; if(SD_SendCommand(SD_CMD16|0x40,SD_OK)) { return(1); // Command IDLE fail } SPI_High_rate(); SPI_Send_byte(0x00); SPI_Send_byte(0x00); //(void)SPI_Receive_byte(); // Dummy SPI cycle return(0); }
//读SD卡的多个block(实际测试过) //输入:u32 sector 扇区地址(sector值,非物理地址) // u8 *buffer 数据存储地址(大小至少512byte) // u8 count 连续读count个block //返回值:0: 成功 // other:失败 u8 SD_ReadMultiBlock(u32 sector, u8 *buffer, u8 count) { u8 r1; //SPIx_SetSpeed(SPI_SPEED_HIGH);//设置为高速模式 //如果不是SDHC,将sector地址转成byte地址 if(SD_Type!=SD_TYPE_V2HC)sector = sector<<9; //SD_WaitDataReady(); //发读多块命令 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=1; SPIx_ReadWriteByte(0xFF); if(count != 0)return count; //如果没有传完,返回剩余个数 else return 0; }
UINT8 SD_Write_Block(UINT32 u16SD_Block,UINT8 *pu8DataPointer) { UINT16 u16Counter; UINT8 SD_response; SPI_SS=ENABLE; gu8SD_Argument.lword=u16SD_Block; gu8SD_Argument.lword=gu8SD_Argument.lword<< SD_BLOCK_SHIFT; if(SD_SendCommand(SD_CMD24|0x40,SD_OK)) { SPI_SS=DISABLE; return(WRITE_COMMAND_FAILS); } WriteSPIByte(0xFE); for(u16Counter=0;u16Counter<BLOCK_SIZE;u16Counter++) WriteSPIByte(*pu8DataPointer++); WriteSPIByte(0xFF); // checksum Bytes not needed WriteSPIByte(0xFF); /* Buggy, replaced with //-- for(u16Counter=0;u16Counter<BLOCK_SIZE;u16Counter++) ; if((ReadSPIByte() & 0x0F) != 0x05) { SPI_SS=DISABLE; return(WRITE_DATA_FAILS); } */ //-- SD_response=0xFF; // #001 created this variable while (SD_response==0xFF) SD_response=ReadSPIByte(); // #001 wait for SD response <> 0xFF if((SD_response & 0x0F) != 0x05) // #001 checks if response = 0101 = data accepted { SPI_SS=DISABLE; return(WRITE_DATA_FAILS); } //-- Thx to Celso Monteiro while(SPI_Receive_byte()==0x00) ; // Dummy SPI cycle SPI_SS=DISABLE; return(OK); }
//读SD卡的一个block //输入:u32 sector 取地址(sector值,非物理地址) // u8 *buffer 数据存储地址(大小至少512byte) //返回值:0: 成功 // other:失败 u8 SD_ReadSingleBlock(u32 sector, u8 *buffer) { u8 r1; //设置为高速模式 SPIx_SetSpeed(SPI_SPEED_4); //如果不是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; }
/*************************************************************************************** * * *** SD_CBufferDataSectorWrite *** * * Description: Write a 512 bytes from the circular buffer as a data sector. * Assume: * - SD Card has been previously erased. * - Write a full sector at a time. * * Entry: void. * ****************************************************************************************/ void SD_CBufferDataSectorWrite(void) { UINT16 u16Counter; SPI_SS = ENABLE; gu8SD_Argument.lword = u32DataSector++; // Set WRITE_BLOCK command argument // to the current data segment gu8SD_Argument.lword = gu8SD_Argument.lword << SD_BLOCK_SHIFT; // Convert sector number to // byte address if (SD_SendCommand(SD_CMD24 | 0x40, SD_OK)) // WRITE_BLOCK command { SPI_SS = DISABLE; return; } WriteSPIByte(0xFE); // Start Block Token for (u16Counter = 0; u16Counter < BLOCK_SIZE; u16Counter++) // Write the block WriteSPIByte(FromCBuffer()); WriteSPIByte(0xFF); // checksum Bytes not needed WriteSPIByte(0xFF); // for(u16Counter=0;u16Counter<BLOCK_SIZE;u16Counter++); // if((ReadSPIByte() & 0x0F) != 0x05) // Read the status token. // Correct response is 0x05 // Foust p5. while ((SPI_Receive_byte() & 0x0F) != 0x05) ; // { // SPI_SS=DISABLE; // return; // } while (SPI_Receive_byte() == 0x00) ; // Wait while the card is busy SPI_SS = DISABLE; SD_CLKDelay(1); // 8 dummy clocks return; }
BYTE ReadBegin(DWORD sector){//读数据前的初始化 BYTE rtn; WORD cnt=0; SPI_SetSpeedHigh();//设定SPI到高速模式 rtn = SD_SendCommand(17,sector<<9);//读命令 if(rtn!=0x00) return 1; CS_LOW(); //等数据的开始 while(SPI_ByteRW(0xFF)!=0xFE){ if((cnt++)==0xFFFF){ CS_HIGH(); return 2;//超时退出 } } return 0; }
UINT8 SD_Write_Block(UINT32 u16SD_Block,UINT8 *pu8DataPointer) { UINT16 u16Counter; T32_8 gu8SD_Argument; /* Check for Write Protection */ if(SD_PROTECTED) return(WRITE_PROTECTED); SD_ENABLE; gu8SD_Argument.lword=u16SD_Block; gu8SD_Argument.lword=gu8SD_Argument.lword<< SD_BLOCK_SHIFT; if(SD_SendCommand(SD_CMD24|0x40,gu8SD_Argument,SD_OK)) { SD_DISABLE; return(WRITE_COMMAND_FAILS); } WriteSPIByte(SDhandle,0xFE); for(u16Counter=0;u16Counter<BLOCK_SIZE;u16Counter++) WriteSPIByte(SDhandle,*pu8DataPointer++); WriteSPIByte(SDhandle,0xFF); // checksum Bytes not needed WriteSPIByte(SDhandle,0xFF); for(u16Counter=0;u16Counter<BLOCK_SIZE;u16Counter++) ; if((ReadSPIByte(SDhandle) & 0x0F) != 0x05) { SD_DISABLE; return(WRITE_DATA_FAILS); } while(ReadSPIByte(SDhandle)==0x00) ; // Dummy SPI cycle SD_DISABLE; return(OK); }
// Read a 512 bytes sector on the SD Card // uiSector : Sector number // pbyReadData : pointer to a 512 bytes buffer that will be filled with secotr data if successful // return : true if data read successully, false otherwise int SD_Read(UINT32 uiSector, UINT8* pbyReadData) { int bSuccess = 1; UINT32 uiAddress = uiSector * 512; SD_Ncc(); // Send single read command SD_SendCommand(17, uiAddress); UINT8 uiResponse = SD_GetR1Response(); if (uiResponse != 0) { printf("SD Card read data failed. Error code : %02X\n", uiResponse); return 0; } // Wait for data token UINT8 uiDataToken = 0; int iNbTry = 0; while (uiDataToken != 0xFE && iNbTry < 2000) { uiDataToken = SD_ReadByte(); iNbTry++; } if (uiDataToken != 0xFE) { printf("SD Card read data timeout. Error code : %02X\n", uiDataToken); return 0; } // Read sector int i; for (i = 0; i < 512; i++) { pbyReadData[i] = SD_ReadByte(); } // Dummy read CRC SD_ReadByte(); SD_ReadByte(); return bSuccess; }
/***************************************************************************** * **************SD_Write_Block************ * * Description: Write a 512 byte sector (block) to the SD card. * * Inputs: u16SD_Block - the sector (block) number where the block is * to be written. * pu8DataPointer - the 512 byte buffer that is to be written * to the SD card. * *****************************************************************************/ UINT8 SD_Write_Block(UINT32 u16SD_Block, UINT8 *pu8DataPointer) { UINT16 u16Counter; SPI_SS = ENABLE; gu8SD_Argument.lword = u16SD_Block; // Set WRITE_BLOCK command argument gu8SD_Argument.lword = gu8SD_Argument.lword << SD_BLOCK_SHIFT; // Convert sector number to // byte address if (SD_SendCommand(SD_CMD24 | 0x40, SD_OK)) // WRITE_BLOCK command { SPI_SS = DISABLE; return (WRITE_COMMAND_FAILS); } WriteSPIByte(0xFE); // Start Block Token for (u16Counter = 0; u16Counter < BLOCK_SIZE; u16Counter++) // Write the block WriteSPIByte(*pu8DataPointer++); WriteSPIByte(0xFF); // checksum Bytes not needed WriteSPIByte(0xFF); for (u16Counter = 0; u16Counter < BLOCK_SIZE; u16Counter++) ; if ((ReadSPIByte() & 0x0F) != 0x05) // Read the status token. // Correct response is 0x05 // Foust p5. { SPI_SS = DISABLE; return (WRITE_DATA_FAILS); } while (SPI_Receive_byte() == 0x00) ; // Wait while the card is busy SPI_SS = DISABLE; SD_CLKDelay(1); // 8 dummy clocks return (OK); }
//在指定扇区,从offset开始读出bytes个字节 //输入:u32 sector 扇区地址(sector值,非物理地址) // u8 *buf 数据存储地址(大小<=512byte) // u16 offset 在扇区里面的偏移量 // u16 bytes 要读出的字节数 //返回值:0: 成功 // other:失败 u8 SD_Read_Bytes(unsigned long address,unsigned char *buf,unsigned int offset,unsigned int bytes) { u8 r1; u16 i=0; r1=SD_SendCommand(CMD17,address<<9,0);//发送读扇区命令 if(r1)return r1; //应答不正确,直接返回 SD_CS=0;//选中SD卡 if(SD_GetResponse(0xFE))//等待SD卡发回数据起始令牌0xFE { SD_CS=1; //关闭SD卡 return 1;//读取失败 } for(i=0; i<offset; i++)SPIx_ReadWriteByte(0xff); //跳过offset位 for(; i<offset+bytes; i++)*buf++=SPIx_ReadWriteByte(0xff); //读取有用数据 for(; i<512; i++) SPIx_ReadWriteByte(0xff); //读出剩余字节 SPIx_ReadWriteByte(0xff);//发送伪CRC码 SPIx_ReadWriteByte(0xff); SD_CS=1;//关闭SD卡 return 0; }
void SD_Write_Block(PTR_LBA_APP_STRUCT lba_data_ptr) { uint_32 u32Counter; gu8SD_Argument.lword = lba_data_ptr->offset; while(SPI_Receive_byte()==0x00) { Watchdog_Reset(); } if(SD_SendCommand(SD_CMD24|0x40,SD_OK)) { return; // Command IDLE fail } SPI_Send_byte(0xFE); for(u32Counter=0;u32Counter<lba_data_ptr->size;u32Counter++) { SPI_Send_byte(*(lba_data_ptr->buff_ptr + u32Counter)); } SPI_Send_byte(0xFF); // checksum Bytes not needed SPI_Send_byte(0xFF); if((SPI_Receive_byte() & 0x0F) != 0x05) { // return; // Command fail } while(SPI_Receive_byte()==0x00) { Watchdog_Reset(); } // Dummy SPI cycle return; }
//把SD卡设置到挂起模式 //返回值:0,成功设置 // 1,设置失败 u8 SD_Idle_Sta(void) { u16 i; u8 retry; for(i=0; i<0xf00; i++); //纯延时,等待SD卡上电完成 //先产生>74个脉冲,让SD卡自己初始化完成 for(i=0; i<10; i++)SPIx_ReadWriteByte(0xFF); //-----------------SD卡复位到idle开始----------------- //循环连续发送CMD0,直到SD卡返回0x01,进入IDLE状态 //超时则直接退出 retry = 0; do { //发送CMD0,让SD卡进入IDLE状态 i = SD_SendCommand(CMD0, 0, 0x95); retry++; } while((i!=0x01)&&(retry<200)); //跳出循环后,检查原因:初始化成功?or 重试超时? if(retry==200)return 1; //失败 return 0;//成功 }
uint_8 SD_ReadCSD(void) { uint_8 i; /*Body*/ if(SD_SendCommand(SD_CMD9|0x40,SD_OK)) { return(4); } while(i!=0xFE) i=SPI_Receive_byte(); for(i=0;i<16;i++) vSD_CSD[i]=SPI_Receive_byte(); (void)SPI_Receive_byte(); (void)SPI_Receive_byte(); (void)SPI_Receive_byte(); return(0); }/*EndBody*/