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

📄 usbcore.c

📁 单片机上实现U盘功能
💻 C
📖 第 1 页 / 共 3 页
字号:
        }
       break;
      
      case GET_INTERFACE: //获取接口
       #ifdef DEBUG0
        Prints("获取接口。\r\n");
       #endif
      break;
      
      case GET_STATUS: //获取状态
       #ifdef DEBUG0
        Prints("获取状态。\r\n");
       #endif
      break;
      
      case SYNCH_FRAME: //同步帧
       #ifdef DEBUG0
        Prints("同步帧。\r\n");
       #endif
      break;
      
      default:  //未定义的标准请求
       #ifdef DEBUG0
        Prints("错误:未定义的标准输入请求。\r\n");
       #endif       
      break;
     }
    break;
    
    case 1:  //类请求
     #ifdef DEBUG0
      Prints("USB类输入请求:");
     #endif
     switch(bRequest)
     {
      case GET_MAX_LUN: //请求为GET_MAX_LUN(0xFE)
       #ifdef DEBUG0
        Prints("获取最大逻辑单元。\r\n");
       #endif
       
       pSendData=MaxLun; //要返回的数据位置
       SendLength=1;     //长度为1字节
       //如果请求的长度比实际长度短,则仅返回请求长度
       if(wLength<SendLength) 
       {
        SendLength=wLength;
       }
       //将数据通过EP0返回
       UsbEp0SendData();
      break;
      
      default:
       #ifdef DEBUG0
        Prints("未知请求。\r\n");
       #endif
      break;
     }
    break;
    
    case 2:  //厂商请求
     #ifdef DEBUG0
      Prints("USB厂商输入请求:\r\n");
     #endif
    break;
    
    default: //未定义的请求。这里只显示一个报错信息。
     #ifdef DEBUG0
      Prints("错误:未定义的输入请求。\r\n");
     #endif
    break;
   }
  }
  //否则说明是输出请求
  else //if(bmRequestType&0x80==0x80)之else
  {
   //根据bmRequestType的D6~5位散转,D6~5位表示请求的类型
   //0为标准请求,1为类请求,2为厂商请求。
   switch((bmRequestType>>5)&0x03)
   {
    case 0:  //标准请求
     #ifdef DEBUG0
      Prints("USB标准输出请求:");
     #endif
     //USB协议定义了几个标准输出请求,我们实现这些标准请求即可
     //请求的代码在bRequest中,对不同的请求代码进行散转
     switch(bRequest)
     {
      case CLEAR_FEATURE: //清除特性
       #ifdef DEBUG0
        Prints("清除特性。\r\n");
       #endif
      break;
      
      case SET_ADDRESS:  //设置地址
       #ifdef DEBUG0
        Prints("设置地址。地址为:");
        PrintHex(wValue&0xFF); //显示所设置的地址
        Prints("\r\n");
       #endif
       D12SetAddress(wValue&0xFF); //wValue中的低字节是设置的地址值
       //设置地址没有数据过程,直接进入到状态过程,返回一个0长度的数据包
       SendLength=0;
       NeedZeroPacket=1;
       //将数据通过EP0返回
       UsbEp0SendData();
      break;
      
      case SET_CONFIGURATION: //设置配置
       #ifdef DEBUG0
        Prints("设置配置。\r\n");
       #endif
       //使能非0端点。非0端点只有在设置为非0的配置后才能使能。
       //wValue的低字节为配置的值,如果该值为非0,才能使能非0端点。
       //保存当前配置值
       ConfigValue=wValue&0xFF;
       D12SetEndpointEnable(ConfigValue);
       //返回一个0长度的状态数据包
       SendLength=0;
       NeedZeroPacket=1;
       //将数据通过EP0返回
       UsbEp0SendData();
      break;
      
      case SET_DESCRIPTOR: //设置描述符
       #ifdef DEBUG0
        Prints("设置描述符。\r\n");
       #endif
      break;
      
      case SET_FEATURE: //设置特性
       #ifdef DEBUG0
        Prints("设置特性。\r\n");
       #endif
      break;

      case SET_INTERFACE: //设置接口
       #ifdef DEBUG0
        Prints("设置接口。\r\n");
       #endif
       //返回一个0长度的状态数据包
       SendLength=0;
       NeedZeroPacket=1;
       //将数据通过EP0返回
       UsbEp0SendData();
      break;
      
      default:  //未定义的标准请求
       #ifdef DEBUG0
        Prints("错误:未定义的标准输出请求。\r\n");
       #endif       
      break;
     }
    break;
    
    case 1:  //类请求
     #ifdef DEBUG0
      Prints("USB类输出请求:");
     #endif
     switch(bRequest)
     {
      case MASS_STORAGE_RESET:
       #ifdef DEBUG0
        Prints("大容量存储设备复位。\r\n");
       #endif
       
       //接下来的数据为命令阶段(CBW)
       TransportStage=COMMAND_STAGE;
       //返回一个0长度的数据包
       SendLength=0;
       NeedZeroPacket=1;
       //将数据通过EP0返回
       UsbEp0SendData();
      break;
      
      default:
       #ifdef DEBUG0
        Prints("未知请求。\r\n");
       #endif
      break;
     }
    break;
    
    case 2:  //厂商请求
     #ifdef DEBUG0
      Prints("USB厂商输出请求:\r\n");
     #endif
    break;
    
    default: //未定义的请求。这里只显示一个报错信息。
     #ifdef DEBUG0
      Prints("错误:未定义的输出请求。\r\n");
     #endif
    break;
   }
  }
 }
 //普通数据输出
 else //if(D12ReadEndpointLastStatus(0)&0x20)之else
 {
  D12ReadEndpointBuffer(0,16,Buffer);
  D12ClearBuffer();
 }
}
////////////////////////End of function//////////////////////////////

/********************************************************************
函数功能:端点0输入中断处理函数。
入口参数:无。
返    回:无。
备    注:无。
********************************************************************/
void UsbEp0In(void)
{
#ifdef DEBUG0
 Prints("USB端点0输入中断。\r\n");
#endif
 //读最后发送状态,这将清除端点0的中断标志位
 D12ReadEndpointLastStatus(1);
 //发送剩余的字节数
 UsbEp0SendData();
}
////////////////////////End of function//////////////////////////////

/********************************************************************
函数功能:端点1输出中断处理函数。
入口参数:无。
返    回:无。
备    注:无。
********************************************************************/
void UsbEp1Out(void)
{
#ifdef DEBUG0
 Prints("USB端点1输出中断。\r\n");
#endif
 //读端点最后状态,这将清除端点1输出的中断标志位
 D12ReadEndpointLastStatus(2);
 //清除端点缓冲区
 D12ClearBuffer();
}
////////////////////////End of function//////////////////////////////

/********************************************************************
函数功能:端点1输入中断处理函数。
入口参数:无。
返    回:无。
备    注:无。
********************************************************************/
void UsbEp1In(void)
{
#ifdef DEBUG0
 Prints("USB端点1输入中断。\r\n");
#endif
 //读最后发送状态,这将清除端点1输入的中断标志位
 D12ReadEndpointLastStatus(3);
 //端点1输入处于空闲状态
 Ep1InIsBusy=0;
}
////////////////////////End of function//////////////////////////////

/********************************************************************
函数功能:端点2输出中断处理函数。
入口参数:无。
返    回:无。
备    注:无。
********************************************************************/
void UsbEp2Out(void)
{
 uint8 Len;
 
#ifdef DEBUG0
 Prints("USB端点2输出中断。\r\n");
#endif

 //当双缓冲没有全满时,可以清除中断标志
 if((D12ReadEndpointStatus(4)&0x60)!=0x60)
 {
  //读最后发送状态,这将清除端点2输入的中断标志位
  D12ReadEndpointLastStatus(4);
 }
 if(TransportStage==COMMAND_STAGE)
 {
  //将数据读回到CBW缓冲区中
  Len=D12ReadEndpointBuffer(4,sizeof(CBW),CBW);
  //清除端点缓冲区
  D12ClearBuffer();
  if(Len==31) //如果接收到的数据长度是31字节,则说明是CBW
  {
   //检查CBW的签名是否正确,签名为“USBC”
   if((CBW[0]=='U')&&(CBW[1]=='S')&&(CBW[2]=='B')&&(CBW[3]=='C'))
   {
    //CBW签名正确,处理SCSI命令
    ProcScsiCommand();
   }
  }
 }
 else if(TransportStage==DATA_STAGE)
 {
  ProcScsiOutData(); //处理SCSI输出数据
 }
 else 
 {
  D12ReadEndpointBuffer(4,0,0);
  D12ClearBuffer();
 }
}
////////////////////////End of function//////////////////////////////

/********************************************************************
函数功能:端点2输入中断处理函数。
入口参数:无。
返    回:无。
备    注:无。
********************************************************************/
void UsbEp2In(void)
{
#ifdef DEBUG0
 Prints("USB端点2输入中断。\r\n");
#endif
 //读最后发送状态,这将清除端点2输入的中断标志位
 D12ReadEndpointLastStatus(5);
 Ep2SendData();  //发送数据
 //如果双缓冲区没有都满,还可以再写
 if((D12ReadEndpointStatus(5)&0x06)!=0x06)
 {
  Ep2SendData(); //再发一次数据,利用双缓冲
 }
}
////////////////////////End of function//////////////////////////////

⌨️ 快捷键说明

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