我遇到了一个与 winusbReadpipe 函数相关的问题。我正在使用 Pic18f4550 Mc(XC8 编译器)和 VC ++ 2013(MFC)。
我只是想从设备/主机读取和写入。Microchip 提供的示例程序运行良好,我能够从主机向设备中的所有端点 01、02、03 发送数据。
但是我无法阅读从设备到主机的任何反馈。我正在两个单独的线程中读取和写入数据。我的想法是只阅读在我的演示板上按下的按钮的反馈,或者至少是回显命令。看来,它只是在读取功能中输入一次,然后就停止了。不确定。
我尝试通过互联网搜索并实施了不同论坛中给出的所有建议,但迄今为止没有成功。最糟糕的是我试图在 Microchip 论坛上发布我的查询,但无法让自己注册,它总是说管理员会批准我的 ID,但还没有发生任何事情。
下面是我的设备端和主机端代码。请告诉我是否还有其他需要。
我期待您对此的支持。
谢谢,
拉胡尔
VC++ 代码:
阅读线程代码
UINT CUsbHighSpeedDlg::ReadThread()
{
while (true)
{
if (AttachedState == TRUE) //Do not try to use the read/write handles unless the USB device is attached and ready
{
m_DebugVal7.SetWindowTextW(TEXT("INSIDE read //pipe"));
WinUsb_ReadPipe(MyWinUSBInterfaceHandle, 0x81, &INBuffer[0], 64, &BytesRead, NULL);
if (INBuffer[0] = 0x81)
{
m_DebugVal5.SetWindowTextW(TEXT("button true"));
}
if ((INBuffer[0] = 0x81) && (INBuffer[1] = 0x00))
{
PushbuttonPressed = TRUE;
m_DebugVal5.SetWindowTextW(TEXT("button true"));
}
if ((INBuffer[0] = 0x81) && (INBuffer[1] = 0x01))
{
PushbuttonPressed = FALSE;
m_DebugVal6.SetWindowTextW(TEXT("button False"));
}
}
} return 0;
}
在 VC++ 中声明的用于使用读/写管道函数的头文件
//WinUsb_Initialize() needs to be called before the application can begin sending/receiving data with the USB device.
[DllImport("Winusb.dll", CharSet = CharSet::Seeifdef, EntryPoint = "WinUsb_Initialize", CallingConvention = CallingConvention::Winapi)]
BOOL __stdcall WinUsb_Initialize(
_In_ HANDLE DeviceHandle,
_Out_ PWINUSB_INTERFACE_HANDLE InterfaceHandle
);
//WinUsb_WritePipe() is the basic function used to write data to the USB device (sends data to OUT endpoints on the device)
[DllImport("winusb.dll", CharSet = CharSet::Seeifdef, EntryPoint = "WinUsb_WritePipe", CallingConvention = CallingConvention::Winapi)]
BOOL __stdcall WinUsb_WritePipe(
_In_ WINUSB_INTERFACE_HANDLE InterfaceHandle,
_In_ UCHAR PipeID,
_In_ PUCHAR Buffer,
_In_ ULONG BufferLength,
_Out_opt_ PULONG LengthTransferred,
_In_opt_ LPOVERLAPPED Overlapped
);
//WinUsb_ReadPipe() is the basic function used to read data from the USB device (polls for and obtains data from
//IN endpoints on the device)
[DllImport("winusb.dll", CharSet = CharSet::Seeifdef, EntryPoint = "WinUsb_ReadPipe", CallingConvention = CallingConvention::Winapi)]
BOOL __stdcall WinUsb_ReadPipe(
_In_ WINUSB_INTERFACE_HANDLE InterfaceHandle,
_In_ UCHAR PipeID,
_Out_ PUCHAR Buffer,
_In_ ULONG BufferLength,
_Out_opt_ PULONG LengthTransferred,
_In_opt_ LPOVERLAPPED Overlapped
);
//WinUsb_SetPipePolicy() can be used to configure the behavior of the WinUSB use of the specified endpoint
[DllImport("winusb.dll", CharSet = CharSet::Seeifdef, EntryPoint = "WinUsb_SetPipePolicy", CallingConvention = CallingConvention::Winapi)]
BOOL __stdcall WinUsb_SetPipePolicy(
_In_ WINUSB_INTERFACE_HANDLE InterfaceHandle,
_In_ UCHAR PipeID,
_In_ ULONG PolicyType,
_In_ ULONG ValueLength,
_In_ PVOID Value
);
//WinUsb_Free() is used to free up resources/close the handle that was returned when calling WinUsb_Initialize()
[DllImport("winusb.dll", CharSet = CharSet::Seeifdef, EntryPoint = "WinUsb_Free", CallingConvention = CallingConvention::Winapi)]
BOOL __stdcall WinUsb_Free(
_In_ WINUSB_INTERFACE_HANDLE InterfaceHandle
);
//WinUsb_FlushPipe() is used to discard any data that may be "cached in a pipe".
[DllImport("winusb.dll", CharSet = CharSet::Seeifdef, EntryPoint = "WinUsb_Free", CallingConvention = CallingConvention::Winapi)]
BOOL __stdcall WinUsb_FlushPipe(
_In_ WINUSB_INTERFACE_HANDLE InterfaceHandle,
_In_ UCHAR PipeID
);
微控制器代码
变量声明部分
#elif defined(__XC8) && defined(FIXED_ADDRESS_MEMORY)
USB_VOLATILE uint8_t EP1OUTEvenBuffer[64] @ EP1_EVEN_DATA_BUFFER_ADDRESS;
USB_VOLATILE uint8_t EP1OUTOddBuffer[64] @ EP1_ODD_DATA_BUFFER_ADDRESS;
USB_VOLATILE uint8_t EP2OUTEvenBuffer[64] @ EP2_EVEN_DATA_BUFFER_ADDRESS;
USB_VOLATILE uint8_t EP2OUTOddBuffer[64] @ EP2_ODD_DATA_BUFFER_ADDRESS;
USB_VOLATILE uint8_t EP3OUTEvenBuffer[64] @ EP3_EVEN_DATA_BUFFER_ADDRESS;
USB_VOLATILE uint8_t EP3OUTOddBuffer[64] @ EP3_ODD_DATA_BUFFER_ADDRESS;
USB_VOLATILE uint8_t EP1INEvenBuffer[64] @ EP1IN_EVEN_DATA_BUFFER_ADDRESS;
USB_VOLATILE uint8_t EP1INOddBuffer[64] @ EP1IN_ODD_DATA_BUFFER_ADDRESS;
#else
#define FIXED_ADDRESS_MEMORY
#define EP1_EVEN_DATA_BUFFER_ADDRESS 0x480
#define EP1_ODD_DATA_BUFFER_ADDRESS 0x4C0
#define EP2_EVEN_DATA_BUFFER_ADDRESS 0x500
#define EP2_ODD_DATA_BUFFER_ADDRESS 0x540
#define EP3_EVEN_DATA_BUFFER_ADDRESS 0x580
#define EP3_ODD_DATA_BUFFER_ADDRESS 0x5C0
#define EP1IN_EVEN_DATA_BUFFER_ADDRESS 0x600 // NEW MEMORY ADDRESS DECLARED
#define EP1IN_ODD_DATA_BUFFER_ADDRESS 0x640// NEW MEMORY ADDRESS DECLARED
#endif //FIXED_MEMORY_ADDRESS
描述符
/* Device Descriptor */
const USB_DEVICE_DESCRIPTOR device_dsc=
{
0x12, // Size of this descriptor in bytes
USB_DESCRIPTOR_DEVICE, // DEVICE descriptor type
0x0200, // USB Spec Release Number in BCD format
0x00, // Class Code
0x00, // Subclass code
0x00, // Protocol code
USB_EP0_BUFF_SIZE, // Max packet size for EP0, see usb_config.h
0x04D8, // Vendor ID: 0x04D8 is Microchip's Vendor ID
0x0052, // Product ID: 0x0052
0x0000, // Device release number in BCD format
0x01, // Manufacturer string index
0x02, // Product string index
0x00, // Device serial number string index
0x01 // Number of possible configurations
};
/* Configuration 1 Descriptor */
const uint8_t configDescriptor1[]={
/* Configuration Descriptor */
0x09,//sizeof(USB_CFG_DSC), // Size of this descriptor in bytes
USB_DESCRIPTOR_CONFIGURATION, // CONFIGURATION descriptor type
0x2E,0x00, // Total length of data for this cfg
1, // Number of interfaces in this cfg
1, // Index value of this configuration
0, // Configuration string index
_DEFAULT | _SELF, // Attributes, see usb_device.h
50, // Max power consumption (2X mA)
/* Interface Descriptor */
0x09,//sizeof(USB_INTF_DSC), // Size of this descriptor in bytes
USB_DESCRIPTOR_INTERFACE, // INTERFACE descriptor type
0, // Interface Number
0, // Alternate Setting Number
4, // Number of endpoints in this intf
0xFF, // Class code
0xFF, // Subclass code
0xFF, // Protocol code
0, // Interface string index
/* Endpoint Descriptor */
0x07, /*sizeof(USB_EP_DSC)*/
USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor
_EP01_OUT, //EndpointAddress
_BULK, //Attributes
64,0x00, //size
1, //Interval
0x07, /*sizeof(USB_EP_DSC)*/
USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor
_EP02_OUT, //EndpointAddress
_BULK, //Attributes
64,0x00, //size
1, //Interval
0x07, /*sizeof(USB_EP_DSC)*/
USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor
_EP03_OUT, //EndpointAddress
_BULK, //Attributes
64,0x00, //size
1, //Interval
0x07, /*sizeof(USB_EP_DSC)*/// New Endpoint for Sending Data To Host
USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor
_EP01_IN, //EndpointAddress// VALUE MODIFED FOR SENDING DATA
_BULK, //Attributes
64,0x00, //size
1 //Interval
};
为批量传输初始化 USB
void APP_DeviceVendorThroughputTestInitialize()
{
EP1OUTEvenHandle = NULL;
EP2OUTEvenHandle = NULL;
EP3OUTEvenHandle = NULL;
EP1INEvenHandle = NULL;
EP1OUTOddHandle = NULL;
EP2OUTOddHandle = NULL;
EP3OUTOddHandle = NULL;
EP1INOddHandle = NULL;
//Now that we are configured, enable the endpoints for use in the demo
// and start the initial transfers
USBEnableEndpoint(_EP01_OUT,USB_OUT_ENABLED|USB_IN_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
USBEnableEndpoint(2,USB_OUT_ENABLED|USB_IN_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
USBEnableEndpoint(4,USB_OUT_ENABLED|USB_IN_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
USBEnableEndpoint(_EP01_IN,USB_OUT_ENABLED|USB_IN_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
//Prepare the OUT endpoints to receive the first packets from the host.
EP1OUTEvenHandle = USBTransferOnePacket(_EP01_OUT, OUT_FROM_HOST,(uint8_t*)&EP1OUTEvenBuffer,64); //First 64-bytes of data sent to EP1 OUT will arrive in the even buffer.
EP1OUTOddHandle = USBTransferOnePacket(_EP01_OUT, OUT_FROM_HOST,(uint8_t*)&EP1OUTOddBuffer,64); //Second 64-bytes of data sent to EP1 OUT will arrive in the odd buffer.
EP1OUTEvenNeedsServicingNext = true; //Used to keep track of which buffer will contain the next sequential data packet.
EP2OUTEvenHandle = USBTransferOnePacket(2, OUT_FROM_HOST,(uint8_t*)&EP2OUTEvenBuffer,64);
EP2OUTOddHandle = USBTransferOnePacket(2, OUT_FROM_HOST,(uint8_t*)&EP2OUTOddBuffer,64);
EP2OUTEvenNeedsServicingNext = true; //Used to keep track of which buffer will contain the next sequential data packet.
EP3OUTEvenHandle = USBTransferOnePacket(4, OUT_FROM_HOST,(uint8_t*)&EP3OUTEvenBuffer,64);
EP3OUTOddHandle = USBTransferOnePacket(4, OUT_FROM_HOST,(uint8_t*)&EP3OUTOddBuffer,64);
EP3OUTEvenNeedsServicingNext = true; //Used to keep track of which buffer will contain the next sequential data packet.
EP1INEvenHandle = USBTransferOnePacket(_EP01_IN, IN_TO_HOST,(uint8_t*)&EP1INEvenBuffer,64); //First 64-bytes of data RECIVE to EP3 IN will arrive in the even buffer.
// EP1INOddHandle = USBTransferOnePacket(_EP01_IN, IN_TO_HOST,(uint8_t*)&EP1INOddBuffer,64); //Second 64-bytes of data RECIVE to EP3 IN will arrive in the odd buffer.
// EP1INEvenNeedsServicingNext = true;
}
数据传输代码,注意:_EP01_Out =0x01 & _EP01_IN =0x81
if(EP1OUTEvenNeedsServicingNext == true) //Check which buffer (even/odd) the next set of data is going to arrive in
{
if(!USBHandleBusy(EP1OUTEvenHandle)) //Check if the endpoint has received any data from the host.
{
PORTDbits.RD1=1;
PORTDbits.RD2=0;
switch(EP1OUTEvenBuffer[0]) //Data arrived, check what kind of command might be in the packet of data.
{
case 0x81: //Get push button state command from PC application.
EP1INEvenBuffer[0] = 0x81;
EP1INEvenHandle = USBTransferOnePacket(_EP01_IN, IN_TO_HOST,(uint8_t*)&EP1INEvenBuffer,64);
break;
case 0x82: //Toggle LED(s) command from PC application.
LATDbits.LD3=0;
break;
case 0x80: //Toggle LED(s) command from PC application.
LATDbits.LD3=1;
break;
EP1OUTEvenHandle = USBTransferOnePacket(_EP01_OUT, OUT_FROM_HOST,(uint8_t*)&EP1OUTEvenBuffer,64);
EP1OUTEvenNeedsServicingNext = false;
}
}
else //else EP1OUTOdd needs servicing next
{
if(!USBHandleBusy(EP1OUTOddHandle)) //Check if the endpoint has received any data from the host.
{
PORTDbits.RD1=0;
PORTDbits.RD2=1;
switch(EP1OUTOddBuffer[0]) //Data arrived, check what kind of command might be in the packet of data.
{
case 0x81:
EP1INEvenBuffer[0] = 0x81;
EP1INEvenHandle = USBTransferOnePacket(_EP01_IN, IN_TO_HOST,(uint8_t*)&EP1INEvenBuffer,64);
break;
case 0x82: //Toggle LED(s) command from PC application.
LATDbits.LD3=0;
break;
case 0x80: //Toggle LED(s) command from PC application.
LATDbits.LD3=1;
break;
}
EP1OUTOddHandle = USBTransferOnePacket(_EP01_OUT, OUT_FROM_HOST,(uint8_t*)&EP1OUTOddBuffer,64);
EP1OUTEvenNeedsServicingNext = true;
}
}
代码结束