📄 mmc.c
字号:
//-------------------------------------------------------------------------
#include <avr/io.h>
#include "mmc.h"
#include "spi.h"
//-------------------------------------------------------------------------
#define CS PB4
#define CSH PORTB|=_BV(CS)
#define CSL PORTB&=~_BV(CS)
//-------------------------------------------------------------------------
void mmcInit(void){
spiInit(); // initialize SPI interface
DDRB|=_BV(PB4); // release chip select,low power selcet
CSH;
}
//-------------------------------------------------------------------------
uint8_t mmcReset_1(void){
uint8_t i,retry,r1;
retry=0;
do{
for(i=0;i<10;i++) spiTransferByte(0xFF); //send dummy at CS high(dummy argument又叫哑元变量 )
r1=mmcSendCommand(MMC_GO_IDLE_STATE, 0); // resetting card
retry++;
if(retry>10) return -1;
} while(r1 != MMC_R1_IDLE_STATE);
retry=0;
do{
r1=mmcSendCommand(MMC_SEND_OP_COND, 0); // initializing card
retry++;
if(retry>100) return -1;
} while(r1!=0);
mmcSendCommand(MMC_CRC_ON_OFF, 0); // turn off CRC checking
mmcSendCommand(MMC_SET_BLOCKLEN, 512); // set block len 512 bytes
return 0;
}
//-------------------------------------------------------------------------
uint8_t mmcReset(void){
uint8_t i;
for(i=0;i<50;i++)if(mmcReset_1()==0)return 0;
return -1;
}
//-------------------------------------------------------------------------
uint8_t mmcSendCommand(uint8_t cmd, uint32_t arg){
uint8_t r1;
CSL; // assert chip select
r1 = mmcCommand(cmd, arg); // issue the command
CSH; // release chip select
return r1;
}
//-------------------------------------------------------------------------
uint8_t mmcRead(uint32_t sector, uint8_t* buffer ){
uint8_t r1;
uint16_t i;
CSL; // assert chip select
r1 = mmcCommand(MMC_READ_SINGLE_BLOCK, sector<<9); // issue command,argument is the data address,the sector contains 512Byte,so leftshift 9bits,so the sector is just the serial number
if(r1 != 0)return r1;
while(spiTransferByte(0xFF)!=MMC_STARTBLOCK_READ);// wait for block start
for(i=0; i<0x200; i++){//0x200即读了512个,2的9次
*buffer++ = spiTransferByte(0xFF); // read in data
}
spiTransferByte(0xFF); // read 16-bit CRC
spiTransferByte(0xFF); //ba crc du wan cai neng pai gan jing
CSH; // release chip select,you fen zhu le
return 0;
}
//-------------------------------------------------------------------------
uint8_t mmcWrite(uint32_t sector, uint8_t* buffer){
uint8_t r1;
uint16_t i;
CSL; // assert chip select
r1 = mmcCommand(MMC_WRITE_BLOCK,sector<<9); // issue command ????????
if(r1 != 0)return r1; //return r1 for further judgement in subfunctions
spiTransferByte(0xFF); // send dummy
spiTransferByte(MMC_STARTBLOCK_WRITE); // send data start token,indicate data will follow,arouse the slaver
for(i=0; i<512; i++){
spiTransferByte(*buffer++); // write data
}
spiTransferByte(0xFF); // write 16-bit CRC (dummy values)
spiTransferByte(0xFF);
r1 = spiTransferByte(0xFF); // read data response token
if((r1&MMC_DR_MASK)!=MMC_DR_ACCEPT)return r1; //the mask get the lower five bits(Higher bits are all ones),compared with 0x05(MMC_DR_ACCEPT)
while(!spiTransferByte(0xFF)); // wait until card not busy(wait for the high level)
CSH; // release chip select
return 0;
}
//-------------------------------------------------------------------------
uint8_t mmcCommand(uint8_t cmd, uint32_t arg){
uint8_t r1,retry=0;
spiTransferByte(cmd|0x40); // send command
spiTransferByte(arg>>24);
spiTransferByte(arg>>16);
spiTransferByte(arg>>8);
spiTransferByte(arg);
spiTransferByte(0x95); // crc valid only for MMC_GO_IDLE_STATE
// end command
// wait for response
// if more than 8 retries, card has timed-out
// return the received 0xFF
while((r1=spiTransferByte(0xFF))==0xFF)if(retry++>8)break;
// return response
return r1;
}
//-------------------------------------------------------------------------
//Routine for reading CID Registers from MMC/SD-Card (16Bytes)
//Return 0 if no Error.
uint8_t Read_CID_MMC(uint8_t *buffer){
uint8_t r1,i;
CSL; // assert chip select
r1 = mmcCommand(MMC_SEND_CID,0); // reading CID Registers
if(r1 != 0)return r1;
while(spiTransferByte(0xFF)!=MMC_STARTBLOCK_READ);// wait for block start
for(i=0; i<16; i++){
*buffer++=spiTransferByte(0xFF); // read in data 16Byte
}
spiTransferByte(0xFF); // read 16-bit CRC
spiTransferByte(0xFF);
CSH; // release chip select
return(0);
}
//-------------------------------------------------------------------------
//Routine for reading CSD Registers from MMC/SD-Card (16Bytes)
//Return 0 if no Error.
uint8_t Read_CSD_MMC(uint8_t *buffer){
uint8_t r1,i;
CSL; // assert chip select
r1 = mmcCommand(MMC_SEND_CSD,0); // reading CSD Registers
if(r1 != 0)return r1;
while(spiTransferByte(0xFF)!=MMC_STARTBLOCK_READ);// wait for block start
for(i=0; i<16; i++){
*buffer++=spiTransferByte(0xFF); // read in data
}
spiTransferByte(0xFF); // read 16-bit CRC
spiTransferByte(0xFF);
CSH;
return(0);
}
//-------------------------------------------------------------------------
//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(void){
uint8_t i,buffer[16];
struct MMC_VOLUME_INFO vinf;
for(i=0;i<16;i++)buffer[i]=0;
Read_CSD_MMC(buffer);
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;
vinf.sector_multiply=buffer[9]&0x03;
vinf.sector_multiply<<=1;
vinf.sector_multiply+=(buffer[10]&0x80)>>7;
//SD的容量
vinf.size_MB=vinf.sector_count>>(9-vinf.sector_multiply);
for(i=0;i<16;i++)buffer[i]=0;
Read_CID_MMC(buffer);
//SD的名称
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
}
//-------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -