Forum: PC-Programmierung com schnittstelle mit c ansprechen


von Kartoffel S. (kartoffelsalat)


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)
1
include <stdio.h>
2
#include <stdlib.h>
3
4
// 32-Bit-Konsolen-Programm zum Senden/Empfangen von Bytes über COM(9600-8N1)
5
// Alle empfangenen Bytes werden zurückgesendet.
6
// OS: W95, W98, W98SE, WinME, WinNT, Win2000, WinXP
7
// Note: Keine Fehlerbehandlung implementiert!
8
#include <windows.h>
9
#include <stdio.h>
10
11
#define COM_BUFFER_SIZE 256       // Read- und Write-Buffer-Size
12
#define BD_RATE         CBR_9600 // 9600 Baud
13
#define HELP_STRING TEXT("Aufruf mit: progname<COM-Port-Nummer>\r\n")
14
15
16
// Hauptprogramm: Aufruf mit: progname <COM-Port-Nummer>
17
int main (int argc, char **argv)
18
{
19
  DCB           dcb;
20
  DWORD         iBytesWritten;
21
  BOOL          bRet      = true;
22
  DWORD         dwRead    = 0;
23
  DWORD         dwSetMask = EV_RXCHAR | EV_ERR;
24
  DWORD         dwEvtMask;
25
  OVERLAPPED    o;
26
  COMMTIMEOUTS  ct;
27
  unsigned char InString[COM_BUFFER_SIZE + 1];
28
  TCHAR         szCOM[6];
29
30
31
  if (argc == 2 &&                              // progname +COM-Port-Nummer ?
32
      atoi (argv[1]) > 0 && atoi (argv[1]) < 5) // COM1 ... COM4?
33
    wsprintf (szCOM, TEXT("COM%s"), argv[1]);   // String "basteln"...
34
  else
35
  {
36
    printf (TEXT("\r\nERROR:\t %s"), HELP_STRING);
37
    return (1); // und tschüß ...
38
  }
39
40
  memset (&o, 0, sizeof (OVERLAPPED)); // Struktur mit 0en füllen
41
  o.hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); // einen Eventsetzten
42
43
  HANDLE hCom = CreateFile (szCOM, GENERIC_WRITE | GENERIC_READ, 0,NULL,
44
                            OPEN_EXISTING, 0, NULL);
45
46
47
  if (hCom == INVALID_HANDLE_VALUE)
48
  { // Fehlerausgabe:
49
    LPVOID lpMsgBuf;
50
    FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM |
51
                    FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(),
52
                    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL);
53
    MessageBox (NULL, (LPCTSTR)lpMsgBuf, "Error: CreateFile", MB_OK |MB_ICONINFORMATION);
54
    LocalFree (lpMsgBuf);
55
    return (1); // und tschüß ...
56
  }
57
58
  dcb.DCBlength = sizeof(DCB);  // Laenge des Blockes MUSS gesetztsein!
59
  GetCommState (hCom, &dcb);    // COM-Einstellungen holen und aendern
60
  dcb.BaudRate  = BD_RATE;      // Baudrate
61
  dcb.ByteSize  = 8;            // Datenbits
62
  dcb.Parity    = NOPARITY;     // Parität
63
  dcb.StopBits  = ONESTOPBIT;   // Stopbits
64
  SetCommState (hCom, &dcb);    // COM-Einstellungen speichern
65
66
  GetCommTimeouts (hCom, &ct);
67
  // Warte-Zeit [ms] vom Beginn eines Bytes bis zum Beginn des nächstenBytes
68
  ct.ReadIntervalTimeout         = 1000 / BD_RATE * (dcb.ByteSize +
69
                                                     (dcb.Parity ==NOPARITY ? 0 : 1) +
70
                                                     (dcb.StopBits ==ONESTOPBIT ? 1 : 2)) * 2;
71
  ct.ReadTotalTimeoutMultiplier  = 0;  // [ms] wird mit Read-Buffer-Sizemultipliziert
72
  ct.ReadTotalTimeoutConstant    = 50; // wird anReadTotalTimeoutMultiplier angehängt
73
  ct.WriteTotalTimeoutMultiplier = 0;
74
  ct.WriteTotalTimeoutConstant   = 0;
75
  SetCommTimeouts (hCom, &ct);
76
77
  // Zwischenspeicher des serial-Drivers einstellen (für read undwrite):
78
  SetupComm (hCom, COM_BUFFER_SIZE, COM_BUFFER_SIZE);
79
  SetCommMask (hCom, dwSetMask); // Empfangssignale definieren
80
81
  do  // in Endlos-Schleife auf Empfangssignale warten:
82
  {
83
    WaitCommEvent (hCom, &dwEvtMask, &o); // Event mit Empfangssignalenverknüpfen
84
85
    if (WAIT_OBJECT_0 == WaitForSingleObject (o.hEvent, INFINITE)) //warten bis Event
86
    {
87
      if (dwEvtMask & EV_RXCHAR) // Zeichen an RxD empfangen:
88
      {
89
        bRet = ReadFile (hCom, &InString, sizeof (InString), &dwRead,NULL);
90
91
        if (!bRet)
92
        { // Fehlerausgabe:
93
          LPVOID lpMsgBuf;
94
          FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM |
95
                          FORMAT_MESSAGE_IGNORE_INSERTS, NULL,GetLastError(),
96
                          MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
97
                          (LPTSTR) &lpMsgBuf, 0, NULL);
98
          MessageBox (NULL, (LPCTSTR)lpMsgBuf, "Error: ReadFile",
99
                      MB_OK | MB_ICONINFORMATION);
100
          LocalFree (lpMsgBuf);
101
        }
102
        else
103
        { // Ausgabe (oder Verarbeitung) der empfangenen Bytes:
104
          InString[dwRead] = '\0'; // in "zero-ended"-Stringverwandeln
105
          printf (TEXT("\r\n\tRxD (%d Byte(s)): %s"), dwRead,InString);
106
          WriteFile (hCom, &InString, dwRead, &iBytesWritten, NULL); //Senden der Bytes
107
        }
108
      }
109
110
      if (dwEvtMask & EV_ERR)
111
      {
112
        MessageBox (NULL, "Error empfangen", "Error: ReadFile",MB_OK);
113
        break; // Schleifen-Abbruch
114
      }
115
    }
116
  }
117
  while (1);
118
119
  CloseHandle (hCom);     // COM schließen
120
  CloseHandle (o.hEvent); // Event-Handle zurückgeben
121
122
  return (0);
123
}

von Holger (Gast)


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

von Holger H. (holger-h-hennef) Benutzerseite


Lesenswert?

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

von Kartoffel S. (kartoffelsalat)


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?

von Kartoffel S. (kartoffelsalat)


Angehängte Dateien:

Lesenswert?

im Anhang
lesen.c

von Holger H. (holger-h-hennef) Benutzerseite


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.

von Kartoffel S. (kartoffelsalat)


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

von Holger H. (holger-h-hennef) Benutzerseite


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.



von Blackbird (Gast)


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

von Blackbird (Gast)


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

von Kartoffel S. (kartoffelsalat)


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

von Kartoffel S. (kartoffelsalat)


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

von Blackbird (Gast)


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

von Nils (Gast)


Angehängte Dateien:

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

von Nils (Gast)


Angehängte Dateien:

Lesenswert?

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

von Nils (Gast)


Angehängte Dateien:

Lesenswert?

Und hier die letzte...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.