打印
[PIC32/SAM]

USB HID通信

[复制链接]
2490|16
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wiba|  楼主 | 2019-7-25 12:46 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
在设备通信中,UART非常常见,也是最简单的,但是,PC尤其是笔记本基本都舍弃了传统的UART端口,只能使用usb转UART的IC来做信号转换,这样效率低,而且还要针对IC安装专门的驱动,非常不方便,而在有些特殊设备上,甚至驱动无法安装,是否可以不安装驱动与PC通信呢?

当然可以!

在USB盛行的今天,USB通信变得极其简单,而在USB中有一个重要的通信标准,就是HID(Human Interface Device),常见的鼠标键盘就是采用HID通信。由于它的标准性,几乎所有PC系统(Windows、Linux、OSX)都集成了它的驱动,所以,可以将它看做一个免驱的设备,类似的还有USB大容量存储。下面我们就用PIC32MZ2048EFH芯片实现USB HID的接口(PIC32MZ EF Start Kit开发板),与PC进行通信,PC端采用C#以及C++分别在windows和linux下实现hid读写,本篇不做描述,详细参考我的其它博客,关于两个平台的hid程序。

接口使用的是micro usb(j4接口)。


使用特权

评论回复
沙发
wiba|  楼主 | 2019-7-25 12:47 | 只看该作者
1、配置时钟(略)

2、配置USB Library,以及device configuration,下面两图中红色部分要修改,其它默认。

(若是要LED显示,或者显示到LCD,请自行配置,需要注意的是,USB或使用的默认第一个Dynamic Timer,若是有其它功能使用到Dynamic Timer,请多设置一个Timer,并将第一个(instance0)预留不用,否则其它功能无法正常使用)




使用特权

评论回复
板凳
wiba|  楼主 | 2019-7-25 12:47 | 只看该作者
3、生成code,并添加自己的code。

添加usb-hid.c与usb-hid.h。

需要执行usb初始化和while循环的task任务,接收可以修改为回调函数,放到usb-hid接收函数中,发送直接调用发送函数即可,注意包大小要与客户端发送的大小一致,可以考虑在包内加标识判断数据大小。

使用特权

评论回复
地板
wiba|  楼主 | 2019-7-25 12:48 | 只看该作者
usb-hid.h

#ifndef _USB_HID_H
#define _USB_HID_H

#define hidMaxBufferSize 64

#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include "system_config.h"
#include "system_definitions.h"

typedef enum
{
    USB_HID_STATE_INIT,
            
    /* Application is waiting for configuration */
    USB_HID_STATE_WAIT_FOR_CONFIGURATION,

    /* Application is running the main tasks */
    USB_HID_STATE_MAIN_TASK,

    /* Application is in an error state */
    USB_HID_STATE_ERROR
}USB_HID_STATE;

使用特权

评论回复
5
wiba|  楼主 | 2019-7-25 12:48 | 只看该作者
typedef struct
{
    /* The application's current state */
    USB_HID_STATE state;

      /* Device layer handle returned by device layer open function */
    USB_DEVICE_HANDLE  usbDevHandle;

    /* Recieve data buffer */
    uint8_t * receiveDataBuffer;


    /* Device configured */
    bool deviceConfigured;

    /* Send report transfer handle*/
    USB_DEVICE_HID_TRANSFER_HANDLE txTransferHandle;

    /* Receive report transfer handle */
    USB_DEVICE_HID_TRANSFER_HANDLE rxTransferHandle;

    /* Configuration value selected by the host*/
    uint8_t configurationValue;

    /* HID data received flag*/
    bool hidDataReceived;

    /* HID data transmitted flag */
    bool hidDataTransmitted;

     /* USB HID current Idle */
    uint8_t idleRate;

} USB_HID_DATA;

使用特权

评论回复
6
wiba|  楼主 | 2019-7-25 12:49 | 只看该作者
void USB_HID_Tasks(void);

bool USB_HID_SendBytes(uint8_t *datas, uint8_t length);

void USB_HID_ReceiveBytes(uint8_t * datas);

bool USB_HID_StartNewReceiveBytes(void);

extern const USB_DEVICE_FUNCTION_REGISTRATION_TABLE funcRegistrationTable[1];
extern const USB_DEVICE_MASTER_DESCRIPTOR usbMasterDescriptor;

#endif

使用特权

评论回复
7
wiba|  楼主 | 2019-7-25 12:49 | 只看该作者
usb-hid.c

#include "usb-hid.h"

USB_HID_DATA usbhidData;

#define APP_MAKE_BUFFER_DMA_READY __attribute__ ((coherent, aligned(16)))

/* Recieve data buffer */
uint8_t receiveDataBuffer[64] APP_MAKE_BUFFER_DMA_READY;

/* Transmit data buffer */
uint8_t  transmitDataBuffer[64] APP_MAKE_BUFFER_DMA_READY;


USB_DEVICE_HID_EVENT_RESPONSE USB_HID_USBDeviceHIDEventHandler
(
    USB_DEVICE_HID_INDEX iHID,
    USB_DEVICE_HID_EVENT event,
    void * eventData,
    uintptr_t userData
)
{
    USB_DEVICE_HID_EVENT_DATA_REPORT_SENT * reportSent;
    USB_DEVICE_HID_EVENT_DATA_REPORT_RECEIVED * reportReceived;

    /* Check type of event */
    switch (event)
    {
        case USB_DEVICE_HID_EVENT_REPORT_SENT:

            /* The eventData parameter will be USB_DEVICE_HID_EVENT_REPORT_SENT
             * pointer type containing details about the report that was
             * sent. */
            reportSent = (USB_DEVICE_HID_EVENT_DATA_REPORT_SENT *) eventData;
            if(reportSent->handle == usbhidData.txTransferHandle )
            {
                // Transfer progressed.
                usbhidData.hidDataTransmitted = true;
            }
            
            break;

        case USB_DEVICE_HID_EVENT_REPORT_RECEIVED:

            /* The eventData parameter will be USB_DEVICE_HID_EVENT_REPORT_RECEIVED
             * pointer type containing details about the report that was
             * received. */

            reportReceived = (USB_DEVICE_HID_EVENT_DATA_REPORT_RECEIVED *) eventData;
            if(reportReceived->handle == usbhidData.rxTransferHandle )
            {
                // Transfer progressed.
                usbhidData.hidDataReceived = true;
            }
         
            break;

        case USB_DEVICE_HID_EVENT_SET_IDLE:

            /* For now we just accept this request as is. We acknowledge
             * this request using the USB_DEVICE_HID_ControlStatus()
             * function with a USB_DEVICE_CONTROL_STATUS_OK flag */

            USB_DEVICE_ControlStatus(usbhidData.usbDevHandle, USB_DEVICE_CONTROL_STATUS_OK);

            /* Save Idle rate recieved from Host */
            usbhidData.idleRate = ((USB_DEVICE_HID_EVENT_DATA_SET_IDLE*)eventData)->duration;
            break;

        case USB_DEVICE_HID_EVENT_GET_IDLE:

            /* Host is requesting for Idle rate. Now send the Idle rate */
            USB_DEVICE_ControlSend(usbhidData.usbDevHandle, & (usbhidData.idleRate),1);

            /* On successfully reciveing Idle rate, the Host would acknowledge back with a
               Zero Length packet. The HID function drvier returns an event
               USB_DEVICE_HID_EVENT_CONTROL_TRANSFER_DATA_SENT to the application upon
               receiving this Zero Length packet from Host.
               USB_DEVICE_HID_EVENT_CONTROL_TRANSFER_DATA_SENT event indicates this control transfer
               event is complete */

            break;
        default:
            // Nothing to do.
            break;
    }
    return USB_DEVICE_HID_EVENT_RESPONSE_NONE;
}

使用特权

评论回复
8
wiba|  楼主 | 2019-7-25 12:49 | 只看该作者
void USB_HID_USBDeviceEventHandler(USB_DEVICE_EVENT event, void * eventData, uintptr_t context)
{
    switch(event)
    {
        case USB_DEVICE_EVENT_RESET:
        case USB_DEVICE_EVENT_DECONFIGURED:

            /* Host has de configured the device or a bus reset has happened.
             * Device layer is going to de-initialize all function drivers.
             * Hence close handles to all function drivers (Only if they are
             * opened previously. */


            usbhidData.deviceConfigured = false;
            usbhidData.state = USB_HID_STATE_WAIT_FOR_CONFIGURATION;
            break;

        case USB_DEVICE_EVENT_CONFIGURED:
            /* Set the flag indicating device is configured. */
            usbhidData.deviceConfigured = true;

            /* Save the other details for later use. */
            usbhidData.configurationValue = ((USB_DEVICE_EVENT_DATA_CONFIGURED*)eventData)->configurationValue;

            /* Register application HID event handler */
            USB_DEVICE_HID_EventHandlerSet(USB_DEVICE_HID_INDEX_0, USB_HID_USBDeviceHIDEventHandler, (uintptr_t)&usbhidData);



            break;

        case USB_DEVICE_EVENT_SUSPENDED:


            break;

        case USB_DEVICE_EVENT_POWER_DETECTED:

            /* VBUS was detected. We can attach the device */

            USB_DEVICE_Attach (usbhidData.usbDevHandle);
            break;

        case USB_DEVICE_EVENT_POWER_REMOVED:

            /* VBUS is not available */
            USB_DEVICE_Detach(usbhidData.usbDevHandle);
            break;

        /* These events are not used in this demo */
        case USB_DEVICE_EVENT_RESUMED:
        case USB_DEVICE_EVENT_ERROR:
        default:
            break;
    }
}

使用特权

评论回复
9
wiba|  楼主 | 2019-7-25 12:50 | 只看该作者
void USB_HID_Initial(void)
{
    usbhidData.state = USB_HID_STATE_INIT;
   
    usbhidData.usbDevHandle = USB_DEVICE_HANDLE_INVALID;
    usbhidData.deviceConfigured = false;
    usbhidData.txTransferHandle = USB_DEVICE_HID_TRANSFER_HANDLE_INVALID;
    usbhidData.rxTransferHandle = USB_DEVICE_HID_TRANSFER_HANDLE_INVALID;
    usbhidData.hidDataReceived = false;
    usbhidData.hidDataTransmitted = true;
    usbhidData.receiveDataBuffer = &receiveDataBuffer[0];
   
}

使用特权

评论回复
10
wiba|  楼主 | 2019-7-25 12:50 | 只看该作者
void USB_HID_Tasks (void )
{

    /* Check if device is configured.  See if it is configured with correct
     * configuration value  */

    switch(usbhidData.state)
    {
        case USB_HID_STATE_INIT:
   
            /* Open the device layer */
            usbhidData.usbDevHandle = USB_DEVICE_Open( USB_DEVICE_INDEX_0, DRV_IO_INTENT_READWRITE );

            if(usbhidData.usbDevHandle != USB_DEVICE_HANDLE_INVALID)
            {
                /* Register a callback with device layer to get event notification (for end point 0) */
                USB_DEVICE_EventHandlerSet(usbhidData.usbDevHandle, USB_HID_USBDeviceEventHandler, 0);

                usbhidData.state = USB_HID_STATE_WAIT_FOR_CONFIGURATION;
            }
            else
            {
                /* The Device Layer is not ready to be opened. We should try
                 * again later. */
            }

            
            
            break;

        case USB_HID_STATE_WAIT_FOR_CONFIGURATION:

            if(usbhidData.deviceConfigured == true)
            {
                /* Device is ready to run the main task */
                usbhidData.hidDataReceived = false;
                usbhidData.hidDataTransmitted = true;
                usbhidData.state = USB_HID_STATE_MAIN_TASK;

                /* Place a new read request. */
                USB_DEVICE_HID_ReportReceive (USB_DEVICE_HID_INDEX_0,
                        &usbhidData.rxTransferHandle, usbhidData.receiveDataBuffer, 64);
            }
            break;

        case USB_HID_STATE_MAIN_TASK:

            if(!usbhidData.deviceConfigured)
            {
                /* Device is not configured */
                usbhidData.state = USB_HID_STATE_WAIT_FOR_CONFIGURATION;
            }
            else if( usbhidData.hidDataReceived )  //receive data
            {

                USB_HID_ReceiveBytes(usbhidData.receiveDataBuffer);
               

            }
        case USB_HID_STATE_ERROR:
            break;
        default:
            break;
    }
}

使用特权

评论回复
11
wiba|  楼主 | 2019-7-25 12:50 | 只看该作者
bool USB_HID_SendBytes(uint8_t *datas, uint8_t length)
{
    if(usbhidData.hidDataTransmitted)
    {
        usbhidData.hidDataTransmitted = false;

        //uint8_t buffers[64];
        transmitDataBuffer[0] = length;

        uint8_t i=1;
        for(i=1;i<length+1;i++)
        {
            transmitDataBuffer[i]=datas[i-1];
        }

        /* Prepare the USB module to send the data packet to the host */
        USB_DEVICE_HID_ReportSend (USB_DEVICE_HID_INDEX_0,
                &usbhidData.txTransferHandle, transmitDataBuffer, 64 );
        
        return true;
    }
    else
        return false;
}

使用特权

评论回复
12
wiba|  楼主 | 2019-7-25 13:26 | 只看该作者
//receive data entry
//first byte is data length
void USB_HID_ReceiveBytes(uint8_t * datas)
{

    uint8_t length = datas[0];
   
   
    uint8_t i;
    for(i=0;i<length;i++)
    {
        receiveDataBuffer[i] = datas[i+1];
        //Uart_Screen_Printf("Data %u:%02X",i,receiveDataBuffer[i]);
    }
   
    uint8_t tmpSend[] = {0xaa,0xbb};
    //output the receive data here
    USB_HID_SendBytes(tmpSend,2);
   
    if(receiveDataBuffer[0]==0x80)
    {
        SYS_PORTS_PinToggle(0,PORT_CHANNEL_H,0);
    }
   
    USB_HID_StartNewReceiveBytes();
}

使用特权

评论回复
13
wiba|  楼主 | 2019-7-25 13:26 | 只看该作者
//allow to recive new hid data
bool USB_HID_StartNewReceiveBytes(void)
{
    usbhidData.hidDataReceived = false;

    /* Place a new read request. */
    USB_DEVICE_HID_ReportReceive (USB_DEVICE_HID_INDEX_0,
            &usbhidData.rxTransferHandle, usbhidData.receiveDataBuffer, 64 );
   
    return true;
}

使用特权

评论回复
14
wiba|  楼主 | 2019-7-25 13:27 | 只看该作者
app.h

/*******************************************************************************
  MPLAB Harmony Application Header File
  Company:
    Microchip Technology Inc.
  File Name:
    app.h
  Summary:
    This header file provides prototypes and definitions for the application.
  Description:
    This header file provides function prototypes and data type definitions for
    the application.  Some of these are required by the system (such as the
    "APP_Initialize" and "APP_Tasks" prototypes) and some of them are only used
    internally by the application (such as the "APP_STATES" definition).  Both
    are defined here for convenience.
*******************************************************************************/

//DOM-IGNORE-BEGIN
/*******************************************************************************
Copyright (c) 2013-2014 released Microchip Technology Inc.  All rights reserved.
Microchip licenses to you the right to use, modify, copy and distribute
Software only when embedded on a Microchip microcontroller or digital signal
controller that is integrated into your product or third party product
(pursuant to the sublicense terms in the accompanying license agreement).
You should refer to the license agreement accompanying this Software for
additional information regarding your rights and obligations.
SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
*******************************************************************************/
//DOM-IGNORE-END

#ifndef _APP_H
#define _APP_H


// *****************************************************************************
// *****************************************************************************
// Section: Included Files
// *****************************************************************************
// *****************************************************************************

#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include "system_config.h"
#include "system_definitions.h"
#include "usb/usb_chapter_9.h"
#include "usb/usb_device.h"
#include "usb-hid.h"



typedef enum
{
    /* Application is initializing */
    APP_STATE_INIT,

    APP_STATE_MAIN_TASK,
            
    APP_STATE_ERROR
            
} APP_STATES;


typedef struct
{
    /* The application's current state */
    APP_STATES state;

} APP_DATA;




void APP_Initialize ( void );


void APP_Tasks ( void );




#endif /* _APP_H */
/*******************************************************************************
End of File
*/

使用特权

评论回复
15
wiba|  楼主 | 2019-7-25 13:27 | 只看该作者
app.c

#include "system_definitions.h"
#include "app.h"


APP_DATA appData;


void APP_Initialize ( void )
{
      
    /* Place the App state machine in its initial state. */
    appData.state = APP_STATE_INIT;
    //Uart_Initial();
   
}

使用特权

评论回复
16
wiba|  楼主 | 2019-7-25 13:28 | 只看该作者
void APP_Tasks (void )
{

    /* Check if device is configured.  See if it is configured with correct
     * configuration value  */

    switch(appData.state)
    {
        case APP_STATE_INIT:

            //Uart_Screen_Printf("Start!");
            
            appData.state = APP_STATE_MAIN_TASK;
            
            USB_HID_Initial();
            
            break;

        case APP_STATE_MAIN_TASK:
            USB_HID_Tasks();
           
            break;
            
        case APP_STATE_ERROR:
            
            break;
            
        default:
            break;
    }
}


/*******************************************************************************
End of File
*/

使用特权

评论回复
17
wiba|  楼主 | 2019-7-25 13:28 | 只看该作者
刚停电了 郁闷 希望没有耽误发帖子

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

77

主题

3312

帖子

3

粉丝