MFC: thread serielle Schnittstelle
-
Hi,
ich hab eine etwas allgemeine Design-Frage:
Über eine USB-Verbindung werden Daten von meinem MFC-Programm an einen FTDI Device gesendet (USB-to-Serial Converter). Als Flusssteuerung verwende ich RTS/CTS und hab sie etwas verändert. Wenn ein Buffer komplett übertragen worden ist, wird CTS beim FTDI Device auf high gezogen. Das soll signalisieren, dass ein neuer Buffer an den FTDI Device gesendet werden darf von meinem MFC Programm.
Nachdem die serielle Übertragungsgeschwindigkeit nicht so schnell ist, hab ich in meinem MFC Programm eine CList installiert, das Datenpakete abfängt, die bereits übere andere Schnittstellen angekommen sind, aber noch nicht an den FTDI Device gesendet werden können.
Bis jetzt verwende ich einen eigenen Thread für die FTDI Kommunikation. D.h. wenn Daten ankommen über andere Schnittstellen, werden diese per Message an den Thread für die FTDI weitergeleitet (OnNewData).
BOOL FTDI_TxData::InitInstance() { //init ftdi handle return TRUE; } /* - wParam -> pointer auf die Daten die an den FTDI gesendet werden sollen */ void FTDI_TxData::OnNewData(WPARAM wParam, LPARAM lParam) { unsigned char array[DATA_TX_BUF_SIZE]; unsigned char * schar = (unsigned char *)wParam; memcpy((void *)&array[0], (void *)&schar, DATA_TX_BUF_SIZE); //daten in clist (public member von der class) speichern list.AddHead(array[0]); }
Brauch ich jetzt einen weiteren Thread, der die Daten aus der Liste holt und diese dann an den FTDI Device sendet? Anschließend wartet er solange bis CTS high gesetzt wird.
Hier mal eine Dummy-Implementierung
//ungefähre sende-routine void GetData() { unsigned char data[DATA_TX_BUF_SIZE]; HANDLE hEvent; hEvent = CreateEvent(NULL, false, false, _T("")); //set event notification for CTS / DTS etc. FT_SetEventNotification(ftHandle,FT_EVENT_MODEM_STATUS,hEvent); //list item holen data[] = GetListHeadItem(); //write data to ftdi FT_Write(ftHandle, &data, DATA_TX_BUF_SIZE, &bytesWritten); //wait for event -> das CTS high geht WaitForSingleObject(hEvent,INFINITE); FT_GetStatus(ftHandle,&RxBytes,&TxBytes,&EventDWord); if(EventDWord & FT_EVENT_MODEM_STATUS) { FT_GetModemStatus(ftHandle,&Status); if(CTS == high) return; } }
Wie hole ich mir jetzt diese Daten ab und sende sie wirklich an den FTDI Device? Benötige ich dafür einen zweiten Thread? Wenn ja, wo muss ich diesen am Besten initialisieren - auch in der FTDI_TxData::InitInstance()?
Gruß
Konrad
-
Hm, da keiner antwortet, erbarme ich mich mal.
Allerdings bin ich kein MFC-Experte und bei hardwarenahen Sachen achte ich auf strikte Trennung zur GUI.
Auf den ersten Blick sieht dein Code ja aus, als ob da einer schreibt, der Ahnung von der Sache hat. Aber auf den zweiten Blick werde ich etwas stutzig.
Meines Wissens nach haben Worker-Threads in der MFC überlicherweise keine Message-Loop. Wie sieht diese Übergabe "per Message an den Thread für die FTDI" aus ? Wird die Funktion OnNewData einfach aus dem anderen Thread aufgerufen ? Das würde ja bedeuten, dass da überhaupt keine Synchronisation stattfindet und beide Threads gleichzeitig auf die Liste zugreifen können ...
Überhaupt die Liste
//daten in clist (public member von der class) speichern
es ist überaus unüblich, Daten auf die verschiedene Threads zugreifen, zu öffentlichen Membern zu machen.
Und mein Hauptproblem, was macht diese Funktion ???
void FTDI_TxData::OnNewData(WPARAM wParam, LPARAM lParam) { unsigned char array[DATA_TX_BUF_SIZE]; unsigned char * schar = (unsigned char *)wParam; memcpy((void *)&array[0], (void *)&schar, DATA_TX_BUF_SIZE); //daten in clist (public member von der class) speichern list.AddHead(array[0]); }
Da wird ein Array als lokale Variable angelegt und die Daten, auf die der wParam zeigt, dahin kopiert. (Dabei wird auch noch viel zuviel gecastet, aber das lassen wir mal beiseite.)
Warum ? Wenn die Funktion verlassen wird, ist die Kopie wieder weg.
list ist ja hoffentlich keine Liste von Pointern und zeigt dann auf lokale Daten der Funktion und nach dem Ende dieser ins Nirwana ?
Ich hoffe mal zu deinen Gunsten, dass die Liste eine Kopie der Daten macht. Dann wäre aber das lokale Kopieren der Daten in der Funktion überflüssig und man könnte direkt den wParam übergeben ...
-
Hi Konrad,
mal eine grundsätzliche Frage:
Warum verwendest Du die FDTI-spezifischen Funktionen FT_xxx() ?
(welche sich in der FTDI Bibliothek Ftd2xx.dll befinden)So wie ich mir Deine Codeschnipsel angeschaut habe, kannst Du das gleiche auch über ganz gewöhnliche serielle Kommunikationsroutinen des Win32-API abwickeln.
Oder evtl. gleich eine fertige serielle Klasse wie z.B. CSerial verwenden. Diese kannst Du auch für die FT232x-Chips verwenden, sofern aktuelle Treiber korrekt installiert worden sind.
Ich selbst habe sowohl mit Win32-API als auch mit den FT_xxx() Funktionen programmiert.
Allerdings bin ich kein MFC-Experte!Martin