NK-RTU980 USB bulk传输
NUC980_Non-OS_BSP_v1.03.000 SDK中没有提供USB bulk传输的例程,基于USBD_HID_Mouse例程进行修改。大体思路参考这个文章,先修改设备、配置、接口、端点等描述符,再安装驱动,最后编写下位机和上位机程序进行验证。
USB Device Controller的框图如下:
特性:
- USB Specification reversion 2.0 compliant
- Supports 12 configurable endpoints in addition to Control Endpoint
- Each of the endpoints can be Isochronous, Bulk or Interrupt and either IN or OUT direction
- Three different operation modes of an in-endpoint - Auto Validation mode, Manual Validation mode, Fly mode
- Supports DMA operation
- 4096 Bytes Configurable RAM used as endpoint buffer
- Supports Endpoint Maximum Packet Size up to 1024 bytes
1.修改描述符
关于描述符的详细说明参考博客。
各种描述符之间的关系:
修改descriptors.c中DeviceDescriptor:
uint8_t gu8DeviceDescriptor[] __attribute__((aligned(4))) =
{
#endifLEN_DEVICE, /* bLength */DESC_DEVICE, /* bDescriptorType */0x00, 0x02, /* bcdUSB */ //0x10,0x01->0x00,0x200xFF, /* bDeviceClass */ //0x00->0xFF0x00, /* bDeviceSubClass */0x00, /* bDeviceProtocol */CEP_MAX_PKT_SIZE, /* bMaxPacketSize0 *//* idVendor */USBD_VID & 0x00FF,((USBD_VID & 0xFF00) >> 8),/* idProduct */USBD_PID & 0x00FF,((USBD_PID & 0xFF00) >> 8),0x00, 0x00, /* bcdDevice */0x01, /* iManufacture */0x02, /* iProduct */0x00, /* iSerialNumber - no serial */0x01 /* bNumConfigurations */
};
修改hid_mouse.h中VID和PID的值(不是必须要修改的):
#define USBD_VID 0x303A //0x0416->0x303A
#define USBD_PID 0x3002 //0x8249->0x3001
在hid_mouse.h中增加OUT节点的定义:
/* Define EP maximum packet size */
#define CEP_MAX_PKT_SIZE 64
#define CEP_OTHER_MAX_PKT_SIZE 64
#define EPA_MAX_PKT_SIZE 512 //修改,由64改为512
#define EPA_OTHER_MAX_PKT_SIZE 64
#define EPB_MAX_PKT_SIZE 512 //新增
#define EPB_OTHER_MAX_PKT_SIZE 64#define CEP_BUF_BASE 0
#define CEP_BUF_LEN CEP_MAX_PKT_SIZE#define EPA_BUF_BASE 0x200 //新增
#define EPA_BUF_LEN EPA_MAX_PKT_SIZE #define EPB_BUF_BASE 0x400 //新增
#define EPB_BUF_LEN EPB_MAX_PKT_SIZE //新增/* Define the interrupt In EP number */
#define INT_IN_EP_NUM 0x01#define INT_OUT_EP_NUM 0x01 //新增
修改descriptors.c中ConfigDescriptor :
uint8_t gu8ConfigDescriptor[] __attribute__((aligned(4))) =
{
#endifLEN_CONFIG, /* bLength */DESC_CONFIG, /* bDescriptorType *//* wTotalLength */LEN_CONFIG_AND_SUBORDINATE & 0x00FF,((LEN_CONFIG_AND_SUBORDINATE & 0xFF00) >> 8), 0x01, /* bNumInterfaces */0x01, /* bConfigurationValue */0x00, /* iConfiguration */0x80 | (USBD_SELF_POWERED << 6) | (USBD_REMOTE_WAKEUP << 5),/* bmAttributes */USBD_MAX_POWER, /* MaxPower *//* I/F descr: HID */LEN_INTERFACE, /* bLength */DESC_INTERFACE, /* bDescriptorType */0x00, /* bInterfaceNumber */0x00, /* bAlternateSetting */0x02, /* bNumEndpoints */ //0x01->0x020xFF, /* bInterfaceClass */ //0x03->0xFF0x01, /* bInterfaceSubClass */0x00, /* bInterfaceProtocol */ //HID_MOUSE->0x000x00, /* iInterface *//* HID Descriptor */ //不使用报告描述符,将此段配置注释。
// LEN_HID, /* Size of this descriptor in UINT8s. */
// DESC_HID, /* HID descriptor type. */
// 0x10, 0x01, /* HID Class Spec. release number. */
// 0x00, /* H/W target country. */
// 0x01, /* Number of HID class descriptors to follow. */
// DESC_HID_RPT, /* Descriptor type. *//* Total length of report descriptor. */
// sizeof(HID_MouseReportDescriptor) & 0x00FF,
// ((sizeof(HID_MouseReportDescriptor) & 0xFF00) >> 8),/* EP Descriptor: bulk in. */LEN_ENDPOINT, /* bLength */DESC_ENDPOINT, /* bDescriptorType */(INT_IN_EP_NUM | EP_INPUT), /* bEndpointAddress */EP_BULK, /* bmAttributes */ //EP_INT->EP_BULK/* wMaxPacketSize */EPA_MAX_PKT_SIZE & 0x00FF,((EPA_MAX_PKT_SIZE & 0xFF00) >> 8),0x00, /* bInterval */ //HID_DEFAULT_INT_IN_INTERVAL->0x00/* EP Descriptor: bulk out. */ //新增一个输出端点。LEN_ENDPOINT, /* bLength */DESC_ENDPOINT, /* bDescriptorType */(INT_OUT_EP_NUM | EP_OUTPUT), /* bEndpointAddress */EP_BULK, /* bmAttributes */ /* wMaxPacketSize */EPB_MAX_PKT_SIZE & 0x00FF,((EPB_MAX_PKT_SIZE & 0xFF00) >> 8),0x00 /* bInterval */
};
修改LEN_CONFIG_AND_SUBORDINATE的值(减去了一个REPORT,增加了一个END):
#define LEN_CONFIG_AND_SUBORDINATE (LEN_CONFIG+LEN_INTERFACE+LEN_ENDPOINT+LEN_ENDPOINT)
修改hid_mouse.c中的HID_InitForHighSpeed()、HID_InitForFullSpeed(),增加OUT端点配置:
/*** @brief USBD Endpoint Config.* @param None.* @retval None.*/
void HID_InitForHighSpeed(void)
{/* EPA ==> Interrupt IN endpoint, address 1 */USBD_SetEpBufAddr(EPA, EPA_BUF_BASE, EPA_BUF_LEN);USBD_SET_MAX_PAYLOAD(EPA, EPA_MAX_PKT_SIZE);USBD_ConfigEp(EPA, INT_IN_EP_NUM, USB_EP_CFG_TYPE_BULK, USB_EP_CFG_DIR_IN);/* EPB ==> Interrupt OUT endpoint, address 1 */USBD_SetEpBufAddr(EPB, EPB_BUF_BASE, EPB_BUF_LEN);USBD_SET_MAX_PAYLOAD(EPB, EPA_MAX_PKT_SIZE);USBD_ConfigEp(EPB, INT_OUT_EP_NUM, USB_EP_CFG_TYPE_BULK, USB_EP_CFG_DIR_OUT); USBD_ENABLE_EP_INT(EPB, USBD_EPINTEN_RXPKIEN_Msk);
}void HID_InitForFullSpeed(void)
{/* EPA ==> Interrupt IN endpoint, address 1 */USBD_SetEpBufAddr(EPA, EPA_BUF_BASE, EPA_BUF_LEN);USBD_SET_MAX_PAYLOAD(EPA, EPA_OTHER_MAX_PKT_SIZE);USBD_ConfigEp(EPA, INT_IN_EP_NUM, USB_EP_CFG_TYPE_BULK, USB_EP_CFG_DIR_IN);/* EPB ==> Interrupt OUT endpoint, address 1 */USBD_SetEpBufAddr(EPB, EPB_BUF_BASE, EPB_BUF_LEN);USBD_SET_MAX_PAYLOAD(EPB, EPB_OTHER_MAX_PKT_SIZE);USBD_ConfigEp(EPB, INT_OUT_EP_NUM, USB_EP_CFG_TYPE_BULK, USB_EP_CFG_DIR_IN); USBD_ENABLE_EP_INT(EPB, USBD_EPINTEN_RXPKIEN_Msk);
}
修改UsbString:
uint8_t gu8ProductStringDesc[] __attribute__((aligned(4))) =
{
#endif34,DESC_STRING,'B', 0, 'U', 0, 'L', 0, 'K', 0,' ', 0, 'T', 0, 'r', 0, 'a', 0, 'n', 0, 's', 0, 'a', 0, 'c', 0, 't', 0, 'i', 0, 'o', 0, 'n', 0
};
编译程序,重新烧录。电脑->设备管理器>其它设备 下多了一个名称为BULK Transaction的设备:
2.生成USB 驱动
运行inf-wizard.exe应用,点击 Next:
选择Vendor ID为0x303A、Product ID为0x3002的设备,点击Next:
Manufacturer Name、Device Name可修改为其它类容,点击Next:
选择一个路径存放驱动文件。
点击Done完成并退出。
3.安装驱动
右键 ->更新驱动程序->浏览我的电脑以查找驱动程序(R),选择刚才存放驱动的文件夹:
点击 下一页。
一般会遇到以上问题,这是因为驱动没有包含数字签名,解决办法。
驱动安装成功之后,设备管理器展示如下:
4.使用工具查看设备描述符
运行testlibusb-win.exe,设备描述符如下:
5.编写NUC980 bulk读写函数及测试程序
在hid_mouse.c中增加bulk读写函数:
/*** @brief USBD Endpoint Write.* @param None.* @retval None.*/
void BulkWriteData( uint8_t *Datas, uint16_t Len )
{uint16_t i;for ( i=0; i<Len; i++){USBD->EP[EPA].ep.EPDAT_BYTE = Datas[i];}USBD->EP[EPA].EPRSPCTL = USB_EP_RSPCTL_SHORTTXEN;USBD_ENABLE_EP_INT(EPA, USBD_EPINTEN_INTKIEN_Msk);
}
/*** @brief USBD Endpoint Read.* @param None.* @retval None.*/
uint16_t BulkReadData( uint8_t *Datas, uint16_t Len )
{uint16_t i;uint16_t DataCnt = USBD->EP[EPB].EPDATCNT;if( DataCnt > 0 ){for( i = 0; i < DataCnt; i++ ){Datas[i] = USBD->EP[EPB].ep.EPDAT_BYTE;}}return DataCnt;
}
main.c中增加接收和发送数据的逻辑,main()函数如下:
int32_t main (void)
{uint8_t i, Cnt = 0;uint8_t DataBuf[EPB_MAX_PKT_SIZE];uint16_t RxLen;sysDisableCache();sysFlushCache(I_D_CACHE);sysEnableCache(CACHE_WRITE_BACK);UART_Init();printf("\n");printf("=======================\n");printf(" USB HID Mouse \n");printf("=======================\n");sysInstallISR(IRQ_LEVEL_1, IRQ_UDC, (PVOID)USBD_IRQHandler);/* enable CPSR I bit */sysSetLocalInterrupt(ENABLE_IRQ);sysEnableInterrupt(IRQ_UDC);USBD_Open(&gsInfo, HID_ClassRequest, NULL);/* Endpoint configuration */HID_Init();/* Start transaction */while(1){if (USBD_IS_ATTACHED()){USBD_Start();break;}}while(1){RxLen = BulkReadData(DataBuf, EPB_MAX_PKT_SIZE );if( RxLen > 0 ){BulkWriteData( DataBuf, EPA_MAX_PKT_SIZE );}}
}
编译之后烧写到NUC980。
6.编写windows应用程序测试数据通信
基于libusb.lib编写一个测试应用,进行简单的数据的发送和接收。代码如下:
#include "lusb0_usb.h"
#include <stdio.h>
#include "stdint.h"
#include <iostream>
#include <sys/timeb.h>
#include "windows.h"using namespace std;// Enables this example to work with a device running the
// libusb-win32 PIC Benchmark Firmware.
//#define BENCHMARK_DEVICE//
// TEST SETUP (User configurable)// Issues a Set configuration request
#define TEST_SET_CONFIGURATION// Issues a claim interface request
#define TEST_CLAIM_INTERFACE// Use the libusb-win32 async transfer functions. see
// transfer_bulk_async() below.
#define TEST_ASYNC// Attempts one bulk read.
#define TEST_BULK_READ// Attempts one bulk write.#define TEST_BULK_WRITE// Device vendor and product id.
//#define MY_VID 0x05AC
//#define MY_PID 0x12A0#define MY_VID 0x303A
#define MY_PID 0x3002// Device configuration and interface id.
#define MY_CONFIG 1 //bConfigurationValue --lwz
#define MY_INTF 0 //bInterfaceNumber --lwz// Device endpoint(s)
#define EP_IN 0x81 //0x81
#define EP_OUT 0x01
// Device of bytes to transfer.
#define RX_BUF_SIZE 512
#define TX_BUF_SIZE 512#define TEST_BULK_SPEEDusb_dev_handle *dev = NULL; /* the device handle *///
usb_dev_handle *open_dev(void);
uint16_t usb_dev_read_sync( uint8_t *Buf, uint16_t bufsz );
bool usb_dev_write_async( uint8_t *Datas, uint16_t DataLen, int timeout );
int usb_dev_read_async( uint8_t *Buf, uint16_t bufsz, int timeout );static int transfer_bulk_async(usb_dev_handle *dev,int ep,char *bytes,int size,int timeout);usb_dev_handle *open_dev(void)
{struct usb_bus *bus;struct usb_device *dev;for (bus = usb_get_busses(); bus; bus = bus->next){for (dev = bus->devices; dev; dev = dev->next){if (dev->descriptor.idVendor == MY_VID&& dev->descriptor.idProduct == MY_PID){return usb_open(dev);}}}return NULL;
}//
// usb_dev_init.
//
void usb_dev_init( void )
{usb_init(); /* initialize the library */
}
//
// usb_dev_open.
//
bool usb_dev_open( void )
{usb_find_busses(); /* find all busses */usb_find_devices(); /* find all connected devices */if (!(dev = open_dev())){printf("error opening device: \n%s\n", usb_strerror());return false;}if (usb_set_configuration(dev, MY_CONFIG) < 0) //MY_CONFIG是配置描述符中的bConfigurationValue{printf("error setting config #%d: %s\n", MY_CONFIG, usb_strerror());usb_close(dev);return false;}if (usb_claim_interface(dev, MY_INTF) < 0) //注册与操作系统通信的接口 --lwz{printf("error claiming interface #%d:\n%s\n", MY_INTF, usb_strerror());usb_close(dev);return false;}return true;
}
//
// usb_dev_close.
//
void usb_dev_close( void )
{if (dev){usb_release_interface(dev, MY_INTF); //注销被usb_claim_interface函数调用后的接口,释放资源 --lwzusb_close(dev);}
}bool usb_dev_isopen( void )
{if( dev != NULL ){return true;}return false;
}void usb_dev_reset_epin( void )
{usb_clear_halt( dev, EP_IN );
}void usb_dev_reset_epout( void )
{usb_clear_halt( dev, EP_OUT );
}int main(char argc,char **argv)
{usb_dev_handle *dev = NULL; /* the device handle */char tmp[RX_BUF_SIZE];int ret;void* async_read_context = NULL;void* async_write_context = NULL;usb_init(); /* initialize the library */usb_find_busses(); /* find all busses */usb_find_devices(); /* find all connected devices */if (!(dev = open_dev())){printf("error opening device: \n%s\n", usb_strerror());return 0;}else{printf("success: device %04X:%04X opened\n", MY_VID, MY_PID);}#ifdef TEST_SET_CONFIGURATIONif (usb_set_configuration(dev, MY_CONFIG) < 0) //MY_CONFIG是配置描述符中的bConfigurationValue{printf("error setting config #%d: %s\n", MY_CONFIG, usb_strerror());usb_close(dev);return 0;}else{printf("success: set configuration #%d\n", MY_CONFIG);}
#endif#ifdef TEST_CLAIM_INTERFACEif (usb_claim_interface(dev, 0) < 0) //注册与操作系统通信的接口 --lwz{printf("error claiming interface #%d:\n%s\n", MY_INTF, usb_strerror());usb_close(dev);return 0;}else{printf("success: claim_interface #%d\n", MY_INTF);}
#endif#ifdef TEST_BULK_SPEEDchar tmpOut[TX_BUF_SIZE];char tmpIn[RX_BUF_SIZE];uint8_t Count = 0;uint64_t ComCnt = 0;uint64_t errCnt = 0;struct timeb rawtime;ftime(&rawtime);uint64_t StartTime = rawtime.time;for( ;; ){for( uint16_t i = 0; i < sizeof(tmpOut); i++ ){tmpOut[i] = Count++;}ComCnt ++;ret = transfer_bulk_async(dev, EP_OUT, tmpOut, sizeof(tmpOut), 5000);if (ret < 0){
// printf("error writing:\n%s\n", usb_strerror());}else{
// printf("success: bulk write %d bytes\n", ret);}// Running an async read testret = transfer_bulk_async(dev, EP_IN, tmpIn, sizeof(tmpIn), 5000);if (ret < 0){printf("error reading:\n%s\n", usb_strerror());}else{printf("success: bulk read %d bytes\n", ret);}//if( memcmp( tmpOut, tmpIn, BUF_SIZE ) != 0 )//{// errCnt ++;//}for( int j = 0; j < TX_BUF_SIZE; j++ ){if( tmpOut[j] != tmpIn[j] ){errCnt ++;break;}}if( (ComCnt % 2000) == 0 ){printf("ComCnt:%d ",ComCnt );printf("errCnt:%d \n",errCnt );struct timeb rawtime1;ftime(&rawtime1);uint64_t endTime = rawtime1.time;printf("transfer speed:%0.2f bps\n", ((float)(ComCnt * TX_BUF_SIZE * 2 * 8) / (endTime - StartTime)) );}// Sleep(3);}
#endif#ifdef TEST_BULK_WRITE#ifdef BENCHMARK_DEVICE ret = usb_control_msg(dev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,14, /* set/get test */2, /* test type */MY_INTF, /* interface id */tmp, 1, 1000); //从默认的管道发送和接受控制数据--lwz#endif#ifdef TEST_ASYNC// Running an async write testfor( int i = 0; i < sizeof(tmp); i++ ){tmp[i] = i;}ret = transfer_bulk_async(dev, EP_OUT, tmp, sizeof(tmp), 5000);#else// Running a sync write testret = usb_bulk_write(dev, EP_OUT, tmp, sizeof(tmp), 5000);#endifif (ret < 0){printf("error writing:\n%s\n", usb_strerror());}else{printf("success: bulk write %d bytes\n", ret);}
#endifmemset(tmp, 0 , TX_BUF_SIZE );
#ifdef TEST_BULK_READ#ifdef BENCHMARK_DEVICEret = usb_control_msg(dev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,14, /* set/get test */1, /* test type */MY_INTF, /* interface id */tmp, 1, 1000);#endif#ifdef TEST_ASYNC //有声明--lwz// Running an async read testret = transfer_bulk_async(dev, EP_IN, tmp, sizeof(tmp), 5000);#else// Running a sync read testret = usb_bulk_read(dev, EP_IN, tmp, sizeof(tmp), 5000);#endifif (ret < 0){printf("error reading:\n%s\n", usb_strerror());}else{printf("success: bulk read %d bytes\n", ret);for(int i = 0; i < ret; i++ ){printf( "%02X ", tmp[i]);}printf("\n");}
#endif#ifdef TEST_BULK_READ#ifdef BENCHMARK_DEVICEret = usb_control_msg(dev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,14, /* set/get test */1, /* test type */MY_INTF, /* interface id */tmp, 1, 1000);#endif#ifdef TEST_ASYNC// Running an async read testret = transfer_bulk_async(dev, EP_IN, tmp, sizeof(tmp), 5000);#else// Running a sync read testret = usb_bulk_read(dev, EP_IN, tmp, sizeof(tmp), 5000);#endifif (ret < 0){printf("error reading:\n%s\n", usb_strerror());}else{printf("success: bulk read %d bytes\n", ret);}
#endif#ifdef TEST_CLAIM_INTERFACEusb_release_interface(dev, 0); //注销被usb_claim_interface函数调用后的接口,释放资源 --lwz
#endifif (dev){usb_close(dev);}printf("Done.\n");return 0; }/*
* Read/Write using async transfer functions.
*
* NOTE: This function waits for the transfer to complete essentially making
* it a sync transfer function so it only serves as an example of how one might
* implement async transfers into thier own code.
*/
static int transfer_bulk_async(usb_dev_handle *dev,int ep,char *bytes,int size,int timeout)
{// Each async transfer requires it's own context. A transfer// context can be re-used. When no longer needed they must be// freed with usb_free_async().//void* async_context = NULL;int ret;// Setup the async transfer. This only needs to be done once// for multiple submit/reaps. (more below)//ret = usb_bulk_setup_async(dev, &async_context, ep);if (ret < 0){printf("error usb_bulk_setup_async:\n%s\n", usb_strerror());goto Done;}// Submit this transfer. This function returns immediately and the// transfer is on it's way to the device.//ret = usb_submit_async(async_context, bytes, size);if (ret < 0){printf("error usb_submit_async:\n%s\n", usb_strerror());usb_free_async(&async_context);goto Done;}// Wait for the transfer to complete. If it doesn't complete in the// specified time it is cancelled. see also usb_reap_async_nocancel().//ret = usb_reap_async(async_context, timeout);// Free the context.usb_free_async(&async_context);Done:return ret;
}//
// usb_dev_read_async.
//
int usb_dev_read_async( uint8_t *Buf, uint16_t bufsz, int timeout )
{if( dev == NULL ){return 0;}int ret;char tmp[RX_BUF_SIZE];ret = transfer_bulk_async(dev, EP_IN, tmp, RX_BUF_SIZE, timeout );if( ret > 0 ){if( bufsz >= ret ){memcpy(Buf, tmp, ret );}}return ret;
}
//
// usb_dev_write_async.
//
bool usb_dev_write_async( uint8_t *Datas, uint16_t DataLen, int timeout )
{if( dev == NULL ){return false;}int ret;ret = transfer_bulk_async(dev, EP_OUT, (char *)Datas, DataLen , timeout);if( ret < 0 ){return false;}return true;
}
//
// usb_dev_read_sync.
//
uint16_t usb_dev_read_sync( uint8_t *Buf, uint16_t bufsz )
{if( dev == NULL ){return 0;}int ret;char tmp[RX_BUF_SIZE];ret = usb_bulk_read(dev, EP_IN, tmp, RX_BUF_SIZE,5000);if( ret > 0 ){if( bufsz >= ret ){memcpy(Buf, tmp, ret );}}return ret;
}
上位机运行日志如下:
计算出的速率大约2.7MB/s,比全速高一点,这个速度还有待提升。
NUC980技术交流QQ群:912184327
NK-RTU980 USB bulk传输相关推荐
- STM32F105 实现USB BULK传输
基于STM32F105 实现USB-BULK传输 由于项目需要,需要USB来传输,之前试的HID模式是已经调通,HID基于中断传输,一毫秒侦测一次,每次的传输量为64字节,一般传输量小的可以采用这种模 ...
- 自定义USB BULK设计(一)——固件程序,LPC2378
前段时间买了块D12+51的开发板来玩,现在公司要求用ARM来做一个USB项目.原来用D12也就做了个LED流水灯,还是HID设备的,现在不能满足要求,你总不能显示公司的设备时,还搞个"人体 ...
- usb音频传输的优劣
这是在网络上找到比较好关于usb音频传输的文章,本人只是整理!!原作者:我代表广大人民 首先,为什么要去找和整理这篇文章!?起源是在一个qq群里面想和一位q友交流.. 不想特别针对人,只想对事,所以, ...
- 基于WinUSB的异步方式bulk传输的稳定性问题
某项目中,设备与PC之间通过USB Bulk模式进行数据传输,PC端的APP跑在Win10上,跟设备通信这部分原本是基于libusb开发的,运行稳定.后来考虑到PC端APP只有for Windows一 ...
- Android使用usb线传输大文件笔记
使用usb线传输大文件 参考资料: 使用USB数据线连接PC端和Android端进行数据的交互 安卓设备通过USB接口实现与pc端的简单数据通信 Socket TCP/IP协议数据传输过程中的粘包和分 ...
- linux usb 批量传输文件,一种Linux系统下提升usb批量传输速度的方法及系统与流程...
本发明涉及通信传输技术领域,具体地说是一种linux系统下提升usb批量传输速度的方法及系统. 背景技术: linux系统访问usb设备有两种方式:编写内核驱动模块ko和在用户空间编写程序,通过内核提 ...
- MS2109 HDMI转USB 高清视频传输方案
MS2109 HDMI转USB 高清视频传输方案 MS2109是一款高清视频传采集晶片,内部集成USB2.0控制器和数据收发模块,HDMIRX模块和音视频处理模块.MS2109可以将HDMI接口输出 ...
- 【安富莱专题教程第8期】基于emWin模拟器的USB BULK上位机开发,仅需C即可,简单易实现...
说明: 1.如果你会emWin话的,就可以轻松制作上位机.做些通信和控制类上位机,比使用C#之类的方便程度一点不差,而且你仅会C语言就可以. 2.并且成功将emWin人性化,可以做些Windows系统 ...
- 关于USB bulk设备中的CBW和CSW
网上关于USB的讲解很多,讲的好的大家可以参见<linux那些事儿之我是USB>,非常具有趣味性.此处恕我才疏学浅只能记录一些皮毛.因为在做烧写工具,所以涉及到这部分的知识.在之前的经验教 ...
- Android usb 控制传输,【android之USB通信】android之USB数据传输-Go语言中文社区
因为老板认为wifi连接的方式传输数据太慢,想通过USB传输来实现与硬件的连接,所以通过android客户端作为主设备,终端硬件作为从设备.其中收到数据的处理和 下发设置帧的生成与wifi连接的方式都 ...
最新文章
- 小米Max怎么刷入开发版获得root超级权限
- ajax查询数据返回结果不变
- 二叉树的二叉链表存储结构构建以及先序遍历
- 16.1116 NOIP 考前模拟(信心题)
- WAMPSerrver集成环境的下载安装
- 小知识—PRINCE2的七大原则之剪裁
- Numpy 数组操作
- js 自动分配金额_(2.4w字,建议收藏)??原生JS灵魂之问(下), 冲刺??进阶最后一公里(附个人成长经验分享)
- 为什么鲍尔默时代的微软会一败再败?
- java jdbc 占位符_java-jdbc
- Unity UGUI——Text组件(Character)
- JAVA-Servlet操纵方法
- ID3、C4.5、CART决策树算法解析(关键内容讲解)
- 步进电机正反转实验_电机正反转电路图讲解
- The current branch master has no upstream branch.的解决
- 引用生产任务单下推进行生产领料,金蝶KIS旗舰版盘点机PDA进销存,车间生产领料防止出错,生产领料流程,根据BOM物料清单自动计算领料数量
- 如何培养孩子的阅读兴趣
- python中argument什么意思_Python中parameters与argument区别
- AI笔记: 数学基础之二项分布与二项式定理
- squeeze 、unsequeeze