Forum: Haus & Smart Home HART - Protokoll unter Linux


von sysf (Gast)


Lesenswert?

Hallo,

ich habe die Aufgabe Hart-Kommunikation unter Linux durchzuführen. Hat 
da jemand vielleicht Erfahrung damit?

Eine funktionierende Windows-Version habe ich mitgeloggt mit Portmon.
Link zum log: http://pastebin.com/eGWh1dV4

Als ich das unter Linux mithilfe von Termios.h implementieren wollte 
bekam ich keinerlei Antwort vom Modem. Auch hier der Log: 
http://pastebin.com/7WtEvbRn

Der Code:


#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>


int openPort(void)  {
        int fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
        if (fd == -1)
        {
                perror("Failed to open /dev/ttyUSB0");
                exit(1);
        }
        return fd;
}

void setupPort(int &fd, termios &options) {
        tcgetattr(fd, &options); // get current settings

        // Set Bautrate to 1200 for input and output
        cfsetispeed(&options, B1200);
        cfsetospeed(&options, B1200);

        // setting up Odd Parity
        options.c_cflag |= PARENB;
        options.c_cflag |= PARODD;
        options.c_cflag &= ~CSTOPB;
        options.c_cflag &= ~CSIZE;
        options.c_cflag |= CS8;

        // Timeout Settings
        options.c_cc[VMIN]  = 1;
        options.c_cc[VTIME] = 0;

        // choosing Raw input
        options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);

        // enable parity check
        options.c_iflag |= (INPCK | ISTRIP);
        //options.c_iflag |= (IGNPAR | ISTRIP); //test with disabled 
parity check


        options.c_cflag |= CRTSCTS;

        // choosing Raw output
        options.c_oflag &= ~OPOST;

        // enabling Software flow control
        options.c_cflag |= (CLOCAL | CREAD); // enable receiver
        tcsetattr(fd, TCSAFLUSH, &options); // Flush input/output buffer 
and apply changes
}


void writePort(int &fd) {
        unsigned char send_bytes[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0x02, 0x80, 0x00, 0x00, 0x82 };
        int wroteN = write(fd, send_bytes, 10);
        if (wroteN < 10) {
                perror("Write to RS232 failed");
        }
}

void readPort(int &fd, int s) {
        char buf[21];
        int res=0;
        printf("Settings:%i\n",s);
        for(int i=0; i<20; i++) {
                res = read(fd,buf,20);
                buf[res]=0;
                printf("[%i|%i]\n",i, res);
        }
        printf("\n\n");
}


void setRTS(int &fd, int level) {
        int status;
        if (ioctl(fd, TIOCMGET, &status) == -1) {
                perror("setRTS to 1 failed");
                exit(-1);
        }
        if (level)      status |= TIOCM_RTS;
        else            status &= ~TIOCM_RTS;

        if (ioctl(fd, TIOCMSET, &status) == -1) {
                perror("setRTS to 0 failed");
                exit(-1);
        }
}


void msleep(int ms) {
        usleep(ms*1000); //convert to microseconds
}


unsigned long getTime() {
        struct timeval detail_time;
        gettimeofday(&detail_time,NULL);
        return (detail_time.tv_usec);
}

void setDTR(int &fd) {
  // sets the SC8in1 in command mode
  int lineData;
  ioctl(fd, TIOCMGET, &lineData);
  lineData |= TIOCM_DTR;
  ioctl(fd, TIOCMSET, &lineData);
}


int main(void) {
        // general Setup
        int fd = openPort();
        struct termios options;
        setupPort(fd, options);

        // start sending data
        setDTR(fd);
        // Different timing between send and receive data
        for(int var=80; var<200; var++) {
                setRTS(fd, 1); // enabling RTS
                msleep(2);
                int start,diff;
                start = getTime();
                writePort(fd);
                // Different timing
                do{
                        diff = getTime() - start;
                }while(diff<var);

                setRTS(fd, 0);
                readPort(fd, var);
                sleep(1);
        }


        tcsetattr(fd, TCSAFLUSH, &options); // Flush input/output buffer 
and apply changes
        return 0;

}

Vielleicht kann mir hier einer helfen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.