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

📄 usbcore.c

📁 USB多媒体键盘鼠标原程序代码
💻 C
📖 第 1 页 / 共 3 页
字号:
 
 //bmAttributes字段,该设备的属性。由于我们的板子是总线供电的,
 //并且我们不想实现远程唤醒的功能,所以该字段的值为0x80。
 0x80,
 
 //bMaxPower字段,该设备需要的最大电流量。由于我们的板子
 //需要的电流不到100mA,因此我们这里设置为100mA。由于每单位
 //电流为2mA,所以这里设置为50(0x32)。
 0x32,
 
 /*******************接口描述符*********************/
 //bLength字段。接口描述符的长度为9字节。
 0x09,
 
 //bDescriptorType字段。接口描述符的编号为0x04。
 0x04,
 
 //bInterfaceNumber字段。该接口的编号,第一个接口,编号为0。
 0x00,
 
 //bAlternateSetting字段。该接口的备用编号,为0。
 0x00,
 
 //bNumEndpoints字段。非0端点的数目。由于USB键盘需要二个
 //中断端点(一个输入一个输出),因此该值为2。
 0x02,
 
 //bInterfaceClass字段。该接口所使用的类。USB键盘是HID类,
 //HID类的编码为0x03。
 0x03,
 
 //bInterfaceSubClass字段。该接口所使用的子类。在HID1.1协议中,
 //只规定了一种子类:支持BIOS引导启动的子类。
 //USB键盘、鼠标属于该子类,子类代码为0x01。
 0x01,
 
 //bInterfaceProtocol字段。如果子类为支持引导启动的子类,
 //则协议可选择鼠标和键盘。键盘代码为0x01,鼠标代码为0x02。
 0x01,
 
 //iConfiguration字段。该接口的字符串索引值。这里没有,为0。
 0x00,
 
 /******************HID描述符************************/
 //bLength字段。本HID描述符下只有一个下级描述符。所以长度为9字节。
 0x09,
 
 //bDescriptorType字段。HID描述符的编号为0x21。
 0x21,
 
 //bcdHID字段。本协议使用的HID1.1协议。注意低字节在先。
 0x10,
 0x01,
 
 //bCountyCode字段。设备适用的国家代码,这里选择为美国,代码0x21。
 0x21,
 
 //bNumDescriptors字段。下级描述符的数目。我们只有一个报告描述符。
 0x01,
 
 //bDescritporType字段。下级描述符的类型,为报告描述符,编号为0x22。
 0x22,
 
 //bDescriptorLength字段。下级描述符的长度。下级描述符为报告描述符。
 sizeof(ReportDescriptor)&0xFF,
 (sizeof(ReportDescriptor)>>8)&0xFF,
 
 /**********************输入端点描述符***********************/
 //bLength字段。端点描述符长度为7字节。
 0x07,
 
 //bDescriptorType字段。端点描述符编号为0x05。
 0x05,
 
 //bEndpointAddress字段。端点的地址。我们使用D12的输入端点1。
 //D7位表示数据方向,输入端点D7为1。所以输入端点1的地址为0x81。
 0x81,
 
 //bmAttributes字段。D1~D0为端点传输类型选择。
 //该端点为中断端点。中断端点的编号为3。其它位保留为0。
 0x03,
 
 //wMaxPacketSize字段。该端点的最大包长。端点1的最大包长为16字节。
 //注意低字节在先。
 0x10,
 0x00,
 
 //bInterval字段。端点查询的时间,我们设置为10个帧时间,即10ms。
 0x0A,
 
 /**********************输出端点描述符***********************/
 //bLength字段。端点描述符长度为7字节。
 0x07,
 
 //bDescriptorType字段。端点描述符编号为0x05。
 0x05,
 
 //bEndpointAddress字段。端点的地址。我们使用D12的输出端点1。
 //D7位表示数据方向,输出端点D7为0。所以输出端点1的地址为0x01。
 0x01,
 
 //bmAttributes字段。D1~D0为端点传输类型选择。
 //该端点为中断端点。中断端点的编号为3。其它位保留为0。
 0x03,
 
 //wMaxPacketSize字段。该端点的最大包长。端点1的最大包长为16字节。
 //注意低字节在先。
 0x10,
 0x00,
 
 //bInterval字段。端点查询的时间,我们设置为10个帧时间,即10ms。
 0x0A
};
////////////////////////配置描述符集合完毕//////////////////////////

/************************语言ID的定义********************/
code uint8 LanguageId[4]=
{
 0x04, //本描述符的长度
 0x03, //字符串描述符
 //0x0409为美式英语的ID
 0x09,
 0x04
};
////////////////////////语言ID完毕//////////////////////////////////

/**************************************************/
/*********        本转换结果来自         **********/
/********* Http://computer00.21ic.org    **********/
/*********        作者: 电脑圈圈         **********/
/*********         欢迎大家使用          **********/
/*********    版权所有,盗版请写明出处   **********/
/**************************************************/

//http://computer00.21ic.org/user1/2198/archives/2007/42769.html
//字符串“电脑圈圈的USB专区 Http://group.ednchina.com/93/”的Unicode编码
//8位小端格式
code uint8 ManufacturerStringDescriptor[82]={
82,         //该描述符的长度为82字节
0x03,       //字符串描述符的类型编码为0x03
0x35, 0x75, //电
0x11, 0x81, //脑
0x08, 0x57, //圈
0x08, 0x57, //圈
0x84, 0x76, //的
0x55, 0x00, //U
0x53, 0x00, //S
0x42, 0x00, //B
0x13, 0x4e, //专
0x3a, 0x53, //区
0x20, 0x00, // 
0x48, 0x00, //H
0x74, 0x00, //t
0x74, 0x00, //t
0x70, 0x00, //p
0x3a, 0x00, //:
0x2f, 0x00, ///
0x2f, 0x00, ///
0x67, 0x00, //g
0x72, 0x00, //r
0x6f, 0x00, //o
0x75, 0x00, //u
0x70, 0x00, //p
0x2e, 0x00, //.
0x65, 0x00, //e
0x64, 0x00, //d
0x6e, 0x00, //n
0x63, 0x00, //c
0x68, 0x00, //h
0x69, 0x00, //i
0x6e, 0x00, //n
0x61, 0x00, //a
0x2e, 0x00, //.
0x63, 0x00, //c
0x6f, 0x00, //o
0x6d, 0x00, //m
0x2f, 0x00, ///
0x39, 0x00, //9
0x33, 0x00, //3
0x2f, 0x00  ///
};
/////////////////////////厂商字符串结束/////////////////////////////

//字符串“《圈圈教你玩USB》之多媒体USB键盘”的Unicode编码
//8位小端格式
code uint8 ProductStringDescriptor[40]={
40,         //该描述符的长度为40字节
0x03,       //字符串描述符的类型编码为0x03
0x0a, 0x30, //《
0x08, 0x57, //圈
0x08, 0x57, //圈
0x59, 0x65, //教
0x60, 0x4f, //你
0xa9, 0x73, //玩
0x55, 0x00, //U
0x53, 0x00, //S
0x42, 0x00, //B
0x0b, 0x30, //》
0x4b, 0x4e, //之
0x1a, 0x59, //多
0x92, 0x5a, //媒
0x53, 0x4f, //体
0x55, 0x00, //U
0x53, 0x00, //S
0x42, 0x00, //B
0x2e, 0x95, //键
0xd8, 0x76  //盘
};
////////////////////////产品字符串结束////////////////////////////

//字符串“2008-07-17”的Unicode编码
//8位小端格式
code uint8 SerialNumberStringDescriptor[22]={
22,         //该描述符的长度为22字节
0x03,       //字符串描述符的类型编码为0x03
0x32, 0x00, //2
0x30, 0x00, //0
0x30, 0x00, //0
0x38, 0x00, //8
0x2d, 0x00, //-
0x30, 0x00, //0
0x37, 0x00, //7
0x2d, 0x00, //-
0x31, 0x00, //1
0x37, 0x00  //7
};
//////////////////////产品序列号字符串结束/////////////////////////

/********************************************************************
函数功能:延时x毫秒函数。
入口参数:x:延时的毫秒数。
返    回:无。
备    注:无。
********************************************************************/
void DelayXms(uint16 x)                
{
 uint16 i;
 uint16 j;
 for(i=0;i<x;i++)
 for(j=0;j<227;j++); //循环语句延时
}
////////////////////////End of function//////////////////////////////

/********************************************************************
函数功能:USB断开连接函数。
入口参数:无。
返    回:无。
备    注:无。
********************************************************************/
void UsbDisconnect(void)
{
#ifdef DEBUG0
 Prints("断开USB连接。\r\n");
#endif
 D12WriteCommand(D12_SET_MODE);  //写设置模式命令
 D12WriteByte(0x06); //设置模式的第一字节
 D12WriteByte(0x47); //设置模式的第二字节
 DelayXms(1000);  //延迟1秒
}
////////////////////////End of function//////////////////////////////

/********************************************************************
函数功能:USB连接函数。
入口参数:无。
返    回:无。
备    注:无。
********************************************************************/
void UsbConnect(void)
{
#ifdef DEBUG0
 Prints("连接USB。\r\n");
#endif
 D12WriteCommand(D12_SET_MODE);  //写设置模式命令
 D12WriteByte(0x16); //设置模式的第一字节
 D12WriteByte(0x47); //设置模式的第二字节
}
////////////////////////End of function//////////////////////////////

/********************************************************************
函数功能:总线挂起中断处理函数。
入口参数:无。
返    回:无。
备    注:无。
********************************************************************/
void UsbBusSuspend(void)
{
#ifdef DEBUG0
 Prints("USB总线挂起。\r\n");
#endif
}
////////////////////////End of function//////////////////////////////

/********************************************************************
函数功能:总线复位中断处理函数。
入口参数:无。
返    回:无。
备    注:无。
********************************************************************/
void UsbBusReset(void)
{
#ifdef DEBUG0
 Prints("USB总线复位。\r\n");
#endif
 Ep1InIsBusy=0; //复位后端点1输入缓冲区空闲。
}
////////////////////////End of function//////////////////////////////

/********************************************************************
函数功能:根据pData和SendLength将数据发送到端点0的函数。
入口参数:无。
返    回:无。
备    注:无。
********************************************************************/
void UsbEp0SendData(void)
{
 //将数据写到端点中去准备发送
 //写之前要先判断一下需要发送的数据是否比端点0
 //最大长度大,如果超过端点大小,则一次只能发送
 //最大包长的数据。端点0的最大包长在DeviceDescriptor[7]
 if(SendLength>DeviceDescriptor[7])
 {
  //按最大包长度发送
  D12WriteEndpointBuffer(1,DeviceDescriptor[7],pSendData);
  //发送后剩余字节数减少最大包长
  SendLength-=DeviceDescriptor[7];
  //发送一次后指针位置要调整
  pSendData+= DeviceDescriptor[7];
 }
 else
 {
  if(SendLength!=0)
  {
   //不够最大包长,可以直接发送
   D12WriteEndpointBuffer(1,SendLength,pSendData);
   //发送完毕后,SendLength长度变为0
   SendLength=0;
  }
  else //如果要发送的数据包长度为0
  {
   if(NeedZeroPacket==1) //如果需要发送0长度数据
   {
    D12WriteEndpointBuffer(1,0,pSendData); //发送0长度数据包
    NeedZeroPacket=0; //清需要发送0长度数据包标志
   }
  }
 }
}
////////////////////////End of function//////////////////////////////

/********************************************************************
函数功能:端点0输出中断处理函数。
入口参数:无。
返    回:无。
备    注:无。
********************************************************************/
void UsbEp0Out(void)
{
#ifdef DEBUG0
 Prints("USB端点0输出中断。\r\n");
#endif
 //读取端点0输出最后传输状态,该操作清除中断标志
 //并判断第5位是否为1,如果是,则说明是建立包
 if(D12ReadEndpointLastStatus(0)&0x20)
 {
  D12ReadEndpointBuffer(0,16,Buffer); //读建立过程数据
  D12AcknowledgeSetup(); //应答建立包
  D12ClearBuffer(); //清缓冲区
  //将缓冲数据填到设备请求的各字段中
  bmRequestType=Buffer[0];
  bRequest=Buffer[1];
  wValue=Buffer[2]+(((uint16)Buffer[3])<<8);
  wIndex=Buffer[4]+(((uint16)Buffer[5])<<8);
  wLength=Buffer[6]+(((uint16)Buffer[7])<<8);
  //下面的代码判断具体的请求,并根据不同的请求进行相关操作
  //如果D7位为1,则说明是输入请求
  if((bmRequestType&0x80)==0x80)
  {
   //根据bmRequestType的D6~5位散转,D6~5位表示请求的类型
   //0为标准请求,1为类请求,2为厂商请求。
   switch((bmRequestType>>5)&0x03)
   {
    case 0:  //标准请求
     #ifdef DEBUG0
      Prints("USB标准输入请求:");
     #endif
     //USB协议定义了几个标准输入请求,我们实现这些标准请求即可
     //请求的代码在bRequest中,对不同的请求代码进行散转
     //事实上,我们还需要对接收者进行散转,因为不同的请求接收者
     //是不一样的。接收者在bmRequestType的D4~D0位中定义。
     //我们这里为了简化操作,有些就省略了对接收者的判断。
     //例如获取描述符的请求,只根据描述符的类型来区别。
     switch(bRequest)
     {
      case GET_CONFIGURATION: //获取配置
       #ifdef DEBUG0
        Prints("获取配置。\r\n");
       #endif
      break;
      
      case GET_DESCRIPTOR:  //获取描述符
       #ifdef DEBUG0
        Prints("获取描述符——");
       #endif
       //对描述符类型进行散转,对于全速设备,
       //标准请求只支持发送到设备的设备、配置、字符串三种描述符
       switch((wValue>>8)&0xFF)
        {
         case DEVICE_DESCRIPTOR: //设备描述符
          #ifdef DEBUG0

⌨️ 快捷键说明

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