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

📄 sl811.h

📁 用SL811做USB主机的源码
💻 H
字号:
/*#define SL811_nMS_LOW   			{PORTD &= ~0x80;}
#define SL811_nMS_HIGH  			{PORTD |= 0x80;}

#define SL811_nDACK_LOW   			{PORTD &= ~0x40;}
#define SL811_nDACK_HIGH  			{PORTD |= 0x40;}

#define SL811_RST_LOW   			{PORTD &= ~0x10;}
#define SL811_RST_HIGH  			{PORTD |= 0x10;}
*/
// SL811_INT @ PD0=INT0
// 对于全速设备应该注意设置control Reg 中的 SOF 位
// 接收无Data0 Data1 之分,可统一写成 0x23
// 发送有Data0 Data1 之分,一开始是 Data0 

//declare memory mapped variables
volatile extern unsigned char SL811_ADDR;
volatile extern unsigned char SL811_COMM;

//define mappings
void mapping_init(void)
{
 asm(
  ".area memory(abs)\n"
  ".org 0x8000\n"
  " _SL811_ADDR:: .blkb 1\n"
  ".org 0x8001\n"
  " _SL811_COMM:: .blkb 1\n"
  ".text\n"
 );
}
#define SL811_USBA_Control	  			 0x00
#define SL811_USBA_BaseAddress 			 0x01
#define SL811_USBA_BaseLength 			 0x02
#define SL811_USBA_PIDDEoUS			 	 0x03
#define SL811_USBA_DAoTC 			 	 0x04

#define SL811_Control		  			 0x05
#define SL811_Interrupt_Enable			 0x06

#define SL811_USBB_Control	  			 0x08
#define SL811_USBB_BaseAddress 			 0x09
#define SL811_USBB_BaseLength 			 0x0A
#define SL811_USBB_PIDDEoUS			 	 0x0B
#define SL811_USBB_DAoTC 			 	 0x0C

#define SL811_Interrupt_Status			 0x0D
#define SL811_SOF_DataSet			     0x0E
#define SL811_SOF_Highbyte				 0x0F

#define SETUP_PID						 0xD0
#define IN_PID						 	 0x90
#define OUT_PID						 	 0x10
#define SOF_PID						 	 0x50
#define PREAMBLE_PID					 0xC0
#define NAK_PID						 	 0xA0
#define STALL_PID						 0xE0
#define DATA0_PID						 0x30
#define DATA1_PID						 0xB0

uint8 YES_UDisk = 0;		  //judge if it'is U disk
uint8 USBA_Status = 0;		  
uint8 USBB_Status = 0;
uint8 Endp0_DataLen = 8;	  //U盘控制端点0的长度
uint8 Config_DataLen = 0;	  //配置描述符加接口描述符数据长度
uint8 BulkOut_PortNum = 2; 	  //批量输入端点号
uint8 BulkOut_DataLen = 0x40; //批量输入端点数据长度
uint8 BulkIn_PortNum = 1;	  //批量输出端点号
uint8 BulkIn_DataLen = 0x40;  //批量输出端点数据长度
uint8 UDisk_Address = 1;	  //U盘设备地址固定分配为1

uint8 GetDataBuffer[64];

void Printf_buffer(void)
{
	uint8 temp;
	
	printf("Get: %x",GetDataBuffer[0]);
	for(temp=1;temp<64;temp++)
		printf(" %x",GetDataBuffer[temp]);
	puts("");	
	printf("Means: %c",GetDataBuffer[0]);
	for(temp=1;temp<64;temp++)
		printf(" %c",GetDataBuffer[temp]);
	puts("\n");		
}

void init_sl811_master(void)
{
 uint8 temp;
 
 puts("Begin to run!");
 puts("RESET SL811 for master mode!");
 //for(temp=0;temp<4;temp++)delayms(250); 

 SL811_ADDR = SL811_SOF_DataSet;
 SL811_COMM = 0xE0;
 SL811_COMM = 0xAE; 		  //Select Master Mode
 
 SL811_ADDR = SL811_Control;
 SL811_COMM = 0x08; 		  //USB Engine reset
 delayms(1);//50);
 SL811_ADDR = SL811_Control;
 SL811_COMM = 0x01; 		  //USB Engine normal 
 delayms(1);//100);

 SL811_ADDR = SL811_Interrupt_Enable;
 SL811_COMM = 0x23;			  //Enable USB-A,USB-B,IR interrupts
}


void SL811_ReadEndPoint(uint8 endp,uint8 len,uint8* buf)
{
	uint8 i,j;

	SL811_ADDR = endp;
	for(i=0;i<len;i++)					  	//读取缓冲区数据
		*(buf++)=SL811_COMM;	
}

void SL811_WriteEndPoint(uint8 endp,uint8 len,uint8* buf)
{
	uint8 i;

	SL811_ADDR = endp;						//选择端点

	for(i=0;i<len;i++)						//写缓冲区数据
		SL811_COMM=*(buf++);
}

void SL811_FWriteEndPoint(uint8 endp,uint8 len,const uint8* buf)
{
	uint8 i;

	SL811_ADDR = endp;						//选择端点

	for(i=0;i<len;i++)						//写缓冲区数据
		SL811_COMM = *(buf++);
}


uint8 USBAGetPacket(uint8* buf, uint8 DE, uint8 DD)
{
	uint8 len,temp;
	
	SL811_ADDR = SL811_USBA_BaseAddress;
	SL811_COMM = USBA_BASEADDRESS;
	SL811_COMM = 0x40;
	SL811_COMM = IN_PID | DE;
	SL811_COMM = DD;	
	SL811_ADDR = SL811_Interrupt_Status;
	SL811_COMM = 0xFF;						// clear the DONE bit
	SL811_ADDR = SL811_USBA_Control;
	SL811_COMM = 0x23;	
	delayms(2);
	if((USBA_Status & 0x01) == 0x01)
	{
	   SL811_ADDR = SL811_USBA_DAoTC;
	   len = 0x40 - SL811_COMM;
	   //printf("Get data num is %x\n", len);
	   temp = len;
	   SL811_ADDR = USBA_BASEADDRESS;
	   do{
	   	  *buf++ = SL811_COMM;
	   }while(temp--);
	   return len;	  		  		 		// return data num got
	}
	return 0xFF;  	  		  		 		// return error	
}

uint8 USBASendZeroPacket(uint8 DE, uint8 DD, uint8 Data_Toggle)
{
	uint8 len,temp;
	
	SL811_ADDR = SL811_USBA_BaseAddress;
	SL811_COMM = USBA_BASEADDRESS;
	SL811_COMM = 0;
	SL811_COMM = OUT_PID | DE;
	SL811_COMM = DD;	
	SL811_ADDR = SL811_Interrupt_Status;
	SL811_COMM = 0xFF;						// clear the DONE bit
	
	SL811_ADDR = SL811_USBA_Control;
	if(Data_Toggle) SL811_COMM = 0x67;		
	else SL811_COMM = 0x27;		
	delayms(2);	
	if((USBA_Status & 0x01) == 0x01) return 0;
	else return 0xFF; 		   		 		// return error
}

uint8 USBA_SendPacket(uint8* buf, uint8 len, uint8 PIDDE, uint8 DD, uint8 Data_Toggle)
{
	SL811_WriteEndPoint(USBA_BASEADDRESS,len,buf);
	SL811_ADDR = SL811_USBA_BaseAddress;
	SL811_COMM = USBA_BASEADDRESS;
	SL811_COMM = len;
	SL811_COMM = PIDDE;
	SL811_COMM = DD;	
	SL811_ADDR = SL811_Interrupt_Status;
	SL811_COMM = 0xFF;						// clear the DONE bit
	SL811_ADDR = SL811_USBA_Control;
	if(Data_Toggle) SL811_COMM = 0x67;		
	else SL811_COMM = 0x27;
	delayms(2);
	if((USBA_Status & 0x01) == 0x01) return 0;
	else return 0xFF; 		   		 		//return error		
}

uint8 USBA_FSendPacket(const uint8* buf, uint8 len, uint8 PIDDE, uint8 DD, uint8 Data_Toggle)
{
	SL811_FWriteEndPoint(USBA_BASEADDRESS,len,buf);
	SL811_ADDR = SL811_USBA_BaseAddress;
	SL811_COMM = USBA_BASEADDRESS;
	SL811_COMM = len;
	SL811_COMM = PIDDE;
	SL811_COMM = DD;	
	SL811_ADDR = SL811_Interrupt_Status;
	SL811_COMM = 0xFF;						// clear the DONE bit
	SL811_ADDR = SL811_USBA_Control;
	if(Data_Toggle) SL811_COMM = 0x67;		
	else SL811_COMM = 0x27;
	delayms(2);
	if((USBA_Status & 0x01) == 0x01) return 0;
	else return 0xFF; 		   		 		//return error		
}

uint8 USBAFirstSendPacket(const uint8* buf, uint8 len, uint8 PIDDE, uint8 DD)
{
	SL811_FWriteEndPoint(USBA_BASEADDRESS,len,buf);
	SL811_ADDR = SL811_USBA_BaseAddress;
	SL811_COMM = USBA_BASEADDRESS;
	SL811_COMM = len;
	SL811_COMM = PIDDE;
	SL811_COMM = DD;	
	//SL811_ADDR = SL811_Interrupt_Status;
	//SL811_COMM = 0x01;						// clear the DONE bit
	SL811_ADDR = SL811_USBA_Control;
	SL811_COMM = 0x03;						//0x03, 0X07: SOF began to work! 0X23,0X27: No SOF!
		   	 								//0x07 = Send to slave; 0x03 = Get from slave;
	delayms(100); 
	SL811_ADDR = SL811_Interrupt_Status;
	SL811_COMM = 0xFF;						// clear the DONE bit
	SL811_ADDR = SL811_USBA_Control;
	SL811_COMM = 0x27;						// Netac will reponse at this time
	delayms(100);
	
	if( USBA_Status != 0x01 ) return 0x01;
	else return 0;
}


// *************************************************************************************
uint8 SL811_ConfigUDisk(void)
{
 uint8 temp;
 
 for(temp=0;temp<10;temp++) delayms(50);

 SL811_ADDR = SL811_SOF_DataSet;
 SL811_COMM = 0xE0;
 SL811_COMM = 0xAE; 		  	     // Select Master Mode   
 SL811_ADDR = SL811_Control;
 SL811_COMM = 0x08; 		  		 // USB bus reset
 delayms(60); 						 // 50ms or more
 SL811_ADDR = SL811_Control;
 SL811_COMM = 0x03; 		  		 // USB select FS. SOF enable
 delayms(150);						 // at least 100ms after bus reset

 //Get_Device_Descriptor traction
 if(USBAFirstSendPacket(Get_Device_Descriptor1,8,SETUP_PID|0x00,0)!= 0) return 0x01;
 delayms(50);  														 //一些U盘响应很慢,所以需要延时,Netac 的U盘在测试中不用。
 if(USBAGetPacket(GetDataBuffer, 0, 0) == 0xFF ) return 0x02;
 Endp0_DataLen = GetDataBuffer[7];
 delayms(40);  	 				  	   	  	   	 			 		 //一些U盘响应很慢,所以需要延时,Netac 的U盘在测试中不用。
 USBASendZeroPacket(0,0,1);											 //一些U盘对空包没有响应,所以不用加错误判断
 puts("Good when first Get_Device_Descriptor traction!");

 //Set Address UDisk_Address = 1 traction
 delayms(40);   			   	 		 	 			 			 //一些U盘响应很慢,所以需要延时,Netac 的U盘在测试中不用。 
 if(USBA_FSendPacket(Set_Address,8,SETUP_PID|0x00,0,0) != 0) return 0x04;
 delayms(40);   									   	  	 	     //一些U盘响应很慢,所以需要延时,Netac 的U盘在测试中不用。
 if(USBAGetPacket(GetDataBuffer, 0, 0) == 0xFF ) return 0x05;
 puts("Good when Set Address!"); 

 //Get_Config_Descriptor traction
 delayms(40);			 		 	   	  	   	 			 		 //一些U盘响应很慢,所以需要延时,Netac 的U盘在测试中不用。 
 if(USBA_FSendPacket(Get_Config_Descriptor1,8,SETUP_PID|0x00,UDisk_Address,0) != 0) return 0x06;
 delayms(40);														 //一些U盘响应很慢,所以需要延时,Netac 的U盘在测试中不用。
 if(USBAGetPacket(GetDataBuffer, 0, UDisk_Address) == 0xFF ) return 0x07;
 Config_DataLen = GetDataBuffer[2];
 delayms(40);	  				   				   	  	   	 		 //一些U盘响应很慢,所以需要延时,Netac 的U盘在测试中不用。 
 USBASendZeroPacket(0,UDisk_Address,1);								 //一些U盘对空包没有响应,所以不用加错误判断	  
 puts("Good when Get_Config_Descriptor traction!"); 
 
 printf("Config_DataLen = %x\n",Config_DataLen);
 printf("Endp0_DataLen = %x\n",Endp0_DataLen); 
 //Get_Config_Descriptor traction 2 
 delayms(40);	  		 		  			   						 //一些U盘响应很慢,所以需要延时,Netac 的U盘在测试中不用。 
 if(USBA_FSendPacket(Get_Config_Descriptor2,8,SETUP_PID|0x00,UDisk_Address,0) != 0) return 0x09;
 delayms(40);     													 //一些U盘响应很慢,所以需要延时,Netac 的U盘在测试中不用。
 for(temp = 0; temp <= ((Config_DataLen / Endp0_DataLen)+0); temp++)
 {
 	USBAGetPacket(GetDataBuffer + temp*Endp0_DataLen, 0, UDisk_Address);
 	delayms(40);  				  					  	 			 //一些U盘响应很慢,所以需要延时,Netac 的U盘在测试中不用。
 }
 USBASendZeroPacket(0,UDisk_Address,1);								 //一些U盘对空包没有响应,所以不用加错误判断
 puts("Good when Get_Config_Descriptor traction 2!"); 
 if(GetDataBuffer[14] == 0x08 && GetDataBuffer[16] == 0x50 ) YES_UDisk = 1;
 
 //得到U盘的批量端点设置。
 if( GetDataBuffer[20] & 0x80)
 {
  BulkIn_PortNum = GetDataBuffer[20] & 0x0F;
  BulkIn_DataLen = GetDataBuffer[22];
 }
 else
 {
  BulkOut_PortNum = GetDataBuffer[20] & 0x0F;
  BulkOut_DataLen = GetDataBuffer[22]; 
 }
 
 if( GetDataBuffer[27] & 0x80)
 {
  BulkIn_PortNum = GetDataBuffer[27] & 0x0F;
  BulkIn_DataLen = GetDataBuffer[29];
 }
 else
 {
  BulkOut_PortNum = GetDataBuffer[27] & 0x0F;
  BulkOut_DataLen = GetDataBuffer[29]; 
 }
 //Printf_buffer(); 
 
 //Set_configuration
 if(USBA_FSendPacket(Set_Configuration,8,SETUP_PID|0x00,UDisk_Address,0) != 0) return 0x0b;
 if(USBAGetPacket(GetDataBuffer, 0, UDisk_Address) == 0xFF ) return 0x0c;
 puts("Finish Set_configuration!"); 

 return 0;
}

⌨️ 快捷键说明

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