Anzeige:
Ergebnis 1 bis 3 von 3

Thema: Komunikation über RS232 bei 32Bit

  1. #1
    mofaklaus
    Gast

    Komunikation über RS232 bei 32Bit

    Hallo Leute,

    ich versuche gerade mit einer BHKW-Steuerung über RS232 eine Verbindung aufzubauen.

    Man soll beim senden von 0x0c eine 48Byte lange Antwort erhalten. Eine Antwort erhalte ich ja schon, aber die ist nicht so wie erwartet. (meistens kürzer)

    Meine Frage ist zu nächst, was die RS232 wirklich sendet bei einem 32Bit Betrienssystem. Ich verwende Suse 8.2 mit Kernel 2.6. Da ist ein int 32Bit lang und ein Char natürlich auch. Also ist das kleinste was ich senden kann ein Zeich. (0x0000000c) z.B
    In meiner antwort befinden sich aber Zeichen wie 0xfffffffe(oder dezimal -32) das ist mit 8 bit nicht zu machen.

    Mache ich einen Gedanken fehler?
    oder werden immer 4x 8bit gesendet?
    oder werden Pro Zeichen nur 8Bit gesendet.

    Nun noch zu meiner Umgebung:
    ich soll die Schnittstelle auf "9600,8,1 kein Parity und kein Flow Control" einstellen.
    und ich habe folgendes Programm geschrieben (bzw. zusammen copiert)

    Code:
    #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 fd;                  /* File descriptor for the port */
    struct termios term_attr;
    
    
    int open_port(void) {
        // * 'open_port()' - Open serial port 1.
        // * Returns the file descriptor on success or -1 on error.
    
        fd = open("/dev/ttyS1", O_RDWR | O_NOCTTY | O_NDELAY);
        if (fd == -1) {
            printf("\nopen_port: Unable to open /dev/ttyS1 - \n\n");
        }
        else {
             // Konfig lesen
            if (tcgetattr(fd, &term_attr) != 0)
            {
                printf("terminal: tcgetattr() failed");
                return(-1);
            }
            // Konfig setzen
            cfsetispeed(&term_attr, B9600);
            cfsetospeed(&term_attr, B9600);
    
            term_attr.c_cflag &= ~PARENB;
            term_attr.c_cflag &= ~CSTOPB;
            term_attr.c_cflag &= ~CSIZE;
            term_attr.c_cflag |= CS8;
            term_attr.c_cflag &= ~CRTSCTS;
    
            term_attr.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    
            term_attr.c_oflag &= ~OPOST;
    
            term_attr.c_lflag = 0;
    
            // Konfig Schreiben
            if (tcsetattr(fd, TCSAFLUSH, &term_attr) != 0)
            {
                printf("terminal: tcsetattr() failed");
            }
    
            fcntl(fd, F_SETFL, 0);
        }
        return (fd);
    }
    
    void close_port() {
         close(fd);
    }
    
    
    int main(void) {
         int iOut;
         int iIn;
         char buffer[100];
         char put=0xC0;
    
         if (open_port() != -1) {
             printf("\nVerbindung zum Dachs wurde hergestellt Port = %d\n", fd);
    
             iOut = write(fd, &put, 1);
             printf("Daten gesendet: %d \n",iOut);
             if (iOut == -1) return (-1);
             iIn = read(fd, buffer, 100);
    
             printf("Empfange %d Zeichen: #%d#%d#%d#%d#%d#%d#%d#%d#\n",iIn, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7], buffer[8]);
             close_port();
             printf("Verbindung wurde getrennt\n");
         }
         else {
               printf("\n\nFehler... Verbindung konnte nicht hergestellt werden\n");
         }
    }

  2. #2
    Registrierter Benutzer
    Registriert seit
    24.09.2005
    Beiträge
    66
    Intern arbeitet RS232 in 8 bit-Blöcken, das braucht dich als Programmierer aber nicht zu interessieren. Auch Geschwindigkeit und die diversen Einstellungen werden automatisch vom Betriebssystem aufbereitet, du profitierst nur noch z.B. von einer sichereren Übertragung durch Parity-Bits.
    Wenn du mit read/write einen Speicherbereich angibst, interessiert der darunter liegende Datentyp nicht. Wichtig ist nur das die korrekte Länge in Bytes angegeben wird, was du z.b. für ints mit sizeof(int) erreichen kannst.
    Wenn du z.B. weißt dass Byte 2-5 einen int darstellen sollen, musst du mittels Zeigerarithmetik einen Zeiger auf Byte 2 zeigen lassen und ihn als int* interpretieren:
    Code:
    char * pcResult =  &buffer[2]; // Das funktioniert weil buffer ein char* ist und der Compiler Zeigeroperationen auf 1 byte ausrichtet
    int* piResult = (int*)pcResult;
    int iResult = *piResult;
    Das lässt sich natürlich auch in einer einzigen Zeile formulieren, allerdings hoffe ich das es so klarer wird wie die Vorgehensweise ist.

    Du gibst die zu lesenden bytes für read mit 100 an, obwohl du schreibst das 48 byte erwartet werden. Das fürt zwangsläufig dazu das read irgendwann erstmal mit einem timeout abbrechen muss. Eventuell solltest du versuchen read mehrmals aufzurufen bis die 48 bytes empfangen wurden.

  3. #3
    Registrierter Benutzer
    Registriert seit
    16.06.2003
    Beiträge
    73
    Hi,

    @mofaklaus
    Auch auf einem 32Bit System ist ein char normalerweise nur 8 Bit lang. Das kannst du auch mal mit

    Code:
    printf ("%d\n", sizeof(char));
    überprüfen. Hier müßte eine 1 rauskommen. D.h. ein char ist ein Byte (8 Bit) lang.
    In deinem Beispielprogramm gibst du die Zeichen, welche du mit read gelesen hast mit der Formatangabe %d aus. Diese erwartet einen Integer und wandelt den im Parameter angegeben char (buffer[0]) in eine Integer um und gibt diesen aus. Mach mal die Ausgabe mit %02x, dann bekommst du 2 stellige Hexadezimalzahlen was der Wirklichkeit deutlich näher kommt.
    Die RS232 Schnittstelle arbeitet immer Zeichen (8 Bit) orientiert. Beim write und read gibts du an, wie viele Zeichen (also 8 Bit Werte) du lesen möchtest.
    Die Angabe beim read ist die Maximalanzahl der Zeichen die der Puffer den du übergibst aufnehmen kann. Wieviele Zeichen wirklich gelesen wurden, sagt dir der Rückgabewert. Gehe nie davon aus, dass du eine komplette Antwort deiner BHKW Steuerung mit einem read Aufruf auslesen kannst. Diese kann gestückelt auf mehrere reads verteilt sein.

    @Yonibear
    Die von dir gepostete Spielerei mit Zeigern ist abhängig von der Endianness des Quell- und Zielsystems der Daten und wird nur funktionieren, wenn Quell- und Zielsystem diesselbe Endianness verwenden! Gerade bei bei Steuerungen die über UART angebunden werden, ist hier äußerste Vorsicht geboten.

    Gruß

    almoeli

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •