我试图与Enttec USB DMX专业沟通。 主要接收DMX。
他们发布的Visual C ++版本在这里 ,但我对如何做才能转换为对象-有点难倒。 Enttec写道,“谈谈使用FTDI库的Mac PRO,并参考D2XX编程指南打开,跟我们的设备。” 任何例如,对于Objective-C的应用程式在那里? 是否存在与Enttec DMX USB Pro的沟通一个简单的方法?
我试图与Enttec USB DMX专业沟通。 主要接收DMX。
他们发布的Visual C ++版本在这里 ,但我对如何做才能转换为对象-有点难倒。 Enttec写道,“谈谈使用FTDI库的Mac PRO,并参考D2XX编程指南打开,跟我们的设备。” 任何例如,对于Objective-C的应用程式在那里? 是否存在与Enttec DMX USB Pro的沟通一个简单的方法?
我已经做了在Mac上FTDI芯片工作显著量,这样我就可以在这里提供一些见解。 我用自己的USB转串口转换器的单通道和双通道的变体,它们都具有相同的行为方式。
FTDI既有自己的虚拟COM端口驱动程序,它代表连接到他们的芯片串行连接在系统上创建一个串行COM端口,和他们D2XX直接通信库。 你会希望与后者,这工作可以从他们的网站不同的平台进行下载 。
适用于Mac的D2XX库进来一个独立的名为.dylib(最近一次是libftd2xx.1.2.2.dylib)或他们最近开始出货新的静态库。 包括在包会,你需要(ftd2xx.h和WinTypes.h)以及相应的头文件。
在Xcode项目,添加名为.dylib为框架,链接,且该ftd2xx.h,WinTypes.h和ftd2xx.cfg文件添加到您的项目。 在您的副本捆绑的框架搭建阶段,确保libftd2xx.1.2.2.dylib和ftd2xx.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 D2XX命令,将对其进行详细的下载中描述D2XX程序员指南 。
这是一些代码,我从我的应用程序,用于连接到这些设备中的一个一个解除:
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;
}
}
}
断开相当简单:
ftdiPortStatus = FT_Close(*electronicsPointer);
*electronicsPointer = 0;
if (ftdiPortStatus != FT_OK)
{
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;
}
( command
是一个NSData实例, runOnMainQueueWithoutDeadlocking()
仅仅是一个方便的功能我使用,以保证在块的执行在主队列 )。
你可以阅读使用类似下面的串行接口原始字节:
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);
在上述的结束, response
将包含你从端口读取的字节中一个NSData实例。
另外,我建议你应该总是在主线程访问FTDI设备。 即使他们说,他们支持多线程访问,我发现,任何一种非主线程访问(甚至从单个线程保证排他性访问)导致Mac上间歇性崩溃。
除了我上面描述的情况,你可以咨询D2XX编程指南其他功能FTDI提供了他们的C库。 再次,你应该只需要到相应的代码已经由设备制造商提供给您的样品动过。
我也陷入了类似的问题(试图写入使用Objective-C的EntTec打开DMX),没有任何成功。 以下@布拉德的伟大的答案后,我意识到,你还需要在每次发送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);
}
希望这可以帮助别人那里!