LINUX - C - RS232 - Raw output & input

OP #2616939
Lesenswert?

Linux steuert mit C Programm über RS232 einen AVR

Hallo Gemeinde,

ich bin dabei ein Programm zu schreiben mit dem ich ein Controller per 
RS232 (FT232LR) zu steuern. meine Programm ist schon fast fertig. doch 
ich habe eine Problem, denn ich kann leider nicht alle Zeichnen über die 
schnittstelle schicken.
Als beispiel, kann ich die folge: 0x0C, 0x00, 0x04 nicht senden. Denn 
0x0C ist ein Steuercode (FF) denn ich leider nicht senden kann, was ist 
den in meinem Programmcode falsch? Ich möchte alle Bytes von 0x00 bis 
0xff senden können, aber wie??
1
 
2
#include <stdio.h>
3
#include <stdlib.h>
4
#include <sys/ioctl.h>
5
#include <sys/types.h>
6
#include <sys/stat.h>
7
#include <fcntl.h>
8
#include <unistd.h>
9
#include <signal.h>
10
#include <termios.h>
11
#include <string.h>
12
#include <stdbool.h>
13

14
int fd = 0;
15

16
int main(int argc, char** argv)
17
{
18
  struct termios oldtios,options;
19
  int currstat = 0;
20
  if((argc < 2)||(argc > 3))
21
    {
22
      printf("Fehler: Ungültige Parameter-Anzahl.\n");
23
      printf("Aufruf:\n");
24
      printf("  %s <device>\n",argv[0]);
25
      return 1;
26
    }
27

28
  /* Das Device öffnen */
29
  if((fd = open(argv[1], O_RDWR | O_NOCTTY | O_NDELAY)) < 0)
30
    {
31
      printf("Fehler: Device \"%s\" kann nicht geöffnet werden.\n", argv[1]);
32
      return 2;
33
    }
34

35
  tcgetattr(fd,&oldtios);
36

37
  fcntl(fd, F_SETFL, 0);
38
  if (tcgetattr(fd, &options) != 0) return(-1);
39

40
  cfsetispeed(&options, B115200);            /* setze 115200 bps */
41
  cfsetospeed(&options, B115200);
42

43
  options.c_cflag &= ~PARENB;               /*  kein Paritybit */
44
  options.c_cflag &= ~CSTOPB;               /* 1 Stopbit */
45
  options.c_cflag &= ~CSIZE;                /* 8 Datenbits */
46
  options.c_cflag |= CS8; 
47
  options.c_cflag &= ~CRTSCTS;
48
  options.c_cflag |= (CLOCAL | CREAD);      /* CD-Signal ignorieren */
49
  /* Kein Echo, keine Steuerzeichen, keine Interrupts */
50
  options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
51
  options.c_oflag &= ~OPOST;                /* setze "raw" Input */
52
  options.c_cc[VMIN]  = 0;                  /* warten auf min. 0 Zeichen */
53
  options.c_cc[VTIME] = 10;                 /* Timeout 10 Sekunden */
54

55
  tcflush(fd,TCIOFLUSH);
56
  if (tcsetattr(fd, TCSAFLUSH, &options) != 0) return(-1);
57
  char buffer[8];
58

59
  // Version
60
  buffer[0]=0x11;
61
  buffer[1]=0x00;
62
  buffer[2]=0x04;
63

64

65
  printf("-Eingabe---------------------\n");
66
  int i;
67
  for (i=0; i<3; i++ )
68
  {
69
    printf("0x%02x ",buffer[i]);
70
  }
71
  printf("\n");
72
  printf("-----------------------------\n");
73

74
  // buffer schreiben
75
  i = write(fd,buffer,3); //ist das OK?
76
  printf("geschrieben: %i\n",i);
77
  printf("-----------------------------\n");
78

79
  int bb = 0;
80
  int x = 0;
81
  bool cmdOK=false;
82
  char cods[10];
83

84
  /*
85

86
      ABHIER?
87
      Lese des Gerätes, antwort solte sein:
88
      0x1A, 0x03, 0x02, 0x00, 0x00, 0x04 (0x04 sollte EOT sein)
89
      aber was ist da falsch?
90
  */
91
  do
92
  {
93
    //printf("\n");
94
    if((bb = read( fd, &cods[x], sizeof( cods )-x )) > 0)
95
    //if((bb = read( fd, &cods, 5 )) > 0)
96
    {
97
      for (i=x;i<x+bb;i++)
98
        {
99
          //printf("0x%02x ",cods[i]);
100
          if (cods[i]==0x04) cmdOK=true;
101
        }
102
      x+=bb;
103
      //printf("\n");
104
      //printf("in if: x=%d\n",x);
105
    }
106
    //printf("nach if bb=%d\n",bb);
107

108
  }while(!cmdOK);
109

110
  printf("-Ausgabe---------------------\n");
111
  for (i=0; i<x; i++ )
112
  {
113
    printf("0x%02x ",cods[i]);
114
  }
115
  printf("\n");
116
  printf("-----------------------------\n");
117

118

119
  close(fd);
120

121

122
  // TTYS0 auf alten Wert setzen
123
  tcflush(fd,TCIOFLUSH);
124
  if (tcsetattr(fd, TCSAFLUSH, &oldtios) != 0) return(-1);
125

126
  return 0;
127
}

Bitte um Hilfs, Danke

Gruß

Oliver
#2617010
Lesenswert?

Du solltest options vor der Verwendung mit Nullen füllen oder nach dem 
tcgetattr() mit oldtios vorbelegen.

Vor und nach dem tcsetattr() könntest du mit
 system(cmd);
die Einstellungen prüfen, wobei cmd mit
 sprintf(cmd,"stty -a < %s",argv[1])
zu belegen ist.

> options.c_cc[VTIME] = 10;          /* Timeout 10 Sekunden */
Wert passt nicht zum Kommentar (hat aber nichts mit dem Problem zu tun).
OP #2617044
Lesenswert?

Hallo,

habe ich jetzt getan. Doch immer noch nicht richtig.

hier mal die Ausgabe:
1
./ioboard /dev/ttyUSB0
2
speed 115200 baud; rows 0; columns 0; line = 0;
3
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
4
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R;
5
werase = ^W; lnext = ^V; flush = ^O; min = 0; time = 10;
6
-parenb -parodd cs8 hupcl -cstopb cread clocal -crtscts
7
-ignbrk -brkint ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl -ixon -ixoff
8
-iuclc -ixany -imaxbel -iutf8
9
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
10
-isig -icanon iexten -echo -echoe echok -echonl -noflsh xcase -tostop -echoprt
11
-echoctl echoke
12
-Eingabe---------------------
13
0x0c 0x00 0x04
14
-----------------------------
15
geschrieben: 3
16
-----------------------------
17
0xf9 0x01 in if: x=2
18
0x02 0x04 in if: x=4
19
-Ausgabe---------------------
20
0xf9 0x01 0x02 0x04
21
-----------------------------

doch es sollte: 0x1A 0x01 0x34 0x04 sein.

doch leider nicht!!

Gruß

Oliver
OP #2617078
Lesenswert?

so:
1
VOR tcsetattr
2
speed 115200 baud; rows 0; columns 0; line = 0;
3
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
4
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R;
5
werase = ^W; lnext = ^V; flush = ^O; min = 0; time = 10;
6
-parenb -parodd cs8 hupcl -cstopb cread clocal -crtscts
7
-ignbrk -brkint ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl -ixon -ixoff
8
-iuclc -ixany -imaxbel -iutf8
9
opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
10
-isig -icanon iexten -echo -echoe echok -echonl -noflsh -xcase -tostop -echoprt
11
-echoctl echoke
12

13

14

15
Nach tcsetattr
16
speed 115200 baud; rows 0; columns 0; line = 0;
17
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
18
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R;
19
werase = ^W; lnext = ^V; flush = ^O; min = 0; time = 10;
20
-parenb -parodd cs8 hupcl -cstopb cread clocal -crtscts
21
-ignbrk -brkint ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl -ixon -ixoff
22
-iuclc -ixany -imaxbel -iutf8
23
opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
24
-isig -icanon iexten -echo -echoe echok -echonl -noflsh -xcase -tostop -echoprt
25
-echoctl echoke


gleich? was ist das ?

neuster source code als file

Gruß

Oliver

PS.: schon mal danke ;-)
Angehängte Dateien:
#2617093
Lesenswert?

> Du solltest options vor der Verwendung mit Nullen füllen oder nach dem
> tcgetattr() mit oldtios vorbelegen.

Damit meinte ich
 memset(&options,0,sizeof(options));
oder
 options = oldtios;
um sicherzugehen, dass die gesamte Struktur definierte Werte aufweist.
Deswegen: "This structure contains at least the following members:".
OP #2617110
Lesenswert?

mist, erschreibt das alte nicht zurück und ich habe jetzt
folgendes eingefügt:
1
struct termios oldtios,options;
2
memset(&options,0,sizeof(options));
3
memset(&oldtios,0,sizeof(oldtios));
4
int currstat = 0;

doch die Steurcodes bei der Ausgabe werden immer noch beachtet.

1
-opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0

was mach ich den da falsch ....

es muss doch gehen ...

Gruß

Oliver
#2617134
Lesenswert?

>> Du solltest options vor der Verwendung mit Nullen füllen oder nach dem
>> tcgetattr() mit oldtios vorbelegen.
>
> Damit meinte ich
>  memset(&options,0,sizeof(options));
> oder
>  options = oldtios;
> um sicherzugehen, dass die gesamte Struktur definierte Werte aufweist.
> Deswegen: "This structure contains at least the following members:".

Ah, da hab ich übersehen, dass du da noch ein tcgetattr(fd, &options) 
drin hast. Da ist ja auch OK.
#2617142
Lesenswert?

Oliver R. schrieb:
> 0xfffffff9 0x01 0x02 0x04
> -----------------------------
>
> doch der controler sendet nur byte weise.

Das ist schon OK. cods ist char, also signed. "0x%02x" gibt zweistellig 
aus, wenn es Platz hat. Hat es aber nicht, weil das signed char 0xf9 
vorzeichenrichtig auf int erweitert wird. Also entweder cods als 
unsigned char deklarieren oder mit
 printf("0x%02x ",(unsigned char)cods[i]);
casten.
Persönliche Seite #2630505
Lesenswert?

Aus C / C++ heraus mache ich das so:




FUNCT int seropen( u8 ser_port_no ) // LINUX

{

int rv ;

struct termios xt ;

char cmdbuf[80] ;



if ( ser_port_no < MAX_INTERFACENO )

  {

  if ( !seropened[ser_port_no] )

    { // 2012-01-08

    nsprintf( cmdbuf, sizeof(cmdbuf), // Dahin die Kommandozeile fuer 
das Umschalten der Baudrate

        "stty <%s %lu",

        sername[ser_port_no],

        ser_settings_field[ser_port_no].baud );


    system( cmdbuf );

    fdser[ser_port_no] = normopen( sername[ser_port_no] , O_RDWR );

    if ( fdser[ser_port_no] >= 0 )

      {

      fcntl( fdser[ser_port_no], F_SETFL, O_NONBLOCK );

      tcgetattr( fdser[ser_port_no] , &xt );        /* Aktuelle 
Einstellung holen für Änderung */

      tcgetattr( fdser[ser_port_no] , &ser_stat_orig[ser_port_no] );  /* 
Aktuelle Einstellung für Exit */

      xt.c_lflag &= ~ICANON ;

      xt.c_lflag &= ~ECHO ;

      xt.c_iflag &= ~ICRNL ;

      xt.c_iflag &= ~BRKINT ;

      xt.c_iflag &= ~IGNBRK ;

      xt.c_iflag &= ~IGNCR ;

      xt.c_iflag &= ~IGNPAR ;

      xt.c_iflag &= ~IMAXBEL ;

      xt.c_iflag &= ~BRKINT ;

      rv = tcsetattr( fdser[ser_port_no] , TCSANOW, &xt );

      if ( rv < 0 )

        {

        uprintf( "cannot tcsetattr serial line %s", sername[ser_port_no] 
);

        }

      seropened[ser_port_no] = true ;

      return 0 ;    // opened succesful

      }

    printf( "cannot open %s for RW, errno=%d", sername[ser_port_no] , 
errno );

    return 1 ;

    }

  return 2 ;

  }

else

  {

  printf( "bad interface number" );

  return 4 ;

  }

}




FUNCT int serclose( u8 ser_port_no )    // LINUX

{

int rv ;



if ( ser_port_no < MAX_INTERFACENO )

  {

  tcsetattr( fdser[ser_port_no], TCSANOW, &ser_stat_orig[ser_port_no] );

  close( fdser[ser_port_no] );

  // vt_opened = false ;

  rv = 0 ;      // no error

  }

else

  {

  rv = 1 ;      // some error

  }

}
Persönliche Seite #2630513
Lesenswert?

Aus der Kommandozeile heraus, z.B. für JAVA-Programme mache ich das so:

stty -F /dev/ttyUSB0 speed 9600 cs8 -parenb -parodd raw -echo


Besonders wichtig ist hier -echo, sonst wird euf jedes hereinkommende 
Zeichen geantwortet, z.B: auf 0x02 mit "^B"


und zurück in den Textmodus geht es mit:


stty -F /dev/ttyUSB0 speed 9600 cs8 -parenb intr 3 quit 28 erase 127 
kill 21 eof 4 eol 13 eol2 undef swtch undef start 17 stop 19 susp 26 
rprnt 18 werase 23 lnext 22 flush 15 min 1 time 0 -parenb -parodd -hupcl 
-cstopb cread clocal -crtscts -ignbrk -brkint -ignpar -parmrk -inpck 
-istrip -inlcr igncr icrnl ixon ixoff -iuclc -ixany -imaxbel -iutf8 
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 
vt0 ff0 isig icanon iexten echo echoe echok -echonl -noflsh -xcase 
-tostop -echoprt echoctl echoke


(Alles in eine einzige Zeile)
OP #2634784
Lesenswert?

Hallo,
ja danke, das geht auch, doch ich wollte gerne die Einstelung der 
schnittstelle in meinem C code haben. Aber genau das wäre die
Einstellung für die Schnittstelle.

stty -F /dev/ttyUSB0 speed 9600 cs8 -parenb -parodd raw -echo

-parend => kein Paritätsbit
-parodd => Ungrade Paritätsbit

ergo: ttyUSB0 9600 8N1 RAW keine echo ;-)

und das jetzt in C !!! ;-)

das ist noch die Frage, denn mein Programm hängt sich noch auf ;-)

Hat da jemand eine Code?


Gruß

Oliver

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren