⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 f34x_msd_mmc.c

📁 C8051F340读写SD卡的程序
💻 C
📖 第 1 页 / 共 3 页
字号:
//-----------------------------------------------------------------------------
// F34x_MSD_MMC.c
//-----------------------------------------------------------------------------
// Copyright 2006 Silicon Laboratories, Inc.
// http://www.silabs.com
//
// Program Description:
//
// MMC FLASH is used for storing the log entries.  Each entry contains
// the temperature in hundredths of a degree C, the day, hour, minute, and
// second that the reading was taken.  The LogUpdate function stores log
// entries in an external memory buffer and then writes that buffer out to the
// MMC when it is full.  Communication with the MMC is performed through the 
// MMC access functions.  These functions provide transparent MMC access to 
// the higher level functions (Logging functions).  The MMC interface is broken
// into two pieces.  The high level piece consists of the user callable MMC
// access functions (MMC_FLASH_Read, MMC_FLASH_Write, MMC_FLASH_Clear, 
// MMC_FLASH_MassErase).  These functions are called by the user to execute
// data operations on the MMC.  They break down the data operations into MMC
// commands.  The low level piece consists of a single command execution
// function (MMC_Command_Exec) which is called by the MMC data manipulation
// functions.  This function is called every time a command must be sent to the
// MMC.  It handles all of the required SPI traffic between the Silicon 
// Laboratories device and the MMC.
//
//
// How To Test:    See Readme.txt
//
//
// FID:            34X000043
// Target:         C8051F34x
// Tool chain:     Keil
// Command Line:   See Readme.txt
// Project Name:   F34x_USB_MSD
//
// Release 1.1
//    -All changes by PKC
//    -09 JUN 2006
//    -Replaced SFR definitions file "c8051f320.h" with "c8051f340.h"
//    -Corrected "SPIDAT" to "SPI0DAT" in function Write_Read_Spi_Byte
//
// Release 1.0
//    -Initial Release
//


//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------

#include "F34x_MSD_Definitions.h"
#include "c8051f340.h"                 // SFR declarations
#include <stdio.h>
#include "F34x_MSD_USB_Main.h"					// Has SYSCLK #define'd
#include "F34x_MSD_Physical_Settings.h"
#include "F34x_MSD_MMC.h"
#include <intrins.h>


// Constants that define available card sizes, 8MB through 128MB                                       
#define PS_8MB       8388608L
#define PS_16MB      16777216L
#define PS_32MB      33554432L
#define PS_64MB      67108864L
#define PS_128MB     134217728L

#define ERROR_CODE	0xFFFF
#define BUFFER_SIZE 16

//#define NSSMD0 SLVSEL

// Erase group size = 16 MMC FLASH sectors
#define PHYSICAL_GROUP_SIZE     (PHYSICAL_BLOCK_SIZE * 16)

// Command table value definitions
// Used in the MMC_Command_Exec function to 
// decode and execute MMC command requests
#define     EMPTY  0
#define     YES   1
#define     NO    0
#define     CMD   0
#define     RD    1
#define     WR    2
#define     R1    0
#define     R1b   1
#define     R2    2
#define     R3    3

// Start and stop data tokens for single and multiple
// block MMC data operations
#define     START_SBR      0xFE
#define     START_MBR      0xFE
#define     START_SBW      0xFE
#define     START_MBW      0xFC
#define     STOP_MBW       0xFD

// Mask for data response Token after an MMC write
#define     DATA_RESP_MASK 0x11

// Mask for busy Token in R1b response
#define     BUSY_BIT       0x80

// Command Table Index Constants:
// Definitions for each table entry in the command table.
// These allow the MMC_Command_Exec function to be called with a
// meaningful parameter rather than a number.
#define     GO_IDLE_STATE            0
#define     SEND_OP_COND             1
#define     SEND_CSD                 2
#define     SEND_CID                 3
#define     STOP_TRANSMISSION        4
#define     SEND_STATUS              5
#define     SET_BLOCKLEN             6
#define     READ_SINGLE_BLOCK        7
#define     READ_MULTIPLE_BLOCK      8
#define     WRITE_BLOCK              9
#define     WRITE_MULTIPLE_BLOCK    10
#define     PROGRAM_CSD             11
#define     SET_WRITE_PROT          12
#define     CLR_WRITE_PROT          13
#define     SEND_WRITE_PROT         14
#define     TAG_SECTOR_START        15
#define     TAG_SECTOR_END          16
#define     UNTAG_SECTOR            17
#define     TAG_ERASE_GROUP_START   18
#define     TAG_ERASE_GROUP_END     19
#define     UNTAG_ERASE_GROUP       20
#define     ERASE                   21
#define     LOCK_UNLOCK             22
#define     READ_OCR                23
#define     CRC_ON_OFF              24

//-----------------------------------------------------------------------------
// UNIONs, STRUCTUREs, and ENUMs
//-----------------------------------------------------------------------------
typedef union LONG {                   // byte-addressable LONG
  long l;
  unsigned char b[4];
} LONG;

typedef union INT {                    // byte-addressable INT
  int i;
  unsigned char b[2];
} INT;

typedef union {                        // byte-addressable unsigned long
    unsigned long l;
    unsigned char b[4];
              } ULONG;

typedef union {                        // byte-addressable unsigned int
    unsigned int i;
    unsigned char b[2];
              } UINT;

// This structure defines entries into the command table;
typedef struct {
    unsigned char command_byte;      // OpCode;
    unsigned char arg_required;      // Indicates argument requirement;
    unsigned char CRC;               // Holds CRC for command if necessary;
    unsigned char trans_type;        // Indicates command transfer type;
    unsigned char response;          // Indicates expected response;
    unsigned char var_length;        // Indicates varialble length transfer;
               } COMMAND;

// Command table for MMC.  This table contains all commands available in SPI
// mode;  Format of command entries is described above in command structure
// definition;
COMMAND code command_list[25] = {
    { 0,NO ,0x95,CMD,R1 ,NO },    // CMD0;  GO_IDLE_STATE: reset card;
    { 1,NO ,0xFF,CMD,R1 ,NO },    // CMD1;  SEND_OP_COND: initialize card;
    { 9,NO ,0xFF,RD ,R1 ,NO },    // CMD9;  SEND_CSD: get card specific data;
    {10,NO ,0xFF,RD ,R1 ,NO },    // CMD10; SEND_CID: get card identifier;
    {12,NO ,0xFF,CMD,R1 ,NO },    // CMD12; STOP_TRANSMISSION: end read;
    {13,NO ,0xFF,CMD,R2 ,NO },    // CMD13; SEND_STATUS: read card status;
    {16,YES,0xFF,CMD,R1 ,NO },    // CMD16; SET_BLOCKLEN: set block size;
    {17,YES,0xFF,RD ,R1 ,NO },    // CMD17; READ_SINGLE_BLOCK: read 1 block;
    {18,YES,0xFF,RD ,R1 ,YES},    // CMD18; READ_MULTIPLE_BLOCK: read > 1;
    {24,YES,0xFF,WR ,R1 ,NO },    // CMD24; WRITE_BLOCK: write 1 block;
    {25,YES,0xFF,WR ,R1 ,YES},    // CMD25; WRITE_MULTIPLE_BLOCK: write > 1;
    {27,NO ,0xFF,CMD,R1 ,NO },    // CMD27; PROGRAM_CSD: program CSD;
    {28,YES,0xFF,CMD,R1b,NO },    // CMD28; SET_WRITE_PROT: set wp for group;
    {29,YES,0xFF,CMD,R1b,NO },    // CMD29; CLR_WRITE_PROT: clear group wp;
    {30,YES,0xFF,CMD,R1 ,NO },    // CMD30; SEND_WRITE_PROT: check wp status;
    {32,YES,0xFF,CMD,R1 ,NO },    // CMD32; TAG_SECTOR_START: tag 1st erase;
    {33,YES,0xFF,CMD,R1 ,NO },    // CMD33; TAG_SECTOR_END: tag end(single);
    {34,YES,0xFF,CMD,R1 ,NO },    // CMD34; UNTAG_SECTOR: deselect for erase;
    {35,YES,0xFF,CMD,R1 ,NO },    // CMD35; TAG_ERASE_GROUP_START;
    {36,YES,0xFF,CMD,R1 ,NO },    // CMD36; TAG_ERASE_GROUP_END;
    {37,YES,0xFF,CMD,R1 ,NO },    // CMD37; UNTAG_ERASE_GROUP;
    {38,YES,0xFF,CMD,R1b,NO },    // CMD38; ERASE: erase all tagged sectors;
    {42,YES,0xFF,CMD,R1b,NO },    // CMD42; LOCK_UNLOCK;
    {58,NO ,0xFF,CMD,R3 ,NO },    // CMD58; READ_OCR: read OCR register;
    {59,YES,0xFF,CMD,R1 ,NO }    // CMD59; CRC_ON_OFF: toggles CRC checking;
                              };

//-----------------------------------------------------------------------------
// Global VARIABLES
//-----------------------------------------------------------------------------

// Removed these. It doesn't work correctly on every MMC card, and we need
// all the resources we can get.
xdata unsigned long PHYSICAL_SIZE;     // MMC size variable;  Set during
                                       // initialization;

xdata unsigned long PHYSICAL_BLOCKS;   // MMC block number;  Computed during
                                       // initialization;

bdata bit Is_Initialized;
 
xdata char LOCAL_BLOCK[BUFFER_SIZE]; 
#define SEND__IN_FUNCTION

#ifdef __F326_VER__ 
static unsigned char Write_Read_Spi_Byte(unsigned char byte);
#endif

#ifdef SEND__IN_FUNCTION 
static unsigned char Write_Read_Spi_Byte(unsigned char byte);
#endif

void Wait_ms(unsigned int count);
void Wait_ns(unsigned int count);

extern BYTE xdata Scratch[PHYSICAL_BLOCK_SIZE];
extern READ_BYTES(unsigned char* pchar,unsigned int len);
extern WRITE_BYTES(unsigned char* pchar,unsigned int len);

#ifdef __F326_VER__ 
#define BACK_FROM_ERROR \
{\
  Write_Read_Spi_Byte(0xFF);\
  SCS = 1;\
  Write_Read_Spi_Byte(0xFF);\
  return ERROR_CODE; \
}
#else 
#define BACK_FROM_ERROR \
{\
  SPI0DAT = 0xFF; \
  while(!SPIF){} \
  SPIF = 0; \
  NSSMD0 = 1;\
  SPI0DAT = 0xFF;\
  while(!SPIF){}  \
  SPIF = 0;  \                      
  return ERROR_CODE; \
}
#endif 
	

//----------------------------------------------------------------------------
// SPI0_Init
//----------------------------------------------------------------------------
//
// Configure SPI0 for 8-bit, 2MHz SCK, Master mode, polled operation, data
// sampled on 1st SCK rising edge.
//
// Parameters   :
// Return Value :
//----------------------------------------------------------------------------

void SPI_Init (void)
{
#ifdef __F326_VER__
#else
  Is_Initialized = 0;
  SPI0CFG = 0x70;                     // data sampled on rising edge, clk
                                       // active low,
                                       // 8-bit data words, master mode;

  SPI0CN = 0x0F;                      // 4-wire mode; SPI enabled; flags
                                       // cleared

#ifdef __F340_VER__
  SPI0CKR = 119;
  NSSMD0 = 1;
#else
  SPI0CKR = SYSCLK/2/10000000;      //119;  // SPI clock <= 10MHz
#endif
#endif
}

sbit Led1 = P2^2;
sbit Led2 = P2^3;



#define MMC_Show_Activity() { if(Led1) { Led1=0;Led2=1;} else { Led1=1;Led2=0; } }

//-----------------------------------------------------------------------------
// MMC_Command_Exec
//-----------------------------------------------------------------------------
//
// This function generates the necessary SPI traffic for all MMC SPI commands.
// The three parameters are described below:
// 
// Cmd:      This parameter is used to index into the command table and read
//           the desired command.  The Command Table Index Constants allow the
//           caller to use a meaningful constant name in the Cmd parameter 
//           instead of a simple index number.  For example, instead of calling 
//           MMC_Command_Exec (0, argument, pchar) to send the MMC into idle 
//           state, the user can call 
//           MMC_Command_Exec (GO_IDLE_STATE, argument, pchar);
//
// argument: This parameter is used for MMC commands that require an argument.
//           MMC arguments are 32-bits long and can be values such as an
//           an address, a block length setting, or register settings for the
//           MMC.
//
// pchar:    This parameter is a pointer to the local data location for MMC 
//           data operations.  When a read or write occurs, data will be stored
//           or retrieved from the location pointed to by pchar.
//
// The MMC_Command_Exec function indexes the command table using the Cmd 
// parameter. It reads the command table entry into memory and uses information
// from that entry to determine how to proceed.  Returns the 16-bit card 
// response value;
//

unsigned int MMC_Command_Exec (unsigned char cmd_loc, unsigned long argument,
                           unsigned char *pchar)
{
  xdata unsigned char loopguard;
  idata COMMAND current_command;      // Local space for the command table 
                                       // entry;
  idata ULONG long_arg;               // Union variable for easy byte 
                                       // transfers of the argument;
                                       // Static variable that holds the 
                                       // current data block length;
  static xdata unsigned int current_blklen = 512;
  unsigned long xdata old_blklen = 512;     // Temp variable to preserve data block
                                       // length during temporary changes;
  idata unsigned int counter = 0;     // Byte counter for multi-byte fields;
  idata UINT card_response;           // Variable for storing card response;
  idata unsigned char data_resp;      // Variable for storing data response;
  idata unsigned char dummy_CRC;      // Dummy variable for storing CRC field;
  unsigned char *plast; 
   
//   xdata unsigned char c;
                                     
  current_command = command_list[cmd_loc]; // Retrieve desired command table entry
										// from code space;
  card_response.i = 0;
#ifdef __F326_VER__
  Write_Read_Spi_Byte(0xFF);
  SCS = 0;
  Write_Read_Spi_Byte(0xFF);
  Write_Read_Spi_Byte(current_command.command_byte | 0x40);
#else
#ifdef SEND__IN_FUNCTION
  Write_Read_Spi_Byte(0xFF);
  NSSMD0 = 0;
  Write_Read_Spi_Byte(0xFF);
  Write_Read_Spi_Byte(current_command.command_byte | 0x40);
#else

  SPI0DAT = 0xFF;                     // Send buffer SPI clocks to ensure no
  while(!SPIF){}                      // MMC operations are pending;
  SPIF = 0;
  NSSMD0 = 0;                         // Select MMC by pulling CS low;
  SPI0DAT = 0xFF;                     // Send another byte of SPI clocks;
  while(!SPIF){}
  SPIF = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -