-         

Ergebnis 1 bis 8 von 8

Thema: Merkwürdiges Kompilierproblem mit dem gcc...

  1. #1
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    25.02.2004
    Ort
    Wilhelmshaven
    Beiträge
    129

    Merkwürdiges Kompilierproblem mit dem gcc...

    Anzeige

    Hallo Zusammen,

    Ich habe einen ATmega32, der einen kleinen Bot steuert und bin gerade dabei, die Kommunikation mit meinem Linux-PC (Ubuntu, Kernel 2.6.24) in C zu implementieren.
    Mein µC gibt momentan timergesteuert über die serielle Schnittstelle ein wiederkehrendes Byte aus. Über ein Terminalprogramm kann ich sehen, wie die Bytes "einfliegen". So weit so gut.

    Nun versuche ich, eine Funktion in C zu schreiben, die die serielle Schnittstelle am PC öffnet und konfiguriert, dass ich einzelne Bytes hin- und herschicken kann.
    Hierzu orientiere ich mich an einigen deutsch- und englischsprachigen Tutorials im Netz (um mal eines zu nennen.).
    In diesen wird immer erläutert, dass die Konfigurationsparameter der Schnittstelle in einer Struktur vom Typ "termios" abgelegt werden. Soweit ist alles klar. Ich erzeuge also eine Struktur und öffne das Device.

    Sobald ich aber die Funktionen
    Code:
    tcgetattr(<filedescriptor>,&<struktur>);     /* Funktion der <termios.h> */
    oder
    Code:
    cfsetispeed(&<struktur>, BAUDRATE);     /* Funktion der <termios.h> */
    verwende, spuckt mir der GCC beim kompilieren eine Warnung entgegen:
    rs232.c:36: Warnung: Übergabe des Arguments 2 von »tcgetattr« von inkompatiblem Zeigertyp
    und
    rs232.c:37: Warnung: Übergabe des Arguments 1 von »cfsetispeed« von inkompatiblem Zeigertyp
    Seltsamerweise verwenden alle Tutorials diese Syntax. Nagut, ist nur eine Warnung, er kompiliert es ja fertig.

    Nun komm ich aber zu meinem eigentlichen Problem:
    In den Tutorials werden die Konfigurationsflags mit folgender Syntax gesetzt:
    Code:
    rs232.c_cflag = CLOCAL | CREAD;     /* als Beispiel */
    Hierbei wird ja bekanntlich auf eine Komponente innerhalb einer Struktur zugegriffen. Ich kann in dieser Zeile keinen Fehler sehen und sämtliche Tutorials benutzen auch genau diese Syntax in ihren Beispielprogrammen.
    Dennoch reagiert mein GCC äußerst ungehalten mit der Aussage:
    rs232.c:39: Fehler: Anfrage nach Element »c_cflag« in etwas, was keine Struktur oder Variante ist
    Ja, und hier bin ich mit meinem Latein am Ende. Wenn ein Tutorial diese Syntax verwendet, gehe ich vielleicht noch davon aus, dass sich dort einfach ein Fehler eingeschlichen hat, aber alle verwenden diese Zeile so...
    Wie, wenn nicht so, kann ich meine Schnittstelle denn konfigurieren?
    Oder sehe ich vielleicht den Wald vor lauter Bäumen nicht?

    MfG rockin_santa

  2. #2
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    45
    Beiträge
    2.236
    Hallo,
    es wäre besser gewesen, wenn Du Dein Programm mal gepostet hättest, warum ?

    Als was wurde RS232 deklariert ?
    Der Fehlermeldung nach ist es keine termios struct

    Bevor wir hier lange Fehlerlesen machen schick ich Dir mal meine bewährte Routine, ok ?

    Wenn Du immernoch was nicht verstehst frag mal ruhig,
    achso Das Programm macht nichts anderes, als in einer Endlosschleife auf Daten vom µC zu warten.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include<sys/time.h>
    #include<sys/types.h>
    #include<unistd.h>
    #include <termios.h>
    #include <fcntl.h>
    #define DEVICE "/dev/ttyS0"
    #define BAUD B9600
    
    int open_port(void){
      int fd_ser;
      struct termios terminal;
      fd_ser = open(DEVICE, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
      if (fd_ser == -1)
      {
        perror("Kann die Serielle nicht oeffnen");
        exit(1);
      }
      fcntl(fd_ser, F_SETFL,FNDELAY);
      terminal.c_cflag = BAUD | CS8 | CLOCAL | CREAD;
      terminal.c_oflag &= ~OPOST;
      terminal.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
      tcflush(fd_ser,TCIOFLUSH);
      tcsetattr(fd_ser,TCSANOW,&terminal);
      return fd_ser;
    }
    
    
    int read_port(int *fd_ser,unsigned char* buffer) {
      int a;
      /*Variablen für select*/
      fd_set rfds;
      struct timeval tv;
      int retval;
    		
      FD_ZERO(&rfds);
      FD_SET(*fd_ser,&rfds);
      tv.tv_sec = 1;
      tv.tv_usec = 0;
      retval = select(*fd_ser+1,&rfds,NULL,NULL,&tv);
      if (retval) {
        a=read(*fd_ser,buffer,255);
        return a;
      } else return 0;
    	
    	
    }
    
    
    int main(void){
      int bytes;
      int i;
      int fd_ser;
      unsigned char puffer[256];
      fd_ser = open_port();
      while(1){
        bytes = read_port(&fd_ser,puffer);
        if( bytes > 0){
          for (i = 0;i< bytes;i++){
            printf("%i\t",puffer[i]);
          }
          printf("\n");
        }
      }
      return 0;
    }
    Gruß Sebastian

    P.S. Ich habe das Programm eben durch den Kompiler gejagt, es gab keine Fehler/Warnungen
    Software is like s e x: its better when its free.
    Linus Torvald

  3. #3
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    25.02.2004
    Ort
    Wilhelmshaven
    Beiträge
    129
    Ich danke Dir, izaseba, ich werde mir Deinen Code heute abend durchsehen.

    Ich gebe zu, ich hätte den ganzen Code ruhig posten können, ich hole das mal nach:

    Code:
    #include <stdio.h>                                              /* Standard I/O */
    #include <string.h>                                             /* Zeichenkettenfunktionen */
    #include <unistd.h>                                             /* UNIX Standardfunktionen */
    #include <fcntl.h>                                              /* Dateikontrolle */
    #include <termios.h>                                            /* POSIX Terminalkonfiguration */
    
    #define BAUDRATE B2400
    #define DEVICE "/dev/ttyUSB0"
    
    int main(void)
    {
        /* Initialisierung */
        int fd;
        struct termios backup, rs232;
    
        /* Arbeitsbeginn */
        fd = rs232_oeffnen();
        rs232_schliessen();
        return 0;
    }
    
    
    /* *** Funktionen *** *** *** *** *** */
    
    /* Oeffnen der virtuellen seriellen Schnittstelle "/dev/ttyUSB0" */
    int rs232_oeffnen(fd, backup, rs232){
        fd = open(DEVICE, O_RDWR | O_NOCTTY | O_NDELAY);            /* Schnittstelle oeffnen */
        printf("Das Device wird geoeffnet\n");
        /* Sicherheitsabfrage, ob Schnittstelle geoeffnet werden konnte */
        if (fd == -1){
            printf("rs232_oeffnen: Konnte /dev/ttyUSB0 nicht oeffnen\n");
            return(-1);
        }
    
        /* Schnittstelle konfigurieren */
        tcgetattr(fd, &backup);                                     /* Aktuelle serielle Einstellungen sichern */
        cfsetispeed(&rs232, BAUDRATE);                              /* eingehende Baudrate setzen */
        cfsetospeed(&rs232, BAUDRATE);                              /* ausgehende Baudrate setzen */
        rs232.c_cflag |= (CLOCAL | CREAD);
        return (fd);
    }
    
    /* Schliessen der virtuellen seriellen Schnittstelle "/dev/ttyUSB0" */
    int rs232_schliessen(fd){
        close(fd);
        printf("Das Device wurde geschlossen\n");
    }

    Gruß

    rockin_santa

  4. #4
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    45
    Beiträge
    2.236
    Hallo
    Code:
    int rs232_oeffnen(fd, backup, rs232){
    Was fällt hier auf ?

    und warum dann so aufrufen ?
    Code:
    fd = rs232_oeffnen();
    Gruß Sebastian
    Software is like s e x: its better when its free.
    Linus Torvald

  5. #5
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    25.02.2004
    Ort
    Wilhelmshaven
    Beiträge
    129
    Hmm,...
    Natürlich ist die Struktur nur in der Funktion nötig, in der konfiguriert wird. Macht Sinn, die dann auch nur dort zu definieren, wie es ja in Deinem Beispiel schön zu sehen ist. Dann muss ich sie auch nicht als Argument übergeben..
    Und selbst wenn, dann müßte die Funktion so beginnen:
    Code:
    int rs232_oeffnen(int *fd, struct termios *backup, struct termios *rs232)
    {
    [...]
    }
    und der Aufruf:
    Code:
    rs232(&fd, &backup, &rs232)
    {
    [...]
    }
    Dann müßte es passen, oder?
    Ich werde die Struktur aber lokal definieren, macht mehr Sinn.

    Vielen Dank,

    rockin_santa

  6. #6
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    45
    Beiträge
    2.236
    Ich werde die Struktur aber lokal definieren, macht mehr Sinn.
    Nun ja, wie Du das machst, ist ganz alleine Deine Sache, ich habe Dir ein Beispiel gepostet, womit ich klar komme

    Zwei Anmerkungen,

    1.wenn Deine Funktion rs232_oeffnen einen Filedeskriptor zurückliefert, brauchst Du wohl auch keinen der Funktion als Argument übergeben, oder ?

    2. Wenn Du Deiner Funktion einen Zeiger auf eine struct gibst, muß der Zugriff auf die Member mit -> erfolgen, und nicht mit .

    Am sonsten wünsche ich Dir viel Spaß weiter mit der Linuxprogrammierung und berichte was draus geworden ist.

    Gruß Sebastian
    Software is like s e x: its better when its free.
    Linus Torvald

  7. #7
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    25.02.2004
    Ort
    Wilhelmshaven
    Beiträge
    129
    So, besten Dank nochmal, ich habe es hingekriegt. Nun kriege ich fein die einzelnen Chars auf der Konsole angezeigt, die mein µC ausgibt

    Gruß

    rockin_santa

  8. #8
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    45
    Beiträge
    2.236
    Es freut mich zu hören, daß es geklappt hat, so schwer war das doch nicht , wobei ich sagen muß, als ich damals mein Programm geschrieben habe, hat es auch etwas gedauert.

    Gruß Sebastian
    Software is like s e x: its better when its free.
    Linus Torvald

Berechtigungen

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