FT232 String senden/empfangen

Gast #2295896
Lesenswert?

Hallo, ich bin auf der Suche nach einer Library für den FT232.

Ein Zeichen senden kann ich (funktioniert auch), aber für mehr reichen 
meine Kenntnisse nicht. Deshalb suche ich einen Codeausschnitt bzw. eine 
Library die einen String senden und empfangen kann. Ich programmieren in 
Codeblocks unter Win7 x64 / mit C++.

Vielen Dank für etwaige Hilfe
#2295902
Lesenswert?

> Ein Zeichen senden kann ich (funktioniert auch), aber für mehr reichen
meine Kenntnisse nicht.

Du kannst 1 Zeichen senden, hast aber Probleme mit Strings?

Das ergibt keinen Sinn. Einen String sendet man, indem man 1 Zeichen 
nach dem anderen sendet. Das kannst du aber offenbar. Wo liegt daher das 
Problem?

1
void sendString( const char* string )
2
{
3
  while( *string )
4
    sendCharacter( *string++ );
5
}

wenn du nicht mit ollen C-style Strings rummachen willst (was ich 
verstehen kann), musst du dir halt was Gleichwertiges mit deiner 
favorisierten String-Klasse einfallen lassen.
Gast #2295910
Lesenswert?

Genauer gesagt sind es mehrere Probleme. Der Null Teminierte String muss 
dieser funktion übergeben werden.Daher muss er konvertiert werden jedoch 
weiß ich leider nicht wie?

FT_STATUS FT_Write (FT_HANDLE ftHandle, LPVOID lpBuffer, DWORD 
dwBytesToWrite,LPDWORD lpdwBytesWritten)

Parameters:

ftHandle Handle of the device.
lpBuffer Pointer to the buffer that contains the data to be written to 
the device.
dwBytesToWrite Number of bytes to write to the device.
lpdwBytesWritten Pointer to a variable of type DWORD


Das lesen ist für mich noch weit komplizierter.Zuerst muss die folgende 
Funktion richtig parametriert werde.

FT_STATUS FT_SetEventNotification (FT_HANDLE ftHandle, DWORD 
dwEventMask, PVOID pvArg)

Parameters
ftHandle Handle of the device.
dwEventMask Conditions that cause the event to be set.
pvArg Interpreted as the handle of an event.

Remarks
An application can use this function to setup conditions which allow a 
thread to block until one of the conditions is met. Typically, an 
application will create an event, call this function, then block on the 
event. When the conditions are met, the event is set, and the 
application thread unblocked.
dwEventMask is a bit-map that describes the events the application is 
interested in. pvArg is interpreted as the handle of an event which has 
been created by the application. If one of the event conditions is met, 
the event is set.
If FT_EVENT_RXCHAR is set in dwEventMask, the event will be set when a 
character has been received by the device.
If FT_EVENT_MODEM_STATUS is set in dwEventMask, the event will be set 
when a change in the modem signals has been detected by the device.
If FT_EVENT_LINE_STATUS is set in dwEventMask, the event will be set 
when a change in the line status has been detected by the device.

Danach ein nullterminierter String aus folgender funktion ausgelesen 
werden.

FT_STATUS FT_Read (FT_HANDLE ftHandle, LPVOID lpBuffer, DWORD 
dwBytesToRead,
LPDWORD lpdwBytesReturned)

Parameters
ftHandle Handle of the device.
lpBuffer Pointer to the buffer that receives the data from the device.
dwBytesToRead Number of bytes to be read from the device.
lpdwBytesReturned Pointer to a variable of type DWORD which receives the 
number of bytes read from the device.

wie gesagt ich verstehe es leider nicht ganz.
Gast #2295912
Lesenswert?

> void sendString( const char* string )
> {
>   while( *string )
>     sendCharacter( *string++ );
> }
>
> wenn du nicht mit ollen C-style Strings rummachen willst (was ich
> verstehen kann), musst du dir halt was Gleichwertiges mit deiner
> favorisierten String-Klasse einfallen lassen.

ja so leicht ist es leider nicht, ich habe Probleme mit den Pointern 
bzw. der Datentyp konvertierung. Aber schon mal Danke
#2295917
Lesenswert?

Mark L. schrieb:
> Genauer gesagt sind es mehrere Probleme. Der Null Teminierte String muss
> dieser funktion übergeben werden.Daher muss er konvertiert werden jedoch
> weiß ich leider nicht wie?
>
> FT_STATUS FT_Write (FT_HANDLE ftHandle, LPVOID lpBuffer, DWORD
> dwBytesToWrite,LPDWORD lpdwBytesWritten)
>
> Parameters:
>
> ftHandle Handle of the device.
> lpBuffer Pointer to the buffer that contains the data to be written to
> the device.
> dwBytesToWrite Number of bytes to write to the device.
> lpdwBytesWritten Pointer to a variable of type DWORD


Ich versteh dein Problem immer noch nicht.
Dein STring hat eine gewisse Länge und damit eine gewisse Byteanzahl. 
Ich ignoriere jetzt mal Unicode sondern gehe von guten alten ASCII 
Strings aus. Wenn dem nicht so ist, dann musst du also entweder 
feststellen wie man von einem Unicode-String die Anzahl der Bytes 
ermittelt, oder wie man einen Unicode String auf ASCII transferiert. 
Beides hat aber erst mal nichts mit FT232 zu tun.

Hast du dann die Anzahl der Bytes, dann ab damit in diese Funktion. Die 
Längenangabe richtig angegebn und fertig, Wo liegt da jetzt schon wieder 
das Problem? Das ist banales C++ / Windows Wissen. So wie ich das sehe, 
hat diese API Funktion auch durchaus eine unter Windows gebräuchliche 
Signatur.
#2295918
Lesenswert?

Mark L. schrieb:
>> void sendString( const char* string )
>> {
>>   while( *string )
>>     sendCharacter( *string++ );
>> }
>>
>> wenn du nicht mit ollen C-style Strings rummachen willst (was ich
>> verstehen kann), musst du dir halt was Gleichwertiges mit deiner
>> favorisierten String-Klasse einfallen lassen.
>
> ja so leicht ist es leider nicht, ich habe Probleme mit den Pointern
> bzw. der Datentyp konvertierung.

Welche Probleme?

Die Sache wäre wesentlich einfacher, wenn du Code zeigen würdest.

Und PS: konzentrier dich erst mal nur auf eine Sache. Senden geht 
einfacher als Empfangen. Also fang erst mal mit Senden an.
#2295927
Lesenswert?

Karl Heinz Buchegger schrieb:

> So wie ich das sehe, hat diese API Funktion auch durchaus eine
> unter Windows gebräuchliche Signatur.

1
  char String[] = "Hallo World";
2
  DWORD len = strlen( String ) + 1;  // + 1 damit das \0 Byte auch mitkommt
3
  DWORD bytesSent = 0;
4

5
  FT_Write( ftHandle, (void*)String, len, &bytesSent );
6

7
  if( bytesSent != len )
8
    cout << "Nicht alle Bytes konnten gesendet werden\n";

Wie gesagt: die Problematik UNICODE ignoriere ich jetzt erst mal, weil 
ich nicht weiß ob das ein konkretes Problem für dich darstellt.
Gast #2295931
Lesenswert?

Soweit bin ich:

Das funktioniert.
1
int write(void)
2
{
3

4
  DWORD Written=0;
5
  unsigned char cmd[]= {'T','E','S','T','\n'};
6

7

8
  /* String zu Char array?
9
    for(unsigned i = 0; i < TEXT.size(); i++)
10
      {
11
        cmd[i] = TEXT[i];
12
     }
13

14
  */
15

16
  ftStatus=FT_Write(ftHandle,cmd,sizeof(cmd),&Written);
17

18
  if (ftStatus == FT_OK)
19
    {
20

21

22
      printf("\nText: \"%s\" written\n",cmd);
23

24
    }
25
  else
26
    {
27
      printf("\nText write failed\n");
28
    }
29

30
  return 0;
31

32
}


aber wie bekomme ich den String\0 nach char []? Ja danke ich dacht mir 
schon das es wohl trivial sei.
Gast #2295979
Lesenswert?

>   FT_Write( ftHandle, (void*)String, len, &bytesSent );
>
>   if( bytesSent != len )
>     cout << "Nicht alle Bytes konnten gesendet werden\n";
>
> Wie gesagt: die Problematik UNICODE ignoriere ich jetzt erst mal, weil
> ich nicht weiß ob das ein konkretes Problem für dich darstellt.

Vielen dank das hilft schon mal weiter, ich wusste nicht das es soo 
möglich ist den string zu senden (void*)String.
#2295982
Lesenswert?

Mark L. schrieb:
> Peter II schrieb:
>> char cmd[]= "TEST\n";
>
> ergibt aber übertragunsfehler:
>
> Ausgabe ist dann <NUL>xTEST<LF>
>
> x ist ein unbekanntes Zeichen.

Wie hast du das festgestellt?

Bei allen 'Messmethoden' muss man immer auch berücksichtigen, dass das 
'Messgerät' Unsinn anzeigt, weil es sich zb erst mal auf eine 
Übertragung einklinken muss. Nach dem ersten Zeichen sollte das 
allerdings dann nicht mehr sein.
1
Angedacht ist:
2

3
String str0 = "Test\n";
4

5

6
write (str0);
7

8

9
int write(string str)
10
{
11

12
"String senden"
13

14
}

Ja. Wie gehts jetzt weiter?
Stringlänge feststellen (Hinweis: dein sizeof da oben ist schon mal 
nicht dafür geeignet), entsprechenden Pointer auf die Bytes in FT_wruite 
reinstecken, die ermittelte Stringlänge reinstecken und ... fertig.

Ich seh immer noch kein Problem.
Gast #2295984
Lesenswert?

1
int write(void)
2
{
3

4
  DWORD Written=0;
5
  unsigned char cmd[]= {'T','E','S','T','\n'};
6

7
  ftStatus=FT_Write(ftHandle,cmd,sizeof(cmd),&Written);
8

9
  if (ftStatus == FT_OK)
10
    {
11

12

13
      printf("\nText: \"%s\" written\n",cmd);
14

15
    }
16
  else
17
    {
18
      printf("\nText write failed\n");
19
    }
20

21
  return 0;
22

23
}


Ausgabe: Test<LF>

1
int write(void)
2
{
3

4
  DWORD Written=0;
5
  unsigned char cmd[]= "TEST\n";
6

7

8
  ftStatus=FT_Write(ftHandle,cmd,sizeof(cmd),&Written);
9

10
  if (ftStatus == FT_OK)
11
    {
12

13

14
      printf("\nText: \"%s\" written\n",cmd);
15

16
    }
17
  else
18
    {
19
      printf("\nText write failed\n");
20
    }
21

22
  return 0;
23

24
}


Ausgabe: <NUL>xTEST<LF>
#2295987
Lesenswert?

Mark L. schrieb:
>>   FT_Write( ftHandle, (void*)String, len, &bytesSent );
>>
>>   if( bytesSent != len )
>>     cout << "Nicht alle Bytes konnten gesendet werden\n";
>>
>> Wie gesagt: die Problematik UNICODE ignoriere ich jetzt erst mal, weil
>> ich nicht weiß ob das ein konkretes Problem für dich darstellt.
>
> Vielen dank das hilft schon mal weiter, ich wusste nicht das es soo
> möglich ist den string zu senden (void*)String.

Das hat mit versenden nichts zu tun.
Der Cast auf void ist notwendig, weil es nun mal in C++ keinen Datentyp 
gibt der für 'Pointer auf irgendwas' steht und in den alle anderen 
Pointertypen implizit konvertiert werden können.
void* realisiert einen 'Pointer auf irgendwas', aber in C++ kann kein 
Pointer vom Compiler implizt darauf hingecastet werden, sondern der 
Programmierer muss das erlauben bzw. einfordern. Die Funktion will einen 
void Pointer, also caste ich den Datenpointer entsprechend um. Das 
normalste von der Welt.

Mir scheint Peter II hat da oben schon recht. Du brauchst in erster 
Linie mal ein vernünftiges Buch.
#2295991
Lesenswert?

Mark L. schrieb:

> Ausgabe: <NUL>xTEST<LF>


Die Art wie du dein Array baust, hat damit nichts zu tun. Deine erste 
Version ist nur die umständliche Schreibweise der 2.ten Version. Das 
Array wird aber in beiden Fällen identisch angelegt.

Ich denke eher, dass das 'x' das du siehst, das 0-Byte vom ersten (bzw. 
vorhergehenden) Versuch ist. Wozu sollte man ein 0-byte übertragen, wenn 
es nicht korrekt angezeigt werden kann. Normalerweise macht man das 
nicht (ausser der Empfänger benötigt das 0byte um das Ende des Strings 
erkennen zu können, was ein normales Terminalprogramm nicht kann. Das 
malt dann eben ein Zeichen für 'kenn ich nicht' hin.)
Gast #2295992
Lesenswert?

Karl Heinz Buchegger schrieb:
> Die Art wie du dein Array baust, hat damit nichts zu tun. Deine erste
> Version ist nur die umständliche Schreibweise der 2.ten Version. Das
> Array wird aber in beiden Fällen identisch angelegt.
nein, einmal hat es am ende eine 0 einmal nicht. Aber der Anfang sollte 
gleich sein.

@Mark L.
Für soetwas hilft doch der debugger, schau dir doch einfach mal die 
Variaben an.
#2295994
Lesenswert?

Peter II schrieb:
> Karl Heinz Buchegger schrieb:
>> Die Art wie du dein Array baust, hat damit nichts zu tun. Deine erste
>> Version ist nur die umständliche Schreibweise der 2.ten Version. Das
>> Array wird aber in beiden Fällen identisch angelegt.
> nein, einmal hat es am ende eine 0 einmal nicht. Aber der Anfang sollte
> gleich sein.

Ah. ok. Daran hab ich jetzt nicht gedacht.

Ist ja auch Schwachsinn einen String mittels Einzelbuchstaben anzulegen. 
Das macht die Stringverarbeitung so schon <Sarkasmus ein> unkompliziert 
</Sarkasmus aus>
Gast #2296045
Lesenswert?

1
int write( char * str )
2
{
3

4
  char TEXT[strlen(str)];
5
  DWORD Written=0;
6

7

8
  for(int i = 0; i < strlen(str); i++)
9
  {
10
    TEXT[i] = str[i];
11
}
12
 
13

14

15
  ftStatus=FT_Write(ftHandle,TEXT,sizeof(TEXT)-1,&Written);
16

17
  if (ftStatus == FT_OK)
18
    {
19

20

21
      printf("\nText: \"%s\" written\n",TEXT);
22

23
    }
24
  else
25
    {
26
      printf("\nText write failed\n");
27
    }
28

29
  return 0;
30

31
}

sorry hat einen moment gedauert, der fehler war die \0 am ende aber 
jetzt funktioniert das senden wie es soll.

Ich benutze das http://www.cplusplus.com/ als Hilfe

Vielen dank schonmal für die Hilfestellung.
Gast #2296052
Lesenswert?

Mark L. schrieb:
> char TEXT[strlen(str)];
>
>   DWORD Written=0;
>   for(int i = 0; i < strlen(str); i++)
>   {
>     TEXT[i] = str[i];
> }

und was soll das? Du kopierst 1:1 alles was in str steht in TEXT rein - 
wozu?

Dann kannst du auch gleich str verwenden und braucht TEXT überhaupt 
nicht.


hast du ein glück das es seit neusten soetwas gibt:
   char TEXT[strlen(str)];

vor ein paar jahren hätte jeder Compiler hier aufgehört.
Gast #2296080
Lesenswert?

ISO C++ forbids declaration of 'write' with no type, war sonst der 
Fehler.

Zur Read Funktion ich habe das Beispiel geteste. Jedoch ohne Erfolg, 
deshalb auch die Frage ob jemand etwas in einer funktionsfähigen Form 
hat.

1
int read (void)
2
{
3

4
#define OneSector 1024
5
DWORD EventDWord;
6
DWORD RxBytes = 0;
7
DWORD TxBytes = 0;
8
DWORD BytesReceived=1;
9
char RxBuffer[OneSector];
10

11
  while(BytesReceived==1)
12
    {
13

14
      ftStatus = FT_GetStatus(ftHandle,&RxBytes,&TxBytes,&EventDWord);
15

16
      if((ftStatus == FT_OK) && (RxBytes >= OneSector))
17
        {
18
          ftStatus = FT_Read(ftHandle,RxBuffer,RxBytes,&BytesReceived);
19
          if (ftStatus == FT_OK)
20
            {
21
              printf("\n Text readout:%s \n",RxBuffer);
22
              BytesReceived=0;
23
            }
24
          else
25
            {
26
              printf("\n Text readout failed\n");
27
              BytesReceived=0;
28
            }
29
        }
30
      else
31
        {
32

33
          printf("\n Read error  %s \n",RxBuffer);
34
          BytesReceived=0;
35

36

37
        }
38

39
    }
40

41
return 0;
42
}
Gast #2296096
Lesenswert?

Wie gesagt war das Beispiel das ich fand verstanden habe ich es nicht.
1
int read (void)
2
{
3

4
  FT_STATUS ftStatus;
5

6
  DWORD RxBytes = 10;
7
  DWORD BytesReceived;
8
  unsigned char RxBuffer[256];
9

10
  FT_SetTimeouts(ftHandle,5000,0); //hier war wohl mein Fehler
11

12
  ftStatus = FT_Read(ftHandle,RxBuffer,RxBytes,&BytesReceived);
13
  if(ftStatus == FT_OK)
14
    {
15
      if(BytesReceived == RxBytes)
16
        {
17
          for(int i = 0 ; i < int(BytesReceived) ; i++)
18
            {
19
              printf("%d \n",RxBuffer[i]);
20
            }
21
        }
22
      else
23
        {
24
          printf("read error\n");
25
        }
26
    }
27
  else
28
    {
29
      printf("FTDI chip not ready\n");
30
    }
31

32
    return 0;
33
}

jetzt hab ich schonmal ein Ansatzt, im der CMD erhalte ich Ascii codes 
von mienem gesendeten String.
Gast #2296109
Lesenswert?

Mark L. schrieb:
> Wie gesagt war das Beispiel das ich fand verstanden habe ich es nicht.

dann versteh es bitte zu erst, Trial and Error ist bei programmieren in 
C das schlechteste was man machen kann.


> if(BytesReceived == RxBytes)

und was ist wenn man weniger zu empfangen ist?


Lies dir die Doku von FTDI durch und Programmiere es selber. Vom Copy 
and Paste lernt man nichts.
Gast #2296128
Lesenswert?

Ja wenn ich alles verstanden hätte wäre ich nicht hier, mir wäre es auch 
lieber alles zu können.
Oder eine Fertige lib zu nutzen die alles kann was ich brauche. Kann es 
aber eben nur so, ich dachte die Beispiele sind für den schnell 
Einstieg?Es geht leider nicht alles zu 100% zu lernen (wer hat den dazu 
Zeit?) somit ist das mein Weg. Ich bitte das zu verstehen. Jedoch, Danke 
für die Hilfe.
Gast #2296138
Lesenswert?

Mark L. schrieb:
> Oder eine Fertige lib zu nutzen die alles kann was ich brauche.

die FTDI lib ist doch schon fertig. Und macht eigentlich alles was man 
braucht.

> Es geht leider nicht alles zu 100% zu lernen (wer hat den dazu Zeit?)
doch geht es, wenn man einmal die Grundlagen verstanden hat, dann spart 
man am ende sogar Zeit. Du hast doch noch mal mal verstanden wie 
"Strings" in C funktionieren - dann sollte man noch nicht Anfangen 
irgendwelche Libs einzubinden.

was soll das hier:

> int(BytesReceived)

weist du überhaupt warum du das dort hingeschrieben hast?
Gast #2296177
Lesenswert?

Mark L. schrieb:
> es ist ein typecast von unsigned in signed, geht doch so, warum nicht?

das Problem dabei ist das es ein cast ist, wenn du aus irgend einem 
grund mal die Variable BytesReceived einen komplett anderen Datentyp 
gibst dann wirkt der Cast immernoch. und es gibt keine warnung vom 
Compiler. Also versucht man ohne cast auszukommenm. Und hier gibt es 
überhaupt keinen Grund mit einem Cast zu arbeiten.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren