Thứ Năm, 28 tháng 7, 2016

STM32 USB-HID

KHỞI TẠO USB HID STM32F103C8T6 ĐƠN GIẢN BẰNG STM32CUBEMX

1. Hardware

Kit STM32F103C8T6


Schematic kit


2. Khởi tạo STM32CubeMx

STEP 1:

Vào chương trình STM32CubeMX -> Chon Create new project. -> Chọn MCU STM32F103C8Tx( STM32F103C8T6).



STEP 2:

Trong muc Pinout.

 Peripherals => USB => Tick vào Device(FS)

 Middlewares=> Custom Human Interface Device Class(HID).




 STEP 3:

Trong mục Pinout.

Peripherals => RCC => High Speed Clock (HSE) =>Chọn => Crytal/Ceramic Resonator.



STEP 4:

Trong mục Clock configuration.

Config Clock USB => 48Mhz.



STEP 5:

Trong mục Configuration.

Trong cửa sổ chính => Connectivity => USB.



STEP 6:

Xuất hiện hôp thoại USB Configuration => Tab Parameter settings => Basic parameters =>  Endpoint 0 Max Packet size => 64 byte. (Maximum gói data endpoint 0 là 64 byte)



STEP 7: 

Trong mục Configuration.

Trong cửa sổ chính => Middlewares =>USB_DEVICE.



STEP 8:

Xuất hiện hôp thoại USB_DEVICE Configuration => Tab Parameter settings => Class parameters :
  • USBD_CUSTOM_HID_REPORT_DESC_SIZE (Total length for Report descriptor (IN ENDPOINT)): 32 (32 byte mô tả report input).
  • USBD_CUSTOMHID_OUTREPORT_BUF_SIZE (Maximum report buffer size (OUT ENDPOINT)): 64 ( maximum 64 byte buffer report output ).



STEP 9:

Xuất hiện hôp thoại USB_DEVICE Configuration => Tab Device Descriptor => Device Descriptor FS => PRODUCT_STRING (Product Identifier) =>Đổi Product string USB HID.


3. Config file mô tả USB HID (USB HID Report Descriptor).




  • Trong file usbd_custom_hid_if.c



__ALIGN_BEGIN static uint8_t CUSTOM_HID_ReportDesc_FS[USBD_CUSTOM_HID_REPORT_DESC_SIZE] __ALIGN_END =
{
  /* USER CODE BEGIN 0 */ 
  0x00, 
  /* USER CODE END 0 */ 
  0xC0    /*     END_COLLECTION             */
 
};

Sửa thành=====>

__ALIGN_BEGIN static uint8_t CUSTOM_HID_ReportDesc_FS[USBD_CUSTOM_HID_REPORT_DESC_SIZE] __ALIGN_END =
{
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
    0x09, 0x00,                    // USAGE (Undefined)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
    0x85, 0x01,                    //   REPORT_ID (1) //report id input là 0x01
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x95, 0x3F,                    //   REPORT_COUNT (63)//report input gồm có 63 byte data và một byte ID=0x01
    0x09, 0x00,                    //   USAGE (Undefined)
    0x81, 0x82,                    //   INPUT (Data,Var,Abs,Vol) - to the host
    0x85, 0x02,                    //   REPORT_ID (2)//report id output là 0x02
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x95, 0x3F,                    //   REPORT_COUNT (63)//report output gồm có 63 byte data và một byte ID=0x02
    0x09, 0x00,                    //   USAGE (Undefined)
    0x91, 0x82,                    //   OUTPUT (Data,Var,Abs,Vol) - from the host
    0xc0                           // END_COLLECTION
};

USBD_CUSTOM_HID_REPORT_DESC_SIZE: 32 byte mô tả đã config trên soft STM32CubeMX.

  • Trong file usb_customhid.h


#define CUSTOM_HID_EPIN_ADDR                 0x81
#define CUSTOM_HID_EPIN_SIZE                 0x02

#define CUSTOM_HID_EPOUT_ADDR                0x01
#define CUSTOM_HID_EPOUT_SIZE                0x02

Sửa thành===>

#define CUSTOM_HID_EPIN_ADDR                 0x81
#define CUSTOM_HID_EPIN_SIZE                 64

#define CUSTOM_HID_EPOUT_ADDR                0x01
#define CUSTOM_HID_EPOUT_SIZE                64
///////////////////////////////

4. Send và Receive data.

  •  Send data:

uint8_t USBD_CUSTOM_HID_SendReport     (USBD_HandleTypeDef  *pdev, uint8_t *report, uint16_t len);
VD: 

uint8_t data[64];

data[0]=0x01;  //report id input là 0x01, byte đầu tiên phải là report id.

USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS,data,64); 

Khi config USBD_CUSTOM_HID_REPORT_DESC_SIZE=64 thì gửi gói data luôn có len=64.

Note: Nếu muốn gửi và nhận gói data >64 byte VD 128 byte có thể sửa như sau:

USBD_CUSTOM_HID_REPORT_DESC_SIZE=128

CUSTOM_HID_ReportDesc_FS[USBD_CUSTOM_HID_REPORT_DESC_SIZE] __ALIGN_END =
{
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
    0x09, 0x00,                    // USAGE (Undefined)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
    0x85, 0x01,                    //   REPORT_ID (1) //report id input là 0x01
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x95, 127,                    //   REPORT_COUNT (127)//report input gồm có 127 byte data và một byte ID=0x01
    0x09, 0x00,                    //   USAGE (Undefined)
    0x81, 0x82,                    //   INPUT (Data,Var,Abs,Vol) - to the host
    0x85, 0x02,                    //   REPORT_ID (2)//report id output là 0x02
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x95, 127,                    //   REPORT_COUNT (127)//report output gồm có 127 byte data và một byte ID=0x02
    0x09, 0x00,                    //   USAGE (Undefined)
    0x91, 0x82,                    //   OUTPUT (Data,Var,Abs,Vol) - from the host
    0xc0                           // END_COLLECTION
};

uint8_t data[128];

data[0]=0x01;  //report id input là 0x01, byte đầu tiên phải là report id.

USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS,data,128); 

  • Receive data:

 Trong file usbd_customhid.c thêm vào phần màu đỏ:

uint8_t My_Buffer[USBD_CUSTOMHID_OUTREPORT_BUF_SIZE];

static uint8_t  USBD_CUSTOM_HID_DataOut (USBD_HandleTypeDef *pdev,
                              uint8_t epnum)
{

  USBD_CUSTOM_HID_HandleTypeDef     *hhid = (USBD_CUSTOM_HID_HandleTypeDef*)pdev->pClassData;

 ((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData)->OutEvent(hhid->Report_buf[0],         hhid->Report_buf[1]);
///////////////////////////////
for(uint8_t i=0;i<64;i++)
{
    My_Buffer[i]=hhid->Report_buf[i];  //gán buffer Report_buf vào My_Buffer để truy xuất data.
}
//////////////////
  USBD_LL_PrepareReceive(pdev, CUSTOM_HID_EPOUT_ADDR , hhid->Report_buf,
                         USBD_CUSTOMHID_OUTREPORT_BUF_SIZE);

  return USBD_OK;
}

5. Example code:


  •   Code nhận data và gửi data đã nhận lên máy tính. Test bằng phần mềm USB HID Demonstrator(v1.02)

  /////////////////////////////////////////////////
  uint8_t data[64];
  data[0]=0x01;
  while (1)
  {
if(check_usb==1)
{
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
for(uint8_t i=1;i<64;i++)
{
    data[i]=My_Buffer[i];
}
USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS,data,64);   
check_usb=0;
}
  }
  /////////////////////////////////////////////
Link demo code:
https://drive.google.com/file/d/0B9pHWA4exz3gU3lzZDBlMWExMGM/view?usp=sharing

USB HID Demonstrator(v1.02): https://drive.google.com/file/d/0B9pHWA4exz3gNWNGak9zY1dVakU/view?usp=sharing

Video demo:

3 nhận xét:

  1. bạn cho mình hỏi, mình tăng số lượng byte gửi như hướng dẫn, nhưng tại sao thời gian gửi xong rất lâu, 8000 Byte hết hơn 3 giây

    Trả lờiXóa
    Trả lời
    1. Endpoint 0 Max Packet size của USB là 64 byte, khi bạn gửi 8000 byte thì nó sẽ bị chia ra gửi lần lượt 64 byte cho đến hết gói data. Do đó nó không đạt đến tốc độ 12Mbps.

      Xóa
  2. Khi gửi một data lớn bạn nên chia nhỏ ra để gửi, ví dụ report input 128 byte, số data gửi là 8000 byte.

    buffer[8000];
    data[0]=0x02;
    for(uint8_t i=0;i<63;i++)
    {
    for(uint8_t j=1;j<128;j++)
    {
    data[j]=buffer[j-1+i*127];
    }
    USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS,data,128);
    }

    Trả lờiXóa