在线时间1148 小时
UID3124330
注册时间2015-11-26
NXP金币977
TA的每日心情 | 开心 2019-3-5 08:47 |
---|
签到天数: 1 天 [LV.1]初来乍到
金牌会员
- 积分
- 7809
- 最后登录
- 2024-4-26
|
最近又出差几日,更新的慢了些。USBHID通信也好久没写了,而且LPC系列的USB通信也是第一次整,很多时候都是用的时候再学习再扩展。想象首先要做的事,再熟悉一下USB通信的套路,这个就得说说圈圈写的书了《圈圈教你玩USB》,简单易懂,想想不管是什么芯片,套路都是一样的,先看两遍再说。先从各个描述符开始,搞清楚各个描述符的关系,才能理解。设备描述符--配置描述符--接口描述符--端点描述符。HID的固有缺点就是数据只能使用中断或者控制传输。由于中断传输查询的时间间隔最小为一个帧(或者微帧),因而HID设备速度受到了限制。
理解了协议,再来理解LPC1768的USB函数。花了本人好几天才稍搞明白函数的调用以及程序的不足。测试程序是根据库函数里边的例程修改的。首先修改描述符。把报告描述符中用途页中的HID_USAGE_PAGE_BUTTON改成HID_USAGE_PAGE_GENERIC,其他的如代码所示:
- const uint8_t HID_ReportDescriptor[] = {
- HID_UsagePageVendor(0x00),
- HID_Usage(0x01), //09
- HID_Collection(HID_Application),
- HID_UsagePage(HID_USAGE_PAGE_GENERIC),//(HID_USAGE_PAGE_BUTTON),//用途页
- HID_UsageMin(1), //用途最小值
- HID_UsageMax(3),
- HID_LogicalMin(0), //逻辑最小值
- HID_LogicalMax(1),
- HID_ReportCount(3), //数据域数量
- HID_ReportSize(1), //数据域大小
- HID_Input(HID_Data | HID_Variable | HID_Absolute),
- HID_ReportCount(1),
- HID_ReportSize(5),
- HID_Input(HID_Constant),
- HID_UsagePage(HID_USAGE_PAGE_LED), //05
- HID_Usage(HID_USAGE_LED_GENERIC_INDICATOR),
- HID_LogicalMin(0),
- HID_LogicalMax(1),
- HID_ReportCount(8),
- HID_ReportSize(1),
- HID_Output(HID_Data | HID_Variable | HID_Absolute),
- HID_EndCollection,
- };
- const uint16_t HID_ReportDescSize = sizeof(HID_ReportDescriptor);
- /* USB Standard Device Descriptor */
- const uint8_t USB_DeviceDescriptor[] = {
- USB_DEVICE_DESC_SIZE, /* bLength 设备描述符的长度*/
- USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType 描述符类型*/
- WBVAL(0x0200), /* 2.00 */ /* bcdUSB 本设备所使用的USB协议版本*/
- 0x00, /* bDeviceClass 类代码*/
- 0x00, /* bDeviceSubClass 子类代码*/
- 0x00, /* bDeviceProtocol 设备所使用的协议*/
- USB_MAX_PACKET0, /* bMaxPacketSize0 端点0最大包长*/
- WBVAL(0xC251), /* idVendor 厂商ID*/
- WBVAL(0x2201), /* idProduct 产品ID*/
- WBVAL(0x0100), /* 1.00 */ /* bcdDevice 设备版本号*/
- 0x04, /* iManufacturer 描述厂商字符串索引*/
- 0x20, /* iProduct 描述产品字符串索引*/
- 0x42, /* iSerialNumber 产品序列号字符串索引*/
- 0x01 /* bNumConfigurations 可能的配置数*/
- };
-
- /* USB Configuration Descriptor */
- /* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */
- const uint8_t USB_ConfigDescriptor[] = {
- /* Configuration 1 */
- USB_CONFIGUARTION_DESC_SIZE, /* bDescriptorType 描述符长度*/
- USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType 描述符类型*/
- WBVAL( /* wTotalLength 配置描述符+接口描述符+端点描述符*/
- USB_CONFIGUARTION_DESC_SIZE +
- USB_INTERFACE_DESC_SIZE +
- HID_DESC_SIZE +
- USB_ENDPOINT_DESC_SIZE
- ),
- 0x01, /* bNumInterfaces 配置所支持的接口数*/
- 0x01, /* bConfigurationValue 配置值*/
- 0x00, /* iConfiguration 配置字符串的索引值*/
- USB_CONFIG_BUS_POWERED /*|*/ /* bmAttributes 该设备的属性*/
- /*USB_CONFIG_REMOTE_WAKEUP*/,
- USB_CONFIG_POWER_MA(100), /* bMaxPower 设备所需的电流*/
- /* Interface 0, Alternate Setting 0, HID Class */
- USB_INTERFACE_DESC_SIZE, /* bLength 接口长度*/
- USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType 接口类型*/
- 0x00, /* bInterfaceNumber 接口的编号*/
- 0x00, /* bAlternateSetting 接口的备用编号*/
- 0x01, /* bNumEndpoints 接口所使用的端点数*/
- USB_DEVICE_CLASS_HUMAN_INTERFACE, /* bInterfaceClass 接口所使用的类*/
- HID_SUBCLASS_NONE, /* bInterfaceSubClass 接口子类*/
- HID_PROTOCOL_NONE, /* bInterfaceProtocol 接口所使用的协议*/
- 0x5C, /* iInterface 接口字符串的索引值*/
- /* HID Class Descriptor */
- /* HID_DESC_OFFSET = 0x0012 */
- HID_DESC_SIZE, /* bLength 类描述符长度*/
- HID_HID_DESCRIPTOR_TYPE, /* bDescriptorType */
- WBVAL(0x0100), /* 1.00 */ /* bcdHID HID协议版本*/
- 0x00, /* bCountryCode 国家代码*/
- 0x01, /* bNumDescriptors 下级描述符的数量*/
- HID_REPORT_DESCRIPTOR_TYPE, /* bDescriptorType 类型*/
- WBVAL(HID_REPORT_DESC_SIZE), /* wDescriptorLength */
- /* Endpoint, HID Interrupt In */
- USB_ENDPOINT_DESC_SIZE, /* bLength */
- USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
- USB_ENDPOINT_IN(1), /* bEndpointAddress */
- USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes 端点的属性*/
- WBVAL(0x0010), /* wMaxPacketSize 端点支持的最大包长度*/
- 0x20, /* 32ms */ /* bInterval 端点的查询时间*/
- /* Terminator */
- 0, /* bLength */
-
- /***********************端点描述符*******************************************/
- USB_ENDPOINT_DESC_SIZE, //bLength字段。端点描述符长度为7字节。
- USB_ENDPOINT_DESCRIPTOR_TYPE, //bDescriptorType字段。端点描述符编号为0x05。
- USB_ENDPOINT_OUT(1), //bEndpointAddress字段。端点的地址。我们使用D12的输入端点1。
- USB_ENDPOINT_TYPE_INTERRUPT, //bmAttributes字段。D1~D0为端点传输类型选择。
- WBVAL(0x0010), //wMaxPacketSize字段。该端点的最大包长。最大包长为64字节。
- 0x01, //bInterval字段。端点查询的时间,端点查询的时间,此处无意义。
- //配置描述符扩充
- 0x00
- };
复制代码 接下来要理解USB中断函数,参考的以为网友的标注如下:
- if (disr & EP_SLOW_INT) {
- while (LPC_USB->USBEpIntSt) { /* Endpoint Interrupt Status */
- for (n = 0; n < USB_EP_NUM; n++) { /* Check All Endpoints */
- if (LPC_USB->USBEpIntSt & (1 << n)) { //如果中断发生
- m = n >> 1; //每两个端点对应一个逻辑端点,处理函数将一个逻辑端点的处理放在一个函数中,所以/2
- LPC_USB->USBEpIntClr = 1 << n; //清除对应中断
- while ((LPC_USB->USBDevIntSt & CDFULL_INT) == 0);//等待命令执行
- val = LPC_USB->USBCmdData; //读取端点状态
- if ((n & 1) == 0) { /* OUT Endpoint 如果是偶数则为输出*/
- if (n == 0) { /* Control OUT Endpoint 0为默认的控制端点*/
- if (val & EP_SEL_STP) { /* Setup Packet 是否为setup包*/
- if (USB_P_EP[0]) {
- USB_P_EP[0](USB_EVT_SETUP);
- continue;
- }
- }
- }
- if (USB_P_EP[m]) {
- USB_P_EP[m](USB_EVT_OUT);//其他端点的输出处理,方法类似
- }
- } else { /* IN Endpoint 奇数为输入端点*/
- //if (USB_P_EP[m]) {
- //USB_P_EP[m](USB_EVT_IN);
- if(m==0)
- USB_EndPoint0(USB_EVT_IN);
- if(m==1)
- USB_EndPoint1(USB_EVT_IN);
- if(m==2)
- USB_EndPoint2(USB_EVT_IN);
- /* ............. */
- //}
- }
- }
- }
- LPC_USB->USBDevIntClr = EP_SLOW_INT;//最后将端点中断的慢中断清除,此句为后加
- }
- }
复制代码 然后修改主函数中的GetInReport()和SetOutReport()函数
- void GetInReport (void)
- InReport =AFRxMsg[0].dataA [0];
- }
- void SetOutReport (void) {
- AFTxMsg [0].dataA [0]= OutReport ;
- CAN_SendMsg(LPC_CAN1, &AFTxMsg[0]);
- }
复制代码 关于CAN通信前面已经写过,直接把函数拿过来用就可以了,初始化,中断等等。然后就接线仿真测试,如图1所示:
几年前玩USB的时候用的一个上位机,现在拿来依然好用。如附件中。
简单的发一个数据,通过USB上位机转到MCU,再通过MCU的CAN转到CAN上位机,如图2所示:
数据接收也是一样的。
对了,查看LPC1768的主板可看到,需要焊掉R1,R2,短接R10,R25方能连接到USBDevice功能。如图3所示:
还有就是开始测试并不顺利,各种问题,尤其是由于PC前端USB口不够,使用了转接延长线,几乎没有数据传输,直接连接就好了,所以也算是前车之鉴吧。
|
-
图1
-
图2
-
图3
-
-
Usb-HID.rar
106.78 KB, 下载次数: 29, 下载积分: 威望 1
USB上位机
|