Ho svolto una notevole quantità di lavoro con i chip FTDI sul Mac, quindi posso fornire una piccola panoramica qui. Ho usato le varianti a canale singolo e doppio canale dei loro convertitori USB-seriale, e si comportano tutti allo stesso modo.
FTDI dispone sia dei driver Virtual COM Port che creano una porta COM seriale sul sistema che rappresenta la connessione seriale collegata al proprio chip, sia le loro librerie di comunicazione diretta D2XX. Vorresti lavorare con quest'ultimo, che è can be downloaded from their site for various platforms.
Le librerie D2XX per Mac sono disponibili in versione standalone .dylib (l'ultima è libftd2xx.1.2.2.dylib) o una nuova libreria statica che hanno iniziato la spedizione di recente. In questo pacchetto sono inclusi anche i file di intestazione appropriati (ftd2xx.h e WinTypes.h).
Nel progetto Xcode, aggiungere il .dylib come framework da collegare e aggiungere i file ftd2xx.h, WinTypes.h e ftd2xx.cfg al progetto. Nella fase di compilazione Copia gruppi combinati, assicurarsi che libftd2xx.1.2.2.dylib e ftd2xx.cfg siano presenti in quella fase. Potrebbe anche essere necessario per regolare il percorso relativo che questa libreria si aspetta, in modo che esso possa funzionare all'interno del vostro pacco app, quindi potrebbe essere necessario eseguire il seguente comando su di esso dalla riga di comando:
install_name_tool -id @executable_path/../Frameworks/libftd2xx.1.2.2.dylib libftd2xx.1.2.2.dylib
Una volta che il progetto è tutto configurato correttamente, ti consigliamo di importare le intestazioni FTDI:
#import "ftd2xx.h"
e iniziare a connettersi ai dispositivi seriali. L'esempio a cui ti colleghi nella tua domanda ha un campione C++ scaricabile che mostra come comunicano con il loro dispositivo. Puoi trasferire quasi tutto il codice C utilizzato e metterlo all'interno della tua applicazione Objective-C. Sembra che stiano usando i comandi standard FTDI D2XX, descritti dettagliatamente nel download D2XX Programmer's Guide.
Questo è un codice che ho sollevato da una delle mie applicazioni, utilizzato per la connessione a uno di questi dispositivi:
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;
}
}
}
disconnessione è abbastanza semplice:
ftdiPortStatus = FT_Close(*electronicsPointer);
*electronicsPointer = 0;
if (ftdiPortStatus != FT_OK)
{
return;
}
Scrivendo al dispositivo seriale è quindi abbastanza facile:
__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
è un NSData istanza e runOnMainQueueWithoutDeadlocking()
è semplicemente a convenience function I use to guarantee execution of a block on the main queue).
Si può leggere di byte non elaborati dalla interfaccia seriale usando qualcosa come il seguente:
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);
Al termine di cui sopra, response
sarà un'istanza NSData contenente i byte che hai letto dal porto.
Inoltre, suggerirei di accedere sempre al dispositivo FTDI dal thread principale. Anche se dicono che supportano l'accesso multithread, ho scoperto che ogni tipo di accesso non-main-thread (anche gli accessi esclusivi garantiti da un singolo thread) causano arresti intermittenti sul Mac.
Oltre ai casi descritti sopra, è possibile consultare la guida alla programmazione D2XX per le altre funzioni fornite da FTDI nella propria libreria C. Di nuovo, dovresti semplicemente spostare il codice appropriato dagli esempi che ti sono stati forniti dal produttore del tuo dispositivo.
I "driver" di cui parli [sembrano disponibili sul sito FTDI Chip] (http://www.ftdichip.com/Drivers/VCP.htm) e non conosco alcun "Obiettivo" C "app di esempio specifiche, ma se è possibile qualsiasi codice di esempio MacOS che utilizza C o C++, dovrebbe funzionare anche all'interno di un'app Objective C. –
Sì, stavo cercando di trovare un codice di esempio MacOS in C o C++ .... – objectiveccoder001
Non sono sicuro che sia d'aiuto, ma potrebbe valere la pena dare un'occhiata a [ofxDmx] (https://github.com/kylemcdonald/ofxDmx) o il blocco cinder [DMXusbPro] (https://github.com/q-depot/Cinder-DMXusbPro) –