野人的笔记 https://bbs.21ic.com/?79434 [收藏] [复制] [RSS]

日志

mmc的spi驱动

已有 1412 次阅读2005-12-2 10:38 |个人分类:单片机设计|系统分类:单片机


网络有人要mmcspi驱动,转载一个别人的程序:


这个程序是基于avr单片机的,使用了硬件spi接口,


导出了三个关键函数:


MMCReadSector(unsigned long sector, unsigned char *buf);


MMCWriteSector(unsigned long sector, unsigned char *buf);


MMCIdentify(void);


使用之前必须先调用函数MMCIdentify进行初始化.然后使用MMCReadSector,MMCWriteSector来进行访问.


mmc_spi.c






//###########################################################
// File: mmc_spi.c
//
// Read-/Writeroutines for MMC MultiMedia cards and
// SD SecureDigital cards in SPI mode.
//
// This will work only for MMC cards with 512 bytes block length !
// This will work only for MMC cards with a partition table !
//
//
//#########################################################################
// Last change: 21.05.2004
//#########################################################################
// holger.klabunde@t-online.de
// http://home.t-online.de/home/holger.klabunde/homepage.htm
//#########################################################################
// Compiler: AVR-GCC 3.2
//#########################################################################


#include <io.h>


#include "dos.h"


#ifdef MMC_CARD_SPI


//######################################################
unsigned char MMCCommand(unsigned char command, unsigned long adress)
//######################################################
{


 SPI_WRITE(0xFF);     //Dummy write
 SPI_WRITE(command);
 SPI_WRITE((unsigned char)(adress>>24)); //MSB of adress
 SPI_WRITE((unsigned char)(adress>>16));
 SPI_WRITE((unsigned char)(adress>>8));
 SPI_WRITE((unsigned char)adress);       //LSB of adress
 SPI_WRITE(0xFF);     //dummy checksum
 SPI_WRITE(0xFF);     //16 bit response
 SPI_WRITE(0xFF);


 return SPDR;          // only last 8 bits used
}


//######################################################
unsigned char MMCReadSector(unsigned long sector, unsigned char *buf)
//######################################################

{
 unsigned int i;
 unsigned char *p;
 unsigned long startadr;
 
 if(sector>=maxsect) return 1; //sectornumber too big


 p=buf; //using a pointer is much faster than indexing buf
 
 MMC_CS_OFF();


//calculate startadress of the sector
 startadr=sector * (unsigned long)BYTE_PER_SEC;


 MMCCommand(MMC_READ_BLOCK,startadr);


 do
  {
   SPI_WRITE(0xFF);
  }while(SPDR!=0xFE); // wait for card response
 
 
 for(i=0; i<BYTE_PER_SEC; i++)
  {
   SPI_WRITE(0xFF); // shift out a byte into SPDR
   *p++=SPDR;       // store byte in buffer
  }


 SPI_WRITE(0xFF); // 16 bit crc follows data
 SPI_WRITE(0xFF);


 MMC_CS_ON();


 return 0;
}


#ifdef DOS_WRITE
//######################################################
unsigned char MMCWriteSector(unsigned long sector, unsigned char *buf)
//######################################################

{
 unsigned int i;
 unsigned char *p, by;
 unsigned long startadr;


 if(sector>=maxsect) return 1; //sectornumber too big
 
 p=buf; //using a pointer is much faster than indexing buf


 MMC_CS_OFF();


//calculate startadress
 startadr=sector * (unsigned long)BYTE_PER_SEC;


 MMCCommand(MMC_WRITE_BLOCK,startadr);


 SPI_WRITE(0xFF); // do we need this TWO dummy writes ?
 SPI_WRITE(0xFF);


 SPI_WRITE(0xFE); // start block token


 for(i=0; i<BYTE_PER_SEC; i++)
  {
   SPI_WRITE(*p++);
  }


 SPI_WRITE(0xFF); // 16 bit crc follows data
 SPI_WRITE(0xFF);


 SPI_WRITE(0xFF); // read response
 by=SPDR & 0x1F;
 if(by != 0x05)   // data block accepted ?
  {
   MMC_CS_ON();
   return 1;
  }


 do
  {
   SPI_WRITE(0xFF);
  }while(SPDR !=0xFF); // wait til busy is gone


 MMC_CS_ON();


 return 0;
}
#endif //DOS_WRITE


//######################################################
unsigned char MMCIdentify(void)
//######################################################
{
 unsigned char by;
 unsigned int i;
 unsigned int c_size, c_size_mult, read_bl_len;
 unsigned long drive_size;


//Init SPI with a very slow transfer rate first !


//SPCR SPI Controlregister
// SPIE=0; //No SPI Interrupt
// SPE=1;  //SPI Enable
// DORD=0; //Send MSB first
// MSTR=1; //I am the master !
// CPOL=0; //SCK low if IDLE
// CPHA=0; //SPI Mode 0
// SPR1=1; //SPI Clock = f/128 = 125kHz @16MHz Clock
// SPR0=1; //or f/64 if SPI2X = 1 in SPSR register
 SPCR=0x53;


//SPSR SPI Statusregister
// SPI2X=1; //Double speed for SPI = 250kHz @16MHz Clock
// SPSR=0x01;
 SPSR=0x00;


 for(i=0; i<10; i++) SPI_WRITE(0xFF); // give min 74 clock pulses before
                                      // sending commands
 
 MMC_CS_OFF();


//send CMD0 for RESET
 SPI_WRITE(MMC_RESET); //command code CMD0
 SPI_WRITE(0x00);
 SPI_WRITE(0x00);
 SPI_WRITE(0x00);
 SPI_WRITE(0x00);
 SPI_WRITE(0x95); // CMD0 needs a checksum !
 SPI_WRITE(0xFF); // get 16 bit response high
 SPI_WRITE(0xFF); // get 16 bit response low
 by=SPDR;         // only last 8 bits neccessary


//repeat CMD1 til result=0
 do
  {
   by=MMCCommand(MMC_INIT,0);
  }while(by!=0);


//read CID
// MMCCommand(MMC_READ_CID,0); // nothing really interesting here


//read CSD Card Specific Data
 MMCCommand(MMC_READ_CSD,0);
 SPI_WRITE(0xFF); // ignore response 0xFE


 for(i=0; i<16; i++) //CSD has 128 bits -> 16 bytes
  {
   SPI_WRITE(0xFF);
   by=SPDR;
//   ShowHex(by);
   iob=by;
  }


 SPI_WRITE(0xFF); // 16 bit crc follows data
 SPI_WRITE(0xFF);


 c_size=iob[6] & 0x03; //bits 1..0
 c_size<<=10;
 c_size+=(unsigned int)iob[7]<<2;
 c_size+=iob[8]>>6;


 by= iob[5] & 0x0F;
 read_bl_len=1;
 read_bl_len<<=by;


 by=iob[9] & 0x03;
 by<<=1;
 by+=iob[10] >> 7;
 
 c_size_mult=1;
 c_size_mult<<=(2+by);


 drive_size=(unsigned long)(c_size+1) * (unsigned long)c_size_mult * (unsigned long)read_bl_len;
 maxsect= drive_size / BYTE_PER_SEC;


 MMC_CS_ON();


//switch to high speed SPI
// SPR1=0; //SPI Clock = f/4 = 4MHz @16MHz Clock
// SPR0=0; //or f/2 if SPI2X = 1 in SPSR register
 SPCR=0x50;


//SPSR SPI Statusregister
// SPI2X=1; //Double speed for SPI = 8MHz @16MHz Clock
 SPSR=0x01;


 return 0;
}



#endif //MMC_CARD_SPI






mmc_spi.h






//#########################################################################


// File: mmc_spi.h


//


// MMC MultiMediaCard and SD SecureDigital definitions for SPI protocol


//


//#########################################################################


// Last change: 21.05.2004


//#########################################################################


// holger.klabunde@t-online.de


// http://home.t-online.de/home/holger.klabunde/homepage.htm


//#########################################################################


// Compiler: AVR-GCC 3.2


//#########################################################################


 


#ifndef __MMC_CARD_SPI_H


#define __MMC_CARD_SPI_H


 


#define SPI_WRITE(a) { SPDR=(a); while(!(SPSR&0x80)); }


 


// you don't really need the /CS pin. it works also if /CS is


// connected to ground.


#define MMC_CS         4     //Pin number for MMC_CS


#define MMC_CS_PORT     PORTB   //Port where MMC_CS is located


#define MMC_CS_ON()       sbi(MMC_CS_PORT,MMC_CS);


#define MMC_CS_OFF()     cbi(MMC_CS_PORT,MMC_CS);


 


// MMC/SD commands


#define MMC_RESET          0x40 + 0


#define MMC_INIT              0x40 + 1


#define MMC_READ_CSD          0x40 + 9


#define MMC_READ_CID           0x40 + 10


#define MMC_STOP_TRANSMISSION      0x40 + 12


#define MMC_SEND_STATUS            0x40 + 13


#define MMC_SET_BLOCKLEN  0x40 + 16


#define MMC_READ_BLOCK             0x40 + 17


#define MMC_READ_MULTI_BLOCK 0x40 + 18


#define MMC_WRITE_BLOCK           0x40 + 24


#define MMC_WRITE_MULTI_BLOCK      0x40 + 25


 


//prototypes


extern unsigned char MMCReadSector(unsigned long sector, unsigned char *buf);


extern unsigned char MMCWriteSector(unsigned long sector, unsigned char *buf);


extern unsigned char MMCIdentify(void);


 


#endif







相关硬件连接的图片,参考一下,需要注意电压的匹配问题!如果看不到请点击图片放大








路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)