Ich habe eine Menge Arbeit mit den FTDI-Chips auf dem Mac gemacht, so kann ich hier einen kleinen Einblick geben. Ich habe die Einkanal- und Zweikanal-Varianten ihrer USB-Seriell-Wandler verwendet, und sie verhalten sich alle gleich.
FTDI verfügt über ihre virtuellen COM-Port-Treiber, die einen seriellen COM-Port auf Ihrem System erstellen, der die an ihren Chip angeschlossene serielle Verbindung und ihre D2XX-Bibliotheken für direkte Kommunikation darstellt. Du wirst mit letzterem arbeiten wollen, welches can be downloaded from their site for various platforms.
Die D2XX-Bibliotheken für den Mac werden in einer eigenständigen .dylib (die neueste Version ist libftd2xx.1.2.2.dylib) oder einer neuen statischen Bibliothek geliefert, die sie vor kurzem ausgeliefert haben. In diesem Paket enthalten sind die entsprechenden Header-Dateien, die Sie benötigen (ftd2xx.h und WinTypes.h).
Fügen Sie in Ihrem Xcode-Projekt die .dylib als zu verknüpfendes Framework hinzu und fügen Sie die Dateien ftd2xx.h, WinTypes.h und ftd2xx.cfg zu Ihrem Projekt hinzu. Stellen Sie in Ihrer Build-Build-Phase für das Build-Paket sicher, dass libftd2xx.1.2.2.dylib und ftd2xx.cfg in dieser Phase vorhanden sind. Sie können auch den relativen Pfad anpassen müssen, dass diese Bibliothek, um erwartet für sie in Ihrem App-Bundle funktionieren, so müssen Sie möglicherweise den folgenden Befehl gegen sie in der Befehlszeile auszuführen:
install_name_tool -id @executable_path/../Frameworks/libftd2xx.1.2.2.dylib libftd2xx.1.2.2.dylib
Sobald Ihre Projekt wird alle richtig konfiguriert ist, sollten Sie die FTDI-Header importieren:
#import "ftd2xx.h"
und starten Sie zu Ihren seriellen Geräten zu verbinden. Das Beispiel, auf das Sie in Ihrer Frage verlinken, enthält ein herunterladbares C++ - Beispiel, das zeigt, wie sie mit ihrem Gerät kommunizieren. Sie können fast den gesamten C-Code, der dort verwendet wird, mitbringen und ihn in Ihre Objective-C-Anwendung einfügen. Sie scheinen nur die Standard-FTDI-D2XX-Befehle zu verwenden, die im herunterladbaren D2XX Programmer's Guide ausführlich beschrieben sind.
Dies ist ein Code, den ich von einem meiner Anwendungen angehoben haben, verwendet, um eines dieser Geräte zu verbinden:
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;
}
}
}
Disconnection ist ziemlich einfach:
ftdiPortStatus = FT_Close(*electronicsPointer);
*electronicsPointer = 0;
if (ftdiPortStatus != FT_OK)
{
return;
}
auf das Schreiben serielles Gerät ist dann recht einfach:
__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
ist ein NSData Instanz, und runOnMainQueueWithoutDeadlocking()
ist nur a convenience function I use to guarantee execution of a block on the main queue).
Sie können roh Bytes von der seriellen Schnittstelle mit so etwas wie die folgenden lesen:
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);
Am Ende der obigen Ausführungen werden response
eine NSData Instanz sein, den Bytes enthält, die Sie vom Hafen gelesen habe.
Außerdem würde ich vorschlagen, dass Sie immer auf das FTDI-Gerät aus dem Hauptthread zugreifen sollten. Obwohl sie sagen, dass sie Multithread-Zugriffe unterstützen, habe ich festgestellt, dass jede Art von Nicht-Haupt-Thread-Zugriff (sogar garantierte exklusive Zugriffe von einem einzelnen Thread) zu zeitweiligen Abstürzen auf dem Mac führt.
Neben den oben beschriebenen Fällen können Sie den D2XX-Programmierleitfaden für die anderen Funktionen von FTDI in der C-Bibliothek konsultieren. Auch hier sollten Sie nur den entsprechenden Code aus den Beispielen, die Ihnen von Ihrem Gerätehersteller zur Verfügung gestellt wurden, verschieben.
Die "Treiber", von denen Sie sprechen, [scheinen auf der FTDI Chip-Website verfügbar zu sein] (http://www.ftdichip.com/Drivers/VCP.htm) und ich kenne kein "Ziel" C "spezifische Beispiel-Apps, aber wenn Sie einen MacOS-Beispielcode verwenden können, der C oder C++ verwendet, sollte das auch in einer Objective-C-App funktionieren. –
Ja, ich habe versucht, einen MacOS-Beispielcode in C oder C++ zu finden .... – objectiveccoder001
Nicht sicher, ob es hilft, aber vielleicht lohnt sich [oxDmx] (https://github.com/kylemcdonald/ofxDmx) oder der [DMXusbPro] (https://github.com/q-depot/Cinder-DMXusbPro) Schlackenblock –