It is currently Mon 15. Oct 2018, 16:46


All times are UTC + 1 hour




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: Erledigt: Seriell lesen
PostPosted: Sat 11. Sep 2010, 22:41 
Offline

Joined: Mon 6. Sep 2010, 19:22
Posts: 34
Hallo

Ich habe eine Frage zum Lesen von der seriellen Schnittstelle. Ich dachte eigentlich das ist Easy-Going, ist es aber irgendwie nicht. Ich setze das Ganze unter C um und meinte es sei Canonical (also zeilenorientiert), Synchron und NON-Blocking. Aber gerade mit diesen Einstellungen erhalte ich keine Daten an der Schnittstelle.

Da das Ganze nicht asyncron abläuft, sollte es auf die Art gehen:

* Serielle Öffnen --> DeviceHandle
* Kommando auf DeviceHandle schreiben
* xyz millisecs warten
* vom selben DeviceHandle lesen (nicht blockierend)


Das Öffnen der Schnittstelle mit allen Params sieht derzeit so aus:

Code:
    struct termios tio;
    int fd;
    memset(&tio,0,sizeof(tio));
    tio.c_iflag=0;
    tio.c_oflag=0;
    tio.c_cflag = CS8|CREAD|CLOCAL;           // 8n1

    cfsetospeed(&tio,BAUDRATE);
    cfsetispeed(&tio,BAUDRATE);

    fd = open(SERIAL_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK | O_SYNC );
    tcsetattr(fd,TCSANOW,&tio);


Beim Lesen erhalte ich aber einen EAGAIN als errno bzw einen
"SERIAL read error 11 Resource temporarily unavailable"

C-Entwickler hier die RS232 besser drauf haben als ich bzw. Hinweise ob das mit Canonical non-blocking etc stimmt beim 1141+?

LG


Last edited by juxmw on Sun 12. Sep 2010, 19:27, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Seriell lesen
PostPosted: Sun 12. Sep 2010, 09:53 
Offline
Administrator
User avatar

Joined: Tue 11. Aug 2009, 13:18
Posts: 175
vielleicht hilft dir die Toolbox vom Praxisbuch Embedded Linux weiter.
Das ist ein super Buch und kann nur empfolhlen werden.

http://www.praxisbuch.net/embedded-linux/downloads.html

PLCBUSguru

_________________
www.p-b-e.de


Top
 Profile  
 
 Post subject: Re: Seriell lesen
PostPosted: Sun 12. Sep 2010, 10:30 
Offline

Joined: Mon 6. Sep 2010, 19:22
Posts: 34
Hi plcGuru

Danke für den Hinweis - ich hab da mal durchgestöbert. Aktuell hilft es mir nicht weiter, aber generell sehr interessant.

Im konkreten Fall ist es ja nicht so, dass ich nicht C könnte - ich weiß nur nicht auf welche Art der 1141 antwortet.
Try and Error hat mich nicht sehr weit gebracht leider :)

LG
juxmw


Top
 Profile  
 
 Post subject: Re: Seriell lesen
PostPosted: Sun 12. Sep 2010, 17:13 
Offline
Administrator
User avatar

Joined: Tue 11. Aug 2009, 13:18
Posts: 175
Hi juxmw,

vielleicht noch folgende Infos zu den Settings:
Baudrate: 9600
Datenbits: 8
Stop-Bit: 1
Parity: None

Es findet auch kein Handshake statt.
Das 1141 verwendet nur 2 Leitungen Rx und Tx.

Gesendet werden immer 8 Bytes und emfangen 9 Bytes
Auf einen gesendeten Befehl kommen immer 2 oder mehr Antworten mit jeweils 9 Bytes.

1. Antwort ist immer das Bus-Echo (1141 empfängt seinen eigenen Befehl) woran du erkennen kannst, dass der Befehl rausging
2. Antwort ist das ACK vom Module

Die 1. Antwort benötigt ca. 500 ms nach verschicken des Befehls
Das ACK kommt dann sehr kurz danach. (eine 230V-Halbwelle später)

PLCBUSguru

_________________
www.p-b-e.de


Top
 Profile  
 
 Post subject: Re: Seriell lesen
PostPosted: Sun 12. Sep 2010, 19:27 
Offline

Joined: Mon 6. Sep 2010, 19:22
Posts: 34
OMG PLCguru - vielen Dank für die Antwort - beim Lesen deines Textes ist mir eingefallen was los sein könnte - es lag zwar nicht direkt am Post, aber irgendwie ist mir ein Licht aufgegangen als Du erwähntest dass 2 Antworten kommen etc.
Ich entwickle auf einem XPORT Pro - und der hat auf der seriellen eine Debug Console liegen ... ich dachte eigentlich die habe ich vor Wochen schon deaktiviert, war sie aber nicht ... daher war das Device beim Lesen auch blockiert.

Also Leute - serielle Consolen deaktivieren, dann klappts auch mit dem Lesen :D
Das Thema ist somit erledigt - vielen Dank ;)

LG
juxmw


Top
 Profile  
 
PostPosted: Sun 12. Sep 2010, 19:45 
Offline

Joined: Mon 6. Sep 2010, 19:22
Posts: 34
Aja - falls es mal wer braucht, hier mein funktionierender Test-Code in C um vom PLC zu schreiben und zu lesen. Keine große Hexerei, aber vielleicht spart jemand Zeit damit, wirklich sauber ist es nicht, aber fürs erste reichts.

Serielle öffnen, SERIAL_DEVICE und BAUDRATE sind zu definieren.
Code:
int tty_open (int *fd) {

    struct termios options;
    /*
     * O_RDWR read and write
     * O_NOCTTY es handelt sich um keine Konsole
     * O_NONBLOCK nicht blockieren
     * O_SYNC warte bei jeden write aufruf, bis er fertig ist
     */
    *fd = open (SERIAL_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK | O_SYNC );

    if (*fd < 0)
    {
        fprintf(stderr, "Open_port: unable to open %s\n", SERIAL_DEVICE);
        exit (1);   // irreparebel, verlasse Programm
    }
    bzero(&options, sizeof(options)); /* clear struct for new port settings */
 
    /*
     *  BAUDRATE: Set bps rate. You could also use cfsetispeed and cfsetospeed.
     *  CRTSCTS : output hardware flow control (only used if the cable has
     *            all necessary lines. See sect. 7 of Serial-HOWTO)
     *  CS8     : 8n1 (8bit,no parity,1 stopbit)
     *  CLOCAL  : local connection, no modem contol
     *  CREAD   : enable receiving characters
     */
    options.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD ;
    options.c_iflag = IGNPAR; //ignore framing / parity errors
    options.c_oflag = 0;

    cfsetispeed(&options, B9600);
    cfsetospeed(&options, B9600);

    /* set input mode (non-canonical, no echo,...) */
    options.c_lflag = 0;
    fcntl(*fd, F_SETFL, FNDELAY); // don't block serial read
    tcflush(*fd, TCIFLUSH); //empty line
    tcsetattr (*fd, TCSANOW, &options);
    return 0;


Function zum Lesen und Schreiben
Code:
int tty_read (int *fd, char *buffer, int size)
{
    int ret;
    ret = read (*fd, buffer, size);

    if (ret < 0) {
        if (errno == EAGAIN) {
            printf("SERIAL EAGAIN ERROR\n");
            printf("SERIAL read error %d %s\n", errno,
            strerror(errno));
            return 0;
        } else {
            printf("SERIAL read error %d %s\n", errno,
            strerror(errno));
            return 0;
        }
    }
    if ( ret == 0 ) {
        printf ("read returned 0 byte\n");
        return 0;
    }
    return 1;
}


int tty_write (int *fd, char *buffer, int size)
{
    int ret;
    ret = write (*fd, buffer, size);
    return ret;
}



im eigentlichen Code ist der Ablauf dann relativ simple (Timing, Wiederholung bei falscher Antwort etc. muss man halt noch ausprogrammieren, daher etwas "Pseudocode".

- Öffne Serielle
- Schreibe Daten
- Warte 500ms
- Lese
- Wiederhole Senden wenn Lesen fehlgeschlagen --> danach nochmal lesen

Das Lesen ist wie vermutet kanonisch (also zeilenorientiert).


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group
Imprint