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

📄 sd-pictail.c

📁 Example Of Using SD/MMC Card with PIC
💻 C
字号:
/*
** SD/MMC card interface 
**
** modified module for use with SD/MMC card PICTail plus (AC164122)
** (top connector, use SPI1 peripheral)
**
** v.2.0 FZ 9/10/2007
** 
*/

#include <p24fj128ga010.h>
#include "sdmmc.h"

// I/O definitions
#define SDWP    _RF1    // Write Protect input
#define SDCD    _RF0    // Card Detect input
#define SDCS    _RB1    // Card Select output

// SD card commands
#define RESET                       0 // a.k.a. GO_IDLE (CMD0)
#define INIT                        1 // a.k.a. SEND_OP_COND (CMD1)
#define SEND_CSD                    9
#define SEND_CID                    10
#define SET_BLEN                    16
#define READ_SINGLE                 17
#define WRITE_SINGLE                24
#define APP_CMD                     55
#define SEND_APP_OP                 41

// SD card responses
#define DATA_START                  0xFE
#define DATA_ACCEPT                 0x05


void initSD( void)
{
    _TRISF8 = 0;        // SDO1 output pin
    _TRISF7 = 1;        // SDI1 input pin
    _TRISF6 = 0;        // SCK1 output pin

//Card I/O's init
    _TRISF0 = 1;        // Card Detect input
    _TRISF1 = 1;        // Write Protect input
    
    _PCFG1 = 1;         // make Card select as digital pin
    _TRISB1 = 0;        // make Card select an output pin
    
    SDCS = 1;
       
    // init the spi module for a slow (safe) clock speed first
    SPI1CON1 = 0x013c;  // CKE=1; CKP=0, sample middle, prescale 1:64

    SPI1STAT = 0x8000;  // enable the peripheral
}   // initSD


// send one byte of data and receive one back at the same time
unsigned char writeSPI( unsigned char b)
{
    SPI1BUF = b;					// write to buffer for TX
    while( !SPI1STATbits.SPIRBF);	// wait for transfer to complete
    return SPI1BUF;    				// read the received value
}// writeSPI

#define readSPI()   writeSPI( 0xFF)
#define clockSPI()  writeSPI( 0xFF)
#define disableSD() SDCS = 1; clockSPI()
#define enableSD()  SDCS = 0


int detectSD( void)
{
    return ( !SDCD);  
} // detect SD

int detectWP( void)
{
    return ( !SDWP);  
} // detect WP


int sendSDCmd( unsigned char c, LBA a)
{
    int i, r;

    // enable SD card
    enableSD();

    // send a comand packet (6 bytes)
    writeSPI( c | 0x40);    // send command 
    writeSPI( a>>24);       // msb of the address
    writeSPI( a>>16);       
    writeSPI( a>>8);
    writeSPI( a);           // lsb
    
    writeSPI( 0x95);        // send CMD0 CRC 

    // now wait for a response (allow for up to 8 bytes delay)
    i = 9;
    do {
        r = readSPI();      // check if ready   
        if ( r != 0xFF) break;
    } while ( --i > 0);

    return ( r);         

/* return response
    FF - timeout 
    00 - command accepted
    01 - command received, card in idle state after RESET

other codes:
    bit 0 = Idle state
    bit 1 = Erase Reset
    bit 2 = Illegal command
    bit 3 = Communication CRC error
    bit 4 = Erase sequence error
    bit 5 = Address error
    bit 6 = Parameter error
    bit 7 = Always 0
*/
    // NOTE CSCD is still low
} // sendSDCmd


int readSECTOR( LBA a, char *p)
// a        LBA of sector requested
// p        pointer to sector buffer
// returns  TRUE if successful
{
    int r, i;
    
    READ_LED = 1;

    r = sendSDCmd( READ_SINGLE, ( a << 9));
    if ( r == 0)    // check if command was accepted
    {  
        // wait for a response
        i = 10000;
        do{
            r = readSPI();     
            if ( r == DATA_START) break;
        }while( --i>0);

        // if it did not timeout, read a 512 byte sector of data
        if ( i)
        {
//  Compiler version 3.01b Work around

           register unsigned i;
           register char * q;
 //        register unsigned i asm( "w5");
 //        register char * q asm("w6");
           q = p;
           i = 512;

            do{ 
                SPI1BUF = 0xFF;					// write to buffer for TX
                while( !(SPI1STAT&1));	// wait for transfer to complete
                *q++ = SPI1BUF;    				// read the received value
            } while (--i>0);

            // ignore CRC
            readSPI();
            readSPI();

        } // data arrived

    } // command accepted

    // remember to disable the card
    disableSD();
    READ_LED = 0;

    return ( r == DATA_START);      // return TRUE if successful
} // readSECTOR


int writeSECTOR( LBA a, char *p)
// a        LBA of sector requested
// p        pointer to sector buffer
// returns  TRUE if successful
{
    unsigned r, i;
    
    WRITE_LED = 1;

    r = sendSDCmd( WRITE_SINGLE, ( a << 9));
    if ( r == 0)    // check if command was accepted
    {  
        writeSPI( DATA_START);
        for( i=0; i<512; i++)
            writeSPI( *p++);

        // send dummy CRC
        clockSPI();
        clockSPI();
    
        // check if data accepted
        if ( (r = readSPI() & 0xf) == DATA_ACCEPT)
        {   
            for( i=0xffff; i>0; i--)
            { // wait for end of write
                if ( (r = readSPI()))
                    break;
            } 
        } // accepted
        else
            r = FAIL;

    } // command accepted

    // remember to disable the card
    disableSD();
    WRITE_LED = 0;

    return ( r);      // return TRUE if successful

} // writeSECTOR



int initMedia( void)
{
    int i, r;

    // 1. with the card not selected     
    disableSD(); 

    // 2. send 80 clock cycles start up
    for ( i=0; i<10; i++)
        clockSPI();

    // 3. now select the card
    enableSD();

    // 4. send a reset command
    r = sendSDCmd( RESET, 0); disableSD();
    if ( r != 1)  
        return 0x84;

    // 5. send repeatedly INIT until receive a 0 
    i = 10000;  // up to .3 sec
    do {
        r = sendSDCmd( INIT, 0); disableSD();
        if ( !r) break; 
    } while( --i > 0);
    if ( i==0)   
        return 0x85;       // timed out 
    
    // 10. increase speed 
    SPI1STAT = 0;           // disable momentarily the SPI1 module
    SPI1CON1 = 0x013b;      // change prescaler to 1:2
    SPI1STAT = 0x8000;      // re-enable the SPI1 module
    
    return 0;           

} // init media

⌨️ 快捷键说明

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