Seltsame Zeichen am ComPort



  • Ich schreibe grad eine kleine Applikation, die Daten von einem USB-GPS-Gerät (navilock 302u) aus dem COM-Port liest ( 4800, 8, N, 1), Synchrone Verbindung, alle 1/10 sec ReadFile(...). Es funktionert gut, solange das Gerät nicht beim Systemstart bereits eingesteckt ist oder die Verbindung kurzzeitig getrennt wurde. Damit meine ich, dass, nachdem beim Abziehen der Com-Port ordnungsgemäß geschlossen wurde und erst nach den Einstecken wieder geöffnet wird, zwar Daten empfangen werden, nur sind die empfangenen Zeichen komplett anders, als sie sein sollten.
    Lasse ich nun TeraTerm mal ganz kurz auf dem Port horchen, zeigt dieses die Daten korrekt an. Danach wird auch bei mir alles korrekt angezeigt. Egal, wie oft ich die Verbindung trenne und weider öffne.
    Offenbar macht TeraTerm eine Art Rücksetzung des Ports. Ich wüsste nun gerne, wie das geht.

    Verbindung wird mit CreateFile hergestellt.

    Hier die richtige Ausgabe:
    GPRMC,075304.436,V,,,,,,,191111,,,N41GPRMC,075304.436,V,,,,,,,191111,,,N*41 GPGGA,075305.443,,,,,0,00,,,M,0.0,M,,000051
    GPGSA,A,1,,,,,,,,,,,,,,,1EGPGSA,A,1,,,,,,,,,,,,,,,*1E GPRMC,075305.443,V,,,,,,,191111,,,N
    42
    GPGGA,075306.436,,,,,0,00,,,M,0.0,M,,000050GPGGA,075306.436,,,,,0,00,,,M,0.0,M,,0000*50 GPGSA,A,1,,,,,,,,,,,,,,,1E
    $GPRMC,075306.436,V,,,,,,,191111,,,N
    43

    Hier die Ausgabe nach Wiederverbindung:
    EDIT [Martin Richter]:...Control Zeichen entfernt, da diese den RSS Feed gestört haben...

    BOOL PortReady;
    
    	m_hCom = CreateFile( m_PortName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
    
    	if ( m_hCom == INVALID_HANDLE_VALUE)
    	{
    		SaveLastError();
    		out = ERROR_CREATING;
    		return out;
    	}
    	PurgeComm( m_hCom, 0xF);
    
    	PortReady = SetupComm( m_hCom, BUFFER_SIZE, BUFFER_SIZE);
    	PortReady = GetCommState( m_hCom, &m_dcb);
    
    	m_dcb.BaudRate = m_BaudRate;
    	m_dcb.ByteSize = m_ByteSize;
    	m_dcb.Parity = m_Parity;
    	m_dcb.StopBits = m_StopBits;
    	m_dcb.fAbortOnError = m_AbortOnError;
    	m_dcb.fDtrControl = FALSE;
    	m_dcb.fInX = FALSE;
    	m_dcb.fRtsControl = FALSE;
    
    	PortReady = SetCommState( m_hCom, &m_dcb);
    	PortReady = GetCommTimeouts( m_hCom, &m_CommTimeouts);
    
    	m_CommTimeouts.ReadIntervalTimeout = m_ReadIntTO;
    	m_CommTimeouts.ReadTotalTimeoutConstant = m_ReadTotTO;
    	m_CommTimeouts.ReadTotalTimeoutMultiplier = m_ReadTotMul;
    	m_CommTimeouts.WriteTotalTimeoutConstant = m_WriteTotTO;
    	m_CommTimeouts.WriteTotalTimeoutMultiplier = m_WriteTotMul;
    
    	PortReady = SetCommTimeouts( m_hCom, &m_CommTimeouts);
    
    	if ( PortReady)
    	{
    		SetErrorFlag( FALSE);
    		out = PORT_OPEN;
    		m_bConnected = TRUE;
    	}
    	else 
    		out = ERROR_SETTING;
    

    Lesefunktion:

    UINT CSBKComPort::WatchComPort( LPVOID pParam)
    {	
    	CSBKComPort* thisComPort = (CSBKComPort*)pParam;
    	CString temp;
    	while( thisComPort->m_bKeepThread == TRUE)
    	{
    		temp = _T("");
    		Sleep( 100);
    		temp.Append(thisComPort->SimpleRead( 200));
    		if ( thisComPort->m_bStoreBlock == FALSE)
    		{
    			thisComPort->m_bStoreBlock = TRUE;
    			thisComPort->StoreBuffer.Append( temp);
    			// Zu lange zeichenketten werden vorne abgeschnitten
    			if ( thisComPort->StoreBuffer.GetLength() > MAX_STORE_LENGTH)
    			{
    				thisComPort->StoreBuffer.Delete( 0, thisComPort->StoreBuffer.GetLength() - MAX_STORE_LENGTH);
    			}
    			thisComPort->m_bStoreBlock = FALSE;
    		}
    	}
    	return 0;
    }
    


  • mikri schrieb:

    Offenbar macht TeraTerm eine Art Rücksetzung des Ports. Ich wüsste nun gerne, wie das geht.

    Das könnte an falschen Einträgen in der DCB-Struktur liegen.

    GetCommState liefert die aktuellen Einstellungen, das sind entweder die beim Start von Windows gesetzten Werte, oder, bei bereits benutzer Schnittstelle, das was das Programm hinterlassen hat, das zuletzt die Schnittstelle benutzt hat.

    Du könntest zwei Varianten versuchen:

    1. Lass das GetCommState weg und lege einen leeren DCB an (mit ZeroMemory oder memset den Inhalt nullen) und setze alle Einträge.

    2. Verwende BuildCommDCB um eine passend gefüllte Struktur zu erzeugen.



  • Danke nn,

    ich habe nun beide Punkte 1) und 2) probiert. Es ist das gleiche wie vorher. Es kommen nur Hieroglyphen. Setzte ich kurz den TeraTerm drauf, funzt danach alles wunderbar. USB abziehen und wieder einstecken: wieder nur Hieroglyphen usw.

    Habe auch schon verschiedene Kombinationen von DCB-Settings probiert und auch alle Werte gesetzt. Dennoch ist nix besser.

    Irgendeine Idee, worauf man besonders achten sollte. TeraTerm kommt übrigens mit so ziemlich allen Einstellungen klar, egal ob 7 oder 8 bit, Parity=N,E,O.. usw.



  • Nachtrag:

    habe nun auch mittels GetCommState den Status kopiert, den das TeraTerm hinterlassen hat. Das hat aber auch nichts genützt.



  • mikri schrieb:

    Irgendeine Idee, worauf man besonders achten sollte. TeraTerm kommt übrigens mit so ziemlich allen Einstellungen klar, egal ob 7 oder 8 bit, Parity=N,E,O.. usw.

    Windows wird wohl kaum eine API nur für TeraTerm haben. Das was du da benutzt, sind die API-Aufrufe für die serielle Schnittstelle. Außerdem kannst du mit PortMon aus der Sysinternals-Suite von MS nachschauen welche seriellen APIs ein Programm verwendet.

    Solche komischen gelesenen Zeichen kommen bei echten seriellen Schnittstellen meist vor, wenn Sender und Empfänger nicht mit den gleichen Einstellungen arbeiten, oder bei hohen Baudraten, wenn die Hardware oder die Leitung Probleme haben.

    Da es mit anderen Programmen geht, würde ich mal auf einen Fehler in deinem Code tippen, wobei mir unklar ist, was das sein könnte.

    Passiert das auch mit fertigen Schnittstellenklassen, wie der hier ?
    http://www.naughter.com/serialport.html
    Oder mit der Klasse aus dem .net-Framework ?



  • Danke erstmal für den Tip mit der Klasse. Nach einigem Debuggen stellte ich fest, dass SetCommState nicht korrekt ausgeführt wurde (Error 87 - ERROR_INVALID_PARAMETER). Kein Wunder also, dass es egal war, was ich ins DCB setzte und somit erstmal die Einstellungen von TerTerm "erben" musste, bevor es ging.

    Mein Fehler war, dass für 1 Stopbit DCB.StopBits = 0 sein muss. Jetzt klappt es, auch nach dem Entfernen.


Anmelden zum Antworten