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

📄 mmc.c

📁 此乃MMC卡读写程序
💻 C
字号:
#include<stdio.h>
#include<reg52.h>
#include<intrins.h>
#include<stdlib.h>
#include<ctype.h>
typedef unsigned char uchar;
typedef unsigned int uint;
typedef unsigned long ulong;
#define HIGH 0
#define LOW 1
#define TRUE 1
#define FALSE 0
sbit MCS=P3^4;
sbit MI=P3^3;
sbit MSCK=P1^3;
sbit MO=P1^1;
sbit MGND=P1^2;
void gen_crc7_syndrome_table (void);
void insert_crc7 (unsigned char *path_trace_message);
int crc7_OK (const unsigned char *path_trace_message);
uchar Response(uchar index);
void M_8clock(void);
void clock(void);
bit M_init(void);
bit ReadSec(ulong add);
bit WriteSec(ulong add);
uchar SendCmd(void);
uchar GetResp(void);
uchar GetByte(void);
uchar SendByte(uchar ch);
void M_delay(void);
void putch(uchar ch);

/*SPI常量定义*/
#define GO_IDLE_STATE         0  /*复位*/
#define SEND_OP_COND          1  /*激活卡的初始化过程*/
#define SEND_CSD              9  /*请求被选择的卡以便发送卡特征数据CSD*/
#define SEND_CID              10 /*请求被选择的卡以便发送卡ID*/
#define STOP_TRANSMISSION     12 /*多块读时停止传输*/
#define SEND_STATUS           13 /*请求被选卡发送状态寄存器的内容*/
#define SEND_BLOCKLEN         16 /*选择块长度,以便随后的块命令(读和写)*/
#define READ_SINGLE_BLOCK     17 /*读一块,长度由SEND_BLOCKLEN决定*/
#define READ_MULTIPLE_BLOCK   18 /*从卡连续传输数据块到主机,直到停止命令中断或被请求的数据块数*/
#define WRITE_BLOCK           24 /*写一块,长度由SEND_BLOCKLEN决定*/
#define WRITE_MULTIPLE_BLOCK  25 /*从主机连续传输数据块到卡,直到停止命令中断或被请求的数据块数*/
#define PROGRAM_CSD           27 /*编程CSD的可编程位*/
#define SET_WRITE_PROT        28 /*如果卡有写保护特性,此命令用来设置地址组的写保护位,该特性在CSD中编码(WP_GRP_SIZE)*/
#define CLR_WRITE_PROT        29 /*如果卡有写保护特性,此命令用来清除地址组的写保护位*/
#define SEND_WRITE_PROT       30 /*如果卡有写保护特性,此命令用来请求卡发送写保护位的状态*/
#define TAG_SECTOR_START      32 /*设置擦除组的首扇区的地址*/
#define TAG_SECTOR_END        33 /*设置擦除组的连续范围末扇区的地址,或单扇区的地址*/
#define UNTAG_SECTOR          34 /*从擦除组除去先前被选择的扇区*/
#define TAG_ERASE_GROUP_START 35 /*设置在擦除组内的首扇区的地址*/
#define TAG_ERASE_GROUP_END   36 /*设置在擦除组内的末扇区的地址*/
#define UNTAG_ERASE_GROUP     37 /*除去先前被选择的擦除组*/
#define ERASE                 38 /*擦除先前被选的扇区*/ 
#define LOCK_UNLOCK           42 /*用来设置或复位密码,锁/开锁卡,数据块的长度由SEND_BLOCKLEN定义*/
#define READ_OCR              58 /*读卡中OCR寄存器*/
#define CRC_ON_OFF            59 /*开关CRC参数,1开,0关*/

/*CRC变量定义*/
#define CRC7_POLYNOMIAL 0x89            /* x^7 + x^3 + 1 */
static unsigned char path_trace_message[] = "\200123456789ABCDEF";
static unsigned char crc7_syndrome_table[3]; 
uchar xdata SecBuf[624]="This is the MMC test!This is the MMC test!This is the MMC test!";
uchar xdata pccommand[6]="";
bit flag=0;
/*硬盘文件分配表*/
//typedef struct
//        {uchar boot=0;        
//         } 
/*MMC变量定义*/
typedef struct
        {uchar Index;
         ulong Address;
         uchar Crc;
         }type1;
union u1{type1 CmdFormat;
         uchar CmdBuf[6];
        };
union u1 data Cmd;

int main (void)
{ uchar i,ch;
  uint m,n;
  ulong address;
  bit errorflag=0;
  MCS=HIGH;MI=HIGH;MSCK=HIGH;
  for (m=0;m<1000;m++)
     for (n=0;n<50;n++);
  SCON=0x52;
  TMOD=0x20;
  TH1=0xf3;   /*12M 2400*/
  TL1=0xf3;
  TR1=1;

  for (m=0;m<512;m++)
      SecBuf[m]=0x23;

  putch(1);
  errorflag=M_init();
  putch(2);
  WriteSec(0x100);
  putch(3);

//  if (errorflag==1) 
//     {putch(1);
//      goto tt;
//      }
//  errorflag=1; //WriteSec(10);
//  if (errorflag==1) 
//     {putch(2);
//      goto tt;
//      }

  for (m=0;m<512;m++)
      SecBuf[m]=0;
//goto scan; 
  address=0xea00; //0xea00为文件分配表位置;
  n=0;
while(n<62720){
mv:goto mz;

 for (i=0;i<6;i++) pccommand[i]=i;
 address=0;
 for (i=6;i>0;i--) {RI=0;while(RI==0);RI=0; 
                    address=address+(ulong)(toint(SBUF));
                    if (i!=1) address=address<<4;
                    }
goto mz;
                TI=0;
                SBUF=(uchar)((address>>24)&0xff);
                while(TI==0);TI=0;
                TI=0;
                TI=0;
                SBUF=(uchar)((address>>16)&0xff);
                while(TI==0);TI=0;
                TI=0;
                TI=0;
                SBUF=(uchar)((address>>8)&0xff);
                while(TI==0);TI=0;
                TI=0;
                TI=0;
                SBUF=(uchar)((address)&0xff);
                while(TI==0);TI=0;
                TI=0;
goto mv;
mz:
 errorflag=ReadSec(address);    /*bit31--bit9:为扇区地址,bit8--bit0:为扇区内字节首地址*/
          for (m=0;m<208;m++)
                {TI=0;
                SBUF=SecBuf[m];
                while(TI==0);TI=0;}
                i=0;
                while(i!=0xd0)
                 {RI=0;
		     while(RI==0);
		     RI=0;i=SBUF;}  
	    for (m=208;m<416;m++)
		    {TI=0;
                SBUF=SecBuf[m];
                while(TI==0);TI=0;}
                i=0;
                while(i!=0xd0)
                 {RI=0;
		     while(RI==0);
		     RI=0;i=SBUF;}  
          for (m=416;m<624;m++)
              {TI=0;
               SBUF=SecBuf[m];
               while(TI==0);TI=0;}
//               RI=0;
//               while(RI==0);
//               RI=0;
 address=address+0x200;
 n++;
 goto mv;
scan:
/* address=0x27000;      n=0x381是时找到led.bin*/
 address=0x97200;

 n=0;
while(1){  
  putch((uchar)(n>>8)&0xff);
  putch((uchar)(n)&0xff);
  errorflag=ReadSec(address);
  address=address+0x200;
  n++;
  for (m=0;m<512;m++)
     {if ((SecBuf[m]==0xc2)&&(SecBuf[m+1]==0x91)&&(SecBuf[m+2]==0x12))
         { for (m=0;m<180;m++)
                {TI=0;
                SBUF=SecBuf[m];
                while(TI==0);TI=0;}
                RI=0;
		    while(RI==0);
		    RI=0;
	    for (m=181;m<360;m++)
		    {TI=0;
                SBUF=SecBuf[m];
                while(TI==0);TI=0;}
                RI=0;
                while(RI==0);
                RI=0;
          for (m=361;m<512;m++)
              {TI=0;
               SBUF=SecBuf[m];
               while(TI==0);TI=0;}
               RI=0;
               while(RI==0);
               RI=0;goto lxx;
          }
        } 
lxx:_nop_();
    }
  } 
tt:goto tt;

}
void putch(uchar ch)
{
  TI=0;
  SBUF=ch;
  while(TI==0);TI=0;
}
/*SPI操作程序*/
bit M_init(void)
{uchar i,Res;
 bit flaginit=0;
//// MCS=HIGH;               	 /*MCS上升沿*/
 for (i=0;i<10;i++) 	       /*发至少74clock*/
    //M_8clock();
     GetByte();              	 /*发10个虚拟字节*/
//// MCS=LOW;                      /*MCS低*/
 flaginit=1;
 Cmd.CmdFormat.Index=0;        /*发送命令0使MMC卡进入SPI模式*/
 Cmd.CmdFormat.Address=0;
 Cmd.CmdFormat.Crc=0x95	;
 SendCmd();
/* if (SendCmd()==0x01) goto M_initEnd;   /*如果响应不等于01则退出!*/
/* if (SendCmd()!=0x01) goto M_initEnd;   /*如果响应不等于01则退出!*/
M_init1: 
 GetByte();                    /*8clock*/
 Cmd.CmdFormat.Index=1;        /*发送命令1(argument 和 CRC 无关紧要)*/
 Cmd.CmdFormat.Address=0;      /*(OCR电压描绘在SPI模式中不用)*/
 Cmd.CmdFormat.Crc=0x95;      
 Res=(SendCmd())&0x01;
 if (Res==1) goto M_init1;   /*循环直到响应不等于01*/
/* if (Res==0x01) goto M_init1;   /*循环直到响应不等于01*/

 //if (Res!=0) flaginit=1; 
 /*           else flaginit=0;  /*如果响应不为0则标志位置1*/
 flaginit=0;
M_initEnd:
//// MCS=HIGH;                    /*取消选择 */
 GetByte();                   /*8colck*/
 return(flaginit); 
}
bit ReadSec(ulong add)
{uint i;
 bit flagread=0;
//// MCS=LOW;                    /*MCS低 */
 Cmd.CmdFormat.Index=16;        /*发送命令16选择数据块长度*/
 Cmd.CmdFormat.Address=512;
 Cmd.CmdFormat.Crc=0;
 SendCmd();

 Cmd.CmdFormat.Index=17;     /*发送读命令17*/
 Cmd.CmdFormat.Address=0xEA00; //add;
 Cmd.CmdFormat.Crc=0;        /*虚拟CRC(在SPI模式中不正常使用)*/
 SendCmd(); 
// if (SendCmd()!=0) 
//        {flagread=1;goto ReadSecEnd;} 
/*         else flagread=0;    /*如果响应不等于0则标志位置1*/
 GetByte();                  /*读开始字节0XFE*/
 GetResp();
 for (i=0;i<512;i++)         /*从MMC卡读512字节到缓冲区地址*/
    SecBuf[i]=GetByte();
 GetByte();                  /*读16位校验和并忽略它*/
 GetByte();
 flagread=0;                 /*成功操作标志*/
ReadSecEnd:                  /*退出*/
//// MCS=HIGH;
 GetByte();
 return(flagread);
}
bit WriteSec(ulong add)
{uint i;
 bit flagwrite=0;
//// MCS=LOW; 			     /*MCS低 */
 Cmd.CmdFormat.Index=16;        /*发送命令16选择数据块长度*/
 Cmd.CmdFormat.Address=512;
 Cmd.CmdFormat.Crc=0;
 SendCmd();

 Cmd.CmdFormat.Index=29;     /*取消写保护*/
 Cmd.CmdFormat.Address=0xEA00;
 Cmd.CmdFormat.Crc=0;        /*虚拟CRC,在SPI模式中不正常使用*/
 SendCmd();


 Cmd.CmdFormat.Index=24;     /*写数据*/
 Cmd.CmdFormat.Address=0xEA00;
 Cmd.CmdFormat.Crc=0;        /*虚拟CRC,在SPI模式中不正常使用*/
 SendCmd();
// if (SendCmd()!=0) 
//      {flagwrite=1;goto WriteSecEnd;} 
/*      else flagwrite=0; /*如果响应不等于0则标志位置1*/

 SendByte(0xfe);             /*开始字节*/
 for (i=0;i<512;i++)         /*发512字节到MMC卡*/
     SendByte(0x33); //SecBuf[i]);
 GetByte();                  /*发送虚拟16位校验和=FFFFH*/
 GetByte();
 GetByte();                  /*读数据响应字节=xxx00101b,只校验CRC,它不用*/
 while (GetByte()==0);       /*循环直到不忙,完成一个块写操作需要一些时间*/
 flagwrite=0;                /*成功操作标志*/
 WriteSecEnd: 
//// MCS=HIGH;
 GetByte();
 return(flagwrite);
}
uchar SendCmd(void)
{uchar result;
 Cmd.CmdFormat.Index=Cmd.CmdFormat.Index|0x40;
 SendByte(Cmd.CmdFormat.Index);         /*command index*/
 SendByte(Cmd.CmdBuf[1]);               /*arg0*/
 SendByte(Cmd.CmdBuf[2]);		    /*arg1*/
 SendByte(Cmd.CmdBuf[3]);               /*arg2*/
 SendByte(Cmd.CmdBuf[4]);               /*arg3*/
 SendByte(Cmd.CmdFormat.Crc|0x01);      /*低位一定要置1,但无关紧要*/
 result=GetResp();                      /*响应*/
 return(result);
}
uchar GetResp(void)
{uchar i,RespData;
 i=0;
while (i<64)                               /*循环至少最大次数64次,8次不够*/
      {RespData=GetByte();
      if (RespData!=0xff) goto GetRestEnd; /*读响应字节 */
      i++;                                 /*当计数未到或响应数据=FFH是循环*/
      }
GetRestEnd:
      return(RespData);
}
uchar GetByte(void)
{uchar x;
 x=SendByte(0xff);
 return(x);
}
uchar SendByte(uchar ch)
{uchar i,M_data=0;
MCS=LOW;
    ch=~ch;
    for (i=0;i<8;i++)
       {MSCK=LOW; 
        MI=(bit)(ch&0x80);
        ch=ch<<1;
        MSCK=HIGH; 
        M_data*=2;
        if (MO==1) M_data++;       
       }
MCS=HIGH;
  return(M_data);
}
void M_delay(void)
{
_nop_();
}
void M_8clock(void)
{uchar i;
for (i=0;i<8;i++)
 {MSCK=HIGH;
  M_delay();
  MSCK=LOW;
  }
}



⌨️ 快捷键说明

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