www.mikrocontroller.net

Forum: PC-Programmierung Größe des RS232-Puffers bei Linux in C?


Autor: chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Forengemeinde,
versuche eine angekommene SMS in C unter Linux von einem Surfstick 
"huawei E160" auszulesen. Gebe also den Befehl zum Auslesen 
"AT+CMGR=0\r\n" ein und erwarte die Antwort vom Surfstick, um diese dann 
mit strtok() zu zerlegen und auszuwerten. Problem ist nur, dass alle 
anderen Kommandos, wie z.B. Netzabfrage "AT+COPS?\n" oder 
Modemmodellabfrage "AT+CGMM\n" Strings zurückgeben. Nur die SMS-Abfrage 
scheitert.
int smsabfrag(){          /////////////// SMS ABFRAGEN
 
int bytes = 0;      
int h;        //Löschzähler für Puffer2
char puffer2[200];    //Puffer zum Auslesen von Schnittstelle
int fd_ser;      //Serielle Schnittstelle
int k=1;       //Zählervariable initialisieren
char *ptr;       //Temporärer String


fd_ser = open_port();    //Schnittstelle öffnen

set_fgcolor(3);
log_meld("Frage SMS ab...\n");

write(fd_ser,   "AT+CMGR=0\r\n",11);

//write(fd_ser, "AT+CPBR=1\r\n",12);
//write(fd_ser, "AT+COPS?\r\n",11);

smsinhalt = 0;         //  Global definierte Variable für den Inhalt der SMS

  
  for (h=0;h==201;h++)  
  {
  puffer2[h] = 0x00;
  }


bytes = read_port(&fd_ser,puffer2);   // Daten lesen
clear_screen();       // Bildschirm löschen

ptr = strtok(puffer2, "\n,");    // Zeilenumbruch maskieren

  while(ptr != NULL)
  {
  set_cursor(3,k);
  
  printf("Detektion: %d. string--> %s \n",k++,ptr); //Ausgabe von Stringnummer und  String
                     
  ptr = strtok(NULL, "\n,");      //  Zeilenumruch maskieren   
       }
                                                            

//////set_fgcolor(4);
//////set_cursor(0,15);
//////printf ("%s", smsinhalt);
//////set_fgcolor(2);
log_meld("SMS abgefragt.\n");

}

Programmoutput:

�� Detektion: 1. string--> AT+CMGR=0

Wenn ich
write(fd_ser,   "AT+CMGR=0\r\n",11);
durch
write(fd_ser, "AT+COPS?\r\n",11);

ersetze, ist der Output richtig:

   Detektion: 1. string--> AT+COPS?
   Detektion: 2. string--> +COPS: 0
   Detektion: 3. string--> 0
   Detektion: 4. string--> "o2 - de"
   Detektion: 5. string--> 0
   Detektion: 6. string-->
   Detektion: 7. string--> OK


Wenn ich allerdings parallel minicom öffne, um dem Datenstrom zu 
beobachten, funktioniert das auslesen mit:
write(fd_ser,   "AT+CMGR=0\r\n",11);

Output:

   Detektion: 1. string-->
   Detektion: 2. string--> +CMGR: "REC READ"
   Detektion: 3. string--> "+49176XXXXXXXX"
   Detektion: 4. string--> "09/11/21
   Detektion: 5. string--> 10:33:21+04"
   Detektion: 6. string--> Test0001
   Detektion: 7. string-->
   Detektion: 8. string--> OK
   Detektion: 9. string--> :

Hier noch die RS232-Einstellungen:

int open_port(void){

int fd_ser;
struct termios terminal;
set_fgcolor(3);
log_meld ("Port öffnen...");
int fefe = 0xFE;

  {
  /*
   * Oeffnet seriellen Port
   * Gibt das Filehandle zurueck oder -1 bei Fehler
   * der Parameter port muss 0, 1, 2 oder 3 sein
   *
   * RS232-Parameter
   * - 19200 baud
   * - 8 bits/byte
   * - no parity
   * - no handshake
   * - 1 stop bit
   */
   int fd;
   struct termios options;
   fd = open("/dev/ttyUSB1", O_RDWR | /*O_NOCTTY | */O_NDELAY); 

    
   if (fd >= 0)
   {
     /* get the current options */
     fcntl(fd, F_SETFL, 0);
     if (tcgetattr(fd, &options) != 0) return(-1);
     bzero(&options, sizeof(options)); 

     cfsetspeed(&options, BAUD);       
   

     /* setze Optionen */
     options.c_cflag &= ~CRTSCTS;   /* Kein Hardwarehandshake */
     options.c_cflag &=  PARENB;         /* kein Paritybit */
     options.c_cflag &=  CSTOPB;         /* 1 Stoppbit */
     options.c_cflag &=  CSIZE;          /* 8 Datenbits */
     options.c_cflag |= CS8;
     options.c_cflag |= (CLOCAL | CREAD);/* CD-Signal ignorieren */
     /* Kein Echo, keine Steuerzeichen, keine Interrupts */
     options.c_lflag &=  (ICANON|  ECHO | ECHOE | ECHOK | ECHONL | ISIG | IMAXBEL );
     options.c_oflag &=  OPOST;          /* setze "raw" Input */
     options.c_oflag &= OFILL;     
     options.c_cc[VMIN]  = 0;            /* warten auf min. 0 Zeichen */
     options.c_cc[VTIME] = 50;           /* Timeout 5 Sekunden */
     tcflush(fd,TCSAFLUSH);
 //  tcflush(fd,TCIOFLUSH);
     /*if (tcsetattr(fd, TCSANOW, &options) != 0) return(-1);

     fcntl(fd, F_SETFL, FNDELAY);
     fcntl(fd, F_SETFL, 0);
     */
     }

  return(fd);

 }

Kann mir das alles nicht mehr erklären. Habt Ihr vielleicht dafür ne 
Erklärung?

Vielen Dank,

MfG

chris

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wenn ich
>
>    write(fd_ser,   "AT+CMGR=0\r\n",11);
>
> durch
>
>    write(fd_ser, "AT+COPS?\r\n",11);
>
> ersetze, ist der Output richtig:

Die Konstante 11 ist hier merkwürdig. Ich nehme an, daß das die Anzahl 
der zu sendenden Zeichen ist; das zweite Beispiel aber verwendet einen 
nur 10 Zeichen langen String, so daß als 11. Zeichen die terminierende 
\0 gesendet wird.

Das wird nicht des Problemes Ursache sein, aber es kann Nebeneffekte 
hervorrufen.

Du solltest überprüfen, ob für Deinen Stream nicht etwa eine 
automatische Zeilenumbrucherweiterung aktiv ist, die aus \n automatisch 
\r\n erzeugt. Oder beim Empfang das Gegenteil davon vornimmt.

Ansonsten: Sieh Dir halt die Sourcen von Minicom an, wie da die 
Schnittstelle initialisiert und behandelt wird.

Autor: chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ich minicom mit VT102 - Emulation parallel laufen lasse, 
funktioniert das Auslesen. Wenn ich allerdings ANSI-Emulation aktiviere, 
habe ich den selben Effekt, wie ohne minicom (funktioniert nicht).

Wo finde ich die minicom source?

MfG

chris

Autor: chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe eine Lösung gefunden, mit der ich nicht zufrieden bin:

2 mal hintereinander folgenden Teil ausgeben:
bytes = read_port(&fd_ser,puffer2);   // Daten lesen

Kann mir jedoch immernoch nicht erklären, warum das von Nöten ist. 
Vielleicht der Empfangspuffer der 232 zu gering?

MfG

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
vielleicht ist ja read_port schuld?
Gibt es dazu auch einen Quelltext?

Autor: Mark .. (mork)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@chris
 /* Kein Echo, keine Steuerzeichen, keine Interrupts */
     options.c_lflag &=  (ICANON|  ECHO | ECHOE | ECHOK | ECHONL | ISIG | IMAXBEL );
     options.c_oflag &=  OPOST;          /* setze "raw" Input */
     options.c_oflag &= OFILL; 
Hier passt Kommentar und Code nicht zusammen. Duch
options.c_lflag &=  (ICANON|  ECHO | ECHOE | ECHOK | ECHONL | ISIG | IMAXBEL );
 löschst Du alle anderen Bits außer ICANON,  ECHO, ECHOE, ECHOK, 
ECHONL und ISIG.

Was Du vermutlich haben willst ist
options.c_lflag &=  ~(ICANON|  ECHO | ECHOE | ECHOK | ECHONL | ISIG | IMAXBEL );
Dadurch werden die o.g. Bits gelöscht und der Rest bleibt gleich. Um 
alle Flags wie Echo, line buffer usw auf einmal zu deaktivieren kann man 
auch cfmakeraw(options) aufrufen (Siehe 
http://linux.about.com/library/cmd/blcmdl3_termios.htm).

MfG Mark

Autor: chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Änderung lt. Mark bringt auch keine Besserung. Hier die read_port:
 int read_port(int *fd_ser,unsigned char* buffer) {
     int a;
     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;
 }

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Definitiv ist der Puffer zu klein! Du hast einen Puffer für 200 Zeichen 
und in read_port() werden über read maximal 255 Zeichen eingelesen!

Das ist aber nicht das Problem. Das Problem ist dein Verständnis wie die 
Kommunikation arbeitet.

Es ist quasi normal mehrere Leseversuche hintereinander zu machen, bis 
"kein weiteres Zeichen gelesen" (bytes = 0) zurückkommt. Bei TCP 
Anforderungen ist das ähnlich.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.