Objective c 与USB设备的FTDI通信-目标C
我正在尝试与Enttec USB DMX Pro进行通信。主要接收DMXObjective c 与USB设备的FTDI通信-目标C,objective-c,ftdi,dmx512,Objective C,Ftdi,Dmx512,我正在尝试与Enttec USB DMX Pro进行通信。主要接收DMX 他们发布了一个Visual C++版本,但是我有点犹豫要怎么做才能转换成Obj-C。Enttec写道,“使用Mac的FTDI库与PRO对话,并参考D2XX编程指南打开并与设备对话。”有Objective-C的示例应用程序吗?有没有一种简单的方法可以与Enttec DMX USB Pro进行通信?我已经在Mac上对FTDI芯片做了大量的工作,因此我可以在这里提供一些见解。我使用了USB串行转换器的单通道和双通道变体,它们的行
他们发布了一个Visual C++版本,但是我有点犹豫要怎么做才能转换成Obj-C。Enttec写道,“使用Mac的FTDI库与PRO对话,并参考D2XX编程指南打开并与设备对话。”有Objective-C的示例应用程序吗?有没有一种简单的方法可以与Enttec DMX USB Pro进行通信?我已经在Mac上对FTDI芯片做了大量的工作,因此我可以在这里提供一些见解。我使用了USB串行转换器的单通道和双通道变体,它们的行为方式都相同 FTDI既有虚拟COM端口驱动程序(用于在系统上创建串行COM端口,表示连接到其芯片的串行连接),也有D2XX直接通信库。你会想和后者合作,后者 Mac的D2XX库有一个独立的.dylib(最新的是libftd2x.1.2.2.dylib)或一个最近开始发布的新静态库。该包中还包括您需要的相应头文件(ftd2x.h和WinTypes.h) 在Xcode项目中,添加.dylib作为要链接的框架,并将ftd2x.h、WinTypes.h和ftd2x.cfg文件添加到项目中。在复制绑定框架构建阶段,确保libftd2x.1.2.2.dylib和ftd2x.cfg存在于该阶段。您可能还需要调整此库所需的相对路径,以便它在您的应用程序包中运行,因此您可能需要在命令行对其运行以下命令:
install_name_tool -id @executable_path/../Frameworks/libftd2xx.1.2.2.dylib libftd2xx.1.2.2.dylib
正确配置项目后,您将需要导入FTDI标题:
#import "ftd2xx.h"
并开始连接到串行设备。在你的问题中链接到的示例有一个可下载的C++示例,展示了它们如何与设备通信。您可以使用那里使用的几乎所有C代码,并将其放在Objective-C应用程序中。它们看起来只是在使用标准的FTDI d2x命令,在可下载的
这是我从一个应用程序中提取的一些代码,用于连接到以下设备之一:
DWORD numDevs = 0;
// Grab the number of attached devices
ftdiPortStatus = FT_ListDevices(&numDevs, NULL, FT_LIST_NUMBER_ONLY);
if (ftdiPortStatus != FT_OK)
{
NSLog(@"Electronics error: Unable to list devices");
return;
}
// Find the device number of the electronics
for (int currentDevice = 0; currentDevice < numDevs; currentDevice++)
{
char Buffer[64];
ftdiPortStatus = FT_ListDevices((PVOID)currentDevice,Buffer,FT_LIST_BY_INDEX|FT_OPEN_BY_DESCRIPTION);
NSString *portDescription = [NSString stringWithCString:Buffer encoding:NSASCIIStringEncoding];
if ( ([portDescription isEqualToString:@"FT232R USB UART"]) && (usbRelayPointer != NULL))
{
// Open the communication with the USB device
ftdiPortStatus = FT_OpenEx("FT232R USB UART",FT_OPEN_BY_DESCRIPTION,usbRelayPointer);
if (ftdiPortStatus != FT_OK)
{
NSLog(@"Electronics error: Can't open USB relay device: %d", (int)ftdiPortStatus);
return;
}
//Turn off bit bang mode
ftdiPortStatus = FT_SetBitMode(*usbRelayPointer, 0x00,0);
if (ftdiPortStatus != FT_OK)
{
NSLog(@"Electronics error: Can't set bit bang mode");
return;
}
// Reset the device
ftdiPortStatus = FT_ResetDevice(*usbRelayPointer);
// Purge transmit and receive buffers
ftdiPortStatus = FT_Purge(*usbRelayPointer, FT_PURGE_RX | FT_PURGE_TX);
// Set the baud rate
ftdiPortStatus = FT_SetBaudRate(*usbRelayPointer, 9600);
// 1 s timeouts on read / write
ftdiPortStatus = FT_SetTimeouts(*usbRelayPointer, 1000, 1000);
// Set to communicate at 8N1
ftdiPortStatus = FT_SetDataCharacteristics(*usbRelayPointer, FT_BITS_8, FT_STOP_BITS_1, FT_PARITY_NONE); // 8N1
// Disable hardware / software flow control
ftdiPortStatus = FT_SetFlowControl(*usbRelayPointer, FT_FLOW_NONE, 0, 0);
// Set the latency of the receive buffer way down (2 ms) to facilitate speedy transmission
ftdiPortStatus = FT_SetLatencyTimer(*usbRelayPointer,2);
if (ftdiPortStatus != FT_OK)
{
NSLog(@"Electronics error: Can't set latency timer");
return;
}
}
}
写入串行设备非常简单:
__block DWORD bytesWrittenOrRead;
unsigned char * dataBuffer = (unsigned char *)[command bytes];
//[command getBytes:dataBuffer];
runOnMainQueueWithoutDeadlocking(^{
ftdiPortStatus = FT_Write(electronicsCommPort, dataBuffer, (DWORD)[command length], &bytesWrittenOrRead);
});
if((bytesWrittenOrRead < [command length]) || (ftdiPortStatus != FT_OK))
{
NSLog(@"Bytes written: %d, should be:%d, error: %d", bytesWrittenOrRead, (unsigned int)[command length], ftdiPortStatus);
return NO;
}
在上面的末尾,response
将是一个NSData实例,其中包含您从端口读取的字节
此外,我建议您应该始终从主线程访问FTDI设备。尽管他们说他们支持多线程访问,但我发现任何类型的非主线程访问(甚至保证来自单个线程的独占访问)都会导致Mac上的间歇性崩溃
除了我上面描述的情况之外,您还可以参考D2XX编程指南,了解FTDI在其C库中提供的其他函数。同样,您只需从设备制造商提供给您的示例中选择适当的代码即可。我遇到了类似的问题(尝试使用Objective-C写入EntTec Open DMX),但没有成功。在遵循@Brad的精彩回答后,我意识到每次发送DMX数据包时都需要切换中断状态 下面是我在一些测试代码中的循环示例,这些代码在帧之间以20毫秒的延迟发送数据包
while (1) {
FT_SetBreakOn(usbRelayPointer);
FT_SetBreakOff(usbRelayPointer);
ftdiPortStatus = FT_Write(usbRelayPointer, startCode, 1, &bytesWrittenOrRead);
ftdiPortStatus = FT_Write(usbRelayPointer, dataBuffer, (DWORD)[command length], &bytesWrittenOrRead);
usleep(20000);
}
希望这对其他人有帮助你所说的“驱动”,我不知道任何“目标C”特定的示例应用程序,但是如果你可以使用任何C或C++的Mac OS示例代码,那么它也应该在一个目标C应用程序中工作。是的,我试图在C或C++中找到一个MACOS示例代码……不确定它是否有用,但可能值得看看或者是渣块!非常感谢你,布拉德。这是非常有用的+1当然!我真的很感激你的帮助response@Brad:非常好的信息。我正在用J2DXX做同样的尝试,我能够与设备通信并检索设备信息等等。但我只是感到困惑,因为我并没有找到一种方法来说明我应该在mifare卡的哪个块中写入数据等等。。。此api不会读取或写入mifare卡,对吗?只针对读卡器device@inba-我不知道MIFARE是如何工作的,但以上只是通过FTDI USB串行转换器发送和接收数据的方式。您需要自己发送MIFARE需要的任何命令。非常好地解释和记录(+1)。使用C++,但是有了这些信息,我可以很容易地使用FTTD2XX库。谢谢好的,详细的描述!我很好奇这项技术在最新版本的OSX中是否仍然适用。这个问题的答案是:表明苹果可能在10.9中打破了某些东西。上述技术目前不适用于我。。。我还有一个问题要问:
NSData *response = nil;
DWORD numberOfCharactersToRead = size;
__block DWORD bytesWrittenOrRead;
__block unsigned char *serialCommunicationBuffer = malloc(numberOfCharactersToRead);
runOnMainQueueWithoutDeadlocking(^{
ftdiPortStatus = FT_Read(electronicsCommPort, serialCommunicationBuffer, (DWORD)numberOfCharactersToRead, &bytesWrittenOrRead);
});
if ((bytesWrittenOrRead < numberOfCharactersToRead) || (ftdiPortStatus != FT_OK))
{
free(serialCommunicationBuffer);
return nil;
}
response = [[NSData alloc] initWithBytes:serialCommunicationBuffer length:numberOfCharactersToRead];
free(serialCommunicationBuffer);
while (1) {
FT_SetBreakOn(usbRelayPointer);
FT_SetBreakOff(usbRelayPointer);
ftdiPortStatus = FT_Write(usbRelayPointer, startCode, 1, &bytesWrittenOrRead);
ftdiPortStatus = FT_Write(usbRelayPointer, dataBuffer, (DWORD)[command length], &bytesWrittenOrRead);
usleep(20000);
}