Forum: PC-Programmierung C win32 api Daten Übertragung


von Skaos (Gast)


Lesenswert?

Hallo leute,
ich habe folgendes Problem, ich habe ein Messgerät, das die Sicherheit 
von elektrischen Geräten prüft. Ich möchte mit einem C-Programm die 
Ergebnisse an den Pc übertragen. Ich habe dieses Programm geschrieben. 
Ich kann leider die Ergebnisse nicht richtig ausgeben, es kommen einfach 
sinnlosen Zahlen. Wenn ich die Ergebnisse durch den  Hyper-Terminal 
ausgebe, sind diese ganz normal, da ist sogar Text dabei nicht nur 
Zahlen.

1
#include <stdio.h>
2
3
#include <stdlib.h>
4
5
#include <windows.h>
6
7
#include <conio.h>
8
9
int main(void) {
10
11
12
13
  DCB dcb;
14
15
  HANDLE hPort;
16
17
18
19
  COMMTIMEOUTS cto;
20
21
  DWORD dw;
22
23
  unsigned char buf[0x100];
24
25
26
27
28
29
  dcb.DCBlength=sizeof(DCB);
30
31
  dcb.BaudRate=CBR_9600;
32
33
  dcb.ByteSize=8;
34
35
  dcb.Parity=NOPARITY;
36
37
  dcb.StopBits=ONESTOPBIT;
38
39
  cto.ReadIntervalTimeout=50;
40
41
    cto.ReadTotalTimeoutConstant=50;
42
43
  cto.WriteTotalTimeoutMultiplier=10;
44
45
  cto.WriteTotalTimeoutConstant=40;
46
47
48
49
  hPort=CreateFile( "COM1",GENERIC_READ | GENERIC_WRITE,0, NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
50
51
52
53
  if (hPort==INVALID_HANDLE_VALUE)
54
55
        {
56
57
            printf("CreateFile\n"); return 1;
58
59
            //printf("Create\n");
60
61
        }
62
63
      
64
65
    while(1)
66
67
    {
68
69
    if(!ReadFile(hPort, buf, 1, &dw,NULL))
70
71
        {
72
73
            //error occurred. Report to user.
74
75
            //sBuffer[0] = buff;
76
77
            //printf("%d\n",sBuffer);
78
79
        }
80
81
    printf("%d\n",buf[0]);
82
83
    }
84
85
86
87
CloseHandle(hPort);
88
89
return 0;
90
91
}

von Karl H. (kbuchegg)


Lesenswert?

>    printf("%d\n",buf[0]);
1
   printf("%c",buf[0]);

Dein Messgerät schickt dir Text.
Du betrachtest gerade die ASCII Codes dieses Textes. Als Dezimalzahlen 
ausgegeben können die ganz schön verwirrend sein

von Skaos (Gast)


Lesenswert?

vielen dank ist werde es morgen sofort testen :)
mfg

von Skaos (Gast)


Angehängte Dateien:

Lesenswert?

Ich habe es gestestet und es funktioniert, leider nicht richtig :(
Die Ausgabe sind sinnlosen ASCII Zeichnen, wie zum Beispiel Smilys.
Ich lade zwei Screenshots hoch, einen mit der Ausgabe auf dem 
HyperTerminal(wie es richtig ist) und den anderen ich in der Console 
bekomme.
Grüße

von Karl H. (kbuchegg)


Lesenswert?

Sieht aus als ob die Baudrate nicht stimmt.

Apropos: Wo stellst du die eigentlich ein?
Du befüllst zwar einen DCB, machst aber nichts damit .-)

von Skaos (Gast)


Lesenswert?

mhh die Baudrate stimmt 9600. 9600 stelle ich in dem Hyperterminal.
Wenn ich mit dem DCB nichts mache :S, wie kann ich dann etwas machen??

von Christian R. (supachris)


Lesenswert?

Skaos schrieb:
> mhh die Baudrate stimmt 9600. 9600 stelle ich in dem Hyperterminal.
> Wenn ich mit dem DCB nichts mache :S, wie kann ich dann etwas machen??

BuildCommDCB(...)
SetCommState(...)

von Edwar Y. (skaos)


Lesenswert?

Hallo danke für die schnelle Antwort, ich habe mein Programm so geändert 
leider bekomme ich immer noch eine falsche Ausgabe... Ich nuetze ich 
BuildCommDCB(...) SetCommState(...)  falsch, ich habe aber auf die msndn 
Seite nicht wirklich vrstanden :(
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <windows.h>
4
#include <conio.h>
5
int main(void) {
6
7
  DCB dcb;
8
  HANDLE hPort;
9
        COMMTIMEOUTS cto;
10
  DWORD dw;
11
  unsigned char buf[0x100];
12
  cto.ReadIntervalTimeout=50;
13
        cto.ReadTotalTimeoutConstant=50;
14
  cto.WriteTotalTimeoutMultiplier=10;
15
  cto.WriteTotalTimeoutConstant=40;
16
  hPort=CreateFile( "COM1",GENERIC_READ | GENERIC_WRITE,0,   NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
17
18
  if (hPort==INVALID_HANDLE_VALUE)
19
        {
20
            printf("CreateFile\n"); return 1;
21
            
22
        }
23
        
24
    GetCommState(hPort, &dcb);
25
    BuildCommDCB("9600,n,8,1", &dcb);
26
    while(1)
27
    {
28
    if(ReadFile(hPort, buf, 1, &dw,NULL))
29
        {
30
            //error occurred. Report to user.
31
        }
32
    printf("%s",buf);
33
    }
34
35
CloseHandle(hPort);
36
return 0;
37
}

von Karl H. (kbuchegg)


Lesenswert?

Edwar Yupanqui schrieb:
> Hallo danke für die schnelle Antwort, ich habe mein Programm so geändert
> leider bekomme ich immer noch eine falsche Ausgabe... Ich nuetze ich
> BuildCommDCB(...) SetCommState(...)  falsch, ich habe aber auf die msndn
> Seite nicht wirklich vrstanden :(


Entschuldige, aber:
Wie wäre es mit Gehirn einschalten?

In der MSDN ist sogar ein vollständiges Beispiel!


>     GetCommState(hPort, &dcb);
>     BuildCommDCB("9600,n,8,1", &dcb);

Und wo ist der SetCommState?

Set Comm State

so wie "Setzen der Kommunikationsparameter"

Du machst:
   Hole die momentan eingestellten    Get Comm State
   Erzeuge die Werte für ...          Build Comm DCB

aber du setzt sie nirgends. Du aktivierst sie nicht! Nur dadurch, dass 
du einer Variabeln bei dir einen Wert zuweist, stellt sich doch nicht 
die serielle Schnittstelle auf einen neuen Baudratenwert ein. Du musst 
dem Betriebssystem schon sagen: "Schau her. So möchte ich das Ding 
eingestellt haben" - Set Comm State

von Edwar Y. (skaos)


Lesenswert?

Ok danke für deine Hilfe.
Ich habe aber gerade entdeckt, dass das Programm ohne SetCommState 
funkrtioniert. Ich muss es so ausgeben:  printf("%c",buf[0]);

Warum geht das ohne SetCommState??

Wenn ich SetCommState nutze, wäre es so?
    GetCommState(hPort, &dcb);
    BuildCommDCB("9600,n,8,1", &dcb);
    SetCommState(hPort, &dcb);

danke und tut mir leid für meine dummen Fragen

von Christian R. (supachris)


Lesenswert?

Edwar Yupanqui schrieb:

> Warum geht das ohne SetCommState??


Weil 9600, 8N1 zufällig die Standard-Einstellung ist. Kannst du auch 
im Gerätemanager umstellen.

von Christian R. (supachris)


Lesenswert?


von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Dieser Code beschreibt eine MFC-Klasse. Einerseits ist das C++ (und kein 
C), andererseits ist die MFC nicht mit der kostenlosen Visual Studio 
Express-Variante nutzbar.

von Christian R. (supachris)


Lesenswert?

Richtig, aber die paar MFC-spezifischen Sachen kann man leicht ersetzen. 
Es ging mir eher ums Prinzip, damit dem TE klar wird, die man die DCB 
anwendet, die commstates setzt usw. und in welcher Reihenfolge das 
passiert.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Hältst Du das für wirklich wahrscheinlich?

von Christian R. (supachris)


Lesenswert?

Hmm....stimmt, er gab sich sehr lernresistent. Naja, man soll die 
Hoffnung nie aufgeben.

von Edwar Y. (skaos)


Lesenswert?

Christian R. schrieb:
> Hmm....stimmt, er gab sich sehr lernresistent. Naja, man soll die
> Hoffnung nie aufgeben.

Danke für das Beispiel. Jetzt funktioniert mein Programm auch.

von Peter (Gast)


Lesenswert?

Ich das Programm getestet, da ichso eine Datenübertragung sehr 
interessant finde.
Ich habe sogar ein paar SAchen ergänzt. Bei mir hat alles klapp, außer 
dass ich von der Schleife nicht rauskomme. Weiß vielleicht wie man das 
programmiert??
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <windows.h>
4
#include <conio.h>
5
int main(void)
6
{
7
  DCB dcb;
8
  FILE *datei;
9
  HANDLE hPort;
10
  COMMTIMEOUTS cto;
11
  DWORD dw;
12
  unsigned char buf[0x100];
13
  cto.ReadIntervalTimeout=50;
14
  cto.ReadTotalTimeoutConstant=50;
15
  cto.WriteTotalTimeoutMultiplier=10;
16
  cto.WriteTotalTimeoutConstant=40;
17
  hPort=CreateFile( "COM1",GENERIC_READ | GENERIC_WRITE,0,   NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
18
19
  if (hPort==INVALID_HANDLE_VALUE)
20
        {
21
            printf("CreateFile\n"); return 1;
22
        }
23
24
    GetCommState(hPort, &dcb);
25
    BuildCommDCB("9600,n,8,1", &dcb);
26
    SetCommState(hPort, &dcb);
27
28
    while(hPort!=NULL)//Ich komme nicht aus der Schleife raus
29
    {
30
        ReadFile(hPort, buf, 1, &dw,NULL);
31
        printf("%c",buf[0]);
32
        datei=fopen("Messung.txt", "a+");
33
        fprintf(datei,"%c",buf[0]);
34
        fclose (datei);
35
    }
36
CloseHandle(hPort);
37
38
return 0;
39
}

von Peter (Gast)


Lesenswert?

> Ich habe sogar ein paar SAchen ergänzt. Bei mir hat alles klapp, außer
> dass ich von der Schleife nicht rauskomme. Weiß vielleicht wie man das
> programmiert??
dafür musst du aber erstmal sagen, wann das programm aus der schleife 
rauskommen soll. Bei Testendruck, bei einem zeichen was empfangen wird 
order evnetuell nach 5min.

Das öffnen und schliesen der Datei würde ich nicht in der Schleife 
machen.

von Peter (Gast)


Lesenswert?

mhhh ja das habe ich schon versucht.
1. Versucht:
1
while(hPort!=NULL) //Ich komme nicht aus der Schleife raus
2
    {
3
        ReadFile(hPort, buf, 1, &dw,NULL);
4
        printf("%c",buf[0]);
5
        if(kbhit())//if (getchar()=='q') break;
6
    }

2. Versucht

while(hPort!=NULL)//Ich komme nicht aus der Schleife raus
    {
        ReadFile(hPort, buf, 1, &dw,NULL);
        printf("%c",buf[0]);
        if(kbhit())
        {
            taste = getch();
            break;
        }
    }

von Karl H. (kbuchegg)


Lesenswert?

Na ja.
Was stellst du dir den vor, wann hPort jemals NULL werden soll?

hPort wird nie von alleine NULL! Du hast den Port in Beschlag und 
solange dein Programm läuft und du den seriellen Port nicht schliesst, 
ist er deinem Programm zugeordnet.

Wenn deine Schleife laufen soll, solange ein Sender sendet, musst du mit 
dem sendenden Programm etwas vereinbaren, woraus der Empfänger erkennen 
kann: Das wars, ab jetzt kommen keine Daten mehr.

Wie du das machst: lass deine Phantasie spielen. Das kann sein, dass die 
Gegenstelle ein bestimmtes Zeichen sendet. Das kann sein, dass die 
Übertragung überhaupt nach einem Protokoll abgewickelt wird, das kann 
sein, dass dein Programm in einen Timeout läuft. Irgendwas. Denk dir was 
aus.

von Peter (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Wie du das machst: lass deine Phantasie spielen. Das kann sein, dass die
> Gegenstelle ein bestimmtes Zeichen sendet. Das kann sein, dass die
> Übertragung überhaupt nach einem Protokoll abgewickelt wird, das kann
> sein, dass dein Programm in einen Timeout läuft. Irgendwas. Denk dir was
> aus.

Danke für deine Hilfe, ich habe es geschafft ;). Gibts eventuell 
Verbesserungsvorschläge???
Ich poste mein Programm, falls es vielleicht jemand interessiert.
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <windows.h>
4
#include <conio.h>
5
#include <time.h>
6
//#include <Sleep.h>
7
int main(void)
8
{
9
    DCB dcb;
10
    FILE *datei;
11
    HANDLE hPort;
12
    DWORD dw;
13
    char zeichen[2000];
14
    char t[1]=":";
15
    int i=1;
16
    int schalter=1;
17
    unsigned char buf[1];
18
    hPort=CreateFile( "COM1",GENERIC_READ | GENERIC_WRITE,0,   NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
19
    GetCommState(hPort, &dcb);
20
    BuildCommDCB("9600,n,8,1", &dcb);
21
    SetCommState(hPort, &dcb);
22
    while (hPort!=0)
23
        {
24
        ReadFile(hPort, buf, 1, &dw,NULL);
25
        printf("%c",buf[0]);
26
        datei=fopen("Messung.txt", "a+");
27
        fprintf(datei,"%c",buf[0]);
28
        fclose (datei);
29
        if(buf[0]==23)break;
30
        }
31
    CloseHandle(hPort);
32
33
return 0;
34
}

von Christian R. (supachris)


Lesenswert?

Peter schrieb:
> Gibts eventuell Verbesserungsvorschläge???

Naja, da du sämtliche Fehler-Behandlung einfach mal weggelassen hast, 
würde ich da mal ansetzen....

von Peter (Gast)


Lesenswert?

Peter schrieb:
> Gibts eventuell Verbesserungsvorschläge???

ja der gleiche wie oben schon einmal, nicht ständig die Datei 
"Messung.txt" öffenen und schließen.

von Karl H. (kbuchegg)


Lesenswert?

Den Schwachsinn

    while (hPort!=0)
        {

hast du immer noch drinnen

hPort ist ein Handle! Das ist eine Art Kennung, die dir vom 
Betriebssystem gegeben wird und der dir exklusiven Zugang zum Gerät 
'serielle Schnittstelle' gewährt. Mit dem Handle hast du das Gerät in 
Beschlag, solange bis du CloseHandle aufrufst.
hPort KANN in deinem Programm niemals 0 werden!
Damit suggeriert diese Schleife etwas, was einfach nicht stimmt, weil 
der Fall gar nicht eintreten kann!


> ja der gleiche wie oben schon einmal, nicht ständig die Datei
> "Messung.txt" öffenen und schließen.

Das kann sogar sinnvoll sein. Wenn von der seriellen die Daten nur 
tröpfchenweise kommen und man sicher gehen möchte, dass jedes 
einkommende Datum sofort tatsächlich am File landet und nicht erst 
vorher noch in einem Cache rumlungert. Sicher ein flush hätte es 
wahrscheinlich auch getan aber im Falle eines Absturzes möchte ich mich 
nicht unbedint darauf verlassen, das das Filesystem hinter mir 
zusammenräumt.


Das komplette Fehlen jeglicher Fehlerbehandlung wiegt da sehr viel 
schwerer. Und natürlich, dass der Code vor der Veröffentlichung erst mal 
aufgeräumt werden sollte. Was da Includes und Variablen rumlungern, die 
kein Mensch braucht ....

von Peter (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Sicher ein flush hätte es
> wahrscheinlich auch getan aber im Falle eines Absturzes möchte ich mich
> nicht unbedint darauf verlassen, das das Filesystem hinter mir
> zusammenräumt.

aber beim öffnen und schliesen müssen mehr Änderrungen am Dateisystem 
gemacht werden als beim flush, damit ist das risiko sogar höher das bei 
einem Abstuzt etwas verloren geht.
Außerdem sollte man heute davon ausgehen das die Hardware und das 
Betriebsystem richtig arbeiten. Wenn nur die Anwendung abstützt bleibt 
das Dateisystem auf jeden fall ganz. Man müsste ja auch sonst eventuell 
beachten das der Speicher defekt ist und eine Variable den Inhalt ändert 
ohne das man etaws dafür kann.

von Karl H. (kbuchegg)


Lesenswert?

Peter schrieb:
> Karl heinz Buchegger schrieb:
>> Sicher ein flush hätte es
>> wahrscheinlich auch getan aber im Falle eines Absturzes möchte ich mich
>> nicht unbedint darauf verlassen, das das Filesystem hinter mir
>> zusammenräumt.
>
> aber beim öffnen und schliesen müssen mehr Änderrungen am Dateisystem
> gemacht werden als beim flush, damit ist das risiko sogar höher das bei
> einem Abstuzt etwas verloren geht.
> Außerdem sollte man heute davon ausgehen das die Hardware und das
> Betriebsystem richtig arbeiten. Wenn nur die Anwendung abstützt bleibt
> das Dateisystem auf jeden fall ganz. Man müsste ja auch sonst eventuell
> beachten das der Speicher defekt ist und eine Variable den Inhalt ändert
> ohne das man etaws dafür kann.

ICh hab's schon lang nicht mehr ausprobiert. Aber wie ist das mit 
heutigen Windows-en. Früher war es so, das man eine Datei, die ein 
Programm zu schreiben offen hatte, nicht auch noch gleichzeitig lesend 
öffnen konnte. Existiert diese Restriktion noch?

(Von daher unter anderem auch die Angewohnheit eine Datei nur solange 
wie unbedingt notwendig offen halten)

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

> Früher war es so, das man eine Datei, die ein
> Programm zu schreiben offen hatte, nicht auch noch gleichzeitig lesend
> öffnen konnte. Existiert diese Restriktion noch?

Unter den 32-Bit-Versionen von Windows war das noch nie so, da konnte 
das Verhalten durch die Flags gesteuert werden, die der Funktion 
CreateFile übergeben werden.

von Peter (Gast)


Lesenswert?

Vielen dank für eure Vorschläge,

Karl heinz Buchegger schrieb:
> Den Schwachsinn
>
>     while (hPort!=0)
>         {
>
> hast du immer noch drinnen

ich hab jetzt ein boolsches Wert

while(schalter==true)

Christian R. schrieb:
> Naja, da du sämtliche Fehler-Behandlung einfach mal weggelassen hast,
> würde ich da mal ansetzen....

Die Fehler-Behandlung habe ich gerade hinzugefügt
Vielen Dank nochmal für eure Hilfe

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.