RS 485 auslesen



  • Hallo Leute!

    ich hab mal wieder eine Frage:

    Ich möchte die Temperatur, welche von einem Pt100 gemessen wurde, über die RS485 Schnittstelle auslesen. Das Pt100-Signal wird über einen RTD-Messwandler gewandelt und an die RxD-Eingänge der RS485 übertragen.
    Hat jemand diesbzgl. Erfahrung?



  • Dieser Thread wurde von Moderator/in SeppJ aus dem Forum C (C89 und C99) in das Forum Rund um die Programmierung verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Auf diese sehr allgemein gehaltenen Frage gibt es auch eine solche Antwort:

    Ja, Jemand hat damit Erfahrung.

    Sehr Systemspezifisch, darum:
    1. Auf der Startseite zu diesem Unterforum (Über dem Link "Neuen Beitrag schreiben") ist ein rosa Kasten. Lies ihn durch. (Die RS485 ist ein serielle Schnittstelle.)
    2. Gibt es als zweiten Beitrag "Wichtig: RTFM! ...". Auch durchlesen.

    Beides beherzigen und dann Frage nochmal stellen.



  • sry, ich werde versuchen, genauere Informationen zu geben. Also das Problem ist, dass ich in C das Signal, welches der Messwandler erzeugt, über die RS 485 auslesen möchte.
    D.h. ich bin auf der Suche nach den nötigen Funktionen, um die RS 485 ansprechen und dann die Signale auslesen zu können.

    Ich hoffe, das Problem ist jetzt verständlicher 🙂



  • huhu002 schrieb:

    sry, ich werde versuchen, genauere Informationen zu geben. Also das Problem ist, dass ich in C das Signal, welches der Messwandler erzeugt, über die RS 485 auslesen möchte.
    D.h. ich bin auf der Suche nach den nötigen Funktionen, um die RS 485 ansprechen und dann die Signale auslesen zu können.

    Ich hoffe, das Problem ist jetzt verständlicher 🙂

    Du brauchst einen Pegelwandler für die serielle Schnittstelle, RS485 hat ein Differenzsignal, das Du besser nicht auf einen COM- Port gibst.
    Unter C mußt Du den Weg über die WinAPI gehen und den finde ich nicht besonders schön, guckst Du in die MSDN.



  • pointercrash() schrieb:

    Du brauchst einen Pegelwandler für die serielle Schnittstelle, RS485 hat ein Differenzsignal, das Du besser nicht auf einen COM- Port gibst.

    Aber der Messwandler gibt doch ein RS 485-Signal aus, wozu muss ich das dann noch wandeln?



  • pointercrash() schrieb:

    Unter C mußt Du den Weg über die WinAPI gehen ....

    Bis jetzt hat er noch noch nicht einmal gesagt, dass er es mit Windows machen möchte.

    Ein fopen("COM1:", "r+"); kann schon funktionieren wenn unter Systemsteuerung die Parameter richtig eingestellt sind.
    Den Pegelwandler brauchst du trotzdem. ~25 €



  • huhu002 schrieb:

    Aber der Messwandler gibt doch ein RS 485-Signal aus, wozu muss ich das dann noch wandeln?

    Hast du eine RS 485 Schnittstelle in deinem Rechner?



  • OS ist Windows XP, und ja, eine RS 485 Schnittstelle habe ich!
    Was wären denn die richtigen Parameter, damit fopen funktioniert?

    sry, bin hier noch relativ neu 😞



  • Nachricht huhu002 schrieb:

    sry, ich werde versuchen, genauere Informationen zu geben.

    Dann gib mal mehr her, denn eine RS 485 gehört nicht zu Standardaustattung einen PC.

    Gibt es zu der Schnittstelle denn keine Anleitung?
    Da können auch Beispiele drin stehen.

    Sonst schau mal nach ob du im Gerätemanager die RS485 findest. Da kannst du die Parameter (Baudrate, Parität, Stop-Bits) einstellen. Die Werte gibt der Messwandler vor.



  • nein leider, in der Anleitung findet sich nichts zur RS 485.

    Die RS 485 finde ich, die Werte habe ich eingestellt.



  • huhu002 schrieb:

    Was wären denn die richtigen Parameter, damit fopen funktioniert?

    Ich weiss nicht ob das mit fopen geht, aber bei CreateFile gibt man "\.\COMn" an, wobei n = nummer des COM-Ports und die \ musst du ggf. escapen (C und so).
    Guckst du Doku zu CreateFile.





  • Ich probiere es jetzt mal anhand der MSDN-Doku, hab aber gleich ein Problem beim Öffnen des COM-Ports.

    Das hier ist der Code:

    #include <windows.h>
    #include <string>
    using namespace std;
    
    int main ()
    {
    
    string gszPort;
    gszPort="\\.\COM5";
    
    HANDLE hComm;
    hComm = CreateFile( gszPort,  
                        GENERIC_READ | GENERIC_WRITE, 
                        0, 
                        0, 
                        OPEN_EXISTING,
                        FILE_FLAG_OVERLAPPED,
                        0);
    if (hComm == INVALID_HANDLE_VALUE)
       printf("error");
    }
    

    Und hier die Fehlermeldungen, die VC ausgibt:

    (9) : warning C4129: 'C': Nicht erkannte Folge von Escapesequenz
    (18) : error C2664: 'CreateFileW': Konvertierung des Parameters 1 von 'std::string' in 'LPCWSTR' nicht möglich
            Kein benutzerdefinierter Konvertierungsoperator verfügbar, der diese Konvertierung durchführen kann, oder der Operator kann nicht aufgerufen werden
    

    Der Port wird doch als String definiert, oder passt das nicht?



  • Erstens: Der Backslash in Strings dient als Escape-Kennzeichen, um nicht darstellbare Zeichen wie Zeilenende \n, Tab \t oder Anführungszeichen \" darzustellen. Deswegen mußt du ihn auch maskieren, wenn er in Reinform vorkommen soll.
    Zweitens: Im Umgang mit der WinAPI sollte man immer bedenken, daß es einen Unterschied gibt zwischen ANSI- und UNICODE-Build. Oder man arbeitet konsequent mit TCHAR und Co.
    Drittens: std::string hat keine implizite Umwandlung nach char*

    typedef basic_string<TCHAR> tstring;
    tstring gszPort = _T("\\\\.\\COM5");
    HANDLE hCom = CreateFile( gszPort.c_str(), ...);
    


  • Ich hab mir jetzt mal den link von theta genauer angesehen, und werde es nun mit dieser Library probieren.
    http://www.codeproject.com/KB/system/serial.aspx

    Das Öffnen bzw. Konfigurieren des Ports wird lt. Tutorial folgendermaßen realisiert:

    int __cdecl _tmain (int /*argc*/, char** /*argv*/)
    {
        CSerial serial;
    	LONG    lLastError = ERROR_SUCCESS;
    
        // Attempt to open the serial port (COM5)
        lLastError = serial.Open(_T("COM5"),0,0,false);
    	if (lLastError != ERROR_SUCCESS)
    		return ::ShowError(serial.GetLastError(), _T("Unable to open COM-port"));
    
        // Setup the serial port (9600,8N1, which is the default setting)
        lLastError = serial.Setup(CSerial::EBaud9600,CSerial::EData8,CSerial::EParNone,CSerial::EStop1);
    	if (lLastError != ERROR_SUCCESS)
    		return ::ShowError(serial.GetLastError(), _T("Unable to set COM-port setting"));
    
        // Register only for the receive event
        lLastError = serial.SetMask(CSerial::EEventBreak |
    								CSerial::EEventCTS   |
    								CSerial::EEventDSR   |
    								CSerial::EEventError |
    								CSerial::EEventRing  |
    								CSerial::EEventRLSD  |
    								CSerial::EEventRecv);
    	if (lLastError != ERROR_SUCCESS)
    		return ::ShowError(serial.GetLastError(), _T("Unable to set COM-port event mask"));
    

    Ich bin mir nur nicht ganz im Klaren, ob ich bei der Kommunikation mit der RS 485 diese EEvent-Unterscheidungen brauche, da ich doch nur die Signale an den Receive-Pins auslesen will?

    Und noch eine Frage: Ich kann einen seriellen Port im BIOS als RS 485 konfigurieren, allerdings bin ich mir bzgl. der Einstellungen nicht sicher (Base I/O, Interrupt Level). Zudem gibt es die Auswahl zwischen RS 485 w/o Echo oder RS 485 w/ Echo.

    Bitte um Hilfe 😞



  • so, jetzt hätte ich mal eine etwas konkretere Frage:

    Ich habe das ganze jetzt mal mit CreateFile usw. probiert.

    #include <windows.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <commdlg.h>
    
    void main()
    {
    
    HANDLE hSerial;
    COMMTIMEOUTS timeouts;
    COMMCONFIG dcbSerialParams;
    char *words, *buffRead, *buffWrite;
    DWORD dwBytesWritten, dwBytesRead;
    int nread,nwrite;
    
    hSerial = CreateFile("COM6",
    GENERIC_READ | GENERIC_WRITE,
    0,
    NULL,
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,//FILE_FLAG_OVERLAPPED, // FILE_ATTRIBUTE_NORMAL
    NULL);
    
    if ( hSerial == INVALID_HANDLE_VALUE)
    {
    if (GetLastError() == ERROR_FILE_NOT_FOUND)
    {
    printf(" serial port does not exist \n");
    }
    printf(" some other error occured. Inform user.\n");
    }
    
    if (!GetCommState(hSerial, &dcbSerialParams.dcb))
    {
    printf("error getting state \n");
    }
    
    dcbSerialParams.dcb.DCBlength = sizeof(dcbSerialParams.dcb);
    
    dcbSerialParams.dcb.BaudRate = CBR_9600;
    dcbSerialParams.dcb.ByteSize = 8;
    dcbSerialParams.dcb.StopBits = ONESTOPBIT;
    dcbSerialParams.dcb.Parity = NOPARITY;
    
    dcbSerialParams.dcb.fBinary = TRUE;
    dcbSerialParams.dcb.fDtrControl = DTR_CONTROL_DISABLE;
    dcbSerialParams.dcb.fRtsControl = RTS_CONTROL_DISABLE;
    dcbSerialParams.dcb.fOutxCtsFlow = FALSE;
    dcbSerialParams.dcb.fOutxDsrFlow = FALSE;
    dcbSerialParams.dcb.fDsrSensitivity= FALSE;
    dcbSerialParams.dcb.fAbortOnError = TRUE;
    
    if (!SetCommState(hSerial, &dcbSerialParams.dcb))
    {
    printf(" error setting serial port state \n");
    }
    
    GetCommTimeouts(hSerial,&timeouts);
    timeouts.ReadIntervalTimeout = 200;//50
    timeouts.ReadTotalTimeoutConstant = 200;//50
    timeouts.ReadTotalTimeoutMultiplier = 100;//10
    timeouts.WriteTotalTimeoutConstant = 200;//50
    timeouts.WriteTotalTimeoutMultiplier= 100;//10
    
    if(!SetCommTimeouts(hSerial, &timeouts))
    {
    printf("error setting port state \n");
    }
    
    //****************Write Operation*********************
    words = "#03";
    nwrite = strlen(words);
    
    buffWrite = words;
    dwBytesWritten = 0;
    
    if (!WriteFile(hSerial, &buffWrite, nwrite, &dwBytesWritten, NULL))
    {
    printf("error writing to output buffer \n");
    }
    printf("Data written to write buffer is \n %s \n", buffWrite);
    
    //***************Read Operation******************//
    buffRead = 0;
    dwBytesRead = 0;
    nread = strlen(words);
    
    if (!ReadFile(hSerial, &buffRead, nread, &dwBytesRead, NULL))
    {
    printf("error reading from input buffer \n");
    }
    printf("Data read from read buffer is \n %s \n", buffRead);
    
    CloseHandle(hSerial);
    
    }
    

    Das ganze läuft ohne Fehler durch, allerdings gibt er mir nur (null) aus.
    Es sollte (lt. Utility Programm) so funktionieren, dass wenn ich '#03' hinausschreibe, er mir die gemessene Temperatur zurückgibt.

    Hoffe, ihr kennt euch aus! Wär über jede Hilfe sehr dankbar!


Anmelden zum Antworten