我正在嘗試與Enttec USB DMX Pro進行通信。主要接收DMX。FTDI與USB設備通信 - 目標C
他們發佈了一個Visual C++版本here,但我有點難以應付如何轉換爲Obj-c。 Enttec寫道:「使用適用於Mac的FTDI庫與PRO交談,並參考D2XX編程指南打開並與設備對話。」 Objective-C的任何示例應用程序都在那裏?有沒有一種簡單的方法與Enttec DMX USB Pro進行通信?
我正在嘗試與Enttec USB DMX Pro進行通信。主要接收DMX。FTDI與USB設備通信 - 目標C
他們發佈了一個Visual C++版本here,但我有點難以應付如何轉換爲Obj-c。 Enttec寫道:「使用適用於Mac的FTDI庫與PRO交談,並參考D2XX編程指南打開並與設備對話。」 Objective-C的任何示例應用程序都在那裏?有沒有一種簡單的方法與Enttec DMX USB Pro進行通信?
我在Mac上用FTDI芯片做了大量的工作,所以我可以在這裏提供一點見解。我已經使用了他們的USB串行轉換器的單通道和雙通道變體,並且它們的行爲都是一樣的。
FTDI有兩個虛擬串口驅動程序,它們會在系統上創建串行COM端口,代表連接到其芯片的串行連接,以及它們的D2XX直接通信庫。你將要與後者合作,其中can be downloaded from their site for various platforms。
Mac的D2XX庫進來獨立的.dylib(最新的是libftd2xx.1.2.2.dylib)或他們最近開始出貨的一個新的靜態庫。包中包含的是你需要的相應頭文件(ftd2xx.h和WinTypes.h)。
在您的Xcode項目中,添加.dylib作爲要鏈接的框架,並將ftd2xx.h,WinTypes.h和ftd2xx.cfg文件添加到您的項目中。在您的Copy Bundled Frameworks構建階段中,確保在該階段中存在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 Programmer's Guide中詳細描述。
這是一些代碼,我從我的應用程序之一解除,用於連接到這些設備之一:
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()
僅僅是a convenience function I use to guarantee execution of a block on the main queue)。
可以使用類似下面的讀取串口原始字節:
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上導致間歇性崩潰。
除上述情況外,您可以參考D2DI編程指南瞭解FTDI在C庫中提供的其他函數。同樣,您只需要從設備製造商提供給您的樣本中移除適當的代碼即可。
WOW!非常感謝,布拉德。這非常有幫助。肯定+1!我真的很感謝回覆 – objectiveccoder001
@Brad:真的很棒的信息。我正在嘗試與J2DXX相同,iam能夠與設備進行通信並檢索設備信息等。但我只是感到困惑,因爲我沒有看到一種方法來說明mifare卡的哪個區塊應該寫入數據等等...這個api不會讀取或寫入mifare卡嗎?只是讀取器設備 – 2013-02-14 17:03:53
@inba - 我不知道MIFARE是如何工作的,但以上只是您如何通過FTDI USB串行轉換器發送和接收數據。您將需要自行發送MIFARE需要的任何命令。 –
我遇到了類似的問題(試圖使用Objective-C寫入EntTec Open DMX),但沒有取得任何成功。遵循@ Brad的偉大回答之後,我意識到每次發送DMX數據包時都需要切換BREAK狀態。
下面是一些測試代碼中的循環示例,它在幀之間發送延遲爲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);
}
希望這可以幫助別人!
您所說的「司機」[看起來可以在FTDI Chip站點上找到](http://www.ftdichip.com/Drivers/VCP.htm),我不知道任何「目標C「特定的示例應用程序,但是如果您可以使用任何使用C或C++的MacOS示例代碼,那麼它們也應該可以在Objective C應用程序中使用。 –
是的,我試圖找到一個在C或C++的MacOS示例代碼.... – objectiveccoder001
不知道它是否有幫助,但可能值得看看[ofxDmx](https://github.com/kylemcdonald/ofxDmx)或[DMXusbPro](https://github.com/q-depot/Cinder-DMXusbPro)煤渣塊 –