Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » VC++ / MFC » CreateFile / TimeStamp

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
27.07.2004, 16:35 Uhr
~wasa
Gast


Tagchen!

sorry das ich schon wieder nerven muss!
Habe doch den Com mit CreateFile geöffnet und lasse mir Messdaten senden. Nun würde ich aber gern Intervalle angeben, wann mein Steuerprogramm Messungen durchführen soll, also bsp nach 5 oder 10 sekunden. Das Problem ist das, wenn einmal der com geöffnet wurde sendet das Messgerät ununterbrochen die Daten rüber. Wenn ich nun nach 5 sek eine Messung vornehmen will, nimmt das Steuerprogramm nicht den aktuellen wert der auf dem Display erscheint sondern den, den das Messgerät zuerst nach der 1. Messung gesendet hat. also einen "falschen" wert. Wie kann ich dies unterbinden bzw. wie komme ich an den exakten zu diesem zeitpunkt gemessenen wert??
Ich habe da was von TimeStamp gehört, aber da habe ich keine ahnung von. Wäre schön wenn mir jemand das erklären könnte, wenn es damit geht.
Oder kann man auch einfach nach der ersten Messung den Com schließen und bei der nächsten den COM wieder öffnen??? Aber wie schließe ich den COM??
Mit CreateFile öffne ich ja, aber wie ich den schließe weiß ich nicht, gibt es da ne funktion (CloseFile?? funktioniert aber net)!
Ich hoffe ihr versteht was ich meine und hoffe ihr könnt mir helfen!!
DANKE SCHOMAL!!!!!
CU WASA
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
27.07.2004, 16:48 Uhr
ao

(Operator)


Ich vermute mal, dass das Messgerät immer sendet, weil es ja gar nicht wissen kann, ob an der Schnittstelle ein Computer horcht oder nicht, oder wird da irgendwas mit den Handshake-Signalen gemacht? Das Kabel zwischen DMM und PC ist doch nur 2- oder 3-adrig, oder?

Ich glaube du brauchst keine Zeitstempel, du musst nur sicherstellen, dass immer die neuesten aus ReadFile stammenden Daten dekodiert und angezeigt werden. Das scheint mir nicht der Fall zu sein.

ao
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
27.07.2004, 16:55 Uhr
~wasa
Gast


Tagchen!

Handshakes wird DTS gesetzt, RTS kurz dann off (obwohl ich nicht weiss wie man das kurz an und dann aus schaltet!)

ob 2 oder 3polig keine Ahnung! wie kriegt man das raus? aufjeden fall hängt es am com. ;-)

habe einen Puffer von 1000 angelegt.
Mit der ReadFile funktion lasse ich mir nen 14 Byte großen String auslesen, da das Messgerät auch nur en 14 Byte string sendet, pro messung.
sobald ich aber den nächsten string nach circa 5 sek auslese stimmt der messwert nicht mehr. Aber schon nach einer sekunde "hinkt" das Auslesen hinterher!

keine Ahnung!
hoffe du kannst helfen!
DANKE
cu wasa
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
27.07.2004, 17:30 Uhr
ao

(Operator)



Zitat von ~wasa:
Handshakes wird DTS gesetzt, RTS kurz dann off

Also gut, dann wird da doch was gemacht. Aber ist auch nicht wirklich wichtig.


Zitat:
habe einen Puffer von 1000 angelegt.

Warum so viel? Einfach nur so, oder hat das einen Zweck?

Ich hätte jetzt erwartet, dass dein Programm etwa folgende Struktur hat:


Code:
    Initialisieren ();

    COM_oeffnen ();

    char cBuffer [14];
    float fValue;
    
    while (! EndOfProgram)
    {
        ReadFile (cBuffer, 14, Com_Port); // wartet, bis 14 Zeichen da sind (kann 5 Sekunden dauern)
        fValue = Dekodieren (cBuffer);
        Anzeigen (fValue);
    }



Auf die Weise hast du automatisch immer aktuelle Daten im Puffer.


Zitat:
sobald ich aber den nächsten string nach circa 5 sek auslese stimmt der messwert nicht mehr. Aber schon nach einer sekunde "hinkt" das Auslesen hinterher!


Wie ist dein Programm aufgebaut? Wo speichert ReadFile die empfangenen Daten, und wo holt die Dekodier-Routine sie ab?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
27.07.2004, 23:44 Uhr
~wasa
Gast


Tagchen!

also, das ist gar nicht so einfach.
Mein Program ist dialogfeld basierend. Habe dort nen Button, der, wenn gedrückt wurde, einen Thread laufen lässt, der ein Verzeichnis nach ner bestimmten Datei durchsucht. sobald die datei gefunden wurde, liest er davon die daten aus. Danach öffnet er den ComPort und liest mittels ReadFile den AusgabeString des Messgerätes ein.
Ich bekomme nen 14 Byte langen String. Den ich dann (leider) dekodieren muss, da binär codiert, wenn dies erfolgt ist gebe ich die Daten in nem Listenfeld aus.
Das läuft alles in dem einen Thread!
Wenn ich die daten ausgegeben habe, soll das Steuerprogramm die nächste Messung vornehmen!


Zitat von Verfasser:

habe einen Puffer von 1000 angelegt.


Warum so viel? Einfach nur so, oder hat das einen Zweck?



Mir wurde gesagt, dass man das machen soll, da das Messgerät doch ständig Daten sendet.


NICHT ERSCHRECKEN, ICH STELL HIER MAL DEN QUELLCODE REIN!!!
ComPort.h

C++:
#include <windows.h>

class CCOM_PORT1{
public:
    CCOM_PORT1();
    ~CCOM_PORT1();

    int modul, rc;

    HANDLE Open_Comport_HS();

    int Write_Comport_HS (HANDLE DriverHandle, DWORD NumBytes, void *Buffer);
    int Read_Comport_HS (HANDLE DriverHandle, DWORD NumBytes, void *Buffer);
    
};



Die Funktionen zum Öffnen / Lesen / Schreiben des COMs

C++:
#include "stdafx.h"
#include "COM_PORT1.h"

CCOM_PORT1::CCOM_PORT1(){
}

CCOM_PORT1::~CCOM_PORT1(){
}



HANDLE CCOM_PORT1::Open_Comport_HS(){
    HANDLE  DriverHandle;
    DCB     Our_DCB;

    
    DriverHandle = CreateFile ("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL);//OPEN_EXISTING
      
    if(DriverHandle!=0){
        GetCommState(DriverHandle, &Our_DCB);

        Our_DCB.BaudRate = 2400;        //2400
        Our_DCB.ByteSize = 8;
        Our_DCB.Parity   = NOPARITY;
        Our_DCB.StopBits = ONESTOPBIT;

        Our_DCB.fDtrControl = DTR_CONTROL_ENABLE;
        //Our_DCB.fRtsControl = RTS_CONTROL_HANDSHAKE;

          SetCommState(DriverHandle,&Our_DCB);

        return DriverHandle;
    }else
        return 0;
}

int CCOM_PORT1::Write_Comport_HS (HANDLE DriverHandle, DWORD NumBytes, void *Buffer){
    DWORD BytesWritten;
    BOOL status;
    status = WriteFile (DriverHandle, Buffer, NumBytes, &BytesWritten, 0);
    return TRUE;
}

int CCOM_PORT1::Read_Comport_HS (HANDLE DriverHandle, DWORD NumBytes, void *Buffer){
    DWORD BytesRead;
    BOOL status;
    char *ptr;

    ptr=(char*)Buffer;
    status = ReadFile (DriverHandle, Buffer, NumBytes, &BytesRead, 0);
    ptr+=BytesRead;
    *(ptr)=0x00;
    
    return TRUE;
}



und nun der Hammer, ist Auszug aus der ..dlg.cpp
müsstest du ja kennen ;-)
hoffe ich kreig kein ärger, wenn ich so viel hier reinstelle

C++:
void CVersion1507Dlg::Verz_RunThread()
{
        // TODO: Code für die Behandlungsroutine der Steuerelement-Benachrichtigung hier einfügen
    WIN32_FIND_DATA V_Data;                //DatenVerzeichnis
    
    CString s_file,s_temp,s_Schreibe, s_Eintrag="", minus="", ein1="", ein2="", ac="", dc="", auto1="", rs232c="", prafix0="", prafix="", prafix2="", prafix3="", komma=",";
    char    c_Daten[13];
    FILE*    f_File;
    int zahl1, zahl2, zahl3, zahl4;
    
    
    // Verzeichnisabfrage
    while (verz_i_Flag)
    {
    HANDLE hSearch = FindFirstFile("C:\\Messungen\\*.what",&V_Data);
    // Wenn File gefunden....
    if((int) hSearch!=-1)
    {
    Onleeren();
    ListenEintrag("-----Datei gefunden-----");
    s_temp = V_Data.cFileName;
    s_file = "C:\\Messungen\\";
    s_file = s_file+s_temp;
    s_Eintrag.Format("Datei:%s",s_file);
    ListenEintrag(s_Eintrag);
                
    f_File    = fopen(s_file,"rt");
    s_temp = fgets(c_Daten,13,f_File);
    s_Eintrag.Format("Daten: %s",s_temp);
    ListenEintrag(s_Eintrag);


    s_Eintrag.Format("Wiederholungen: %c", c_Daten[0]);
    ListenEintrag(s_Eintrag);
    s_Eintrag.Format("Intervall: %c", c_Daten[1]);
    ListenEintrag(s_Eintrag);
    
    // Com öffnen
    com_ComHandle1=com_port_1.Open_Comport_HS();
    Sleep(500);
    ListenEintrag("COM geöffnet!!");
    
    for (int n=1; n<=3; n++)
    {
    com_port_1.Read_Comport_HS(com_ComHandle1, 14, L);
             //L ist halt der Buffer L[1000];
  

    // Byte 0 auslesen und interpretieren
    int y=(L[0]&0x01);
    int y1=(L[0]&0x02);
    int y2=(L[0]&0x04);
    int y3=(L[0]&0x08);
    if(y == 0) {rs232c = "no";} else {rs232c = "yes";}
    if(y1 == 0)    {auto1 = "no";}    else {auto1 = "yes";}
    if(y2 == 0)    {dc = "";} else {dc = "Gleichgröße";}
    if(y3 == 0) {ac = "";} else {ac = "Wechselgröße";}
    //s_Eintrag.Format("rs232: %s  auto: %s  dc: %s  ac: %s", rs232c, auto1, dc, ac);
    //ListenEintrag(s_Eintrag);

    // Byte 1 und 2 auslesen und interpretieren sowie in "Zahlen" umwandeln
    int x=(L[1]&0x07)*16+(L[2]&0x0F);
    switch (x)
    {
    case 125: zahl1 = 0;
        break;
    case 5:    zahl1 = 1;
        break;
    case 91:    zahl1 = 2;
        break;
    case 31:    zahl1 = 3;
        break;
    case 39:    zahl1 = 4;
        break;
    case 62:    zahl1 = 5;
        break;
    case 126:    zahl1 = 6;
        break;
    case 21:    zahl1 = 7;
        break;
    case 127:    zahl1 = 8;
        break;
    case 63:    zahl1 = 9;
        break;
    }
    // das mache ich nunn noch mal für byte 3-8 habe ich aber aus
            // Platzgründen weggelassen
    // Byte 9 auslesen und interpretieren
    int neun=(L[9]&0x01);
    int neun1=(L[9]&0x02);
    int neun2=(L[9]&0x04);
    int neun3=(L[9]&0x08);
    if(neun != 0)
    {
        prafix0 = "diode";
    }
    else
    {
        if(neun1 != 0)
        {
            prafix0 = "k";
        }
        else
        {
            if(neun2 != 0)
            {
                prafix0 = "n";
            }
            else
            {
                if(neun3 != 0)
                {
                    prafix0 = "u";
                }
                else
                {
                    prafix0 = "";
                }
            }
        }
    }
            // Mache ich noch für Byte 10-13 um Präfixe etc zu ermitteln
            // Wegen Platzgründen weggelassen

            // Das stimmt nun halt so nicht, wegen der undefinierten konstanten
s_Eintrag.Format("Gesamter Messwert mit Einheit: %s%i%i%i%i%s%s%s%s", minus, zahl1, zahl2, zahl3, zahl4, prafix0, prafix, prafix2, prafix3);
    ListenEintrag(s_Eintrag);
    
    
    // Intervallangabe pause
    Sleep(5000);
    }


    //Wegen löschen Testzwecke
    Sleep(30000);
    
/*
    fclose(f_File);
    DeleteFile(s_file);
    TRACE("\n\n*************Datei %s wurde gelöscht*************\n\n",s_file);
    s_Eintrag.Format("Datei %s wurde gelöscht",s_file);
    ListenEintrag(s_Eintrag);
    Sleep(2000);
*/

    }
    else
    {
    ListenEintrag("-----keine Datei gefunden-----");
    Sleep(1000);

    }
}
}


habe soviel wie möglich weggelassen!
SORRY! ist ziemlich viel! aber ich komme echt nicht weiter!
VIELEN VIELEN DANK SCHONMAL!!!
cu wasa
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
28.07.2004, 08:58 Uhr
ao

(Operator)


1. COM-Schnittstellen müssen mit OPEN_EXISTING geöffnet werden, nicht mit CREATE_NEW. Lies nach in der MSDN-Lib unter CreateFile.

2. Schließt du den Port wieder, wenn die Thread-Funktion durchgelaufen ist? Falls nein, klappt das nächste Öffnen nicht, es gibt kein Handle, auf dem gelesen werden kann, und die Daten im L-Puffer bleiben die alten.

Du solltest bei Aktionen wie CreateFile, ReadFile etc. auf jeden Fall den Erfolg kontrollieren, nur um sicher zu sein, dass dein Programm so läuft wie geplant. Es gibt dazu Debug-Hilfen wie assert() oder auch ASSERT(), die nur in der Entwicklungsversion wirksam sind, nicht in der endgültigen Release-Version.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
28.07.2004, 11:18 Uhr
~wasa
Gast


tagchen!

also ich sollte vielleicht sagen das ich Anfänger darin bin. Den Quelltext zum Öffnen / Lesen und Schreiben des COMs (also comport.h und cmport.cpp) habe ich von meinem Prof bekommen. Den rest hab ich selber gemacht.

Bearbeitung von Benutzer:

COM-Schnittstellen müssen mit OPEN_EXISTING geöffnet werden, nicht mit CREATE_NEW. Lies nach in der MSDN-Lib unter CreateFile.



Also muss ich nur CREATE_NEW mit OPEN_EXISTING tauschen????? Oder ändert sich da noch was??? Bei meiner Version von Visual C++ 6.0 gibts leider keine Hilfe (Uni version)


Bearbeitung von Benutzer:

Schließt du den Port wieder, wenn die Thread-Funktion durchgelaufen ist? Falls nein, klappt das nächste Öffnen nicht, es gibt kein Handle, auf dem gelesen werden kann, und die Daten im L-Puffer bleiben die alten.

Du solltest bei Aktionen wie CreateFile, ReadFile etc. auf jeden Fall den Erfolg kontrollieren, nur um sicher zu sein, dass dein Programm so läuft wie geplant. Es gibt dazu Debug-Hilfen wie assert() oder auch ASSERT(), die nur in der Entwicklungsversion wirksam sind, nicht in der endgültigen Release-Version.


Den Com schliesse ich nicht. weiß auch gar nicht wie das gehen soll. Wenn ich das nächste mal lesen will ( nach 5 sek) dann macht der das auch.
Beispiel:
beim 1. Lesen kommt: -013.4 mV
beim 2 Lesen nach 5 Sekunden kommt: -13.5 mV aber es müssten -015.2 mV sein

Ich hoofe du kannst helfen und beDANKE mich schonmal!
cu wasa
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
28.07.2004, 12:49 Uhr
ao

(Operator)


Die MSDN-Library gibts auch im Internet unter http://msdn.microsoft.com . Damit solltest du dich mal vertraut machen, das ist nämlich "die" amtliche Dokumentation. An den Stil muss man sich gewöhnen, aber danach findet man eigentlich alles. Leider funktioniert diese Seite nur mit dem Internet Explorer richtig, mit anderen Browsern kriegt man mehr oder weniger nur die Hälfte zu sehen.

Hier im Forum gibts auch schon mehrere Threads über das Thema. Suche nach "CreateFile ReadFile". Ein Treffer ist z.B. hier.

Diese Comport-Klasse ist ja wirklich toll, macht den Port auf, aber nie wieder zu. Und verwendet dabei noch falsche Parameter. Und hängt dem Anwender noch die Handle-Verwaltung ans Bein. Vollkommen nutzloses Ding.

Um das mal schnell zu flicken, musst du am Ende, wenn alles fertig ist,
C++:
CloseHandle (com_ComHandle1);
aufrufen. Könnte sein, dass es danach läuft.

Für ne ordentliche Reparatur gibts zwei Möglichkeiten:

1. Die ComPort-Klasse wegschmeißen und von Grund auf neu bauen (empfohlen), dabei das Handle auf die Schnittstelle in einer Membervariablen verwalten und *keinesfalls* nach draußen reichen, sicherstellen, dass CloseHandle spätestens im Destruktor gerufen wird (damit keine offenen Ports zurückbleiben), eine Close-Funktion (als Gegenstück zum Open) anbieten und die Read- und Write-Funktionen so umschreiben, dass sie nur dann TRUE zurückgeben, wenn sie wirklich erfolgreich waren.

2. Die ComPort-Klasse wegschmeißen und direkt mit den WinAPI-Funktionen (CreateFile, ReadFile, CloseHandle) arbeiten. Das ist zwar umständlich, aber es gibt wenigstens die Chance, dass es richtig gemacht wird.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
28.07.2004, 13:15 Uhr
~wasa
Gast


tagchen!

also habe das mit closehandle() gemacht und funktioniert sehr gut!
Ist zwar keine elegante lösung, wenn ich in einer for schleife den com öffne, lese und weider schliesse, aber es funktioniert, das ist ja die hauptsache.
wenn ich nochmal die zeit habe, werde ich das bestimmt ändern wie du oben geschrieben hast!!!
AUF JEDENFALL VIELEN VIELEN DANK!!!
hast was gut bei mir!
bis denne cu wasa
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ VC++ / MFC ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: