英锐恩单片机论坛,Microchip单片机,模拟器件,接口电路,麦肯单片机,单片机应用交流

 找回密码
 立即注册
搜索
电子烟方案单片机单片机开发深圳单片机开发
单片机方案国产单片机8位单片机电子烟方案开发
查看: 4549|回复: 0
打印 上一主题 下一主题

一个PIC+MMC做的MP3程序

[复制链接]
跳转到指定楼层
1#
发表于 2009-4-27 14:10:56 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
//cheap mmc mp3 2006
#include <16f88.H>
#use delay(clock=8000000)
#use fast_io(a)
#use fast_io(b)
#use rs232(baud=9600, xmit=PIN_a7,rcv=PIN_b5)
#byte port_a  = 0x05 //port a
#byte port_b  = 0x06 //b
#byte tris_a    = 0x85 //port a
#byte tris_b  = 0x86 //b
#byte option_reg = 0x81
#byte  ADRESL = 0x9E
#byte  ADRESH = 0x1E
#byte ADCON0  = 0x1F
#bit    GODONE = ADCON0.2
#byte ADCON1 = 0x9F
#byte ANSEL  =  0x9B
#byte OSCCON = 0x8F
#byte CVRCON = 0x9D
#byte CMCON = 0x9C
#byte SSPCON = 0x14
#byte SSPSTAT = 0x94
#byte SSPBUF = 0x13
#byte intcon  = 0X0B
#bit  SSPEN = SSPCON.5
#bit SS   = port_a.0
#bit XCS  = port_a.1
#bit XDCS  =port_a.3
#bit XCLK  = port_b.4
#bit XDI  = port_b.1
#bit XDREQ  = port_a.4
#bit MCLR  = port_a.5
#bit XRESET  = port_a.2
#bit XDO   = port_a.6
#bit MOSI  =port_b.2
#bit XDI_TRIS =tris_b.1
#bit TRACKUP = port_b.6
#bit TRACKDOWN  = port_b.7
#bit VOLUMEUP  = port_b.5
#bit VOLUMEDOWN  = port_b.3

#bit PAUSE  = port_b.0

///////////////////prototypes
void  find_bpb(void);
void  mmc_skip(char count);
void mmc_read(void);
char  getsongstart(int32 filenumber);
char  song(int32 startsector,int32 endsector);
void printout_rootdir(void);
void find_highest_song_number(void);
int32 get_next_shuffle(void);
char rand(void);
//super fat functions::::
int32 readfat(int32 fatoffset);


int mmc_init();
int mmc_response(unsigned char response);
int mmc_read_block_to_serial(int32 block_number);
int mmc_get_status();
char mmc_open_block(int32 block_number);
char mmc_get_byte(void);
void mmc_close_block(void);
void mmc_cancel_block(void);
int mmc_read_block_to_vs1011(int32 block_number);
#inline
void init(void);
void resetvs1011_hard(void);
void resetvs1011_soft(void);
void morezeroes(void);
int16 vs_command(char inout,address,a,b);
char vs_spi_write(char aa);
void play_range(int32 start, int32 end);
///////////////////////end prototypes
/////////////////////globals
char volume;
char data_lo, data_hi;
char BPB_SecPerClus;
int16 bpbstart;
int16 RootDirSectors;
int16 FirstDataSector;
int16 BPB_ResvdSecCnt;
int16 BPB_BytsPerSec;
int32 FirstRootDirSecNum; //;, songstarter, songlength, currentsong;
int32 songstarter;
int32 songlength;
int32 currentsong;
int32 fatstart, datsec;
int32 ccl, pcl, root_ccl;
int32 root_p_cl;
int32 highestsong;
int32 BPB_RootEntCnt;
int32 BPB_FATSz16;
int32 BPB_FATSz32;
int32 BPB_RootClus;
char BPB_NumFATs, fatmode;
char offset;
char column_pointer[16];
//char pointerh, pointerl, globalpointer;
char random_byte;//global variable for the random number generator (keeps the last value around for seeding purposes?)
////////////////////end globals
//BYTE CONST RNDL [256]= {208,75,137,110,218,247,165,23,248,216,204,59,118,35,193,29,83,158,93,57,224,194,3,207,205,149,203,22,129,171,10,
#rom  0x2100={208,75,137,110,218,247,165,23,248,216,204,59,118,35,193,29,83,158,93,57,224,194,3,207,205,149,203,22,129,171,10,
142,251,99,249,244,144,16,17,238,37,197,111,151,4,192,104,7,95,150,67,101,69,15,132,186,87,156,206,27,166,20,182,
163,92,198,119,213,180,61,152,39,185,19,58,45,33,64,24,160,40,222,172,131,227,221,105,108,177,183,73,43,157,12,199,
113,9,245,126,130,106,120,210,215,31,167,246,76,139,195,239,50,229,169,55,122,212,30,112,6,85,141,82,236,21,32,89,
219,173,188,127,74,214,187,190,176,62,123,189,121,184,148,225,34,1,196,28,49,46,79,77,54,117,240,175,242,140,231,
13,128,25,97,146,228,179,116,70,53,178,18,254,78,109,155,241,233,81,255,159,202,102,2,174,14,147,234,60,8,84,52,98,
100,230,145,211,125,11,181,164,26,90,134,161,36,71,223,143,232,136,63,68,51,96,243,66,65,235,47,154,237,252,72,209,
114,138,115,86,250,5,94,133,42,44,88,226,103,253,124,168,91,48,217,56,80,135,220,107,191,201,162,153,38,170,41,200,0}

////////////////////////////////////////////////////////////////////////////////////////////////
#int_timer0
void volume_handler(void){
if (!VOLUMEUP){
//  volume = spicommand(0x03,0x0b,0x00,0x00);
  if (volume<255){
   volume++;
  }
//  spicommand(0x02,0x0b,volume,volume);
}
if (!VOLUMEDOWN){
//  volume = spicommand(0x03,0x0b,0x00,0x00);
  if (volume>0){
   volume--;
  }
//  spicommand(0x02,0x0b,volume,volume);
}
}

void main(void){
char flag, result, n, shufflemode;
init();
enable_interrupts(GLOBAL);
enable_interrupts(INT_TIMER0);
xcs=1;
xdcs=1;
// while(1){
  volume=0x23;
//  delay_ms(250);
//  printf("IKF");//putc(13); putc(10);
  result=mmc_init();
//  if (result==1){printf("nogo"); while(1){;}}
  if (result==1){while(1){;}}
//  BPB_BytsPerSec=0;
  find_bpb();
  resetvs1011_hard();
//  if(BPB_BytsPerSec!=0x200){
//  printf("POP"); putc(13);putc(10);
//   find_bpb();
//  }
// printf("card parameters found"); putc(13);putc(10);
currentsong=0x01;
find_highest_song_number();
root_ccl= BPB_RootClus;
flag='s';
result=0x00;
// shufflemode=0;
if (!TRACKUP){
  for(n=0;n<16;n++){
   column_pointer[n]=0;  
  }
  while(!TRACKUP){random_byte++; offset++;}
  while(1){
   if ((TRACKUP)&&(TRACKDOWN)){
    currentsong=get_next_shuffle();
    result=getsongstart(currentsong);
    if(result==0x01){
//     printf("playing: %lX ",currentsong); putc(13);putc(10); putc(13);putc(10);
     flag=song( songstarter,(songstarter+(songlength/512)) );
    }
   }
  }
}
while(1){
////////////////////////////////////////////////////////auto track increment. press and hold...
//single increment/decrement of track is within the "song" function
  if (!TRACKUP){
   for(n=120;n>0;n--){
    delay_ms(3);
    if (TRACKUP){
     break;
    }
   }
   while (!TRACKUP){
    delay_ms(1);
    n++;
    if (n==15){
     n=0;
     currentsong++;
     if (currentsong>highestsong){currentsong=0x01;}//putc('s');}
     //putc('f');
    }
   }
  }
  if (!TRACKDOWN){
   for(n=120;n>0;n--){
    delay_ms(3);
    if (TRACKDOWN){
     break;
    }
   }
   while (!TRACKDOWN){
    delay_ms(1);
    n++;
    if (n==15){
     n=0;
     currentsong--;
     if (currentsong==0x00){currentsong=highestsong;}// putc('s');}
     //putc('f');
    }
   }
  }
//////////////////////////end AUTO TRACK INCREMENT

  if ((TRACKUP)&&(TRACKDOWN)){
   n=0;
   result=getsongstart(currentsong);
   if(result==0x02){
    currentsong=0x01;
    flag='s';
//    printf("got to end of card, going back to track one"); putc(13);putc(10);
   }
   else if(result==0x01){
//    printf("playing: %lX ",currentsong); putc(13);putc(10);
    flag=song( songstarter,(songstarter+(songlength/512)) );
   }
   if ((flag=='n')||(flag=='s')){
     currentsong++;
//    printf("auto advanced"); putc(13);putc(10);
   }
   else if (flag=='p'){
    if (currentsong>1){
     currentsong--;
//    printf("previous track attempt"); putc(13);putc(10);
    }
    else{currentsong=highestsong;}//loop around to the last track on the card
   }
  }
}
}
char getsongstart(int32 filenumber){
char Emm,Pee,Three;
int32 Largeccl, ccltemp, eocmark;
int16  x, y, z;
//    printf("getting song paramaters for: %lX ",filenumber);
  eocmark=0;
//  if (fatmode==16){
//   mmc_open_block((Firstrootdirsecnum+(filenumber/16))+bpbstart);
//  }else{// if 32 mode:
   root_ccl= BPB_RootClus;
   y=filenumber/16;
   z=y;
   y=y/BPB_SecPerClus;
   x=y*BPB_SecPerClus;
   x=z-x;
   while(y>0){
    root_p_cl=root_ccl;
    root_ccl=readfat(root_p_cl);
//    printf("current root cluster:%4LX   ",root_ccl);
    eocmark=root_ccl & 0x0FFFFFFF;
    y--;
   }
   if (eocmark>0x0fffffef){
    return (0x02);
   }
   ccltemp=root_ccl-2;
   ccltemp=ccltemp * (int32)BPB_SecPerClus;
   ccltemp=ccltemp + (int32)datsec;
   ccltemp=ccltemp + (int32)x;
   mmc_open_block(ccltemp);
//  }
mmc_skip((filenumber & 0x000F)*16);
mmc_read();
// printf("firstCharOf File Name is:%X   ",data_lo);
if(data_lo==0x00){
  mmc_cancel_block();
  return(0x00);//was 0x02
}
if(data_lo != 0xe5){
//  putc(254);putc(1);
//  putc(data_lo);putc(data_hi);
//  mmc_skip(6);
//  mmc_read();
//  putc(data_lo);putc(data_hi);
//  mmc_read();
//  putc(data_lo);putc(data_hi);
//  mmc_read();
//  putc(data_lo);putc(data_hi);
//  putc('.');

  mmc_skip(3);
  mmc_read();
//  putc(data_lo);putc(data_hi);
  Emm=data_lo;
  Pee=data_hi;
  mmc_read();
//  putc(data_lo);putc(data_hi); putc(13);putc(10);
  Three=data_lo;
  if (((Emm=='m') || (Emm=='M')|| (Emm=='W')|| (Emm=='w')) && ((Pee=='P') || (Pee=='p')|| (Pee=='A')|| (Pee=='a')) && (Three=='3')||(Three=='V')||(Three=='v')){
   mmc_skip(4);
   mmc_read();
   if (fatmode==32){
    Largeccl= ((int16)data_hi<<8)+data_lo;// clusterf high bytes. they're in a funny place to maintain compatibility with fat16
    Largeccl=Largeccl<<16;
   }
   mmc_skip(2);
   mmc_read();
   ccl= ((int32)data_hi<<8)+data_lo;
   if (fatmode==32){
    ccl = ccl+ Largeccl;   //add on the high bytes of the cluster address
   }
   songstarter=( ((((int32)data_lo+((int32)data_hi<<8))-0)  *BPB_SecPerClus) +bpbstart+Firstdatasector);
   mmc_read();
   *(((char*)&songlength)+0)=data_lo;
    *(((char*)&songlength)+1)=data_hi;
        //songlength=(int16)data_lo + ((int16)data_hi<<8);
   mmc_read();
   *(((char*)&songlength)+2)=data_lo;
   *(((char*)&songlength)+3)=data_hi;
        //songlength=songlength + (((int16)data_lo+((int16)data_hi<<8))  <<16);
   mmc_cancel_block();
   return(0x01);
  }
}
mmc_cancel_block();
return(0x00);
}
char song(int32 startsector,int32 endsector){
int32 ccltemp;
short int hardflag;
char insanity;//, sectprint;
char shutdowncounter, x ;
x=0;
insanity=0;
// sectprint=1;
resetvs1011_soft();
startsector = startsector/BPB_SecPerClus;
endsector = endsector/BPB_SecPerClus;
for(;startsector<=endsector;startsector++){
  for (x=0;x<BPB_SECPERCLUS;X++){
   ccltemp=ccl-2;
   ccltemp=ccltemp * (int32)BPB_SecPerClus;
   ccltemp=ccltemp + (int32)datsec;
   ccltemp=ccltemp + (int32)x;
  // if (sectprint==1){
  //  printout_sector(ccltemp);
  //  sectprint=0;
  // }
   insanity = mmc_read_block_to_vs1011(ccltemp);//this is where it all gets played
   if(insanity==1){insanity = mmc_read_block_to_vs1011(ccltemp);}//try again
   if(insanity==1){vs_command(0x02,0x0b,0xFE,0xFE);}//go silent and wait for user input
   if (!TRACKUP){return('n');}
   if (!TRACKDOWN){
    if (currentsong>0){return('p');}
   }
  }
  pcl=ccl;
  ccl=readfat(pcl);
  vs_command(0x02,0x0b,volume,volume);
  if(!PAUSE){
   delay_ms(20);
   while (!PAUSE){delay_ms(20);}
//   delay_ms(20);
   while (PAUSE){delay_ms(20);}
//   delay_ms(20);
   while (!PAUSE){;}
   delay_ms(20);
  }
}
return('s');
}


////////////////////////////////////////////////////////////////////////////////////////////////
void play_range(int32 start, int32 end){
for(;start<END;START++){
  mmc_read_block_to_vs1011(start);
}
}

void mmc_cancel_block(void){
// SS=1;
// delay_cycles(10);
// SS=0;
SPI_WRITE(0x4C);                // send mmc read single block command
SPI_WRITE(0); // arguments are address
SPI_WRITE(0);
SPI_WRITE(0);
SPI_WRITE(0x00);
// mmc_response(0x00);
// mmc_response(0xFE);
// for (i=0;i<8;i++){
//  SPI_WRITE(0xFF);
// }
  SPI_WRITE(0xFF);   SPI_WRITE(0xFF);
SS=1;
// for (i=0;i<4;i++){
//  SPI_WRITE(0xFF);
// }
  SPI_WRITE(0xFF);
}
///////////// ///////////// ////////////////// ///////////????????????//////////////
void find_bpb(){
int32 bigtemp;
bpbstart=0;
mmc_open_block(0);
mmc_skip(0xE0);
mmc_read();
bpbstart=((int16) data_hi<<8);
bpbstart+=data_lo;
mmc_cancel_block();
// mmc_skip(0x1C);
// mmc_close_block();
mmc_open_block((int32) bpbstart);
mmc_skip(5);
mmc_read();
BPB_bytspersec=data_hi; //11
mmc_read();
BPB_bytspersec=BPB_bytspersec+((int16) data_lo<<8); //11.12
BPB_SecPerClus=data_hi; //13
mmc_read();
BPB_ResvdSecCnt=((int16) data_hi<<8)+data_lo;  //14.15
mmc_read();
BPB_NumFATs=data_lo;  //16
BPB_RootEntCnt=data_hi;  //17
mmc_read();
BPB_RootEntCnt=BPB_RootEntCnt+((int16) data_lo<<8);  //17.18
mmc_read();
mmc_read();
BPB_FATSz16=data_lo+((int16) data_hi<<8);  //22.23
mmc_skip(6);
mmc_read();
BPB_FATSz32=0;
BPB_FATSz32=data_lo+((int32) data_hi<<8);  //36.37
bigtemp=BPB_FATSz32;
mmc_read();
BPB_FATSz32=data_lo+((int32) data_hi<<8);  //36.37.38.39
BPB_FATSz32=BPB_FATSz32 <<16;
BPB_FATSz32=bigtemp+BPB_FATSz32;
mmc_read();
mmc_read();
mmc_read();
BPB_RootClus=data_lo+((int32) data_hi<<8);  //44.45
bigtemp=BPB_RootClus;
mmc_read();
// mmc_skip(0xE8);
// mmc_close_block();
mmc_cancel_block();
BPB_RootClus=data_lo+((int32) data_hi<<8);  //44.45.46.47
BPB_RootClus=BPB_RootClus<<16;
BPB_RootClus=BPB_RootClus+bigtemp;
root_ccl=BPB_RootClus;
fatstart=bpbstart+BPB_ResvdSecCnt;
RootDirSectors = ((BPB_RootEntCnt * 32) + (BPB_BytsPerSec - 1)) / BPB_BytsPerSec;
if(BPB_FATSz16 != 0){
  fatmode=16;
  FirstDataSector = BPB_ResvdSecCnt + (BPB_NumFATs * BPB_FATSz16) + RootDirSectors;
}else{
   fatmode=32;
  FirstDataSector = BPB_ResvdSecCnt + (BPB_NumFATs * BPB_FATSz32) + RootDirSectors;
}
FirstRootDirSecNum = BPB_ResvdSecCnt + ((int32) BPB_NumFATs * (int32) BPB_FATSz16);
  datsec = (int32)bpbstart + (int32)firstdatasector;


// printf("fm: %4D",fatmode);   putc(13);putc(10);
// printf(" 16: %4LX",BPB_FATSz16);  putc(13);putc(10);
// printf(" clst: %4LX",BPB_RootClus); putc(13);putc(10);
// printf(" bpb %4LX",bpbstart);   putc(13);putc(10);


// putc(13);putc(10); printf(" bpbst:%4LX  ",bpbstart);
// putc(13);putc(10); printf(" BPB_bpsec:%4LX  ",BPB_bytspersec);
// putc(13);putc(10); printf(" BPB_ScPeC:%4LX  ",BPB_SecPerClus);
// putc(13);putc(10); printf(" BPB_RsvdScCt:%4LX  ",BPB_ResvdSecCnt);   
// putc(13);putc(10); printf(" BPB_NmFAT:%4LX  ",BPB_NumFATs);
// putc(13);putc(10); printf(" BPB_RootEntCnt:%4LX  ",BPB_RootEntCnt);
// putc(13);putc(10); printf(" BPB_FATSz16:%4LX  ",BPB_FATSz16);
// putc(13);putc(10); printf(" fatstart: %4LX  ",fatstart);
// putc(13);putc(10); printf(" FirstRootDirSecNum:%4LX  ",FirstRootDirSecNum);
// putc(13);putc(10); printf(" FirstDataSector:%4LX  ",FirstDataSector);
// putc(13);putc(10); printf(" RootDirSectors:%4LX  ",RootDirSectors);
// putc(13);putc(10);
}
////////////?????????????????/////////////////////?///////////////////////


void find_highest_song_number(void){
int32 clust_high;
int32 eocmark;
root_ccl= BPB_RootClus;
clust_high=0;
do{
  root_p_cl=root_ccl;
  root_ccl=readfat(root_p_cl);
//  printf("cluster seek:%4LX   ",root_ccl);
  eocmark=root_ccl & 0x0FFFFFFF;
  clust_high++;
// putc('Z');
}while(eocmark<0x0fffffef);
highestsong=clust_high * BPB_SecPerClus;
highestsong= highestsong*16;
highestsong--;
// printf("clust_high:: %LX ",clust_high); putc(13);putc(10);
// printf("highestsong:: %LX ",highestsong); putc(13);putc(10);

}

//-----------------------------------//this is limited to 2048 directiry entries
int32 get_next_shuffle(void){
int16 a, work;
char b, c;
work=0xffff;
// printf("seeking number----------:");
// putc(13);putc(10);
while(work>highestsong){
  b = rand();
  b = b/16;
//  printf("column number: %X ",b);
  //putc(13);putc(10);
//  printf("is up to: %X ",column_pointer[b]);
//  putc(13);putc(10);
  if (column_pointer[b]<255){
   c = column_pointer[b]++;
//   printf(" c is: %X ",c);
   c=c+offset;
   work=read_eeprom(c);
//   work=RNDL[c];
//   printf("work is: %lX ",work);
   a = (int16) b * 256;
   work=work+a;
//   printf("for a final number: %lX ",work);
  }
}
// printf("random hopeful!: %lX ",work);
return (work);
}

char rand(void) {
char sum;
sum = 0;
// This calculates parity on the selected bits (mask = 0xb4).
if(random_byte & 0x80){ sum   = 1;}
if(random_byte & 0x20){ sum ^= 1;}
if(random_byte & 0x10){ sum ^= 1;}
if(random_byte & 0x04){ sum ^= 1;}
random_byte <<= 1;
random_byte |= sum;
return(random_byte);

}




//super fat :::::
//-----------------------------------
////////////////////////////
int32 readfat(int32 fatoffset){
int16 temp;
int32 tempb;
int8 los;
temp=0;
// if (fatmode==32){
  fatoffset=fatoffset*2;
// }
los = *(((char*)&fatoffset)+0); //the bottom byte of the address goes directly to a word in the FAT
fatoffset=fatoffset / 256;
fatoffset+=fatstart;
mmc_open_block(fatoffset);
mmc_skip(los);
mmc_read();
temp = ((int16) data_hi * 256)+ (int16) data_lo;
// if (fatmode==16){
//  return temp;//only two bytes per entry
// }
mmc_read();//for fat32, four bytes per entry
tempb=0;
tempb = ((int16) data_hi * 256)+ (int16) data_lo;
tempb=tempb<<16;
tempb=tempb+(int32) temp;
mmc_cancel_block();
// printf(" cluster getter returns:::%4LX   ",tempb);
return tempb;
}
//-----------------------------------
////////////////////////////////////////////////////////////////////////////////////////////////
void resetvs1011_hard(void){
SS=1; xcs=1; xdcs=1;
delay_ms(500);
do{
  xreset=0;//hard reset
  delay_cycles(100);
  xreset=1;
  delay_cycles(500);
  vs_command(0x02,0x00,0x00,0x04);//sets new mode w/o shared pin and reset bit
  delay_ms(100);
}while(!XDREQ);
delay_ms(1);
vs_command(0x02,0x00,0x08,0x00);//go into new mode (w/o pin sharing, w/o sdi tests)
delay_ms(1);
vs_command(0x02,0x0b,volume,volume);//set volume
delay_ms(1);
vs_command(0x02,0x03,0x99,0x50);// set xtal 12.960MHZ + doubler
// printf("_%x",vs_command(0x03,0x03,0x99,0x50));
}

//-----------------------------------
void resetvs1011_soft(void){
vs_command(0x02,0x00,0x08,0x04);//go into new mode (w/o pin sharing, w/o sdi tests)
delay_ms(1);
vs_command(0x02,0x0b,volume,volume);//set volume
delay_ms(1);
vs_command(0x02,0x03,0x99,0x50);// set xtal 12.960MHZ + doubler
delay_ms(1);
// morezeroes();
}

/*///////////////////////////////////////////////////////////////////////////////////////////////
void morezeroes(void){
int16 c;
xcs=1;
if (XDREQ){
  xdcs=0;
  for(c=0;c<2048;c++){
   vs_spi_write(0);
   while (!XDREQ){;}
  }
  xdcs=1;
}
}

*////////////////////////////////////////////////////////////////////////////////////////////////
char vs_spi_write(char aa){
char h;
char i;
h=0;
i=7;
XCLK=0;delay_cycles(10);
do{
  XDI=bit_test(aa,i);
  XCLK=1;
  if(XDO==1){bit_set(h,i);}
  XCLK=0;
}while((i--)>0);
return (h);
}

////////////////////////////////////////////////////////////////////////////////////////////////
int16 vs_command(char inout, address,a,b){//for sending non-song related data to the decoder..
int16 result;
SS=1;
xdcs=1;
SSPEN=0;
XDI_TRIS=0;
xcs=0;
vs_spi_write(inout);
vs_spi_write(address);//load the buffer with address
*(((char*)&result)+1)=vs_spi_write(a);   //load buffer with hi  data(ignored on read command)
*(((char*)&result)+0)=vs_spi_write(b);   //load buffer with data low value
xcs=1;    //deselect the vs1011 command registers (go into sdi mode)
XDI_TRIS=1;
SSPEN=1;
return (result);
}

void mmc_read(void){
data_lo=SPI_READ(0xFF);
data_hi=SPI_READ(0xFF);
}

/////////////////////////////////////////////////////////////////////////////////////////////////
void mmc_skip(char count){
for (;count>0;count--){
  SPI_WRITE(0xFF);
  SPI_WRITE(0xFF);
}
}

////////////////////////////////////////////////////////////////////////////////////////////////
char mmc_open_block(int32 block_number){
block_number*=512;
SS=0;                     // set SS = 0 (on)
SPI_WRITE(0x51);                // send mmc read single block command
SPI_WRITE(*(((char*)&block_number)+3)); // arguments are address
SPI_WRITE(*(((char*)&block_number)+2));
SPI_WRITE(*(((char*)&block_number)+1));
SPI_WRITE(0x00);
SPI_WRITE(0xFF);                // checksum is no longer required but we always send 0xFF
if((mmc_response(0x00))==1) return 1;   // if mmc_response returns 1 then we failed to get a 0x00 response (affirmative)
if((mmc_response(0xFE))==1) return 1;   // wait for data token
return(0);
}
void mmc_close_block(void){
SPI_READ(0xFF);                 // CRC bytes that are not needed
SPI_READ(0xFF);
SS=1;            // set SS = 1 (off)
SPI_WRITE(0xFF);                // give mmc the clocks it needs to finish off
}
////////////////////////////////////////////////////////////////////////////////////////////////////
int mmc_init(){ //Initialises the MMC into SPI mode and sets block size
char p;
int i;
SETUP_SPI(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_4 | SPI_SS_DISABLED);
SSPSTAT |= 0x40;                          // set CKE = 1 - clock idle low
SSPCON &= 0xEF;                          // set CKP = 0 - data valid on rising edge
SS=1;   //                    // set SS = 1 (off)
for(i=0;i<10;i++){                       // initialise the MMC card into SPI mode by sending clks on
         SPI_WRITE(0xFF);
}
SS=0;                         // set SS = 0 (on) tells card to go to spi mode when it receives reset
SPI_WRITE(0x40);                        // send reset command
for(p=4;p>0;p--){
  SPI_WRITE(0x00);                        // all the arguments are 0x00 for the reset command
}
SPI_WRITE(0x95);                        // precalculated checksum as we are still in MMC mode
// puts("Sent go to SPI ");
if(mmc_response(0x01)==1) return 1;     // if = 1 then there was a timeout waiting for 0x01 from the mmc (bad!)
// puts("Got response from MMC ");
i = 0;
while((i < 255) && (mmc_response(0x00)==1)){     // must keep sending command if response
         SPI_WRITE(0x41);                // send mmc command one to bring out of idle state
  for(p=4;p>0;p--){
          SPI_WRITE(0x00);
  }
         SPI_WRITE(0xFF);                // checksum is no longer required but we always send 0xFF
         i++;
// printf("%d ",i);
}
if(i >= 254) return 1;                   // if >= 254 then there was a timeout waiting for 0x00 from the mmc (bad!)
// puts("Got out of idle response from MMC ");
SS=1;                    // set SS = 1 (off)
SPI_WRITE(0xFF);                        // extra clocks to allow mmc to finish off what it is doing
SS=0;                     // set SS = 0 (on)
SPI_WRITE(0x50);                // send mmc command one to bring out of idle state
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x02);                // high block length bits - 512 bytes
SPI_WRITE(0x00);                // low block length bits
SPI_WRITE(0xFF);                // checksum is no longer required but we always send 0xFF
if((mmc_response(0x00))==1) return 1; //(bad!)
SS=1;            // set SS = 1 (off)
// puts("Got set block length response from MMC ");
return 0; //(good)
}

////////////////////////////////////////////////////////////////////////////////////////////////
int mmc_get_status(){ // Get the status register of the MMC, for debugging
char  p;
xcs=1;
xdcs=1;
SS=0;                     // set SS = 0 (on)
SPI_WRITE(0x58);                // send mmc command one
for(p=4;p>0;p--){
  SPI_WRITE(0x00);
}
SPI_WRITE(0xFF);                // checksum is no longer required but we always send 0xFF
SS=1;                    // set SS = 1 (off)
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////
int mmc_response(unsigned char response){ //reads the MMC until we get the response we want or timeout
unsigned long count = 0x0FFF;             // 16bit repeat, it may be possible to shrink this to 8 bit but there is not much point
while(SPI_READ(0xFF) != response && --count > 0);
if(count==0) return 1;                     // loop was exited due to timeout (bad)
else return 0;                             // loop was exited before timeout (good)
}
////////////////////////////////////////////////////////////////////////////////////////////////
int mmc_read_block_to_serial(int32 block_number){ //read block from the MMC and outputs each byte to RS232. just for fun
unsigned long i;
mmc_open_block(block_number);
for(i=0;i<512;i++){
   putc(SPI_READ(0xFF));               // we should now receive 512 bytes
}
mmc_close_block();
// puts(" ----End of read block---- ");
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////
int mmc_read_block_to_vs1011(int32 block_number){
unsigned long i, ii;
SSPEN=1;
block_number*=2;
SS=0;                     // set SS = 0 (on)
SPI_WRITE(0x51);                // send mmc read single block command
SPI_WRITE(*(((char*)&block_number)+2)); // arguments are address
SPI_WRITE(*(((char*)&block_number)+1));
SPI_WRITE(*(((char*)&block_number)+0));
SPI_WRITE(0x00);
SPI_WRITE(0xFF);                // checksum is no longer required but we always send 0xFF
if((mmc_response(0x00))==1) return 1;   // if mmc_response returns 1 then we failed to get a 0x00 response (affirmative)
if((mmc_response(0xFE))==1) return 1;   // wait for data token
// MOSI=1;
SSPEN=0;//switch to manual control of SPI port pins. the pic will not be reading these bytes into sspbuf
XdCS=0;//allow vs1011 to see the spi data
for(i=16;i>0;i--){
  while(!XDREQ){;}
  for(ii=0;ii<32;ii++){
  
   XCLK=1;XCLK=0; //doing it this way (without looping) to kill off a few cycles per byte
   XCLK=1;XCLK=0;//if you really want to go crazy, do this whole thing 32 times
   XCLK=1;XCLK=0;// that would save you about 1000 clock cycles or so, per block
   XCLK=1;XCLK=0;
   XCLK=1;XCLK=0;
   XCLK=1;XCLK=0;
   XCLK=1;XCLK=0;
   XCLK=1;XCLK=0;
  }
}
XdCS=1;//turn off vs1011 chip select
SSPEN=1;//back to normal spi mode for pic to mmc communication
SPI_READ(0xFF);                 // CRC bytes that are not needed, so we just use 0xFF
SPI_READ(0xFF);
SS=1;            // set SS = 1 (off)
SPI_WRITE(0xFF);// give mmc the clocks it needs to finish off
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////
#inline
void init(void){
tris_a=0b01110000;
tris_b=0b11101011;
// port_a=0;
// XCS=1;
option_reg =0b00000111;
// option_reg= 0b00000000;//allow rb pullups so that external pullup resistors are not needed
// ADCON0  = 0b00000000;//not using the adc, but here are the control bytes
// ADCON1 = 0b00000000;
// ANSEL   =  0b00000000;
OSCCON = 0b01110010; // 01110010 for internal 8MHz clock, 0b01110000 otherwise
// CVRCON = 0b00000000; //00001101for 3.3 volt output in case you want it for some reason
// CMCON = 0b00000111;
}
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

小黑屋|公司首页|Microchip单片机,模拟器件,接口电路,麦肯单片机,单片机应用交流 ( 粤ICP备09008620号 )

GMT+8, 2024-5-3 19:20 , Processed in 0.053461 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表