Schnittstelle zu langsam?!

Winner

Erfahrenes Mitglied
Hallo zusammen! Ich habe da ein Problem und weis nicht genau, wie ich dieses lösen soll! Zwar ist es, das ich binär Daten von einer Seriellenschnitstelle einlese.

Die Datensätzte (immer 47 char Zeichen lang) erhalte ich 100 mal die Sekunde (100Hz).

+Meine Baudrate ist auf 115200 eingestellt! Mit der mitglieferten Firmware des Reciervers kann ich es aufzeichnen und zwar korrekt. Aber tu ich das aus meinem Programm heraus und schreibe es in eine Datei, kann fehelen mit immer Datensätze!!

Wie kann ich das lösen oder was kann ich tun! Auch das zwischen Buffern in einer Variable, so das die Datei nur alle 10Sekungen geöffent wird zum schreiben bringt nichts bin da jetzt echt ratlos. Die Erhöhung der Baudrate fürht auch nicht zum erfolg!

Ich weis da jetzt wirkölich nicht mehr weiter kann mir einer helfen bitte

besten dank
 
Hallo,

ich denke, du solltest das Abfragen der seriellen Schnittstelle und Buffern der Daten in einem eigenen Thread ausführen und alles andere außerhalb davon.

Gruß
MCoder
 
Danke MCoder

Das tu ich bereits! Es läuft ein Thread der die entsprechenden Daten vom Comport holt und die dann direkt zwischen buffert!

Man ich weis da keinen Rat mehr! Mit 10 Hz klappt es! Aber ich muss es leider mit 10 hinbekommen! Was fürn mist!

Ich komm da leider mit meinem momentanen Kenntnisstand nicht weiter

HIIIILFE
 
Mit der mitglieferten Firmware des Reciervers kann ich es aufzeichnen und zwar korrekt. Aber tu ich das aus meinem Programm heraus und schreibe es in eine Datei, kann fehelen mit immer Datensätze!!
Das heißt also, dass dir damit immer 47 Byte fehlen? Normalerweise werden die eingehenden Daten am seriellen Port gepuffert, so das nichts verlorengehen sollte. Bist du dir sicher, dass du das Protokoll richtig umgesetzt hast (Start-/Stopp-Bedingungen, Anfang-/Ende-Kennung beim Datensatz, Quittierungen usw.)?

Meine Baudrate ist auf 115200 eingestellt! ... Die Erhöhung der Baudrate fürht auch nicht zum erfolg!
Die am PC eingestellte Baudrate muss immer zum sendenden Gerät passen. Falls du die Baudrate veränderst (erhöhst), muss sie bei beiden Partnern geändert werden. Wenn sie nicht übereinstimmt, dürfte keine Kommunikation zustandekommen.

Verwendest du eigentlich synchrone oder asynchrone (mit Flag FILE_FLAG_OVERLAPPED ) Kommunikation?

Gruß
MCoder
 
Hallo MCoder! Ja das ist mir schon klar mit der Baudrate!

Aber ich zeige dir am besten mal meine beiden Funktionen die ich verwende um den Comprt zu öffnen und die Daten zu holen!

Das schreiben auf dem Port klappt ja wunderbar, deswegen brauche ich den code hierniocht hin zuschreiben.

Also zuerst das öffnen des Ports:
Code:
int CComPort::OpenPort(int portnr, int baudrate, int datenbits, 
					int paritaet, int stopbits, int /*protokoll*/)
{
	if (m_hPort!=NULL) 
	{
		TRACE("Fehler: m_hPort != NULL\n");
		return 1;
	}
	DCB dcb;
	CString port;
	port.Format("\\\\.\\COM%d",portnr);
	m_hPort = CreateFile(port,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
	if (m_hPort == INVALID_HANDLE_VALUE) 
	{
		TRACE("Fehler: invalid_handle_value\n");
		return 2;
	}
	if (!GetCommState(m_hPort,&dcb)) 
	{
		TRACE("Fehler: kein getcommstate\n");
		return 3;
	}

	//* Übertragungsrichtlinien festlegen
	switch (baudrate)
	{
	case CBR_110: dcb.BaudRate = CBR_110; break;
	case CBR_300: dcb.BaudRate = CBR_300; break;
	case CBR_600: dcb.BaudRate = CBR_600; break;
	case CBR_1200: dcb.BaudRate = CBR_1200; break;
	case CBR_2400: dcb.BaudRate = CBR_2400; break;
	case CBR_4800: dcb.BaudRate = CBR_4800; break;
	case CBR_9600: dcb.BaudRate = CBR_9600; break;
	case CBR_14400: dcb.BaudRate = CBR_14400; break;
	case CBR_19200: dcb.BaudRate = CBR_19200; break;
	case CBR_56000: dcb.BaudRate = CBR_56000; break;
	case CBR_57600: dcb.BaudRate = CBR_57600; break;
	case CBR_115200: dcb.BaudRate = CBR_115200; break;
	case CBR_128000: dcb.BaudRate = CBR_128000; break;
	case CBR_256000: dcb.BaudRate = CBR_256000; break;
	default: dcb.BaudRate = CBR_19200; 
	}

	switch (datenbits)
	{
	case 5: dcb.ByteSize = 5; break;
	case 6: dcb.ByteSize = 6; break;
	case 7: dcb.ByteSize = 7; break;
	case 8: dcb.ByteSize = 8; break;
	default: dcb.ByteSize = 5;
	}

	switch (paritaet)
	{
	case EVENPARITY: dcb.Parity = EVENPARITY; break;
	case ODDPARITY: dcb.Parity = ODDPARITY; break;
	case NOPARITY: dcb.Parity = NOPARITY; break;
	case MARKPARITY: dcb.Parity = MARKPARITY; break;
	case SPACEPARITY: dcb.Parity = SPACEPARITY; break;
	default: dcb.Parity = NOPARITY;
	}

	switch (stopbits)
	{
	case ONESTOPBIT: dcb.StopBits = ONESTOPBIT; break;
	case ONE5STOPBITS: dcb.StopBits = ONE5STOPBITS; break;
	case TWOSTOPBITS: dcb.StopBits = TWOSTOPBITS; break;
	default: dcb.StopBits = ONESTOPBIT;
	}
	
	
	dcb.fDtrControl = DTR_CONTROL_ENABLE;
	dcb.fDsrSensitivity = FALSE;
	if (!SetCommState(m_hPort,&dcb)) 
	{
		TRACE("Fehler: kein setcommstate\n");
		return 4;
	}

	//* Timeouts festlegen, das ist reine Testangelegenheit
	COMMTIMEOUTS commi;
	commi.ReadIntervalTimeout = 0; //15;
	commi.ReadTotalTimeoutConstant = 0; //100;
	commi.ReadTotalTimeoutMultiplier = 1; //100;
	//commi.WriteTotalTimeoutConstant = 5;
	//commi.WriteTotalTimeoutMultiplier = 10;
	SetCommTimeouts(m_hPort,&commi);

	return 0;
}

/** Die Funktion schließt den Port, sofern er nicht schon geschlossen ist.
  */
int CComPort::ClosePort()
{
	if (m_hPort!=NULL)
	{
		CloseHandle(m_hPort);
		m_hPort = NULL;
	}
	return 0;
}

/** Die Funktion schreibt Daten vom Typ CString auf den Port.
  */
int CComPort::WritePort(CString txt)
{
	DWORD bytes;
	WriteFile(m_hPort,txt,txt.GetLength(),&bytes,NULL);
	return 0;
}

Und als nächsets die lese Methode!

Code:
int CComPort::ReadPort(CString &txt)
{
	char buf[251];
	DWORD bytes;
	ReadFile(m_hPort,buf,sizeof(buf),&bytes,NULL);
	if (bytes==0) return 1;
	txt = buf;
	bool ende = false;
	int nr = 0;
	int bufgroesse = sizeof(buf);
	while (!ende)
	{
		if (nr>=bufgroesse) ende = true;
		if (buf[nr]==-52) ende = true;
		else nr = nr + 1;
	}
	if (nr<bufgroesse) txt = txt.Left(nr);
	return 0; 
}

/** Die Funktion schließt den Port und setzt ihn auf NULL zurück.
  */
int CComPort::SetPortNull()
{
	ClosePort();
	m_hPort = NULL;
	return 0;
}

Was könnt ich verbessern! Kannst du mir helfen oder Tipps geben MCoder

Bitte, wäre coll wenns noch vom WE klappt, dann bin ich beruhigt, da es eigentlich heute laufen sollte!

Gruß u bestern dank
 
Hallo,

zwei Dinge würde ich ändern:

1. Die Timeouts würde ich nicht auf 0 setzen, kleinere Verzögerungen beim Versenden können durchaus auftreten und die Verabeitung wird dadurch nicht langsamer.

2. Das Lesen sollte besser byteweise erfolgen, weil ReadFile() sonst evt. wartet (bin mir da nicht ganz sicher) bis der angeforderte Buffer gefüllt wurde, was vielleicht bei der weiteren Verarbeitung Probleme macht.
Versuch's mal so:
C++:
int CComPort::ReadPort(CString &txt)
{
    char  byte;
    DWORD dwBytesRead;
    
    txt = "";
    
    while( ReadFile(m_hPort, &byte, 1, &dwBytesRead, NULL) && dwBytesRead == 1 )
    {
        if( byte == (-52) )
        {
            break;
        }
        
        txt += byte;
    }    

    return 0;
}

Wie hast das eigentlich mit dem Thread gelöst? ReadPort() müsste ja in einer Endlosschleife laufen.

Gruß
MCoder
 
Danke für die schnelle Antwort!

Ja du hast richtig vermutet! Das läuft in einer do while Schleife!

Abbruchbedingung ist eine Eingabe durch den Nutzer!

Aber schon mal besten dank, ich werde deine Verbesserungsn vorschläge mal einbauen und schauen zu was für einer Lösung ich komme!

Dir schon mal ein schönes WE und vielen lieben dank!

Besten Gruß Winner
 
Hallo!

Jetzt seteh ich vor einem kleien aber für mich anscheidn einProblem.

Da das ganze mit binär Daten laufen soll möchte ich die oben gesehenen Methoden an char Array anpassen leider klappt das genze nicht und ich weis nicht was ich falsch mache!! könnt ihr mir vielleicht helfen?

Mein code:

Code:
nt CComPort::ReadPort(char &txt)
{

    char  byte;
    char test[82];
    DWORD dwBytesRead;  
//    txt = "";
    int iCountBuffer = 0;
    
    int iIN = 0; // Variable die festlegt wieviel Zeichen eingesen wurden

    while( ReadFile(m_hPort, &byte, 1, &dwBytesRead, NULL) && dwBytesRead == 1 )    
    { 
       
        if( byte == (-52) )
        { 
            //AfxMessageBox(txt);
            
            //hier drin dann auch die Daten wegschreiben, sobald ein leeres Zeichen da ist, ansonsten nichts tun
            //txt = "";
            break;
        }
        iIN++;
        //memcpy(&txt,&byte,sizeof(byte));
        
        //txt[iIN-1] = byte;
        
        memcpy(test + iCountBuffer, &byte,1);

        
       // txt += byte;
        
        iCountBuffer++;

        if(iIN>=82)
        {
            test[82] = '\0';
            //txt = test;
            memcpy(&txt,test,iIN);
                
            AfxMessageBox(test);
            //AfxMessageBox(txt);
            //txt = "";
            break;
        }
    
    } 
    return 0;

So rufe ich diesen dann auf:

Code:
          char *cFromCom[82];
            myCom.ReadPort(cFromCom);

Man ich weis dass ist bestimmt totla eay aber ich bekome es leider nicht hin! Kann mir da einer weiter helfen! Wäre echt schön!

Bis dann
 
Hallo,

funktioniert das Andere (fehlende Daten) jetzt?
Ansonsten - wenn ich alles richtig verstanden habe - sollte sich dein aktuelles Problem so lösen lassen:
C++:
// ReadPort-Methode

int CComPort::ReadPort(char *pBuffer, int nSize)
{
    char  byte;
    DWORD dwBytesRead;  
    int   iIN = 0; // Variable die festlegt wieviel Zeichen eingesen wurden

    while( ReadFile(m_hPort, &byte, 1, &dwBytesRead, NULL) && dwBytesRead == 1 )    
    { 
        if( byte == (-52) ||     // Endezeichen
            byte == 0     ||     // leeres Zeichen
            iIN  == (nSize - 1)  // Ende des Buffers
          )
        { 
            break;
        }

        pBuffer[iIN++] = byte;
    }

    pBuffer[iIN] = '\0';
    return 0;
}    

// Verwendung

char pBuffer[82];
myCom.ReadPort(pBuffer, sizeof(pBuffer));
Gruß
MCoder
 
Guten Morgen MCoder!

Ich kann dir das jetzt leider nicht sagen, ob die datensätze vollständig sind, da ich das Gerät über das WE hin nicht testen kann!

Aber ich werde sobald ich die von dir geschriebene Funktion getestet habe mal Rückmeldung geben! Aufjedenfall vielen lieben dank und dir ein schönes Wochenende!


Gruß Winner
 
Zurück