极海APM32F427如何实现自定义USB HID设备与PC进行通信

描述

《极海芯得》系列内容为用户使用极海系列产品的经验总结,均转载自21ic论坛极海半导体专区,全文未作任何修改,未经原文作者授权禁止转载。

最近需要使用到 APM32F427 枚举成Custom HID设备进行用户自定义通信,但是官方的例程只有提供的HID枚举为鼠标或者键盘类型的设备。这里记录一下,怎么使用Geehy官方的USB中间件,实现自定义的USB HID设备进行用户通信。

1. USB HID设备简介

USB HID类是USB设备的一个标准设备类,它属于人机交互操作的设备,用于控制计算机操作的一些方面,如USB鼠标、USB键盘、USB游戏操纵杆等。但HID设备类不一定要有人机接口,只要符合HID类别规范的设备都是HID设备。

USB HID设备的一个好处就是操作系统自带了HID类的驱动程序,而用户无需去开发驱动程序,只要使用API系统调用即可完成通信。所以经常会把MCU的USB外设枚举为自定义的HID设备类,用于和电脑的上位机进行通信。

关于USB HID设备,这里只是简单介绍下,大家可以查阅网上的资料,或者从下面的USB官网进行学习。

USB HID设备类官网介绍:https://www.usb.org/hid

2. 基于官网的USB中间件如何实现Custom HID设备

2.1 准备工作

官方 F427 芯片的SDK已经提供了很多的USB例程,我们基于官方的USB例程修改即可。

1、下载官网APM32F427 SDK:https://www.geehy.com/product/fifth/APM32F427_425_423#design

2、我们要实现自定义的USB HID设备,与之最接近的就是427 SDK中提供的OTGD_Custom_HID_Keyboard例程。我们复制一份该例程,基于该例程修改为USB Custom HID设备例程。

usb

2.2 修改USB HID报告描述符

报告描述符就是描述报告(HID接口上传输事务中的数据)的一组数据结构。

USB的报告描述符组成,都有其特定的组成格式。关于USB HID的报告描述符的组成和格式,可参考官方文档《Device Class Definition for human interface device (HID)》。这里不多介绍报告描述符了,直接介绍如何修改代码即可。

把usbd_custom_hid_if.c文件定义的报告描述符数组:

usb

把该文件定义的报告描述符直接修改为如下代码:

/**

 * @brief   CUSTOM HID report descriptor

 */

uint8_t USBD_CUSTOM_HIDReportDesc[USBD_CUSTOM_HID_REPORT_DESC_SIZE] =

{

    /* USER CODE BEGIN 0 */

    0x06, 0xFF, 0x00,      /* USAGE_PAGE (Vendor Page: 0xFF00) */      

        0x09, 0x01,            /* USAGE (Demo Kit)               */ 

        0xa1, 0x01, /* COLLECTION (Application) */ 

        // The Input report 

        0x09,0x03, // USAGE ID - Vendor defined 

        0x15,0x00, // LOGICAL_MINIMUM (0) 

        0x26,0x00, 0xFF, // LOGICAL_MAXIMUM (255) 

        0x75,0x08, // REPORT_SIZE (8) 

        0x95,64, // REPORT_COUNT :SendLength 

        0x81,0x02, // INPUT (Data,Var,Abs) 

        // The Output report 

        0x09,0x04, // USAGE ID - Vendor defined 

        0x15,0x00, // LOGICAL_MINIMUM (0) 

        0x26,0x00,0xFF, // LOGICAL_MAXIMUM (255) 

        0x75,0x08, // REPORT_SIZE (8) 

        0x95,64, // REPORT_COUNT:ReceiveLength 

        0x91,0x02, // OUTPUT (Data,Var,Abs) 

    /* USER CODE END 0 */

    0xC0    /*     END_COLLECTION                     */

};

该描述符主要是定义了输入输出Input、Ouput两个报告。其中,Input用于MCU上传数据,Output下传数据。所有报告大小定义为64byte,也就是说每次最大上下传数据量也就为64byte。

另外数组 USBD_CUSTOM_HID_REPORT_DESC_SIZE 这个宏定义需要修改为我们定义的报告描述符的大小,也就是34。在对应的头文件修改如下:

usb

2.3 修改接收回调函数

usbd_custom_hid_if.c文件实现了一个接收处理函数,当USB检测到有数据接收时,会调用该函数进行接收数据处理。

我们需要修改该函数,当有数据接收时,使得 USB_Received_Flag 变量置1,用于上层数据处理函数的处理。修改的代码如下:

uint8_t USB_Received_Flag = 0;

/*!

 * @brief       USB device CUSTOM HID interface receive handler

 *

 * @param       buffer: Command data buffer

 *

 * @param       length: Command data length

 *

 * @retval      USB device operation status

 */

USBD_STA_T USBD_FS_CUSTOM_HID_ItfReceive(uint8_t *buffer, uint8_t *length)

{

    USBD_STA_T usbStatus = USBD_OK;

    UNUSED(length);

    USB_Received_Flag = 1;  // 检测到有数据接收,标志位置1

    USBD_CUSTOM_HID_RxPacket(&gUsbDeviceFS);

    return usbStatus;

}

2.4 实现应用层用户代码的收发函数

1、实现USB Custom HID设备接收函数

我们实现一个USB HID的数据接收函数,当检测到 USB_Received_Flag 标志位置1之后,就可以调用该函数进行数据接收。

uint32_t USB_GetData(uint8_t *data, uint32_t dataNum)

{

    USBD_CUSTOM_HID_INFO_T* usbDevHID = (USBD_CUSTOM_HID_INFO_T*)gUsbDeviceFS.devClass[gUsbDeviceFS.classID]->classData;

    if (usbDevHID == NULL)

    {

        return 0;

    }

    if (dataNum > usbDevHID->reportSize)

    {

        dataNum = usbDevHID->reportSize;

    }

    for (uint32_t i = 0; i < dataNum; i++)

    {

        *data++ = usbDevHID->report[i];

    }

    return dataNum;

}

接收到的数据会存放在USB的 gUsbDeviceFS 全局变量中,该全局变量包含了USB的所有信息。

2、实现USB Custom HID设备发送函数

USB HID设备发送数据,我们只需要调用F427 SDK提供的 USBD_CUSTOM_HID_TxReport 函数发送数据即可。我们对该函数封装一层用于用户调用。

uint32_t USB_SendData(uint8_t *data, uint32_t dataNum)

{

    // USBD_CUSTOM_HID_IN_EP_SIZE 64

    if (USBD_OK != USBD_CUSTOM_HID_TxReport(&gUsbDeviceFS, data, 64))

    {

        return 0;

    }

    return dataNum;

}

2.5 实现主函数与PC进行读写通信

前面已经实现的用户应用层USB Custom HID设备的收发函数,我们可以在主函数调用USB HID收发函数进行读写通信。测试是否确实和PC端上位机实现了数据的收发。

主函数代码实现如下:

int main(void)

{

    uint8_t report[64] = {0};

    DAL_DeviceConfig();

    /* Infinite loop */

    while (1)

    {

        // USB_Received_Flag 变量置1,说明有USB数据接收到。下面对接收的数据进行处理

        if (USB_Received_Flag == 1)

        {

            USB_Received_Flag = 0;

            USB_GetData(report, 64);  // 获取USB接收到的数据

//            打印测试

//            for (uint32_t i = 0; i < 64; i++)

//                printf("%02X ", report[i]);

            USB_SendData(report, 64);  // 把接收到的数据原封不懂的发送回给上位机

        }

    }

}

该主函数就是实现了简单的USB HID数据的收发,把PC端下发给F427的USB数据,然后再返回给PC端上位机。

3. USB Custom HID设备通信的测试验证

3.1 在电脑的设备管理器查看

在第二节修改完代码之后,编译下载到APM32F427芯片,运行起来后,我们可以在windows系统的设备管理器的人体学输入设备,查看到我们自己实现的USB Custom HID的。如下:

usb

又或者通过控制面板的设备和打印机的选项,可以查看到我们实现的USB HID设备,如下:

usb

可以看到我们实现的APM32 Custom HID设备,说明修改的代码已经正常运行。

3.2 通过PC端上位机工具进行数据收发测试

我们需要使用USB HID的调试工具,进行数据收发测试。关于这样的上位机工具,网上有很多的。我这里使用的是 PortHelper 工具。这个工具大家可以网上搜一下下载。

或者下载我分享的下面这个百度网盘链接下载:

链接:https://pan.baidu.com/s/1qkZCs-dG__czkDrAvN7z-w?pwd=q6er 提取码:q6er

1、打开PortHelper 上位机,然后选择USB调试,然后找到 APM32 Custom HID  设备,然后打开USB。

usb

2、PortHelper 测试与APM32F427进行USB数据收发

打开USB之后,然后我们勾选hex发送,hex显示。然后点击发送即可,如下图:

usb

然后可以PC端上位机发送的数据给APM32F427,芯片原样返回数据给该上位机。

到这里就实现的我们自定义的USB Custom HID设备,该设备主要是接收PC端上位机发送过来的数据,然后APM32F427接收进行处理。在实际项目我是需要基于这个通信进行更复杂的项目开发。

注:文章作者在原帖中提供了代码文件,有需要请至原文21ic论坛

原文地址:https://bbs.21ic.com/icview-3501049-1-1.html?_dsign=8cbdef4d

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分