/* * http://ghmicro.com/index.php/pic/13-18f4620/11-18f4620-a-sd-card */ #include #include #include "sdcard.h" #include "spi.h" char sd_output_buffer1[256]; char sd_output_buffer2[256]; char sd_input_buffer1[256]; char sd_input_buffer2[256]; void sd_init(void){ int i,r; CSel=1; //init chip select (active low) SD_LED=0; //LED off for(i=0; i<256 ;i++){ //fill the send buffers sd_output_buffer1[i]=0; sd_output_buffer2[i]=0; sd_input_buffer1[i]=0; //and clear the receive buffers sd_input_buffer2[i]=0; } r = sd_initMedia(); if(r){ //card init failed - 1 blink while(1){ SD_LED = 1; delay_ms(150); SD_LED = 0; delay_s(1); } } } int sd_initMedia(void){ int i,r; CSel = 1; spi_putc(0xff); //while card is not selected for(i=0;i<16;i++) //send 80 clock cycles to start up spi_putc(0xff); CSel = 0; //then select the card r = sd_sendCmd(0,0); //send reset command to enter SPI mode CSel = 1; spi_putc(0xff); //disable SD if(r != 1) //error check - need 1 return 0x84; i = 10000; //send init for up to 0.3s CSel = 0; do{ r = sd_sendCmd(1,0); //send init command CSel = 1; spi_putc(0xff); //disable SD if(!r) break; }while(--i > 0); if(i==0) //time out error 0x85 return 0x85; sspcon1 = 0b00010000; //speed up spi clock sspcon1.SSPEN = 1; return 0; } int sd_writeSector(LBA a, char *p1, char *p2){ unsigned r,i; SD_LED = 1; //turn on write LED r = sd_sendCmd(24,(a<<9)); if(r == 0){ spi_putc(0xfe); //send Data Start byte for(i=0;i<256;i++) //first 256 bytes spi_putc(*p1++); for(i=0;i<256;i++) //second 256 bytes spi_putc(*p2++); spi_putc(0xff); //send dummy CRC spi_putc(0xff); if((r=spi_putc(0xff) & 0x0f) == 0x05){ //check if data accepted for(i=10000;i>0;i--){ if(r=spi_putc(0xff)) break; } } else r=0; //fail } CSel = 1; spi_putc(0xff); //disable SD SD_LED = 0; //LED off return(r); } int sd_readSector(LBA a, char *p1, char *p2){ int r,i; SD_LED = 1; //turn on read LED r = sd_sendCmd(17,(a<<9)); if(r == 0){ //check if command was accepted i=10000; //wait for a response do{ r = spi_putc(0xff); if(r==0xfe) break; }while(--i > 0); if(i){ //if no timeout, read 512 byte sector for(i=0;i<256;i++) *p1++ = spi_putc(0xff); for(i=0;i<256;i++) *p2++ = spi_putc(0xff); spi_putc(0xff); //ignore CRC spi_putc(0xff); } } CSel = 1;spi_putc(0xff); //disable SD SD_LED = 0; //read LED off return(r == 0xfe); } int sd_sendCmd(unsigned char c, LBA a){ int i,r; CSel = 0; //send command packet (6 bytes) spi_putc(c|0x40); //send command & frame bit spi_putc(a>>24); //send 32-bit address spi_putc(a>>16); spi_putc(a>>8); spi_putc(a); spi_putc(0x95); //send CRC i = 9; //wait for response do{ r = spi_putc(0xff); //check if ready if(r != 0xff) break; }while(--i > 0); return(r); } /* void main(void){ LBA addr; int i,r; trisd=0; trisc=0b00010000; CSel=1; //init chip select (active low) LED=0; //LED off osccon=0x72; //8MHz clock osctune.6=0; //disable PLL while(!osccon.IOFS); //wait for osc stable sspstat = 0b00000000; //SMP(7)=0, CKE(6)=0 (clock edge idle to active) sspcon1 = 0b00010010; //CKP(4)=1 clock polarity (idle high) //SSPM3:SSPM0(3:0)=010 spi clock FOSC/64 (<400kHz) sspcon1.SSPEN=1; //SSPEN(5)=1 enable SPI for(i=0;i<256;i++){ //fill the send buffers data1[i]=i; data2[i]=i; buffer1[i]=0; //and clear the receive buffers buffer2[i]=0; } r=initMedia(); if(r){ //card init failed - 1 blink while(1){ LED=1; delay_ms(150); LED=0; delay_s(1); } } else{ //write card addr = 10000; for(i=0;i<1000;i++){ if(!writeSector(addr+i,data1,data2)){ while(1){ //write failed - 2 blinks LED=1; delay_ms(150); LED=0; delay_ms(150); LED=1; delay_ms(150); LED=0; delay_s(1); } } } addr=10000; //verify write for(i=0;i<1000;i++){ if(!readSector(addr+i,buffer1,buffer2)){ while(1){ //verify failed - 3 blinks LED=1; delay_ms(150); LED=0; delay_ms(150); LED=1; delay_ms(150); LED=0; delay_ms(150); LED=1; delay_ms(150); LED=0; delay_s(1); } } //verify if(memcmp(data1,buffer1,256)||memcmp(data2,buffer2,256)){ while(1){ //mismatch - 4 blinks LED=1; delay_ms(150); LED=0; delay_ms(150); LED=1; delay_ms(150); LED=0; delay_ms(150); LED=1; delay_ms(150); LED=0; delay_ms(150); LED=1; delay_ms(150); LED=0; delay_s(1); } } } } while(1){ //success! LED=1; delay_s(1); LED=0; delay_s(1); } } */