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

📄 usb_disk.c

📁 基于at89c51单片机的mp3 U盘原理实验代码
💻 C
字号:

#include "AT89C51SND1_REG.H"
#include "UDISK_DEF.H"

extern void ReadFlash();	 //Defined in FLASH_RW.C
extern void WriteFlash();

code unsigned char Device_Descriptor[18] = {
				    	 0x12,			   //0x12
						 0x01,             //DEVICE descriptor
						 0x10, 0x01,       //spec rev level (BCD) 1.0
						 0x0,              //device class
						 0x0,              //device subclass
						 0x0,              //device protocol
						 0x20,             //max packet size
						 0x05, 0x82,       //National's vendor ID
						 0x00, 0x11,       //National's product ID  
						 0x00, 0x00,       //National's revision ID  
						 0,                //index of manuf. string   
						 0,                //index of prod.  string  
						 0,                //index of ser. # string   
						 0x01              //number of configs. 	
						};

code unsigned char Configuration_Descriptor_All[32] = {

		        	    9,                 //Size of Descriptor in Bytes
					    2,                 //Configuration Descriptor (0x02)
					    0x20,              //Total length in bytes of data returned  LSB
						0x00,              //MSB
						1,                 //Number of Interfaces
						1,                 //Value to use as an argument to select this configuration
					    0,                 //Index of String Descriptor describing this configuration
						0x80,
						0xfa,              //Maximum Power Consumption in 2mA units 
					    9,
					    4,
					    0,                 //the index of the interface descriptor Number of Interface
					    0,                 //Value used to select alternative setting
						2,                 //EndPoint Number Used in this Descriptor
						8,                 //Class Code (Assigned by USB Org)
						6,	               //interface subclass1=RBC,2=SFF,3=QIC,4=UFI,5=SFF,6=SCSI
						0x50,              //bulk 0nly Transport
						0,                 //Index of String Descriptor Describing this interface
						                   //Bulk-in Endpoint
						0x07,             //length of this desc.   
						0x05,             //ENDPOINT descriptor TYPE
						0x81,             //address (IN) Endpoint 4 84
						0x02,             //attributes  (BULK)    
						0x40, 0x00,       //max packet size (64)  
						0x0,              //Does not apply to Bulk endpoints
						                  //Bulk-out Endpoint
						0x07,             //length of this desc.   
						0x05,             //ENDPOINT descriptor TYPE
						0x02,             //address (OUT) Endpoint 5 05
						0x02,             //attributes  (BULK)
						0x40, 0x00,       //max packet size (64)
						0x0               //Does not apply to Bulk endpoints
					};


code unsigned char B_InquiryData[] = {
							0x00,	                       //Direct Access Device
							0x80,	                       //RMB
							0x00,	                       //ISO/ECMA/ANSI
							0x01,	                       //Response Data Format
							0x1f,	                       //Additional Length
							0x00,	                       //Reserved
							0x00,	                       //Reserved
							0x00,	                       //Reserved 
							'J', 'M', 'B', 'I', 'E', ' ', ' ', ' ',	       //Vendor Information
							'U', 'S', 'B', '-', 'M', 'P', '3', ' ', 'V', '3', '.', '0', ' ', ' ', ' ', ' ',//Product Identification
							0, 0, 0, 0					   //Product Revision Level n.nn
							};	               

//SCSI-Read_Format_capacities命令的返回数据	 
code unsigned char B_Read_Format_capacities[] = {0x00, 0x00, 0x00, 0x10,	        //capacity list header
									0x00, 0x00, 0x07, 0xf5,	0x01, 0x00, 0x02, 0x00,	//capacity descriptor
								    //Number of Blocks =2037,unformatted media,blocklength = 512Bytes
									0x00, 0x00, 0x07, 0xfd,	0x00, 0x00, 0x02, 0x00  //Formattable Capacity Descriptors
									};
//SCSI-Read_Capacity命令的返回数据
code unsigned char B_Read_Capacity[] = {
								0x00, 0x00, 0xfe, 0xa0,	   //Last  Logical Block Address for 32MB 
								0x00, 0x00, 0x02, 0x00	   //block length in bytes
								};
//SCSI-Mode_Sense命令的返回数据    	   		
code unsigned char B_Mode_Sense_ALL[] = {0x0b, 0x00,       //Mode Data Length
							0x00, 0x08, 0x00, 0x00,
							0x7d, 0, 0, 0, 0x02, 0x00
							};
//SCSI-Mode_Sense命令的返回数据			
code unsigned char B_Mode_Sense_TPP[] = {0xf0, 0x00,       //Mode Data Length
							05, 00, 00, 00, 00, 0x0b, 00, 00, 00, 00, 0x24, 00, 00, 00, 00, 00
							};
//SCSI-Mode_Sense命令的返回数据			
code unsigned char B_Mode_Sense_ZERO[] = {0x00, 0x06,      //Mode Data Length
							0x00,	                       //Medium Type Code
							0,                             //write enabled
							0, 0, 0, 0                     //reserved	
                            };


unsigned char data bulk_CSW[]={0x55,0x53,0x42,0x53,	//bytes 4 dCSWSignature
					      0x00,0x00,0x00,0x00,	    //bytes 4 dCSWTag
					      0x00,0x00,0x00,0x00,		//bytes 4 dDataResiduce
					      0x00};			        //bCSWStatus  00=good state.



struct_CBW data bulk_CBW;



void AtmelUSBInit()
{
	int data i;	
	PLLNDIV	=	0x04;
	PLLCON |=	(0x3&Rdiv)<<6;
	PLLRDIV	=	(0x3ff&Rdiv)>>2;
	USBCLK=0;
	PLLCON&=(~PLLRES);
	PLLCON|=PLLEN;
	USBCON&=(~USBE);
	for(i=0;i<3000;i++);
	USBCON|=USBE;

}	

void EpEnable(void)
{
	UEPNUM=0x00;	UEPCONX=0x80;
	UEPNUM=0x01;	UEPCONX=0x86;
	UEPNUM=0x02;	UEPCONX=0x82;
	UEPRST=0x07;	UEPRST= 0x00;
	UEPIEN=0x07;	USBIEN|=EEOFINT;
	USBADDR=FEN;
}

unsigned char ReadEp(unsigned char EpNum,unsigned char *Data)
{
	unsigned char data i=0;
	UEPNUM=EpNum;
	while(i<UBYCTLX)
	{
		Data[i++]=UEPDATX;
	}	
	UEPSTAX&=~(RXOUTB0|RXOUTB1|RXSETUP);
	return(i);
}

void WriteEp(unsigned char EpNum,unsigned char nLength,unsigned char *Data)
{
	unsigned char data i=0;
	UEPNUM=EpNum;
	UEPSTAX|=DIR;
	while(nLength--) UEPDATX=Data[i++];	
	UEPSTAX|=TXRDY;
	while(!(UEPSTAX&TXCMP)) ;
	UEPSTAX&=(~(TXCMP));
}



void Set_Address(unsigned char EpNum)
{
	WriteEp(0,0,0);
	USBADDR|=EpNum;
	USBADDR|=FEN;
	USBCON|=FADDEN;
}


void Get_Descriptor(unsigned char DesType,unsigned char nLength)
{
	if(DesType==0x01)
		WriteEp(0,18,Device_Descriptor);

	if((DesType==0x02)&&(nLength==0x09))
		WriteEp(0,9,Configuration_Descriptor_All);

	if((DesType==0x02)&&(nLength==0xff))
	{
	    WriteEp(0,32,Configuration_Descriptor_All);
	    WriteEp(0,2,&Device_Descriptor[4]);
	}

	if((DesType==0x02)&&(nLength==0x20)) 
		WriteEp(0,32,Configuration_Descriptor_All);
}

void Set_Configuration(unsigned char wValue)
{
  if(wValue == 0)
  {
		UEPNUM=0x00;	UEPCONX=0x80;
		UEPNUM=0x01;	UEPCONX=0x86;
		UEPNUM=0x02;	UEPCONX=0x82;
		USBCON&=(~CONFG);
		WriteEp(0,0,0);	
  }
  else if(wValue == 1) 
  {
		UEPNUM=0x00;	UEPCONX=0x80;
		UEPNUM=0x01;	UEPCONX=0x86;
		UEPNUM=0x02;	UEPCONX=0x82;
		USBCON|=CONFG;
		WriteEp(0,0,0);	
  }
}

void Ep0()
{
  unsigned char data DT[32]={0,};
  unsigned char data i;
  i = ReadEp(0,DT);
  if (((DT[0] & 0x60)==0) && i)
  {
    switch (DT[1])
    {
      case set_address				:Set_Address(DT[2]);			break;
      case get_descriptor			:Get_Descriptor(DT[3],DT[6]);	break;
      case set_configuration	    :Set_Configuration(DT[2]);		break;
      default						:;					            break;
	}
  }
  else if(DT[0]==0xa1)
	{
		WriteEp(0,0,0);
	}							  						
}


void WriteEpBulk(unsigned char EpNum,unsigned char nLength,unsigned char *Data)
{
	unsigned char data i;
	UEPNUM=EpNum;
	UEPSTAX|=DIR;
	for(i=0;i<nLength;i++) UEPDATX=Data[i];
	UEPSTAX|=TXRDY;
}

void TransmitCSW()
{
  WriteEpBulk(1, sizeof(bulk_CSW), bulk_CSW);
  while(!(UEPSTAX&TXCMP)) ;
  UEPSTAX&=(~(TXCMP));
}

void main_txdone()
{
  UEPSTAX&=(~(TXCMP));
  TransmitCSW();
}

 void SCSI_Mode_Sense()
{
  if(bulk_CBW.CBWCB[2] == SCSI_MSPGCD_TPP)                 //Page Code=Timer and Potect Page
    {WriteEpBulk(1, sizeof(B_Mode_Sense_TPP), B_Mode_Sense_TPP);}
  else if(bulk_CBW.CBWCB[2] == SCSI_MSPGCD_RETALL)		   //Page Code=All
    {WriteEpBulk(1, sizeof(B_Mode_Sense_ALL), B_Mode_Sense_ALL);}
  else {WriteEpBulk(1, sizeof(B_Mode_Sense_ZERO), B_Mode_Sense_ZERO);}
}

void SCSI_Read_Format_Capacities()
{
  if(bulk_CBW.CBWCB[7]==0 && bulk_CBW.CBWCB[8]==0)return;
  WriteEpBulk(1, sizeof(B_Read_Format_capacities), B_Read_Format_capacities);
}

void SCSI_Read10()
{
  unsigned char data i;
	union
	{
		unsigned long   Block;
		unsigned char	Addr[4];
	}data BLK;
    unsigned char length;

	BLK.Addr[2] = bulk_CBW.CBWCB[4];
	BLK.Addr[3] = bulk_CBW.CBWCB[5];

    length = bulk_CBW.CBWCB[8];
    while(length>0)
     {

	  K9F_FUN = COMMAND;
	  K9F5608 = 0x00;
	  K9F_FUN = ADDRESS;
	  K9F5608 = 0;
	  K9F5608 = BLK.Addr[3];
	  K9F5608 = BLK.Addr[2];

	  K9F_FUN = D_DATA;
	  UEPNUM=0x01;
	  UEPSTAX|=DIR;
	  while(!(K9F_FUN & RB));

	  for(i=0;i<8;i++)
	  {
		  ReadFlash();
		  UEPSTAX|=TXRDY;
		  while(!(UEPSTAX&TXCMP));
		  UEPSTAX&=(~(TXCMP));
	  }
	  K9F5608 = INACTIVE;

	  length--;	
	  BLK.Block ++;
     }
  TransmitCSW();
}

void delay()
{
  unsigned char data i=20;
  while(i-->0);
}

void SCSI_Write10()	
{
    union
     {
	   unsigned long page;
	   unsigned char addr[4];
     }data PG; 

    unsigned char data i=0,length=0,nBeginPage=0;

 
    K9F_FUN = COMMAND;
    K9F5608 = 0x60;
    K9F_FUN = ADDRESS;
    K9F5608 = BuffBlock;
	K9F5608 = 0xff;
    K9F_FUN = COMMAND;						  
    K9F5608 = 0xd0;
    K9F_FUN = D_DATA;
	delay();

    while(!(K9F_FUN & RB));
	
	K9F_FUN = COMMAND;
    K9F5608 = 0x60;
    K9F_FUN = ADDRESS;
    K9F5608 = BuffBlock|0x20;	
	K9F5608 = 0xff;
    K9F_FUN = COMMAND;						  
    K9F5608 = 0xd0;
    K9F_FUN = D_DATA;	

	PG.addr[2] = bulk_CBW.CBWCB[4];
	PG.addr[3] = bulk_CBW.CBWCB[5];

	length = bulk_CBW.CBWCB[8];	
	nBeginPage = PG.addr[3]&0x1f;
	UEPNUM = 0x02;	
	delay();
	while(!(K9F_FUN & RB)); 

    if(nBeginPage>0)
	  {
	     for(i=0;i<nBeginPage;i++)
		   { 
			  K9F_FUN = COMMAND;
			  K9F5608 = 0x00;
			  K9F_FUN = ADDRESS;
              K9F5608 = 0;					 //A0-A7
              K9F5608 = (PG.addr[3]&0xe0)|i; 	 //A9-A16
	          K9F5608 = PG.addr[2]; 			 //A17-A24 
			  K9F_FUN = D_DATA;
              delay();
		      while(!(K9F_FUN & RB)); 

			  K9F_FUN = COMMAND;
			  K9F5608 = 0x8a;
			  K9F_FUN = ADDRESS;
              K9F5608 = 0;					          //A0-A7
              K9F5608 = BuffBlock|(PG.addr[3]&0x20)|i;  //A9-A16
	          K9F5608 = 0xff; 				          //A17-A24 
			  K9F_FUN = D_DATA;
			  delay();
		      while(!(K9F_FUN & RB));
		   }
		 nBeginPage=0;
	  }

	while(length>0)
	  {
	  	 K9F_FUN = COMMAND;
	     K9F5608 = 0x80;
	     K9F_FUN = ADDRESS;
	     K9F5608 = 0;							  //A0-A7	 
		 K9F5608 = (PG.addr[3]&0x3f)|BuffBlock;   //A9-A16  
		 K9F5608 = 0xff;				 		  //A17-A24
		 K9F_FUN = D_DATA;
		 for(i=0;i<8;i++)
		   {
			  while (!(UEPINT & EP2));	
			  WriteFlash();
			  UEPSTAX &= 0xB9;
		   }
		 K9F_FUN = COMMAND;
		 K9F5608 = 0x10;
		 K9F_FUN = D_DATA;
		 length--;	
		 delay();
		 while(!(K9F_FUN & RB));

	     if(((PG.addr[3]&0x1f)==0x1f)||(length==0))
		   {
		   
			    for(i=((PG.addr[3]&0x1f)+1);i<32;i++)
	             {
	               K9F_FUN = COMMAND;
		           K9F5608 = 0x00;
		           K9F_FUN = ADDRESS;
                   K9F5608 = 0;						     //A0-A7  
                   K9F5608 = (PG.addr[3]&0xe0)|i; 	     //A9-A16
	               K9F5608 = PG.addr[2]; 			     //A17-A24 
		           K9F_FUN = D_DATA;
		           delay();
		           while(!(K9F_FUN & RB));

		           K9F_FUN = COMMAND;
		           K9F5608 = 0x8a;
		           K9F_FUN = ADDRESS;
                   K9F5608 = 0;						        //A0-A7
                   K9F5608 = (PG.addr[3]&0x20)|BuffBlock|i; //A9-A16
	               K9F5608 = 0xff; 				            //A17-A24 
		           K9F_FUN = D_DATA;
		           delay();
		           while(!(K9F_FUN & RB));
	             }
			  	
		   	  K9F_FUN = COMMAND;
              K9F5608 = 0x60;				 //擦除当前block
              K9F_FUN = ADDRESS;
              K9F5608 = PG.addr[3];          //A9-A16
	          K9F5608 = PG.addr[2]; 		 //A17-A24 
              K9F_FUN = COMMAND;
              K9F5608 = 0xd0;
              K9F_FUN = D_DATA;
			  delay();
		      while(!(K9F_FUN & RB));        //等待操作完成  

			  for(i=0;i<32;i++)	
			    {
				   K9F_FUN = COMMAND;
				   K9F5608 = 0x00;
			  	   K9F_FUN = ADDRESS;
                   K9F5608 = 0;				                //A0-A7
                   K9F5608 = (PG.addr[3]&0x20)|BuffBlock|i; //A9-A16
	               K9F5608 = 0xff; 			                //A17-A24 
				   K9F_FUN = D_DATA;
				   delay();
		           while(!(K9F_FUN & RB)); 

				   K9F_FUN = COMMAND;
				   K9F5608 = 0x8a;  
			  	   K9F_FUN = ADDRESS;
                   K9F5608 = 0;						   //A0-A7
                   K9F5608 = (PG.addr[3]&0xe0)|i;      //A9-A16
	               K9F5608 = PG.addr[2]; 			   //A17-A24 
				   K9F_FUN = D_DATA;
				   delay();
		           while(!(K9F_FUN & RB));
  			    }

			  if(length>0)
			    {
				   K9F_FUN = COMMAND;
                   K9F5608 = 0x60;
                   K9F_FUN = ADDRESS;
                   K9F5608 = (PG.addr[3]&0x20)|BuffBlock;  //A9-A16
	               K9F5608 = 0xff; 				           //A17-A24 
                   K9F_FUN = COMMAND;
                   K9F5608 = 0xD0;
                   K9F_FUN = D_DATA;
				   delay();
				   while(!(K9F_FUN & RB));
				}
 		   }
		  PG.page++;
	  }

	TransmitCSW();	
}	

void main_rxdone()
{
  unsigned char data i;
  unsigned char data Buf[64];

  i = ReadEp(2,Buf);

	 P3_5 =0;
	 bulk_CSW[4] = Buf[4];  bulk_CSW[5] = Buf[5]; bulk_CSW[6] = Buf[6]; bulk_CSW[7] = Buf[7];
	 for(i=0;i<12;i++) bulk_CBW.CBWCB[i] = Buf[i+15];
	 switch(bulk_CBW.CBWCB[0])
		{
			case Inquiry			     :WriteEpBulk(1,36,B_InquiryData);break;
			case Mode_Sense			     :SCSI_Mode_Sense();              break;
			case Read10				     :SCSI_Read10();                  break;
			case Read_Capacity		     :WriteEpBulk(1, sizeof(B_Read_Capacity), B_Read_Capacity);break;
			case Read_Format_Capacities	 :SCSI_Read_Format_Capacities();  break;
			case Test_Unit_Ready	     :TransmitCSW();                  break;
			case Verify				     :TransmitCSW();                  break;
			case Write10			     :SCSI_Write10();                 break;
			case Medium_Removal		     :TransmitCSW();                  break;
		}
     P3_5 =1;
}

void Flash_Reset(void)		                                     //flash reset
{ 
	unsigned int data i;
	K9F_FUN = COMMAND;                     
	K9F5608 = 0xff;	                 //reset command
	for (i=0; i<3000; i++) ;	                                 //delay 	
}

⌨️ 快捷键说明

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