STM32 USB 键盘

来源:互联网 发布:串口通信编程 编辑:程序博客网 时间:2024/06/08 17:53

作者:dengchonglin

转自:http://blog.csdn.net/dengchonglin/article/details/6915379


1、使用 USB 鼠标历程。

2、修改几个USB节点

 


/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Extern variables ----------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/* USB Standard Device Descriptor */
const u8 Joystick_DeviceDescriptor[JOYSTICK_SIZ_DEVICE_DESC] =
  {
   0x12,                       /*bLength */
    USB_DEVICE_DESCRIPTOR_TYPE, /*bDescriptorType*/
    0x01,                       /*bcdUSB */
    0x10,
    0x00,                       /*bDeviceClass*/
    0x00,                       /*bDeviceSubClass*/
    0x00,                       /*bDeviceProtocol*/
    0x40,                       /*bMaxPacketSize40*/
    0xf3,                       /*idVendor (0x0483)*/
    0x04,
    0x04,                       /*idProduct = 0x5750*/
    0x01,
    0x00,                       /*bcdDevice rel. 2.00*/
    0x02,
    1,                          /*Index of string descriptor describing
                                              manufacturer */
    2,                          /*Index of string descriptor describing
                                             product*/
    3,                          /*Index of string descriptor describing the
                                             device serial number */
    0x01                        /*bNumConfigurations*/

  }
  ; /* Joystick_DeviceDescriptor */


/* USB Configuration Descriptor */
/*   All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */
const u8 Joystick_ConfigDescriptor[JOYSTICK_SIZ_CONFIG_DESC] =
  {
 0x09, /* bLength: Configuation Descriptor size */
    USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */
    JOYSTICK_SIZ_CONFIG_DESC,
    /* wTotalLength: Bytes returned */
    0x00,
    0x01,         /* bNumInterfaces: 1 interface */
    0x01,         /* bConfigurationValue: Configuration value */
    0x00,         /* iConfiguration: Index of string descriptor describing
                                 the configuration*/
    0xC0,         /* bmAttributes: Bus powered */
    0x32,         /* MaxPower 100 mA: this current is used for detecting Vbus */

    /************** Descriptor of Custom HID interface ****************/
    /* 09 */
    0x09,         /* bLength: Interface Descriptor size */
    USB_INTERFACE_DESCRIPTOR_TYPE,/* bDescriptorType: Interface descriptor type */
    0x00,         /* bInterfaceNumber: Number of Interface */
    0x00,         /* bAlternateSetting: Alternate setting */
    0x02,         /* bNumEndpoints */
    0x03,         /* bInterfaceClass: HID */
    0x01,         /* bInterfaceSubClass : 1=BOOT, 0=no boot */
    0x01,         /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
    0,            /* iInterface: Index of string descriptor */
    /******************** Descriptor of Custom HID HID ********************/
    /* 18 */
    0x09,         /* bLength: HID Descriptor size */
    HID_DESCRIPTOR_TYPE, /* bDescriptorType: HID */
    0x00,         /* bcdHID: HID Class Spec release number */
    0x01,
    0x00,         /* bCountryCode: Hardware target country */
    0x01,         /* bNumDescriptors: Number of HID class descriptors to follow */
    0x22,         /* bDescriptorType */
    JOYSTICK_SIZ_REPORT_DESC,/* wItemLength: Total length of Report descriptor */
    0x00,
    /******************** Descriptor of Custom HID endpoints ******************/
    /* 27 */
    0x07,          /* bLength: Endpoint Descriptor size */
    USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: */

    0x81,          /* bEndpointAddress: Endpoint Address (IN) */
    0x03,          /* bmAttributes: Interrupt endpoint */
    0x08,          /* wMaxPacketSize: 16 Bytes max */
    0x00,
    0x20,          /* bInterval: Polling Interval (32 ms) */
    /* 34 */
    
    0x07, /* bLength: Endpoint Descriptor size */
    USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: */
/* Endpoint descriptor type */
    0x01, /* bEndpointAddress: */
/* Endpoint Address (OUT) */
    0x03, /* bmAttributes: Interrupt endpoint */
    0x08, /* wMaxPacketSize: 16 Bytes max  */
    0x00,
    0x20, /* bInterval: Polling Interval (20 ms) */
    /* 41 */


  }
  ; /* MOUSE_ConfigDescriptor */
const u8 Joystick_ReportDescriptor[JOYSTICK_SIZ_REPORT_DESC] =
  {


0x05, 0x01, // USAGE_PAGE (Generic Desktop)
 0x09, 0x06, // USAGE (Keyboard)
 0xa1, 0x01, // COLLECTION (Application)
 0x05, 0x07, //     USAGE_PAGE (Keyboard/Keypad)
 0x19, 0xe0, //     USAGE_MINIMUM (Keyboard LeftControl)
 0x29, 0xe7, //     USAGE_MAXIMUM (Keyboard Right GUI)
 0x15, 0x00, //     LOGICAL_MINIMUM (0)
 0x25, 0x01, //     LOGICAL_MAXIMUM (1)
 0x95, 0x08, //     REPORT_COUNT (8)
 0x75, 0x01, //     REPORT_SIZE (1)
 0x81, 0x02, //     INPUT (Data,Var,Abs)
 0x95, 0x01, //     REPORT_COUNT (1)
 0x75, 0x08, //     REPORT_SIZE (8)
 0x81, 0x03, //     INPUT (Cnst,Var,Abs)
 0x95, 0x06, //   REPORT_COUNT (6)
 0x75, 0x08, //   REPORT_SIZE (8)
 0x25, 0xFF, //   LOGICAL_MAXIMUM (255)
 0x19, 0x00, //   USAGE_MINIMUM (Reserved (no event indicated))
 0x29, 0x65, //   USAGE_MAXIMUM (Keyboard Application)
 0x81, 0x00, //     INPUT (Data,Ary,Abs)
 0x25, 0x01, //     LOGICAL_MAXIMUM (1)
 0x95, 0x02, //   REPORT_COUNT (2)
 0x75, 0x01, //   REPORT_SIZE (1)
 0x05, 0x08, //   USAGE_PAGE (LEDs)
 0x19, 0x01, //   USAGE_MINIMUM (Num Lock)
 0x29, 0x02, //   USAGE_MAXIMUM (Caps Lock)
 0x91, 0x02, //   OUTPUT (Data,Var,Abs)
 0x95, 0x01, //   REPORT_COUNT (1)
 0x75, 0x06, //   REPORT_SIZE (6)
 0x91, 0x03, //   OUTPUT (Cnst,Var,Abs)
 0xc0        // END_COLLECTION

 


  }
  ; /* Joystick_ReportDescriptor */

 

3、void Joystick_Reset(void)

 /* Initialize Endpoint In 1 */
 SetEPType(ENDP1, EP_INTERRUPT); //初始化为中断端点类型
 SetEPTxAddr(ENDP1, ENDP1_TXADDR); //设置发送数据的地址
 SetEPTxCount(ENDP1, 8); //设置发送的长度
// SetEPRxStatus(ENDP1, EP_RX_DIS);
 SetEPTxStatus(ENDP1, EP_TX_NAK); //设置端点处于忙状态
 /* Initialize Endpoint Out 1 */
 SetEPRxAddr(ENDP1, ENDP1_RXADDR); //设置接收数据的地址
 SetEPRxCount(ENDP1, 1); //设置接收长度
 SetEPRxStatus(ENDP1, EP_RX_VALID); //设置端点有效,可以接收数据


 4、设置USB键盘控制LED

#define  EP1_OUT_Callback   EP1_OUT_Callback

void EP1_OUT_Callback(void)
{
 u8 DataLen; //保存接收数据的长度
 u8 DataBuffer[64]; //保存接收数据的缓冲区
 DataLen = GetEPRxCount(ENDP1); //获取收到的长度
 PMAToUserBufferCopy(DataBuffer, ENDP1_RXADDR, DataLen); //复制数据
 SetEPRxValid(ENDP1); //设置端点有效,以接收下一次数据

}

5、USB 键盘发送数据到 PC


void Joystick_Send(u8 *Key)
{
 while(_GetEPTxStatus(ENDP1)!=(0x02<<4));
 /*copy mouse position info in ENDP1 Tx Packet Memory Area*/
 UserToPMABufferCopy(Key, GetEPTxAddr(ENDP1), 8);
 /* enable endpoint for transmission */
 SetEPTxValid(ENDP1);

 memset(Key,0x00,8);
 while(_GetEPTxStatus(ENDP1)!=(0x02<<4));
 /*copy mouse position info in ENDP1 Tx Packet Memory Area*/
 UserToPMABufferCopy(Key, GetEPTxAddr(ENDP1), 8);
 /* enable endpoint for transmission */
 SetEPTxValid(ENDP1);
}

/*
发送一串字符模拟键盘输入这段字符
Keys   字符缓冲区
KeyLen 长度
SendEnterFlag 发送结束后是否发送 ENTER 键
*/
void Joystick_Send_KeyString(u8 *Keys,u16 KeyLen,u16 SendEnterFlag)
{
 u8 Buffer[8] = {0, 0, 0, 0, 0, 0, 0, 0};
 u8 loop,i;
 u16 nSendCouter;
 u16 nTableOffset;
 nSendCouter = 0 ;
// i=2;
 for(loop=0;loop<KeyLen;loop++)
 {
  //memset(Buffer,0x00,sizeof(Buffer));
  //KEY down 消息
  //memcpy(Buffer+2,Keys+loop*6,6);
  nTableOffset = Keys[loop] - 0x20 ;
  if(nSendCouter)
  {
   if((Buffer[0] != Key_Table[nTableOffset][0]) || nSendCouter >= 6)
   {
    //如果有数据需要按 SHFIT 和不需要按SHFIT的去别
    //则先把之前缓冲区里面的数据发送出去
    //或者缓冲区满就发送出去
    Joystick_Send(Buffer);
    Buffer[0] = Key_Table[nTableOffset][0] ;
    Buffer[2] = Key_Table[nTableOffset][1] ;
    nSendCouter = 1 ;
   }
   else
   {
    for(i=0;i<nSendCouter;i++)
    {
     //判断缓冲区里面有没有重复的数据
     //如果有重复的就先把缓冲区里面的
     //数据发送出去
     if(Buffer[2+i] == Key_Table[nTableOffset][1])
     {
      Joystick_Send(Buffer);
      nSendCouter = 0 ;
      break;
     }
    }
    Buffer[0] = Key_Table[nTableOffset][0] ;
    Buffer[2+nSendCouter] = Key_Table[nTableOffset][1] ;
    nSendCouter ++ ;
   }
  }
  else
  {
   Buffer[0] = Key_Table[nTableOffset][0] ;
   Buffer[2] = Key_Table[nTableOffset][1] ;
   nSendCouter ++ ;
  }

 }
 if(nSendCouter)
 {
  Joystick_Send(Buffer);
 }
 if(SendEnterFlag)
 {
  Buffer[0] = 0 ;
  Buffer[2] = 0x28 ;
  Joystick_Send(Buffer);
 }
}

void Joystick_Send_Keyup(void)
{
 u8 Buffer[8] = {0, 0, 0, 0, 0, 0, 0, 0};

 while(_GetEPTxStatus(ENDP1)!=(0x02<<4));
 /*copy mouse position info in ENDP1 Tx Packet Memory Area*/
 UserToPMABufferCopy(Buffer, GetEPTxAddr(ENDP1), 8);
 /* enable endpoint for transmission */
 SetEPTxValid(ENDP1);
}