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

📄 usb.c

📁 MP3播放器和U盘功能的源代码。采用集成了MP3解码芯片和USB接口芯片的AT89C51SND1C单片机
💻 C
📖 第 1 页 / 共 2 页
字号:
  while(!(UEPSTAX&TXCMP)) ;
  UEPSTAX&=(~(TXCMP));				                //清除TXCMP
  UEPINT = 0;
}

void main_txdone()					                 //数据发送完毕给出回复
{
  UEPSTAX&=(~(TXCMP));				                 //清除TXCMP
  TransmitCSW();
}

//////////////////////////////////有关输出端点的调用//////////////////////////////////////////////
#define Inquiry							0x12
#define	Mode_Sense						0x1A
#define	Read10							0x28
#define Read_Capacity 					0x25 
#define Read_Format_Capacities 	        0x23 
#define Test_Unit_Ready 				0x00 
#define Verify 							0x2F 
#define Write10 						0x2A 
#define Medium_Removal					0x1E

#define SCSI_MSPGCD_TPP		    	    0x1C
#define SCSI_MSPGCD_RETALL			    0x3F

//SCSI-Inquiry命令的返回数据  
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 
							'K', 'T', '-', 'T', 'E', 'C', 'H', ' ',	       //Vendor Information
							'M', 'P', '3', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', 'V', '1', '.', '0', '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	
};


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);
}

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=10;
  while(i-->0);
}

#define BuffBlock (0xc0) 	  //缓冲区为从偶数块开始的连续两个Block	这里定为2046和2047两个Block
							  //BuffBlock只代表块号的低字节
void SCSI_Write10()			  //之所以选用两个Block作为缓冲区,与Flash的Copy - Back功能的特性相关,
{  							  //清仔细阅读Flash 的datasheet
   unsigned char Page_Buf[512];
   unsigned int j;
    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;	
    delay();
    while(!(K9F_FUN & RB));  
	//从SCSI命令中分离出逻辑地址
//   	PG.addr[0] = bulk_CBW.CBWCB[2];
//	PG.addr[1] = bulk_CBW.CBWCB[3];
	PG.addr[2] = bulk_CBW.CBWCB[4];   //PG为前面定义的结构体
	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++)
		   {
/*COPY BACK命令  001*************************
			  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));                          //等待操作的完成  
END OF COPY BACK命令  001**************************/
//void ReadPage(unsigned int block, unsigned int page, unsigned char *pPage)
              
	          //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) = (PG.addr[3]&0xe0)|i; 	     //A9-A16
	          *((unsigned char xdata *)K9F5608) = PG.addr[2];                //A17-A24 
	          K9F_FUN = D_DATA;

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

	          for(j=0;j<512;j++) 
	          {
		         Page_Buf[j]= *((unsigned char xdata *)K9F5608); 
	          }
//int WritePage(unsigned int block, unsigned int page, unsigned char *pPage)  
//{
	         //j = 512;
	          //unsigned int blockPage = (block << 5) + page;

	          K9F_FUN = COMMAND;
	          *((unsigned char xdata *)K9F5608) = 0x80;
	          K9F_FUN = ADDRESS;
	          *((unsigned char xdata *)K9F5608)  = 0;
	          *((unsigned char xdata *)K9F5608)  = BuffBlock|(PG.addr[3]&0x20)|i;
	          *((unsigned char xdata *)K9F5608)  =0xff;
              K9F_FUN = D_DATA;

	          for(j=0;j<512;j++)
	         {
		        *((unsigned char xdata *)K9F5608)= Page_Buf[j];
	         }         

	         K9F_FUN = COMMAND;
	         *((unsigned char xdata *)K9F5608) = 0x10;
             delay();
	         while(!(K9F_FUN & RB));                  //等待操作的完

⌨️ 快捷键说明

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