Forum: Mikrocontroller und Digitale Elektronik Linux serial port cross compile


von Hate M. (hate)


Lesenswert?

Guten Tag,

versuche über die serielle Schnittstelle (c Code) einen Sensor 
anzusprechen.
Dieser liefert mir anschließend seine Messdaten zurück.

Starte ich den Code auf dem Linux Laptop funktioniert die Verbindung 
einwandfrei.
Nun mache ich ein cross compile für meinen Embedded Linux Controller. 
Code ist der gleiche nur Port ändert sich.

Der recv buffer bleibt jedoch leer. Daten werden gesendet. Verkabelung 
stimmt ebenfalls.
1
#include <errno.h>
2
#include <fcntl.h> 
3
#include <stdio.h>
4
#include <stdlib.h>
5
#include <string.h>
6
#include <termios.h>
7
#include <unistd.h>
8
#include <sys/select.h>
9
#include <sys/time.h>
10
#include <sys/types.h>
11
#include <sys/ioctl.h>
12
13
int set_interface_attribs(int fd, int speed)
14
{
15
    struct termios tty;
16
17
    if (tcgetattr(fd, &tty) < 0) {
18
        printf("Error from tcgetattr: %s\n", strerror(errno));
19
        return -1;
20
    }
21
22
    cfsetospeed(&tty, (speed_t)speed);
23
    cfsetispeed(&tty, (speed_t)speed);
24
25
    tty.c_cflag |= (CLOCAL | CREAD);    /* ignore modem controls */
26
    tty.c_cflag &= ~CSIZE;
27
    tty.c_cflag |= CS8;         /* 8-bit characters */
28
    tty.c_cflag &= ~PARENB;     /* no parity bit */
29
    tty.c_cflag &= ~CSTOPB;     /* only need 1 stop bit */
30
    tty.c_cflag &= ~CRTSCTS;    /* no hardware flowcontrol */
31
32
    /* setup for non-canonical mode */
33
    tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
34
    tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
35
    tty.c_oflag &= ~OPOST;
36
37
    /* fetch bytes as they become available */
38
    tty.c_cc[VMIN] = 49;
39
    tty.c_cc[VTIME] = 10;
40
41
    if (tcsetattr(fd, TCSANOW, &tty) != 0) {
42
        printf("Error from tcsetattr: %s\n", strerror(errno));
43
        return -1;
44
    }
45
  sleep(2);
46
  if (tcsetattr(fd, TCSAFLUSH, &tty) != 0) {
47
        printf("Error from tcsetattr: %s\n", strerror(errno));
48
        return -1;
49
    }
50
    return 0;
51
}
52
53
int main()
54
{
55
    char *portname = "/dev/ttyS1";
56
    int fd = 0;
57
    int wlen;
58
    unsigned char send_bytes[] ={0xde,0x01,0x05,0x59,0x83};
59
60
    fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC);
61
    if (fd < 0) {
62
        printf("Error opening %s: %s\n", portname, strerror(errno));
63
        return -1;
64
    }
65
    set_interface_attribs(fd, B115200);
66
67
  //wlen = write(fd, send_bytes, 5);
68
69
  int maxfd,n;
70
  maxfd = fd + 1;
71
72
    struct timeval timeout;
73
    fd_set readSet;
74
  unsigned char buf[254];
75
  int rdlen;
76
77
  do {
78
    /*
79
  wlen = write(fd,"\xde\x01\x05\x59\x83", 5);
80
81
  if (wlen != 5) {
82
    printf("Error from write: %d, %d\n", wlen, errno);
83
  }
84
  */
85
  printf("-->\n");
86
87
  timeout.tv_usec = 0;  // milliseconds
88
  timeout.tv_sec  = 1;  // seconds
89
90
  FD_ZERO(&readSet);
91
  FD_SET(fd,&readSet);
92
  
93
  n = select(maxfd,&readSet, NULL, NULL,&timeout);
94
  if (n>0)
95
  {
96
    if (FD_ISSET(fd, &readSet))
97
    {
98
    printf("--reading--->\n");
99
    rdlen = read(fd, buf, sizeof(buf) - 1);
100
    printf("length: %i\n",rdlen);
101
102
    if (rdlen > 1) {
103
      unsigned char   *p;
104
      printf("Read %d:", rdlen);
105
      for (p = buf; rdlen-- > 0; p++)
106
        printf(" 0x%x", *p);
107
      printf("\n");
108
    } else if (rdlen <= 0) {
109
      printf("Error from read: %d: %s\n", rdlen, strerror(errno));
110
    }
111
    }
112
  }
113
  else if(n<=0)
114
  {
115
    printf("FEHLER\n");
116
  }
117
  }while (1);
118
close(fd);
119
}

von Markus F. (mfro)


Lesenswert?

Laß' dir mal fd und FD_SETSIZE ausgeben (fd muß kleiner sein, sonst 
tut's nicht).

select() kann auf den "großen" Linuxen normalerweise bis zum 
File-Deskriptor 255 benutzt werden, es kann aber durchaus sein, daß das 
beim embedded Linux beschnitten wurde.

Dann bliebe nur, stattdessen poll() zu benutzen (ist wahrscheinlich 
sowieso die bessere Idee).

von Hate M. (hate)


Lesenswert?

Markus F. schrieb:
> Laß' dir mal fd und FD_SETSIZE ausgeben (fd muß kleiner sein, sonst
> tut's nicht).
>
> select() kann auf den "großen" Linuxen normalerweise bis zum
> File-Deskriptor 255 benutzt werden, es kann aber durchaus sein, daß das
> beim embedded Linux beschnitten wurde.
>
> Dann bliebe nur, stattdessen poll() zu benutzen (ist wahrscheinlich
> sowieso die bessere Idee).

Ich bin noch sehr am Anfang mit meinen Kenntnissen.
Habe nun folgendes versucht:

Führe den Sende Code auf dem Rechner aus und den Empfangscode auf dem 
Embedded Controller. -> Daten werden auf dem Controller empfangen.

Nun das gleiche anders herum. Und die Daten werden auf dem Rechner 
empfangen.
Der Code müsste als soweit stimmen.
Nur wenn Senden und Empfangen auf dem Controller läuft kackt er ab.

von Markus F. (mfro)


Lesenswert?

Abgesehen von der potentiellen select() Problematik: Dir ist bewußt, daß 
Du Software-Handshake eingeschaltet hast (IXON)?

Das schließt eigentlich Binärdatenübertragung (die wohl - wie die 
auskommentierte Senderoutine zu implizieren scheint - gewünscht ist?) 
aus...

von Hate M. (hate)


Lesenswert?

Markus F. schrieb:
> Abgesehen von der potentiellen select() Problematik: Dir ist bewußt, daß
> Du Software-Handshake eingeschaltet hast (IXON)?
>
> Das schließt eigentlich Binärdatenübertragung (die wohl - wie die
> auskommentierte Senderoutine zu implizieren scheint - gewünscht ist?)
> aus...

Nein das war mir nicht bewusst. Habe es nun auf OFF
fd liefert mir eine 3.
Trotzdem läuft es auf dem Controller nicht.

: Bearbeitet durch User
von bash (Gast)


Lesenswert?

probier es erst ma in der shell

cat /dev/ttyS0


vorher framin etc setzen etwa so:

stty 9600 cs8 -parenb crtscts -echo -F /dev/ttyS0;

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

bash schrieb:
> probier es erst ma in der shell
>
> cat /dev/ttyS0

Er hat allerdings
1
    char *portname = "/dev/ttyS1";
hart eincodiert, was m.E. schon mutig ist. Wer sagt denn, das es die 
richtige serielle ist?

von bash (Gast)


Lesenswert?

er soll natürlich mit dem richtigen Port probieren /dev/tty XXX

probieren um Fehler in seiner SW auszuschließen...

von Hate M. (hate)


Lesenswert?

Hallo,

wie schon erwähnt funktioniert die Schnittstelle schon. Und der Port ist 
ebenfalls richtig.

Wenn ich den Code nur auf die Read Funktion reduziere und dann auf dem 
Embedded ausführe werden Daten empfangen. (PC<-->EmbController).

Wenn ich den Code nur auf die Write Funktion reduziere und auf dem 
Embedded ausführe werden Hex Daten(Binär) 
gesendet.(PC<-->EmbController).

Wenn der Code vollständig ist. Also write dann anschließend read. 
Funktioniert es nicht.

Mit der shell habe ich es auch schon probiert. Dies funktioniert 
ebenfalls.

von Chris (Gast)


Lesenswert?

Und mit einem normalen Terminalprogramm auf der seriellen Schnittstelle 
funktioniert alles?
Es könnte auch am Treiber der seriellen Schnittstelle liegen.

von Hate M. (hate)


Lesenswert?

Chris schrieb:
> Und mit einem normalen Terminalprogramm auf der seriellen Schnittstelle
> funktioniert alles?
> Es könnte auch am Treiber der seriellen Schnittstelle liegen.

ich kann über diese Schnittstelle Daten empfangen. Also Daten (binär) 
die ich vom PC sende.

wenn ich rein diesen code Ausführe
1
dlen = read(fd, buf, sizeof(buf) - 1);

das gleiche auch in die andere Richtung.
Habe es noch zusätzlich mit dem Oszi überprüft. Stimmt soweit alles.

habe es auch über das Terminal versucht:

cat /dev/ttyS2

Daten werden empfangen vom PC.


Sobald write and read (Code erster Post) ausgeführt wird bleibt der 
Buffer leer.
Ich habe das schon an einer 2ten ser Schnittstelle versucht. Gleiches 
Ergebnis.

Habe etwas gelesen über die poll Funktion. Kann mir da jmd eine Hilfe 
dazu geben.

: Bearbeitet durch User
von Hate M. (hate)


Lesenswert?

Habe das alles nun auch über das Terminal versucht.

echo -ne "\xde\x01..usw." > /dev/ttyS2

über 2tes Terminal Fenster

cat /dev/ttyS2

Gesendet und empfangen wird etwas (Oszi). Jedoch zeigt die cat Funktion 
nichts an.

Führe ich rein cat /dev/ttyS2 aus. Und sende die Daten über den PC 
funktioniert es.

So habe alles nochmal als python script getestet. Auf dem Rechner läufts 
wieder und auf dem Controler nicht (buffer LEER)
1
import serial
2
3
ser = serial.Serial('/dev/ttyS2', 115200, timeout=1)
4
5
if(ser.isOpen()):
6
    print'serial is not open'
7
8
9
while True:
10
    
11
12
    ser.write([0xde, 0x01, 0x05, 0x59, 0x83]) 
13
    reply = ser.read(100)
14
15
    if len(reply) == 0:
16
        print'length = LEER'
17
        #break
18
    print len(reply)
19
20
print'Serial close'
21
ser.close()

: Bearbeitet durch User
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.