www.mikrocontroller.net

Forum: PC-Programmierung winapi com RS232 lesen und schreiben


Autor: soso (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ich möchte mit der Winapi auf die com schnittstelle lesen und schreiben.
Die initialisierung über createFile hab ich bereits hionter mir das 
funktioniert auch soweit. nur hab ich keinen schimmer wie ich nun 
schriebn und lesen kann.

ich bräuchte eine schreibfunktion, welche ein array mit bekannter laenge 
auf die com schnittstelle schreibt. (kein String, der bei null aufhöhrt, 
da durchaus auch nullen geschrieben werden sollen.)

des weiteren würde ich gerne aus dem eingangsbuffer lesen. weird die 
Funktion aufgerufen soll sie blockieren, bis ein Zeichen angekommen ist. 
das soll dann zurückgeliefert werden.


hier mal die Funktionen:
static void send_RS232(char *data, int length){

    DWORD temp, numbytes_ok;
    COMSTAT ComState;


    ClearCommError(hPort, &temp, &ComState);

    if(!temp)
    {

     if(!WriteFile(hPort, data, length, &numbytes_ok, NULL))
     {
       DWORD err = GetLastError();
       MessageBoxA(NULL, "FEHLER #06 schreiben auf Port fehlgeschlagen", "comPort", 0);

       printf("Letzter Fehler: %ld\r\n", (long int)err);

    return ;
     }
    }


}


/**
 * Diese Funktion empfaengt ein zeichen ueber den RS232 Buffer
 */
char receive(){


  unsigned long gelesen;
  char Buffer=0;

  DWORD dwEvtMask;

  gelesen = 0;


  SetCommMask (hPort, EV_RXCHAR);

  dwEvtMask = 0;

  OVERLAPPED o;
  o.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  WaitCommEvent(hPort, &dwEvtMask, &o);

  while(WAIT_OBJECT_0 == WaitForSingleObject(o.hEvent, INFINITE))
  {
      if (dwEvtMask & EV_RXCHAR){
        if(!ReadFile(hPort,&Buffer,1,&gelesen,NULL)){
          printf("lesefehler\r\n");
        }else{
          break;
        }
      }
  }


  return Buffer;
}


/**
 * Diese Funktion initialisiert die RS232 Schnittstelle
 */
void init_rs232(){

  int baudrate = 9600;


  // Setze Baudrate und Comport
  printf("Initialisiere RS232 Schnittstelle\r\n\r\n");
  printf("Setze Port auf Com3\r\n");
  printf("Setze Baudrate auf %d\r\n", baudrate);
  printf("\r\n\r\n");

  hPort =  CreateFile("COM3", GENERIC_WRITE|GENERIC_READ, 0, NULL,
        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);

    if(!SetupComm(hPort, 512, 512))
    {
    MessageBoxA(NULL, "FEHLER #01 (Comport kann nicht geoeffnet werden)", "comPort", 0);
    return;
    }

    DCB dcb;
    ZeroMemory(&dcb, sizeof(DCB));

    char buffer[100];
    strcpy(buffer,"baud=9600 parity=N data=8 stop=1");
    if (BuildCommDCB((char*)&buffer, &dcb))
    {
    if (dcb.BaudRate != CBR_9600)
    {
      MessageBoxA(NULL, "FEHLER #02", "comPort", 0);
      return;
    }
    }
    else
    {
    MessageBoxA(NULL, "FEHLER #03", "comPort", 0);
    return;
    }

    if(GetCommState(hPort, &dcb))
    {
     dcb.BaudRate = CBR_9600;
     dcb.ByteSize = 8;
     dcb.Parity = 0;
     dcb.StopBits = 0;
     SetCommState(hPort, &dcb);
    }
    else
    {
    MessageBoxA(NULL, "FEHLER #04", "comPort", 0);
    return ;
    }

    if (hPort == INVALID_HANDLE_VALUE)
    {
    MessageBoxA(NULL, "FEHLER #05", "comPort", 0);
    return ;
    }



/*
    CloseHandle(hCom);

    MessageBoxA(NULL, "Alles im grünen Bereich!", "comPort", NULL);
*/





}

hat jemand ne idee warum sowohl das empfangen als auch das senden nicht 
geht? oder nen code wo ich sehen kann wie das auszusehen hat?

er wartet beim lesen immerhin auf ein zeichen. kommt dieses wird ein 
lesefehler geschmissen, warum auch immer

beim schreiben kommt auch immer ein fehler

danke und Gruß

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
warum zu komlpliziert mit WaitForSingleObject? Mach doch einfach ein 
Read. Wenn du schon den Fehler beim Read abfängst kann doch auch gleich 
den Fehler mit GetLastError ermitteln und anzeigen.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da es Unmengen von fertigem Beispielcode für die Programmierung der 
seriellen Schnittstelle mit der Win32-API gibt, wüsste ich nicht, warum 
Du Dir nicht eines dieser funktionierenden Beispiele ansehen und die 
Unterschiede zu Deinem Code herausfinden können solltest.

Beispiele solltest Du auch mit der foreneigenen Suchfunktion finden 
können, das Thema taucht etwa wöchentlich hier auf.

Autor: soso (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
aber leider ohne funktionierende Beispiele. meines hab ich auch hier aus 
dem forum zusammengeschustert. könntet ihr mir vielleicht ein 
funktionierendes zeigen?

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zu deinem Obigen Beispiel:

In der Routine "init_rs232" fehlt irgendwie
der Aufruf "SetCommState" mit der du auch
die RS 232 Parameter setzt. Du liest ja nur
die aktuellen Parameter aus. Schau mal bei
Microsoft nach, dort wird die Programmierung
der seriellen Schnittstelle eigentlich gut
beschrieben (In Google suchen nach z. B.
"GetCommState" o. ä., dann findest du den Link).

Gruß

Ralf

Autor: Karl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann jemand eine gute Library für die Serielle Schnittstelle empfehlen? 
Ich hatte jetzt eine von Code Guru. Ich habe das Programm unter Win7 
geschrieben, und musste es für XP wieder neu compilieren. Gibt es da 
etwas besseres?

Autor: Karl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ach ja eine C++ Klasse suche ich.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
es sind doch dafür nur eine paar api aufrufe erforderlich, warum noch 
extra ein lib ringsrumschrauben die noch noch extra fehler mitbringt?

> Ich habe das Programm unter Win7
> geschrieben, und musste es für XP wieder neu compilieren. Gibt es da
> etwas besseres?
warum das denn, die api hat sich da nicht weiter geändert? Was gab es 
für ein Fehler?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter schrieb:
> es sind doch dafür nur eine paar api aufrufe erforderlich, warum noch
> extra ein lib ringsrumschrauben die noch noch extra fehler mitbringt?

Na ja.
Das Einstellen der Parameter ist nicht der große Grund, warum die 
Serielle gekapselt wird.
Eher schon das Einrichten von Buffern, bzw. einer Queue in der 
Empfansgroutine.


Aber im Grunde zeigt die Fragestellung nur wieder mal, dass der 
Fragesteller nicht googeln und Links auswerten will. Libraries bzw. 
Kapselungen für die serielle Schnittstelle gibt es wie Sand am Meer. 
Auch Firmen überlassen einem gerne für einen Obulus ihre Sicht der 
Dinge.

Autor: Karl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So leicht ist es da gar nicht, etwas zu finden. Für die Meisten braucht 
man MFC.

Autor: soso (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was ich halt suche ist eine einfache möglichkeit.

man hat einen sende und einen empfangsbuffer, wo man liest / schreibt.

um alles andere sollte sich die libary kümmern.

ich finde so Aussagebn wie "kann nicht mit google umgehen" unangebracht, 
da ich immer vorher bei Google suche, aber bisher nichts gefunden habe. 
Daher die Frage, habt ihr da was?

Zu Microsoft, ich finde die API Dokumentation diesbezüglich schlecht, da 
hier kein Beispiel zu finden ist. für einen Neuling auf diesem Gebiet 
ist das nicht einfach so einzisteigen.

Nochmal zur Ausgangsfrage, Hat jemand ein Beispielprogramm oder eine 
Bibliothek (dll) wo man sich das mal angucken kann oder welche man frei 
benutzen darf?

Gruß

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
soso schrieb:
> man hat einen sende und einen empfangsbuffer, wo man liest / schreibt.

und genau das macht auch die Windows-Api, sie hat ein empfangspuffer und 
ein sendepuffer.

Autor: Karl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also die boost Library sieht ja ganz nett aus. Die kann auch nen 
Serialport erstellen. Bloß mal sehen, ob ich damit zurecht komme.

Autor: soso (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wie gesagt nen Beispiel wäre schön

Autor: Karl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Na ich probiere mal die boost. Wenn das damit gut geht könnte man auch 
einen Wiki Artikel daraus machen.

Autor: Karl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also die Boost Lib ist irgendwie nicht sehr Anfänger freundlich.

http://www.boost.org/doc/libs/1_41_0/doc/html/boos...

Also erst einmal braucht man ein IO Device, warum auch immer.

io_service io;
serial_port port( io, "COM1" );

Aber warum man jetzt nicht einfach.

Die Einstellungen sind auch total aufwendig:

port.set_option(boost::asio::serial_port_base::baud_rate(9600) );
Da braucht man erst einmal ein Baudraten Objekt, warum auch immer.

Aber warum ich jetzt nicht einfach port.open(); machen kann erschließt 
sich mir immer noch nicht.

Autor: Blackbird (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> ... So leicht ist es da gar nicht, etwas zu finden. ...

Naja, weil das Senden recht einfach, das Empfangen aber von der 
Anwendung abhängig ist.
Asynchron senden kann man immer. Soll doch der andere Empfänger selber 
zusehen, ob er die Daten auch zum richtigen Zeitpunkt abfragt, bevor sie 
verlorengehen.

Aber Empfangen kann man nicht eben so mal irgendwann, wenn man im 
Proramm gerade mal am Empfangspuffer vorbeikommt.

Das läßt man sich ANZEIGEN (per Event zum Beispiel) und reagiert darauf 
(mit der ReadFile-Funktion).
In einer Warteschleife auf Zeichen warten kann man auch (Polling), aber 
dann bleibt nicht genug zusammenhängende Zeit für den anderen Kram 
übrig. Oder man lagert das Polling oder das Event-Handling in einen 
eigenen Thread aus, der dann wiederum den Hauptthread informiert (und 
der auch eine Eingangs-Queue haben sollte).

Nun kannst Du ungefähr ermessen, warum es nur komplexe Libs und so'n 
Kram gibt, die das alles zuverlässig hinkriegen. So mal schnell einen 
Beispielcode aus einem größenen Projekt zu extrahieren - nee, wirklich 
nicht!


Blackbird

Autor: Oliver R. (superberti)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

also den MSDN-Artikel

http://msdn.microsoft.com/en-us/library/ms810467.aspx

über serielle Kommunikation gibt es jetzt schon stolze 15 Jahre bei 
Microsoft. Mit jeder Menge Beispielcode, der unter JEDER Windowsversion 
ab '95 funktioniert. Keine zusätzlichen Libs nötig, jeder C-Compiler 
kann's kompilieren.
Nur durchlesen muss man es noch selbst.

Gruß,

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.