请选择 进入手机版 | 继续访问电脑版
查看: 188|回复: 1

[原创] [IRD-LPC1768-DEV] 篇六 USBHID与CAN通信数据互转

[复制链接]
  • TA的每日心情
    开心
    2019-3-5 08:47
  • 签到天数: 1 天

    [LV.1]初来乍到

    39

    主题

    833

    帖子

    1

    金豆

    金牌会员

    Rank: 6Rank: 6

    积分
    2621
    最后登录
    2019-6-24
    发表于 2019-3-30 11:42:01 | 显示全部楼层 |阅读模式
          最近又出差几日,更新的慢了些。USBHID通信也好久没写了,而且LPC系列的USB通信也是第一次整,很多时候都是用的时候再学习再扩展。想象首先要做的事,再熟悉一下USB通信的套路,这个就得说说圈圈写的书了《圈圈教你玩USB》,简单易懂,想想不管是什么芯片,套路都是一样的,先看两遍再说。先从各个描述符开始,搞清楚各个描述符的关系,才能理解。设备描述符--配置描述符--接口描述符--端点描述符。HID的固有缺点就是数据只能使用中断或者控制传输。由于中断传输查询的时间间隔最小为一个帧(或者微帧),因而HID设备速度受到了限制。
          理解了协议,再来理解LPC1768的USB函数。花了本人好几天才稍搞明白函数的调用以及程序的不足。测试程序是根据库函数里边的例程修改的。首先修改描述符。把报告描述符中用途页中的HID_USAGE_PAGE_BUTTON改成HID_USAGE_PAGE_GENERIC,其他的如代码所示:
    1. const uint8_t HID_ReportDescriptor[] = {
    2.   HID_UsagePageVendor(0x00),
    3.   HID_Usage(0x01),    //09
    4.   HID_Collection(HID_Application),
    5.     HID_UsagePage(HID_USAGE_PAGE_GENERIC),//(HID_USAGE_PAGE_BUTTON),//用途页
    6.     HID_UsageMin(1),                     //用途最小值
    7.     HID_UsageMax(3),
    8.     HID_LogicalMin(0),                     //逻辑最小值
    9.     HID_LogicalMax(1),
    10.     HID_ReportCount(3),                       //数据域数量
    11.     HID_ReportSize(1),                        //数据域大小
    12.     HID_Input(HID_Data | HID_Variable | HID_Absolute),
    13.     HID_ReportCount(1),
    14.     HID_ReportSize(5),
    15.     HID_Input(HID_Constant),
    16.     HID_UsagePage(HID_USAGE_PAGE_LED),  //05
    17.     HID_Usage(HID_USAGE_LED_GENERIC_INDICATOR),
    18.     HID_LogicalMin(0),
    19.     HID_LogicalMax(1),
    20.     HID_ReportCount(8),
    21.     HID_ReportSize(1),
    22.     HID_Output(HID_Data | HID_Variable | HID_Absolute),
    23.   HID_EndCollection,
    24. };

    25. const uint16_t HID_ReportDescSize = sizeof(HID_ReportDescriptor);


    26. /* USB Standard Device Descriptor */
    27. const uint8_t USB_DeviceDescriptor[] = {
    28.   USB_DEVICE_DESC_SIZE,              /* bLength 设备描述符的长度*/
    29.   USB_DEVICE_DESCRIPTOR_TYPE,        /* bDescriptorType 描述符类型*/
    30.   WBVAL(0x0200), /* 2.00 */          /* bcdUSB 本设备所使用的USB协议版本*/
    31.   0x00,                              /* bDeviceClass 类代码*/
    32.   0x00,                              /* bDeviceSubClass 子类代码*/
    33.   0x00,                              /* bDeviceProtocol 设备所使用的协议*/
    34.   USB_MAX_PACKET0,                   /* bMaxPacketSize0 端点0最大包长*/
    35.   WBVAL(0xC251),                     /* idVendor 厂商ID*/
    36.   WBVAL(0x2201),                     /* idProduct 产品ID*/
    37.   WBVAL(0x0100), /* 1.00 */          /* bcdDevice 设备版本号*/
    38.   0x04,                              /* iManufacturer 描述厂商字符串索引*/
    39.   0x20,                              /* iProduct 描述产品字符串索引*/
    40.   0x42,                              /* iSerialNumber 产品序列号字符串索引*/
    41.   0x01                               /* bNumConfigurations 可能的配置数*/
    42. };

    43. /* USB Configuration Descriptor */
    44. /*   All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */
    45. const uint8_t USB_ConfigDescriptor[] = {
    46. /* Configuration 1 */
    47.   USB_CONFIGUARTION_DESC_SIZE,       /* bDescriptorType 描述符长度*/
    48.   USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType 描述符类型*/
    49.   WBVAL(                             /* wTotalLength 配置描述符+接口描述符+端点描述符*/
    50.     USB_CONFIGUARTION_DESC_SIZE +
    51.     USB_INTERFACE_DESC_SIZE     +
    52.     HID_DESC_SIZE               +
    53.     USB_ENDPOINT_DESC_SIZE
    54.   ),
    55.   0x01,                              /* bNumInterfaces 配置所支持的接口数*/
    56.   0x01,                              /* bConfigurationValue 配置值*/
    57.   0x00,                              /* iConfiguration 配置字符串的索引值*/
    58.   USB_CONFIG_BUS_POWERED /*|*/       /* bmAttributes 该设备的属性*/
    59. /*USB_CONFIG_REMOTE_WAKEUP*/,
    60.   USB_CONFIG_POWER_MA(100),          /* bMaxPower 设备所需的电流*/
    61. /* Interface 0, Alternate Setting 0, HID Class */
    62.   USB_INTERFACE_DESC_SIZE,           /* bLength 接口长度*/
    63.   USB_INTERFACE_DESCRIPTOR_TYPE,     /* bDescriptorType 接口类型*/
    64.   0x00,                              /* bInterfaceNumber 接口的编号*/
    65.   0x00,                              /* bAlternateSetting 接口的备用编号*/
    66.   0x01,                              /* bNumEndpoints 接口所使用的端点数*/
    67.   USB_DEVICE_CLASS_HUMAN_INTERFACE,  /* bInterfaceClass 接口所使用的类*/
    68.   HID_SUBCLASS_NONE,                 /* bInterfaceSubClass 接口子类*/
    69.   HID_PROTOCOL_NONE,                 /* bInterfaceProtocol 接口所使用的协议*/
    70.   0x5C,                              /* iInterface 接口字符串的索引值*/
    71. /* HID Class Descriptor */
    72. /* HID_DESC_OFFSET = 0x0012 */
    73.   HID_DESC_SIZE,                     /* bLength 类描述符长度*/
    74.   HID_HID_DESCRIPTOR_TYPE,           /* bDescriptorType */
    75.   WBVAL(0x0100), /* 1.00 */          /* bcdHID HID协议版本*/
    76.   0x00,                              /* bCountryCode 国家代码*/
    77.   0x01,                              /* bNumDescriptors 下级描述符的数量*/
    78.   HID_REPORT_DESCRIPTOR_TYPE,        /* bDescriptorType 类型*/
    79.   WBVAL(HID_REPORT_DESC_SIZE),       /* wDescriptorLength */
    80. /* Endpoint, HID Interrupt In */
    81.   USB_ENDPOINT_DESC_SIZE,            /* bLength */
    82.   USB_ENDPOINT_DESCRIPTOR_TYPE,      /* bDescriptorType */
    83.   USB_ENDPOINT_IN(1),                /* bEndpointAddress */
    84.   USB_ENDPOINT_TYPE_INTERRUPT,       /* bmAttributes 端点的属性*/
    85.   WBVAL(0x0010),                     /* wMaxPacketSize 端点支持的最大包长度*/
    86.   0x20,          /* 32ms */          /* bInterval 端点的查询时间*/
    87. /* Terminator */
    88.   0,         /* bLength */
    89.        
    90.         /***********************端点描述符*******************************************/

    91.     USB_ENDPOINT_DESC_SIZE,                //bLength字段。端点描述符长度为7字节。

    92.     USB_ENDPOINT_DESCRIPTOR_TYPE,            //bDescriptorType字段。端点描述符编号为0x05。

    93.     USB_ENDPOINT_OUT(1),                    //bEndpointAddress字段。端点的地址。我们使用D12的输入端点1。

    94.     USB_ENDPOINT_TYPE_INTERRUPT,              //bmAttributes字段。D1~D0为端点传输类型选择。

    95.     WBVAL(0x0010),                           //wMaxPacketSize字段。该端点的最大包长。最大包长为64字节。

    96.     0x01,                                        //bInterval字段。端点查询的时间,端点查询的时间,此处无意义。

    97.     //配置描述符扩充

    98.     0x00
    99. };
    复制代码
    接下来要理解USB中断函数,参考的以为网友的标注如下:
    1. if (disr & EP_SLOW_INT) {
    2.     while (LPC_USB->USBEpIntSt) {                   /* Endpoint Interrupt Status */

    3.       for (n = 0; n < USB_EP_NUM; n++) {    /* Check All Endpoints */
    4.         if (LPC_USB->USBEpIntSt & (1 << n)) {    //如果中断发生
    5.           m = n >> 1;             //每两个端点对应一个逻辑端点,处理函数将一个逻辑端点的处理放在一个函数中,所以/2
    6.           LPC_USB->USBEpIntClr = 1 << n; //清除对应中断
    7.           while ((LPC_USB->USBDevIntSt & CDFULL_INT) == 0);//等待命令执行
    8.           val = LPC_USB->USBCmdData; //读取端点状态

    9.           if ((n & 1) == 0) {               /* OUT Endpoint 如果是偶数则为输出*/
    10.             if (n == 0) {                   /* Control OUT Endpoint 0为默认的控制端点*/
    11.               if (val & EP_SEL_STP) {       /* Setup Packet 是否为setup包*/
    12.                 if (USB_P_EP[0]) {
    13.                   USB_P_EP[0](USB_EVT_SETUP);
    14.                   continue;
    15.                 }
    16.               }
    17.             }
    18.             if (USB_P_EP[m]) {
    19.               USB_P_EP[m](USB_EVT_OUT);//其他端点的输出处理,方法类似
    20.             }
    21.           } else {                          /* IN Endpoint 奇数为输入端点*/
    22.                         //if (USB_P_EP[m]) {
    23.               //USB_P_EP[m](USB_EVT_IN);
    24.                           if(m==0)
    25.                             USB_EndPoint0(USB_EVT_IN);
    26.                           if(m==1)
    27.                                   USB_EndPoint1(USB_EVT_IN);
    28.                           if(m==2)
    29.                                   USB_EndPoint2(USB_EVT_IN);
    30.                           /* ............. */
    31.             //}
    32.           }
    33.         }
    34.       }
    35.                         LPC_USB->USBDevIntClr = EP_SLOW_INT;//最后将端点中断的慢中断清除,此句为后加
    36.     }
    37.   }
    复制代码
    然后修改主函数中的GetInReport()和SetOutReport()函数
    1. void GetInReport (void)
    2.         InReport =AFRxMsg[0].dataA [0];
    3. }
    4. void SetOutReport (void) {
    5. AFTxMsg [0].dataA [0]= OutReport ;
    6.                 CAN_SendMsg(LPC_CAN1, &AFTxMsg[0]);
    7. }
    复制代码
    关于CAN通信前面已经写过,直接把函数拿过来用就可以了,初始化,中断等等。然后就接线仿真测试,如图1所示:
    几年前玩USB的时候用的一个上位机,现在拿来依然好用。如附件中。
    简单的发一个数据,通过USB上位机转到MCU,再通过MCU的CAN转到CAN上位机,如图2所示:
    数据接收也是一样的。
    对了,查看LPC1768的主板可看到,需要焊掉R1,R2,短接R10,R25方能连接到USBDevice功能。如图3所示:
    还有就是开始测试并不顺利,各种问题,尤其是由于PC前端USB口不够,使用了转接延长线,几乎没有数据传输,直接连接就好了,所以也算是前车之鉴吧。

    图1

    图1

    图2

    图2

    图3

    图3

    Usb-HID.rar

    106.78 KB, 下载次数: 2, 下载积分: 威望 1

    USB上位机

    回复

    使用道具 举报

  • TA的每日心情
    无聊
    2019-5-1 06:15
  • 签到天数: 5 天

    [LV.2]偶尔看看I

    0

    主题

    91

    帖子

    0

    金豆

    中级会员

    Rank: 3Rank: 3

    积分
    201
    最后登录
    2019-5-1
    发表于 2019-4-30 10:29:41 | 显示全部楼层
    谢谢分享
    开心!!!
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    小黑屋|手机版|Archiver|恩智浦技术社区

    GMT+8, 2019-6-24 17:08 , Processed in 0.081372 second(s), 14 queries , MemCache On.

    Powered by Discuz! X3.4

    © 2001-2013 Comsenz Inc.

    快速回复 返回顶部 返回列表