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

📄 usb.c

📁 关于 at89c51snd1c 的海量存储mass storge的基于keil c的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
{
  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);
}

extern void ReadFlash();
extern void WriteFlash();

void SCSI_Read10()
{
  unsigned char data i;
	union
	{
		unsigned long   Block;
		unsigned char	Addr[4];
	}data BLK;
    unsigned char length;									//传输的簇数
//将起始地址变换为K9F5608适合的模式;  
//    BLK.Addr[0] = bulk_CBW.CBWCB[2];
//	BLK.Addr[1] = bulk_CBW.CBWCB[3];
	BLK.Addr[2] = bulk_CBW.CBWCB[4];
	BLK.Addr[3] = bulk_CBW.CBWCB[5];

//将扇区数填入计数变量每循环一次读出一扇区的值;	  
//    PG.Addr[0]	=	bulk_CBW.CBWCB[7];
//	PG.Addr[1]	=	bulk_CBW.CBWCB[8];
    length = bulk_CBW.CBWCB[8];
    while(length>0)
     {

	  K9F_FUN = COMMAND;	                         	    //读出一个page
	  *((unsigned char xdata *)K9F5608) = 0x00;
	  K9F_FUN = ADDRESS;
	  *((unsigned char xdata *)K9F5608) = 0;				//A0-A7	
	  *((unsigned char xdata *)K9F5608) = BLK.Addr[3];     	//A9-A16
	  *((unsigned char xdata *)K9F5608) = BLK.Addr[2];     	//A17-A24

	  K9F_FUN = D_DATA;
	  UEPNUM=0x01;											//指向端点
	  UEPSTAX|=DIR;											//传输方向
	  while(!(K9F_FUN & RB));

	  for(i=0;i<8;i++)		                                //读出512个字节的数据发送到usb     
	  {
		  ReadFlash();
		  UEPSTAX|=TXRDY;
		  while(!(UEPSTAX&TXCMP));		                    //等待发送完成   
		  UEPSTAX&=(~(TXCMP));          	                //清中断标志clear TXCMP
		  UEPINT=0;
	  }
	  *((unsigned char xdata *)K9F5608) = INACTIVE;

	  length--;							                    //传输的簇数减1
	  BLK.Block ++;  						                //flash的页地址加1
     }
  TransmitCSW();							                //返回CSW
}

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

#define BuffBlock (0xc0) 	  //缓冲区为从偶数块开始的连续两个Block	这里定为2046和2047两个Block
							  //BuffBlock只代表块号的低字节
void SCSI_Write10()			  //之所以选用两个Block作为缓冲区,与Flash的Copy - Back功能的特性相关,
{  							  //清仔细阅读Flash 的datasheet
    union
     {
	   unsigned long page;
	   unsigned char addr[4];
     }data PG; 

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

	//所有写入都要缓冲,所以先清除缓冲区     
    K9F_FUN = COMMAND;
    *((unsigned char xdata *)K9F5608) = 0x60;				 //擦除第2046个Block作为缓冲区
    K9F_FUN = ADDRESS;
    *((unsigned char xdata *)K9F5608) = BuffBlock;     		 //A9-A16  
	*((unsigned char xdata *)K9F5608) = 0xff; 				 //A17-A24 	
    K9F_FUN = COMMAND;						  
    *((unsigned char xdata *)K9F5608) = 0xd0;
    K9F_FUN = D_DATA;
	delay();
//    printuf(" %x",PG.addr[0]);printuf(" %x",PG.addr[1]);printuf(" %x",PG.addr[2]);printuf(" %x",PG.addr[3]);
//	printuf(" %x",length); printuf(" %x",nBeginPage);
    while(!(K9F_FUN & RB));                                  //等待擦除操作的完成 
	
	K9F_FUN = COMMAND;
    *((unsigned char xdata *)K9F5608) = 0x60;				 //擦除第2047个Block作为缓冲区
    K9F_FUN = ADDRESS;
    *((unsigned char xdata *)K9F5608) = BuffBlock|0x20;		 //A9-A16  
	*((unsigned char xdata *)K9F5608) = 0xff; 				 //A17-A24 	
    K9F_FUN = COMMAND;						  
    *((unsigned char xdata *)K9F5608) = 0xd0;
    K9F_FUN = D_DATA;	
	//从SCSI命令中分离出逻辑地址
//   	PG.addr[0] = bulk_CBW.CBWCB[2];
//	PG.addr[1] = bulk_CBW.CBWCB[3];
	PG.addr[2] = bulk_CBW.CBWCB[4];
	PG.addr[3] = bulk_CBW.CBWCB[5];

	length = bulk_CBW.CBWCB[8];		  //windows 系统每次写入的最大长度为0x80个扇区取一字节已够用
	nBeginPage = PG.addr[3]&0x1f;	  //计算出要写入块内的要写入的起始扇区号
	UEPNUM = 0x02;	 				  //指向Bulk端点2
	delay();
	while(!(K9F_FUN & RB));           //等待擦除操作的完成 

    if(nBeginPage>0)			      //如果起始写入page与flash的Block未对齐,则将当前Block中的前nBeginPage页
	  {							      //拷贝到缓冲区的相同位置   
	     for(i=0;i<nBeginPage;i++)
		   { 
			  K9F_FUN = COMMAND;
			  *((unsigned char xdata *)K9F5608) = 0x00;		  //命令的第一个字节
			  K9F_FUN = ADDRESS;
              *((unsigned char xdata *)K9F5608) = 0;					 //A0-A7
              *((unsigned char xdata *)K9F5608) = (PG.addr[3]&0xe0)|i; 	 //A9-A16
	          *((unsigned char xdata *)K9F5608) = PG.addr[2]; 			 //A17-A24 
			  K9F_FUN = D_DATA;
              delay();
		      while(!(K9F_FUN & RB));                         //等待操作的完成

			  K9F_FUN = COMMAND;
			  *((unsigned char xdata *)K9F5608) = 0x8a;		  //命令的第二个字节
			  K9F_FUN = ADDRESS;
              *((unsigned char xdata *)K9F5608) = 0;					          //A0-A7
              *((unsigned char xdata *)K9F5608) = BuffBlock|(PG.addr[3]&0x20)|i;  //A9-A16
	          *((unsigned char xdata *)K9F5608) = 0xff; 				          //A17-A24 
			  K9F_FUN = D_DATA;
			  delay();
		      while(!(K9F_FUN & RB));                          //等待操作的完成  
		   }
		 nBeginPage=0;		                                   //起始扇区值赋为0
	  }

	while(length>0)			                                   //传输的扇区数大于0
	  {
	  	 K9F_FUN = COMMAND;				         	           //数据写入到缓冲区的对应位置
	     *((unsigned char xdata *)K9F5608) = 0x80;
	     K9F_FUN = ADDRESS;
	     *((unsigned char xdata *)K9F5608) = 0;							  //A0-A7	 
		 *((unsigned char xdata *)K9F5608) = (PG.addr[3]&0x3f)|BuffBlock; //A9-A16  
		 *((unsigned char xdata *)K9F5608) = 0xff;				 		  //A17-A24
		 K9F_FUN = D_DATA;
		 for(i=0;i<8;i++)							           //端点数据写入到Flash的缓冲区
		   {
			  while (!(UEPINT & 0x04));					       //等待接收数据RXOUTB1	
			  //写64字节
			  WriteFlash();
			  UEPSTAX &= 0xB9;		                           //准备再接收  	
			  UEPINT = 0;
		   }
		 K9F_FUN = COMMAND;
		 *((unsigned char xdata *)K9F5608) = 0x10;
		 K9F_FUN = D_DATA;
		 length--;					                          //传输的扇区数减1 
		 delay();
		 while(!(K9F_FUN & RB));							  //等待操作的完成

	     if(((PG.addr[3]&0x1f)==0x1f)||(length==0))	          //缓冲区写满即写满32页或传输数据结束时 
		   {
		   
			    for(i=((PG.addr[3]&0x1f)+1);i<32;i++)		  //如果当length==0时并且(PG.addr[3]&0x1f)!=0x1f
	             { 											  //拷贝从((PG.addr[3]&0x1f)+1)到32号页的数据到缓冲区的对应位置
	               K9F_FUN = COMMAND;						  //执行Flash的COPY-BACK命令
		           *((unsigned char xdata *)K9F5608) = 0x00;
		           K9F_FUN = ADDRESS;
                   *((unsigned char xdata *)K9F5608) = 0;						     //A0-A7  
                   *((unsigned char xdata *)K9F5608) = (PG.addr[3]&0xe0)|i; 	     //A9-A16
	               *((unsigned char xdata *)K9F5608) = PG.addr[2]; 				     //A17-A24 
		           K9F_FUN = D_DATA;
		           delay();
		           while(!(K9F_FUN & RB));                    //等待操作的完成  

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

			  for(i=0;i<32;i++)					   //将缓冲Block中的内容拷贝到当前Block中
			    {
				   K9F_FUN = COMMAND;
				   *((unsigned char xdata *)K9F5608) = 0x00;
			  	   K9F_FUN = ADDRESS;
                   *((unsigned char xdata *)K9F5608) = 0;				              //A0-A7
                   *((unsigned char xdata *)K9F5608) = (PG.addr[3]&0x20)|BuffBlock|i; //A9-A16
	               *((unsigned char xdata *)K9F5608) = 0xff; 			              //A17-A24 
				   K9F_FUN = D_DATA;
				   delay();
		           while(!(K9F_FUN & RB));                        //等待操作的完成 

				   K9F_FUN = COMMAND;
				   *((unsigned char xdata *)K9F5608) = 0x8a;  
			  	   K9F_FUN = ADDRESS;
                   *((unsigned char xdata *)K9F5608) = 0;						 //A0-A7
                   *((unsigned char xdata *)K9F5608) = (PG.addr[3]&0xe0)|i;      //A9-A16
	               *((unsigned char xdata *)K9F5608) = PG.addr[2]; 				 //A17-A24 
				   K9F_FUN = D_DATA;
				   delay();
		           while(!(K9F_FUN & RB));                         //等待操作的完成 
  			    }

			  if(length>0)		//传输未完成时
			    {
				   K9F_FUN = COMMAND;
                   *((unsigned char xdata *)K9F5608) = 0x60;		//擦除相应的缓冲区
                   K9F_FUN = ADDRESS;
                   *((unsigned char xdata *)K9F5608) = (PG.addr[3]&0x20)|BuffBlock;  //A9-A16
	               *((unsigned char xdata *)K9F5608) = 0xff; 				         //A17-A24 
                   K9F_FUN = COMMAND;
                   *((unsigned char xdata *)K9F5608) = 0xD0;
                   K9F_FUN = D_DATA;
				   delay();
				   while(!(K9F_FUN & RB));                          //等待操作的完成 
				}
 		   }
		  PG.page++;												//逻辑簇地址加1
	  }

	TransmitCSW();												    //向Host返回CSW
//    printuf(" %x",PG.addr[0]);printuf(" %x",PG.addr[1]);printuf(" %x",PG.addr[2]);printuf(" %x\n",PG.addr[3]);
}

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

  i = ReadEp(2,Buf);												//读出端点数据
//  if(Buf[0] == 0x55)												//命令数据包
//	{
	 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;													   //指示灯灭
//	}
//  else
//      SCSI_Write10();

}
//flash芯片复位函数
void Flash_Reset(void)		                                     //flash reset
{ 
	unsigned int data i;
	K9F_FUN = COMMAND;                     
	*((unsigned char xdata *)K9F5608) = 0xff;	                 //reset command
	for (i=0; i<3000; i++) ;	                                 //delay 	
}

//读取一个page的内容
void ReadPage(unsigned int block, unsigned int page, unsigned char *pPage)
{
	int i;
	unsigned int blockPage = (block << 5) | page;

	K9F_FUN = COMMAND;
	*((unsigned char xdata *)K9F5608) = 0x00;
	K9F_FUN = ADDRESS;
    *((unsigned char xdata *)K9F5608) = 0;						 //A0-A7
    *((unsigned char xdata *)K9F5608) = blockPage & 0xff; 	     //A9-A16
	*((unsigned char xdata *)K9F5608) = (blockPage >> 8) & 0xff; //A17-A24 
	K9F_FUN = D_DATA;

	i = 512;
    while(!(K9F_FUN & RB));                  //等待操作的完成

	while((i--)>0) 
	{
		*pPage++ = *((unsigned char xdata *)K9F5608); 
	}
}

⌨️ 快捷键说明

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