www.mikrocontroller.net

Forum: PC-Programmierung com schnittstelle mit c ansprechen


Autor: Kartoffel Salat (kartoffelsalat)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo allerseits

Ich bin daran die rs232 über eine c routine anzusprechen das senden habe 
ich berits geschafft. für das Empfangen habe ich in diesem forum ein 
codebeispiel gefunden welches ich nun zum laufen bringen möchte.

es gibt aber noch ein problem bei welchem ich nicht weiter komme.

beim compilieren mekert der compiler bei

 BOOL          bRet      = true;

89 C:\Dev-Cpp\lesen.c `bRet' undeclared (first use in this function)

für was ist das bRet
was mache ich falsch?

vielen dank für eure Hilfe...

übriger code: (ACHTUNG ZEILENUMBRÜCHE BEACHTEN)

include <stdio.h>
#include <stdlib.h>

// 32-Bit-Konsolen-Programm zum Senden/Empfangen von Bytes über COM(9600-8N1)
// Alle empfangenen Bytes werden zurückgesendet.
// OS: W95, W98, W98SE, WinME, WinNT, Win2000, WinXP
// Note: Keine Fehlerbehandlung implementiert!
#include <windows.h>
#include <stdio.h>

#define COM_BUFFER_SIZE 256       // Read- und Write-Buffer-Size
#define BD_RATE         CBR_9600 // 9600 Baud
#define HELP_STRING TEXT("Aufruf mit: progname<COM-Port-Nummer>\r\n")


// Hauptprogramm: Aufruf mit: progname <COM-Port-Nummer>
int main (int argc, char **argv)
{
  DCB           dcb;
  DWORD         iBytesWritten;
  BOOL          bRet      = true;
  DWORD         dwRead    = 0;
  DWORD         dwSetMask = EV_RXCHAR | EV_ERR;
  DWORD         dwEvtMask;
  OVERLAPPED    o;
  COMMTIMEOUTS  ct;
  unsigned char InString[COM_BUFFER_SIZE + 1];
  TCHAR         szCOM[6];


  if (argc == 2 &&                              // progname +COM-Port-Nummer ?
      atoi (argv[1]) > 0 && atoi (argv[1]) < 5) // COM1 ... COM4?
    wsprintf (szCOM, TEXT("COM%s"), argv[1]);   // String "basteln"...
  else
  {
    printf (TEXT("\r\nERROR:\t %s"), HELP_STRING);
    return (1); // und tschüß ...
  }

  memset (&o, 0, sizeof (OVERLAPPED)); // Struktur mit 0en füllen
  o.hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); // einen Eventsetzten

  HANDLE hCom = CreateFile (szCOM, GENERIC_WRITE | GENERIC_READ, 0,NULL,
                            OPEN_EXISTING, 0, NULL);


  if (hCom == INVALID_HANDLE_VALUE)
  { // Fehlerausgabe:
    LPVOID lpMsgBuf;
    FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM |
                    FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(),
                    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL);
    MessageBox (NULL, (LPCTSTR)lpMsgBuf, "Error: CreateFile", MB_OK |MB_ICONINFORMATION);
    LocalFree (lpMsgBuf);
    return (1); // und tschüß ...
  }

  dcb.DCBlength = sizeof(DCB);  // Laenge des Blockes MUSS gesetztsein!
  GetCommState (hCom, &dcb);    // COM-Einstellungen holen und aendern
  dcb.BaudRate  = BD_RATE;      // Baudrate
  dcb.ByteSize  = 8;            // Datenbits
  dcb.Parity    = NOPARITY;     // Parität
  dcb.StopBits  = ONESTOPBIT;   // Stopbits
  SetCommState (hCom, &dcb);    // COM-Einstellungen speichern

  GetCommTimeouts (hCom, &ct);
  // Warte-Zeit [ms] vom Beginn eines Bytes bis zum Beginn des nächstenBytes
  ct.ReadIntervalTimeout         = 1000 / BD_RATE * (dcb.ByteSize +
                                                     (dcb.Parity ==NOPARITY ? 0 : 1) +
                                                     (dcb.StopBits ==ONESTOPBIT ? 1 : 2)) * 2;
  ct.ReadTotalTimeoutMultiplier  = 0;  // [ms] wird mit Read-Buffer-Sizemultipliziert
  ct.ReadTotalTimeoutConstant    = 50; // wird anReadTotalTimeoutMultiplier angehängt
  ct.WriteTotalTimeoutMultiplier = 0;
  ct.WriteTotalTimeoutConstant   = 0;
  SetCommTimeouts (hCom, &ct);

  // Zwischenspeicher des serial-Drivers einstellen (für read undwrite):
  SetupComm (hCom, COM_BUFFER_SIZE, COM_BUFFER_SIZE);
  SetCommMask (hCom, dwSetMask); // Empfangssignale definieren

  do  // in Endlos-Schleife auf Empfangssignale warten:
  {
    WaitCommEvent (hCom, &dwEvtMask, &o); // Event mit Empfangssignalenverknüpfen

    if (WAIT_OBJECT_0 == WaitForSingleObject (o.hEvent, INFINITE)) //warten bis Event
    {
      if (dwEvtMask & EV_RXCHAR) // Zeichen an RxD empfangen:
      {
        bRet = ReadFile (hCom, &InString, sizeof (InString), &dwRead,NULL);

        if (!bRet)
        { // Fehlerausgabe:
          LPVOID lpMsgBuf;
          FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM |
                          FORMAT_MESSAGE_IGNORE_INSERTS, NULL,GetLastError(),
                          MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                          (LPTSTR) &lpMsgBuf, 0, NULL);
          MessageBox (NULL, (LPCTSTR)lpMsgBuf, "Error: ReadFile",
                      MB_OK | MB_ICONINFORMATION);
          LocalFree (lpMsgBuf);
        }
        else
        { // Ausgabe (oder Verarbeitung) der empfangenen Bytes:
          InString[dwRead] = '\0'; // in "zero-ended"-Stringverwandeln
          printf (TEXT("\r\n\tRxD (%d Byte(s)): %s"), dwRead,InString);
          WriteFile (hCom, &InString, dwRead, &iBytesWritten, NULL); //Senden der Bytes
        }
      }

      if (dwEvtMask & EV_ERR)
      {
        MessageBox (NULL, "Error empfangen", "Error: ReadFile",MB_OK);
        break; // Schleifen-Abbruch
      }
    }
  }
  while (1);

  CloseHandle (hCom);     // COM schließen
  CloseHandle (o.hEvent); // Event-Handle zurückgeben

  return (0);
}

Autor: Holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
BOOL          bRet      = true;
so besser ???
BOOL          bRet      = TRUE;
Der kennt true nicht!

BOOL          bRet      = 0x01;

Da is nur ein kleiner bug drin, mit ser variablen.
Also trivialer Fehler.


komentier mal

BOOL          bRet      = true;
da raus

Gruss Holger

Autor: Holger Harten (holger-h-hennef) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lege mal den Code als Anhang bei.
Mit der Kommentarzeile ist auch was nicht ok.
Gruss Holger

Autor: Kartoffel Salat (kartoffelsalat)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
genial!!!,danke, wie dumm von mir, hätte ich auch draufkommen können....

Nun es kann jetzt compiliert werden, fliegt aber beim ersten return raus 
mit einer fehlermeldung.
an was liegt das wohl?

ich bin leider noch nicht so erfahren mit c programmieren bzw mit dem 
Umgang der winAPI

was soll den eigentlich überprüft werden in der ersten if schleife?

Autor: Kartoffel Salat (kartoffelsalat)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
im Anhang
lesen.c

Autor: Holger Harten (holger-h-hennef) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was möchtest du zum testen machen ? .
Das Prog ist ein wenig unübersichtlich gemacht.
Ich muss das erst in kleinere Funktionen zerlegen, um das zu peilen,
was damit los ist,u. woher der Fehler kommen kan.
Das kan veile Gründe haben.


Bist du mit einem Microkontroller zugange ? .
Mit FTDI CHIP ???
Hast du USB seiell Anschluss, oder normales V24-Port.
Wen du immer sendest kan der Buffer 256 Byte überlaufen.
Mit dem Event ist bei USB-V24 so eine sache.
Ich muss das Prog erst mal an meiner Hardware testen.
Ich kan dir auch ein Kleines Terminal-Prog. schicken damit kan man
die Hardware erst mal testen.
Gruss Holger.

Autor: Kartoffel Salat (kartoffelsalat)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
was ich vor habe:

Ich erfasse mit einem Mikrokontriller (xc866 Infineon) periodisch 
Messwerte welche nacheinender (alle 5 Sekunden über die Rs232 gesendet 
und vom pc empfangen werden. (Bd: 300,8N1)

Ich Möchte nun eine C konsolenapplikationschreiben (für eine win 
Applikation reichen meine C kenntnisse nicht)welche die Messwerte im 
Fenster anzeigt.

Die programmierung für die Anzeige und Speichreung ist kein Problem, 
aber mit dem Einlesen und Ausgeben über die RS232 tuhe ich mich schwer.
Deshalb versuche ich den geposteten Code zu übernehmen und entsprechend 
abzuändern. bei der ganzen winapi sache sehe ich nicht durch.

Ich brauche diese Applikation also nicht um die hardware zu testen 
sondern um die Daten des uP zu visualisieren.

um den C-code zu testen habe ich allerdings einen zweiten Pc übers 
Nullmodem kabel verbunden.

habe einen Normalen Seriellen RS232 Port (D sub, 9Pol)

Gruss Raphael

Autor: Holger Harten (holger-h-hennef) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Raphael
Genau so habe ich auch angefangen.
Geht den die V24 PC<---->PC Kopplung
mit z.B Hyper-Term von PC auf PC ?
Wen du da am Keyboard tastest ?.

Ich habe Microsft Visual Studio  C++ V.6.
Was hast du für einen Compiler ?

Ich werde mal nach meinem Window V24-TerminalProg raussuchen.
Als Source Code.
Dan können wir uns weiter austauschen.

Und du kanst dan den Code aufbohren, und lernen wie so ein
VT100 V24-Terminal-Code funktioniert.

So habe ich das auch gemacht, mit uC dran ADC,Temp. messen usw.

Die Terminal-Progs als Source Code sind echte Monster-Files,
können etliche modis usw,
und man kan nicht sorecht was mit anfangen.

Ich versuche natürlich auch dein Beispiel sicher zum laufen zu bekommen.
Das ist der Schlüssel zum Erfolg.

"VT100 DEC-Terminal Emulation".


Obwohl so ein ConsolenProg für Anfänger nich ganz einfach ist,
mit Scrollen,CR LF und der Cursorsteuerung.
Wichtig ist auch das du den Source-Code selber compilen kanst.
Open Binary mode.

Gruss Holger.



Autor: Blackbird (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Raphael,
der Orginal-Source-Code ist von mir mal vor langer Zeit in das Forum 
hier reingestellt worden.
Das Erste, was in Deinem Codebeispiel fehlt, ist #include <windows.h>
Denn die Console ist auch ein Windows-Fenster und die API-Aufrufe sind 
Win32-APIs.
Dann ist auch das mit TRUE, true und 0x01 "geklärt".


Wenn Du mit 300,8N1 empfangen willst, solltest Du im Sourcecode die 
entprechenden Stellen auch anpassen:

#define BD_RATE         CBR_300 // 300 Baud

bRet liefert den Fehlercode der ReadFile-Funktion. Der wird mit der 
nachfolgenden Funktion (GetLastError und FormatMessage) lesbar 
ausgegeben.

Jedes empfangene Zeichen oder Zeichenkette (wieviel, das bestimmt das 
Timeout), wird mit einer 0 (0x00 oder '\0') am Ende versehen, angezeigt: 
printf (TEXT("\r\n\tRxD (%d Byte(s)): %s"), dwRead,InString);
und zurückgesendet:
WriteFile (hCom, &InString, dwRead, &iBytesWritten, NULL);

Das Anzeigen kannst Du nach eigenen Wünschen verändern, das Zurücksenden 
weglassen.
Sind die Daten von µC denn ASCII-Zeichen? Wenn nicht, so müssen sie vor 
dem Anzeigen erst noch in das ASCII-Format gewandelt werden (oder Du 
hast den schönsten Buchstabensalat auf dem Monitor).

Blackbird

Autor: Blackbird (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Code ist mit MS VC 6.0 entwickelt und getestet worden, sollte aber 
auch mit jedem anderen Windows-Compiler/Linker funktionieren.

Aber #include <windows.h> nicht vergessen!

Blackbird

Autor: Kartoffel Salat (kartoffelsalat)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Holger
> Geht den die V24 PC<---->PC Kopplung
> mit z.B Hyper-Term von PC auf PC ?
> Wen du da am Keyboard tastest ?.

Ja das funktioniert mit zwei hyperterminals problemlos
>
> Ich habe Microsft Visual Studio  C++ V.6.
> Was hast du für einen Compiler ?

ich arbeite mit dem
DEV.C++ von Bloodshed.
habe mir schon öffters gedanken drüber gemacht auf MS Visualstudio zu 
wechseln. ist das zu empfehlen? Visualstudio  kann ja kostenlos auf der 
MS page heruntergeladen werden...

> Ich werde mal nach meinem Window V24-TerminalProg raussuchen.
> Als Source Code.
> Dan können wir uns weiter austauschen.
> Und du kanst dan den Code aufbohren, und lernen wie so ein
> VT100 V24-Terminal-Code funktioniert.
>

das wäre ausgezeichtet!

Vielen dank für deine Hilfe

Gruss Raphael

Autor: Kartoffel Salat (kartoffelsalat)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Blackbird
Hallo

> der Orginal-Source-Code ist von mir mal vor langer Zeit in das Forum
> hier reingestellt worden.

Ja genau von dort hab ich Ihn auch, dort ist noch ein anderes beispiel 
mit welchem nur auf den port geschrieben werden kann. Das hat 
einwandferei funktioniert.

das Thema "TRUE" at sich geklärt.
Beim aktuellen Beispiel kommt aber immer noch die genannte 
Fehlermeldung:

""Aufruf mit: progname<COM-Port-Nummer""

wiso?

> Das Erste, was in Deinem Codebeispiel fehlt, ist #include <windows.h>

<windows.h> ist schon drin, ein paar zeilen weiter unten.

> Sind die Daten von µC denn ASCII-Zeichen? Wenn nicht, so müssen sie vor
> dem Anzeigen erst noch in das ASCII-Format gewandelt werden (oder Du
> hast den schönsten Buchstabensalat auf dem Monitor).

nein es sind Hexwerte die empfangen werden.

erstmal muss ich überhaupt was empfangen können.

gruss Raphael

Autor: Blackbird (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Naja, wenn Du  nicht angibst, welche COM-Schnittstelle das Programm 
öffnen soll, dann kommt diese Aufforderung. Ist doch so programmiert.
Zuerst wird geprüft, ob die Aufrufzeile alle Angaben enthält, wenn 
nicht, siehe Meldung.

Bei Dir müßte in der Kommandozeile das eingegeben werden:

lesen 1
 (danach ENTER drücken)

Damit wird die COM1 bedient. mit "lesen 2" wird COM2 bedient.


Hexwerte anzeigen wird Chaos auf dem Bildschirm bringen. Die solltest Du 
vor dem Anzeigen noch in ASCII-Zeichen wandeln oder in die von Dir 
gewünschte Entsprechung (sind's Temperaturen oder Zählerstände oder 
...?).


Blackbird

Autor: Nils (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Moin moin!

Ich hoffe, es stört niemanden, daß ich diesen alten Thread wiederbelebe. 
Ich arbeite aber mit dem gleichen Basis-Code von Blackbird. Vielleicht 
schaut er ja noch hier rein, oder sonst jemand, der von der Materie mehr 
Ahnung hat als ich...
Ich habe dieses Problem auch schon auf Roboternetz.de gepostet, aber 
dort ist die "PC-Programmierer"-Ecke nicht so gut besucht wie hier und 
es gab keine Antworten.

Wie gesagt, der Code ist der von Blackbird gepostete und funktioniert 
soweit, d.h. er läßt sich mit Visualstudio6 (Win32-Konsole) kompilieren 
und empfängt Daten. Ich habe ihn der Übersicht halber auf das reduziert, 
was ich brauche, nämlich das Einlesen von Daten, die der ATmega16 per 
USART sendet (soll ein Datenlogger werden).

Der AVR sendet testweise in seinem Programm nur einmal ein Telegramm von 
10 bytes. Er hängt am STK500, benutzt also dessen 5V-Versorgung und den 
Spare-RS232-Port. Damit sendet er immer dann ein Telegramm, wenn ich den 
Resetknopf auf dem STK500 drücke.

Jetzt zum Problem: Nachdem die 10 bytes empfangen worden sind, wird am 
COM-Port des PCs anscheinend das Event EV_RXCHAR noch einmal gesetzt. 
Aber ohne daß nochmal Daten empfangen worden wären. Die Ausgabe sieht so 
aus wie in dem angehängten Bild. Hier wurde zum Beispiel dreimal das 
Programm im AVR ausgeführt. Also wird dreimal das Telegramm empfangen, 
aber dann kommt immer noch eine Zeile, weil das Empfangsprogramm per 
Event nochmal in die ReadFile()-Schleife und damit auch zum printf() 
springt. Und ich habe keine Ahnung, wieso. Ich habe versucht, das Event 
an verschiedenen Stellen per ResetEvent() manuell zurückzusetzen (dazu 
auch mal beim Erzeugen des Events den Parameter MANUAL_RESET gesetzt), 
aber es kommt trotzdem wieder. COM_BUFFER_SIZE steht übrigens 
normalerweise auf 10, ich hatte es nur auf 11 gesetzt, um zu schauen, ob 
ich nicht versehentlich noch ein elftes Byte sende oder so... Aber mit 
10 sieht es genauso aus, nur daß halt in der Ausgabe die letzte Null in 
jeder Zeile nicht da ist.

Die C-Codes für den AVR und den PC hängen an, außerdem die 
Bildschirmausgabe.

Vielen Dank für jede Hilfe,

Nils

Autor: Nils (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
OK, da man anscheinend immer nur eine Datei anhängen kann, hier ist die 
zweite...

Autor: Nils (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Und hier die letzte...

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.