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

📄 usb.c

📁 关于 at89c51snd1c 的海量存储mass storge的基于keil c的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "REGSND1.H"
#include "USBDEF.H"
#include "UART.h"

//时钟参数宏
#define		Rdiv    	11
//USB寄存器设置相关的宏定义
#define		PLLRES		(0x1<<3)        //PLLCON
#define		PLLEN		(0x1<<1)
#define		USBE		(0x1<<7)        //USBCON
#define 	EEOFINT		(0x1<<4)
#define 	FEN			(0x1<<7)
#define 	FADDEN		(0x1)
#define 	CONFG		(0x1<<1)
#define 	DIR			(0x1<<7)		//UEPSTAX
#define 	RXOUTB1		(0x1<<6)
#define 	STALLRQ		(0x1<<5)
#define 	TXRDY		(0x1<<4)
#define 	STLCRC		(0x1<<3)
#define 	RXSETUP		(0x1<<2)
#define 	RXOUTB0		(0x1<<1)
#define 	TXCMP		(0x1<<0)

//USB 请求的bRequert的含意宏
#define	get_status			0x00		//取得状态
#define	clear_feature 		0x01		//清除特性
#define	reserved			0x02		//保留
#define	set_feature			0x03		//设置特性

#define	set_address			0x05		//设置地址
#define	get_descriptor		0x06		//取得描述符

#define	get_configuration	0x08		//取得配置
#define	set_configuration	0x09		//设置配置
#define	get_interface		0x0a		//取得接口
#define	set_interface		0x0b		//设置接口

/**---------------------------------------------------------------------------------

----------------------------------------------------------------------------------**/

void AtmelUSBInit()		//用于USB的PLL时钟20M晶振时如下设置
{
	int data i;	
	PLLNDIV	=	0x04;                     //设置PLL时钟
	PLLCON |=	(0x3&Rdiv)<<6;
	PLLRDIV	=	(0x3ff&Rdiv)>>2;
	USBCLK=0;
	PLLCON&=(~PLLRES);                    //使能PLL
	PLLCON|=PLLEN;               
	USBCON&=(~USBE);                      //关闭USB并复位USB
	for(i=0;i<3000;i++);                  //等待PLL工作稳定
	USBCON|=USBE;                         //开启USB控制器

}	

void EpEnable(void)				          //初始化USB端点
{
	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)	                  //读数据到缓冲//UBYCTX得到数据长度
	{
		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++];	                         //写入FIFO
	UEPSTAX|=TXRDY;											     //开始发送
	while(!(UEPSTAX&TXCMP)) ;
	UEPSTAX&=(~(TXCMP));								         //清除TXCMP
}

//-------------以下用于对端点进行处理

void Set_Address(unsigned char EpNum)	                         //设置USB地址1-127
{
	WriteEp(0,0,0);											     //在Status阶段过后才能改变设备地址
	USBADDR|=EpNum;
	USBADDR|=FEN;											     //设置地址
	USBCON|=FADDEN;											     //地址使能
}

//设备描述符
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 //recerive 500ma
									
									    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
										};

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()            //?????????                              //---端点0处理主函数
{
  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)								//非标准USB请求
	{
		WriteEp(0,0,0);
	}							  						
}

/******************************************************************************/
/**                   以下为利用Bulk_Only传输协议的函数部分                  **/
/******************************************************************************/
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.

typedef struct _STRUCT_CBW
{
	unsigned char CBWCB[12];                        //for UFI Command all have 12bit

} struct_CBW;

struct_CBW data bulk_CBW;

void WriteEpBulk(unsigned char EpNum,unsigned char nLength,unsigned char *Data)
{
	unsigned char data i;
	UEPNUM=EpNum;			                        //---设置端点号
	UEPSTAX|=DIR;			                        //...设置为In模式
	for(i=0;i<nLength;i++) UEPDATX=Data[i];         //---填缓冲区
	UEPSTAX|=TXRDY;		                            //---发送数据
}

void TransmitCSW()									//向Host返回CSW
{
  WriteEpBulk(1, sizeof(bulk_CSW), bulk_CSW);
  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 
							'U', 'E', 'S', 'T', 'C', '-', 'Z', 'H',	       //Vendor Information
							'a', 'n', 'g', ' ', 'T', 'i', 'a', 'n', ' ', 'y', 'i',' ', 'V', '1', '.', '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()

⌨️ 快捷键说明

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