📄 sdmmc.c
字号:
/**************************************************************************************
//------------------ MMC/SD-Card Reading and Writing implementation -------------------
//FileName : mmc.c
//Function : Connect AVR to MMC/SD
//Created by : ZhengYanbo
//Created date : 15/08/2005
//Version : V1.2
//Last Modified: 19/08/2005
//Filesystem : Read or Write MMC without any filesystem
//CopyRight (c) 2005 ZhengYanbo
//Email: Datazyb_007@163.com
****************************************************************************************/
/*
读扇区方法:
1. Set_block_length(default is 512 bytes).Use set_block_length command.如果你的缓冲区是512字节,那么这个区一般不用设置.
2. Send block read command.我用的是cmd16
//Command 16 is for reading Blocks from MMC/SD-Card
unsigned char CMD[] = {0x51,0x00,0x00,0x00,0x00,0xFF};
3. Wait for block start token(is 0xFE)
//Read Start Byte form MMC/SD-Card (FEh/Start Byte)
while (Read_Byte_MMC() != 0xfe){};
4. Read 512 bytes out from your Card.
5. Read CRC bytes(2 bytes) 这里对我没有用处,空读就行了.
//CRC-Byte
Read_Byte_MMC();//CRC - Byte
Read_Byte_MMC();//CRC - Byte
6. Disable SD Card and return TRUE
另外请大家使用时候注意下面函数:
unsigned char MMC_Start_Read_Sector(unsigned long sector);
void MMC_get_data(unsigned int Bytes,unsigned char *buffer);
void MMC_get_data_LBA(unsigned long lba, unsigned int Bytes,unsigned char *buffer);
void MMC_GotoSectorOffset(unsigned long LBA,unsigned int offset);
void MMC_LBA_Close(void);
如果你的RAM足够大,那么你可以一次缓冲完一个sector,这些函数可以删除(因为我写这些函数时候,使用的CPU是8515) 如果使用例如MEGA8515这样的CPU,RAM不足1KB,你只能定义例如sectBuf[64]这样小的DATA BUFFER. 那么这些函数就可以保留,先使用MMC_Start_Read_Sector(unsigned long sector)打开一个LBA,时候再去读数据到你的循环缓冲区sectBuf[64],分8次完成一个LBA数据.
*/
#include "config.h"
#if USE_MMC
//BUFFER_TYPE sectorBuffer; //512 bytes for sector buffer
//--------------------------------------------------------------
uint16 readPos=0;
uint8 sectorPos=0;
uint8 LBA_Opened=0; //Set to 1 when a sector is opened.
uint8 Init_Flag; //Set it to 1 when Init is processing.
//---------------------------------------------------------------
// Prototypes
//---------------------------------------------------------------
void MMC_Port_Init(void);
uint8 Read_Byte_MMC(void);
//uint8 Read_Byte_MMC_Long(void);
void Write_Byte_MMC(uint8 value);
uint8 MMC_Read_Block(uint8 *CMD,uint8 *Buffer,uint16 Bytes);
uint8 Write_Command_MMC(uint8 *CMD);
uint8 Read_CSD_MMC(uint8 *Buffer);
uint8 Read_CID_MMC(uint8 *Buffer);
void delay_us(uint8 us);
//****************************************************************************
// Port Init
void MMC_Port_Init(void)
//****************************************************************************
{
//Config ports
MMC_DDR&=~(1<<SPI_MISO); //Set Pin MMC_DI as Input
MMC_DDR|=(1<<SPI_CLK); //Set Pin MMC_Clock as Output
MMC_DDR|=(1<<SPI_MOSI); //Set Pin MMC_DO as Output
MMC_DDR|=(1<<MMC_Chip_Select); //Set Pin MMC_Chip_Select as Output
//busy led port init
MMC_DDR|=(1<<SPI_Busy); //Set spi busy led port output
MMC_PORT|=(1<<SPI_Busy); //busy led off
MMC_Disable(); //Set MMC_Chip_Select to High,MMC/SD Invalid.
}
//****************************************************************************
//Routine for Init MMC/SD card(SPI-MODE)
uint8 MMC_Init(void)
//****************************************************************************
{
uint8 retry,temp,spimode,spispeeddub;
uint8 i;
uint8 CMD[] = {MMC_RESET,0x00,0x00,0x00,0x00,0x95};
//MMC_Port_Init(); //Init SPI port
spimode=SPCR;
spispeeddub=SPSR;
SPSR=0;
SPCR=0;
for(i=0;i<200;i++) //Wait MMC/SD ready...
{
NOP();
delay_us(255);
}
Init_Flag=1; //Set the init flag
MMC_Disable();
for (i=0;i<0x0f;i++)
{
Write_Byte_MMC(0xff); //send 74 clock at least!!!
}
//Send Command CMD0 to MMC/SD Card
retry=0;
do
{ //retry 200 times to send CMD0 command
temp=Write_Command_MMC(CMD);
retry++;
if(retry==200)
{ //time out
return(INIT_CMD0_ERROR);//CMD0 Error!
}
}
while(temp!=1);
//Send Command CMD1 to MMC/SD-Card
CMD[0] = MMC_INIT; //Command 1
CMD[5] = 0xFF;
retry=0;
do
{ //retry 100 times to send CMD1 command
temp=Write_Command_MMC(CMD);
retry++;
if(retry==100)
{ //time out
return(INIT_CMD1_ERROR);//CMD1 Error!
}
}
while(temp!=0);
Init_Flag=0; //Init is completed,clear the flag
MMC_Disable(); //set MMC_Chip_Select to high
SPCR=spimode;
SPSR=spispeeddub;
return(0); //All commands have been taken.
}
//****************************************************************************
//returns the :
// size of the card in MB ( ret * 1024^2) == bytes
// sector count and multiplier MB are in u08 == C_SIZE / (2^(9-C_SIZE_MULT))
// name of the media
void MMC_get_volume_info(VOLUME_INFO_TYPE *vinf)
//****************************************************************************
{
uint8 tmp[4],buffer[16];
#if !(HW_SPI_Mode)
uint8 spimode,spispeeddub;
spimode=SPCR;
spispeeddub=SPSR;
SPCR&=~(1<<SPIE);
#endif
// read the CSD register
Read_CSD_MMC(buffer);
// get the C_SIZE value. bits [73:62] of data
// [73:72] == buffer[6] && 0x03
// [71:64] == buffer[7]
// [63:62] == buffer[8] && 0xc0
vinf->sector_count = buffer[6] & 0x03;
vinf->sector_count <<= 8;
vinf->sector_count += buffer[7];
vinf->sector_count <<= 2;
vinf->sector_count += (buffer[8] & 0xc0) >> 6;
// get the val for C_SIZE_MULT. bits [49:47] of sectorBuffer.data
// [49:48] == buffer[5] && 0x03
// [47] == buffer[4] && 0x80
vinf->sector_multiply = buffer[9] & 0x03;
vinf->sector_multiply <<= 1;
vinf->sector_multiply += (buffer[10] & 0x80) >> 7;
// work out the MBs
// mega bytes in u08 == C_SIZE / (2^(9-C_SIZE_MULT))
vinf->size_MB = vinf->sector_count >> (9-vinf->sector_multiply);
// get the name of the card
Read_CID_MMC(buffer);
vinf->name[0] = buffer[3];
vinf->name[1] = buffer[4];
vinf->name[2] = buffer[5];
vinf->name[3] = buffer[6];
vinf->name[4] = buffer[7];
vinf->name[5] = 0x00; //end flag
/* //----------------------------------------------------------
// LCDclrscr();
//Print Product name on lcd
Com_putstring("Product:\r\n",10,&RTbuf_UART0);
Com_putstring(vinf->name,6,&RTbuf_UART0);
Com_putstring("\r\n",2,&RTbuf_UART0);
//Print Card Size(eg:128MB)
Com_putstring("Tot:",4,&RTbuf_UART0);
tmp[0]=((vinf->size_MB>>12)&0x0f)+0x30;
tmp[1]=(vinf->size_MB>>8)&0x0f+0x30;
tmp[2]=(vinf->size_MB>>4)&0x0f+0x30;
tmp[3]=vinf->size_MB&0x0f+0x30;
Com_putstring(tmp,4,&RTbuf_UART0);
Com_putstring("MB\r\n",4,&RTbuf_UART0);
Com_putstring("sector_mult:",12,&RTbuf_UART0);
// tmp[0]=((vinf->sector_multiply>>12)&0x0f)+0x30;
// tmp[1]=(vinf->sector_multiply>>8)&0x0f+0x30;
tmp[0]=(vinf->sector_multiply>>4)&0x0f+0x30;
tmp[1]=vinf->sector_multiply&0x0f+0x30;
Com_putstring(tmp,2,&RTbuf_UART0);
Com_putstring("\r\n",2,&RTbuf_UART0);
Com_putstring("sect_cnt:",9,&RTbuf_UART0);
tmp[0]=((vinf->sector_count>>12)&0x0f)+0x30;
tmp[1]=(vinf->sector_count>>8)&0x0f+0x30;
tmp[2]=(vinf->sector_count>>4)&0x0f+0x30;
tmp[3]=vinf->sector_count&0x0f+0x30;
Com_putstring(tmp,4,&RTbuf_UART0);
*/
#if !(HW_SPI_Mode)
SPCR=spimode;
SPSR=spispeeddub;
#endif
MMC_Disable();
}
//****************************************************************************
//Send a Command to MMC/SD-Card
//Return: the second byte of response register of MMC/SD-Card
uint8 Write_Command_MMC(uint8 *CMD)
//****************************************************************************
{
uint8 tmp;
uint8 retry=0;
uint8 i;
//set MMC_Chip_Select to high (MMC/SD-Card disable)
MMC_Disable();
//send 8 Clock Impulse
Write_Byte_MMC(0xFF);
//set MMC_Chip_Select to low (MMC/SD-Card active)
MMC_Enable();
//send 6 Byte Command to MMC/SD-Card
for (i=0;i<0x06;i++)
{
Write_Byte_MMC(*CMD++);
}
//get 16 bit response
Read_Byte_MMC(); //read the first byte,ignore it.
do
{ //Only last 8 bit is used here.Read it out.
tmp = Read_Byte_MMC();
retry++;
}
while((tmp==0xff)&&(retry<100));
return(tmp);
}
//****************************************************************************
//Routine for reading a byte from MMC/SD-Card
uint8 Read_Byte_MMC(void)
//****************************************************************************
{
uint8 temp=0;
uint8 i;
MMC_PORT&=~(1<<SPI_Busy);
//Software SPI
if(Init_Flag)
{
for (i=0; i<8; i++) //MSB First
{
MMC_PORT&=~(1<<SPI_CLK); //Clock Impuls (Low)
if(Init_Flag)
delay_us(200);
temp = (temp << 1) + ((MMC_PIN&(1<<SPI_MISO))>>SPI_MISO); //read mmc data out pin
MMC_PORT|=(1<<SPI_CLK); //set Clock Impuls High
if(Init_Flag)
delay_us(200);
}
}
else
{
#if !(HW_SPI_Mode)
SPDR=0xFF;
while(!(SPSR & 0x80)){};
temp=SPDR;
#else
Spi_SendReceive(&temp,1,1);
#endif
}
MMC_PORT|=(1<<SPI_Busy);
return (temp);
}
//****************************************************************************
//Routine for sending a byte to MMC/SD-Card
void Write_Byte_MMC(uint8 value)
//****************************************************************************
{
uint8 i;
MMC_PORT&=~(1<<SPI_Busy);
//Software SPI
if(Init_Flag){
for (i=0; i<8; i++)
{ //write a byte
if (((value >> (7-i)) & 0x01)==0x01)
MMC_PORT|=(1<<SPI_MOSI); //Send bit by bit(MSB First)
else
MMC_PORT&=~(1<<SPI_MOSI);
MMC_PORT&=~(1<<SPI_CLK); //set Clock Impuls low
if(Init_Flag)
delay_us(200);
MMC_PORT|=(1<<SPI_CLK); //set Clock Impuls High
if(Init_Flag)
delay_us(200);
}//write a byte
MMC_PORT|=(1<<SPI_MOSI); //set Output High
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -