mmc_lib.c
来自「用ATMEL AVR CPU开发MMC CARD 的MMC库」· C语言 代码 · 共 189 行
C
189 行
#include <avr/io.h>
#include "mmc_lib.h"
void mmc_send_byte(unsigned char data)
{
SPDR=data;
loop_until_bit_is_set(SPSR, SPIF); // wait for byte transmitted...
}
unsigned char mmc_write_cmd(char *cmd)
{
unsigned char i;
mmc_send_byte(0xFF); //Dummy delay 8 clocks
cbi(MMC_PORT, MMC_CS); //MMC Chip Select -> Low (activate)
for (i=0; i<6; i++) {//Send 6 Bytes
mmc_send_byte(*cmd++);
}
for(i=0; i<255; i++) {//waiting for response (!0xff)
mmc_send_byte(0xFF);
if (SPDR != 0xFF) {
return(SPDR);
}
}
return(SPDR); // TimeOut !
}
unsigned char mmc_init(void)
{
cbi(MMC_DDR, SPI_MISO); //MMC Data Out -> Input
sbi(MMC_DDR, SPI_CLK); //MMC Clock -> Output
sbi(MMC_DDR, SPI_MOSI); //MMC Data In -> Output
sbi(MMC_DDR, MMC_CS); //MMC Chip Select -> Output
sbi(MMC_PORT, MMC_CS); //MMC Chip Select -> High (deactivate)
SPCR = 1<<SPE | 1<<MSTR | 1<<SPR0; //SPI Enable, SPI Master Mode
unsigned char i;
for (i=0; i<15; i++) { //Pulse 80+ clocks to reset MMC
mmc_send_byte(0xFF);
}
unsigned char res;
char cmd[] = {0x40, 0x00, 0x00, 0x00, 0x00, 0x95}; //CMD0
res=mmc_write_cmd(cmd); //store result of reset command, should be 0x01
sbi(MMC_PORT, MMC_CS); //MMC Chip Select -> High (deactivate);
mmc_send_byte(0xFF);
if (res != 0x01) { //Response R1 from MMC (0x01: IDLE, The card is in idle state and running the initializing process.)
return(1);
}
cmd[0]=0x41;
cmd[5]=0xFF;
i=0;
while((mmc_write_cmd(cmd) != 0) && (i < 255)) {
sbi(MMC_PORT, MMC_CS); //MMC Chip Select -> High (deactivate);
mmc_send_byte(0xFF);
i++;
}
sbi(MMC_PORT, MMC_CS); //MMC Chip Select -> High (deactivate);
if (i < 255) {
return(0);
}
return(2);
}
unsigned char mmc_read_block(char *cmd, char *buffer, unsigned long count)
{
if (mmc_write_cmd(cmd) != 0x00) {
sbi(MMC_PORT, MMC_CS); //MMC Chip Select -> High (deactivate);
return(1); //wrong response!
}
unsigned char res=0xff;
unsigned long i=0;
while((res != 0xFE) && (i < 255)) { //wait for startbyte (0xFE)
mmc_send_byte(0xFF);
res=SPDR;
i++;
}
if (i >= 255) { //startbyte received ?
sbi(MMC_PORT, MMC_CS); //MMC Chip Select -> High (deactivate);
return(2);
}
for (i=0;i<count;i++)
{
mmc_send_byte(0xFF);
*buffer++ = SPDR;
}
//read 2 bytes CRC (not used);
mmc_send_byte(0xFF);
mmc_send_byte(0xFF);
sbi(MMC_PORT, MMC_CS); //MMC Chip Select -> High (deactivate);
return(0);
}
unsigned char mmc_read_sector(unsigned long sector, char *buffer)
{
char cmd[] = {0x51, 0x00, 0x00, 0x00, 0x00, 0xFF}; //CMD17
sector = sector << 9;
cmd[1] = (sector & 0xFF000000) >> 24;
cmd[2] = (sector & 0x00FF0000) >> 16;
cmd[3] = (sector & 0x0000FF00) >> 8;
return(mmc_read_block(cmd, buffer, 512));
}
unsigned char mmc_write_sector(unsigned long sector, char *buffer)
{
char cmd[] = {0x58, 0x00, 0x00, 0x00, 0x00, 0xFF}; //CMD24
sector = sector << 9;
cmd[1] = (sector & 0xFF000000) >> 24;
cmd[2] = (sector & 0x00FF0000) >> 16;
cmd[3] = (sector & 0x0000FF00) >> 8;
if (mmc_write_cmd(cmd) != 0x00) {
sbi(MMC_PORT, MMC_CS); //MMC Chip Select -> High (deactivate);
return(1); //cmd24 wrong response!
}
unsigned short i=0;
for (i=0;i<255;i++) { //delay before sending datablock to MMC
mmc_send_byte(0xFF);
}
mmc_send_byte(0xFE); //send startbyte
for (i=0;i<512;i++) { //send datablock to MMC
mmc_send_byte(*buffer++);
}
//write 2 dummy bytes to MMC (CRC);
mmc_send_byte(0xFF);
mmc_send_byte(0xFF);
unsigned char res=0x00;
i=0;
while((res != 0xFF) && (i < 255)) { //wait while MMC is busy!
mmc_send_byte(0xFF);
res=SPDR;
i++;
}
sbi(MMC_PORT, MMC_CS); //MMC Chip Select -> High (deactivate);
if (i<255) {
return(0);
}
else {
return(2);
}
}
unsigned char mmc_read_csd(char *buffer)
{
char cmd[] = {0x49,0x00,0x00,0x00,0x00,0xFF};
return(mmc_read_block(cmd, buffer, 16));
}
unsigned char mmc_read_cid(char *buffer)
{
char cmd[] = {0x4A,0x00,0x00,0x00,0x00,0xFF};
return(mmc_read_block(cmd, buffer, 16));
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?