Serielle Kommunikation



  • Hallo zusammen.
    Bin neu hier in dem Forum, hoffe jedoch trotzdem dass mir jemand helfen kann.

    @Mod: keine Ahnung ob dass das richtige Forum ist, falls nicht bitte einfach verschieben, thx.

    Ich will eine serielle Kommunikation mit einem Energiezähler aufbauen (Daten auslesen).
    Definiert/spezifiziert ist das nach IEC 62056-21.
    Ist so dass über einen "Ifrarot-Knopf" mit dem Energiezähler die Verbindung hergestellt wird.

    Habe das ganze bereits mit realterm getestet.
    Bei folgenden Einstellungen:
    300 Baud
    7E1
    kein Hardware-flow-control
    gibt mir der Zähler nach meiner Aufforderung ( /?!<CR><LF> ) alle seine Daten bekannt.
    D.h. Kabel und Kommunikation funktionieren grundsätzlich.

    Ich will/muss nun das ganze auf Linux zum laufen bringen, komme da aber nicht wirklich weiter 😞

    Ich glaube es hängt wahrscheinlich an den Einstellungen für den seriellen Port, evt. kennt sich hier jemand aus und kann mir weiterhelfen.

    Versuche nun schon verzweifelt seit einiger Zeit die richtigen Einstellungen herauszufinden, komme aber einfach nicht weiter.
    Wenn ich mir z.b. http://www.easysw.com/~mike/serial/serial.html anschaue, da gibts zig Einstellungen und daher auch zig kombinationsmöglichkeiten. Hab schon ewig viel herumprobiert, komme aber wie gesagt nicht drauf 😞

    Habe ein Beispielprogramm gefunden und das als Basis genommen und versucht dort die Einstellungsparameter richtig einzustellen, aber ich komm nicht weiter.

    Hier der code:

    ser.c

    /* ser.c
            (C) 2004-5 Captain http://www.captain.at
    
            Sends 3 characters (ABC) via the serial port (/dev/ttyS0) and reads
            them back if they are returned from the PIC.
    
            Used for testing the PIC-MMC test-board
            http://www.captain.at/electronic-index.php
    
    */
    #include <stdio.h>   /* Standard input/output definitions */
    #include <string.h>  /* String function definitions */
    #include <unistd.h>  /* UNIX standard function definitions */
    #include <fcntl.h>   /* File control definitions */
    #include <errno.h>   /* Error number definitions */
    #include <termios.h> /* POSIX terminal control definitions */
    
    #include "captain/capser.h"
    
    int fd;
    
    int initport(int fd) {
    
            struct termios options;
    
            // Get the current options for the port...
            tcgetattr(fd, &options);
    
            // Set the baud rates to 19200...
            cfsetispeed(&options, B300);
            cfsetospeed(&options, B300);
    
            // Enable the receiver and set local mode...
            options.c_cflag |= (CLOCAL | CREAD);
    
            // Set Even parity (7E1)
            options.c_cflag |= PARENB;
            options.c_cflag |= PARODD;
            options.c_cflag &= ~CSTOPB;
            options.c_cflag &= ~CSIZE;
            options.c_cflag |= CS7;
    
            // no hardware flow control
            //options.c_cflag &= ~CNEW_RTSCTS;
            options.c_cflag &= ~CRTSCTS;
    
            // Raw Input
            options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
            //cfmakeraw(&options);
    
            // Disable software flow control
            options.c_iflag &= ~(IXON | IXOFF | IXANY);
    
            // Raw Output
            options.c_oflag &= ~OPOST;
    
            // Set the new options for the port...
            tcsetattr(fd, TCSANOW, &options);
            return 1;
    }
    
    int main(int argc, char **argv) {
    
            fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
            if (fd == -1) {
                    perror("open_port: Unable to open /dev/ttyS0 - ");
                    return 1;
            } else {
                    fcntl(fd, F_SETFL, 0);
            }
    
            printf("baud=%d\n", getbaud(fd));
            initport(fd);
            printf("baud=%d\n", getbaud(fd));
    
            char sCmd[254];
    #ifdef _KONNI_
            sCmd[0] = 0x41;
            sCmd[1] = 0x42;
            sCmd[2] = 0x43;
            sCmd[3] = 0x00;
    #endif // _KONNI_
            sCmd[0] = 0x2F;  // /
            sCmd[1] = 0x3F;  // ?
            sCmd[2] = 0x21;  // !
            sCmd[3] = 0x0D;  // CR
            sCmd[4] = 0x0A;  // LF
            sCmd[4] = 0x00;
    
            if (!writeport(fd, sCmd)) {
                    printf("write failed\n");
                    close(fd);
                    return 1;
            }
    
            printf("written:%s\n", sCmd);
    
            //usleep(500000);
            char sResult[254];
            //fcntl(fd, F_SETFL, FNDELAY); // don't block serial read
            fcntl(fd, F_SETFL, 0); // blocking mode
    
            if (!readport(fd,sResult)) {
                    printf("read failed\n");
                    close(fd);
                    return 1;
            }
            printf("readport=%s\n", sResult);
            close(fd);
            return 0;
    }
    

    captain/capser.c:

    /* capser.c
            (C) 2004-5 Captain http://www.captain.at
    
            Helper functions for "ser"
    
            Used for testing the PIC-MMC test-board
            http://www.captain.at/electronic-index.php
    */
    #include <stdio.h>   /* Standard input/output definitions */
    #include <string.h>  /* String function definitions */
    #include <unistd.h>  /* UNIX standard function definitions */
    #include <fcntl.h>   /* File control definitions */
    #include <errno.h>   /* Error number definitions */
    #include <termios.h> /* POSIX terminal control definitions */
    
    int writeport(int fd, char *chars) {
            int len = strlen(chars);
            chars[len] = 0x0d; // stick a <CR> after the command
            chars[len+1] = 0x00; // terminate the string properly
            int n = write(fd, chars, strlen(chars));
            if (n < 0) {
                    fputs("write failed!\n", stderr);
                    return 0;
            }
            return 1;
    }
    
    int readport(int fd, char *result) {
            printf("KONNI WAS HERE - befor read\n");
            int iIn = read(fd, result, 254);
            // konni: wasn das fuer ein scheiss ... speicherschmierer deluxe
            printf("KONNI WAS HERE - after read\n");
            result[iIn-1] = 0x00;
            if (iIn < 0) {
                    if (errno == EAGAIN) {
                            printf("SERIAL EAGAIN ERROR %d %s\n", errno, strerror(errno));
                            return 0;
                    } else {
                            printf("SERIAL read error %d %s\n", errno, strerror(errno));
                            return 0;
                    }
            }
            return 1;
    }
    
    int getbaud(int fd) {
            struct termios termAttr;
            int inputSpeed = -1;
            speed_t baudRate;
            tcgetattr(fd, &termAttr);
            /* Get the input speed.                              */
            baudRate = cfgetispeed(&termAttr);
            switch (baudRate) {
                    case B0:      inputSpeed = 0; break;
                    case B50:     inputSpeed = 50; break;
                    case B110:    inputSpeed = 110; break;
                    case B134:    inputSpeed = 134; break;
                    case B150:    inputSpeed = 150; break;
                    case B200:    inputSpeed = 200; break;
                    case B300:    inputSpeed = 300; break;
                    case B600:    inputSpeed = 600; break;
                    case B1200:   inputSpeed = 1200; break;
                    case B1800:   inputSpeed = 1800; break;
                    case B2400:   inputSpeed = 2400; break;
                    case B4800:   inputSpeed = 4800; break;
                    case B9600:   inputSpeed = 9600; break;
                    case B19200:  inputSpeed = 19200; break;
                    case B38400:  inputSpeed = 38400; break;
            }
            return inputSpeed;
    }
    

    Anpassungen die ich durchgeführt habe:
    Im initport die Einstellungen so angepasst dass die für mich glaube ich richtig sind (was aber wahrscheinlich nicht der Fall sein wird).
    sCmd angepasst auf den Init-String den mein Zähler verlangt damit er mir die Daten schickt.

    Wird der port mittels fcntl auf non-blocking gestellt, dann bekomme ich sofort immer beim read den EAGAIN Fehler.

    Wenn ich irgendwelche wichtigen Angaben vergessen habe damit mir jemand helfen kann, dann sorry und einfach fragen bitte.

    Wie gesagt, mit realterm unter windows schicke ich dem Zähler einfach den init-string, und er antwortet mit den daten (ascii).

    thx, gruss konni




Anmelden zum Antworten