Forum: Compiler & IDEs C array über serielle schnittstelle emfangen


von Alex G. (alex94) Benutzerseite


Lesenswert?

Hallo,
ich möcht ein Array über die RS232 schnittstelle an meinen µC (Atmega8) 
senden. Die Hardware funktioniert einwandfrei. Das Array besteht aus 8 
hexadezimal Werten. Diese soll man einfach am Pc über ein terminal 
programm an den µC senden können. Die Baudrate liegt bei 9600Bd. So ich 
hab leider noch keine so guten C erfahrungen und weiß deshalb nicht wo 
ich eig. anfangen muss. Ich hab wie gesagt keine ahnung wie das C 
programm auf dem µC ausehen muss :( Das Avr GCC Tutorial hat mich nicht 
weit gebracht.

Danke im voraus.

mfg alex

von Karl H. (kbuchegg)


Lesenswert?

Alex Peterson schrieb:
> Hallo,
> ich möcht ein Array über die RS232 schnittstelle an meinen µC (Atmega8)
> senden. Die Hardware funktioniert einwandfrei. Das Array besteht aus 8
> hexadezimal Werten. Diese soll man einfach am Pc über ein terminal
> programm an den µC senden können. Die Baudrate liegt bei 9600Bd. So ich
> hab leider noch keine so guten C erfahrungen und weiß deshalb nicht wo
> ich eig. anfangen muss. Ich hab wie gesagt keine ahnung wie das C
> programm auf dem µC ausehen muss :( Das Avr GCC Tutorial hat mich nicht
> weit gebracht.

Vergiss fürs erste das Array.
Beschäftige dich damit, ein einzelnes Zeichen zu übertragen.
Wie das geht steht im Tutorial.

Ein Array mit 8 Zeichen zu übertragen ist dann ganz einfach 8 einzelne 
Werte hintereinander zu übertragen.

von Alex G. (alex94) Benutzerseite


Lesenswert?

ok vielen Dank, das wede ich mal versuchen.

von Alex G. (alex94) Benutzerseite


Lesenswert?

Hallo, ich habe es immer noch nicht hingekriegt und ich habe mir das 
folgende Skript zusammen kopiert (leider bin ich mir nicht sicher ob es 
funktioniert)
1
#include <inttypes.h>
2
#include <avr/io.h>
3
4
5
6
 
7
#ifndef F_CPU
8
9
 
10
#warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 4000000"
11
#define F_CPU 8000000UL    // Systemtakt in Hz - Definition als unsigned long beachten >> Ohne ergeben Fehler in der Berechnung
12
#endif
13
 
14
#define BAUD 9600UL          // Baudrate
15
 
16
// Berechnungen
17
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
18
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
19
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
20
 
21
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
22
  #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! 
23
#endif
24
25
void Usart_EnableRX(void)
26
{
27
    UCSRB |= ( 1 << RXEN );
28
}
29
 
30
 int main(void)
31
{
32
    UCSRB |= (1<<TXEN);                // UART TX einschalten
33
    UCSRC |= (1<<URSEL)|(3<<UCSZ0);    // Asynchron 8N1 
34
 
35
    UBRRH = UBRR_VAL >> 8;
36
    UBRRL = UBRR_VAL & 0xFF;
37
  
38
  uint8_t uart_getc(void)
39
{
40
    while (!(UCSRA & (1<<RXC)))   // warten bis Zeichen verfuegbar
41
        ;
42
    return UDR;                   // Zeichen aus UDR an Aufrufer zurueckgeben
43
}   
44
}

ich wollte mal fragen ob ihr mal drüber schauen könnt.

mfg alex

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Was soll das denn sein?
1
 int main(void)
2
{
3
    UCSRB |= (1<<TXEN);                // UART TX einschalten
4
    UCSRC |= (1<<URSEL)|(3<<UCSZ0);    // Asynchron 8N1 
5
 
6
    UBRRH = UBRR_VAL >> 8;
7
    UBRRL = UBRR_VAL & 0xFF;
8
  
9
  uint8_t uart_getc(void)
10
{
11
    while (!(UCSRA & (1<<RXC)))   // warten bis Zeichen verfuegbar
12
        ;
13
    return UDR;                   // Zeichen aus UDR an Aufrufer zurueckgeben
14
}   
15
}

C kennt keine Funktionen, die innerhalb von anderen Funktionen 
definiert werden.

Außerdem wird diese Funktion nirgends aufgerufen, und Dein 
"Usart_EnableRX" ebensowenig.

Bevor Du anfängst, ein Programm zusammenzustoppeln, solltest Du Dir erst 
einmal Gedanken über die Abfolge der für Deine Problemstellung 
erforderlichen Schritte machen.

Du willst ein Array über eine serielle Schnittstelle übertragen. Eine 
serielle Schnittstelle aber überträgt nur Bytes, nichts anderes. Also 
musst Du einen Weg finden, das Array als Folge einzelner Bytes 
anzusprechen.
Ist es ein Array von Bytes, so ist die Angelegenheit einfach, weil schon 
erledigt.
Ist es ein Array eines anderen Datentyps, so musst Du mit eine Typecast 
und dem sizeof-Operator arbeiten.
Sinnvoll ist in beiden Fällen die Verwendung eines Pointers auf Bytes, 
der auf die Arrayanfangsadresse gesetzt wird.

Letztlich musst Du also eine definierte Anzahl von Bytes empfangen und 
die in das Array eintragen.

So etwas kann man mit einer Schleife machen, die für jedes einzelne Byte 
einmal durchlaufen wird. Jedes Mal wird ein Byte empfangen - Dein 
Codefragment "uart_getc" macht das. Das empfangene Byte wird in das 
Array eingetragen und danach der Schreibzeiger auf das Array um eins 
erhöht.

Das allerdings ist nicht sehr fehlertolerant. Was macht Dein Programm, 
wenn mehr Daten kommen, als in Dein Array hineinpassen? Sollen nach dem 
Start nur genau einmal Daten übertragen werden?

Wenn Du all dies geklärt hast, dann kannst Du Dir ein Programm 
zusammenschreiben.

von Alex G. (alex94) Benutzerseite


Lesenswert?

Vielen DAnk für deine ausfürliche Antwort.
Ich werde dann mal die ganzen Sachen klären.

von Alex G. (alex94) Benutzerseite


Lesenswert?

Hallo,
nachdem ich ein zeichen empfangen habe (mit folgendem code) kann ich 
dann UDR wie eine variable verwenden?

Hier nochmal der Code:
1
      while (!(UCSRA & (1<<RXC)))   // warten bis Zeichen verfuegba
2
    {
3
    }
4
    return UDR;

von Stefan K. (syliosha)


Lesenswert?

Prinzipell ja, aber in dem Zusammenhang vollkommen falsch. Ich nehme mal 
an, dass dieser Code innerhalb einer anderen Funktion ist. Wenn du dir 
mal ein C-Buch(Kernighan/Richie, der Klassiker) zu gemüte führen 
würdest, würdest du sehen, dass der Inhalt von UDR als Ergebnis beim 
Aufrufen der Funktion als Wert zurückgegeben wird.

von Karl H. (kbuchegg)


Lesenswert?

Alex Peterson schrieb:
> Hallo,
> nachdem ich ein zeichen empfangen habe (mit folgendem code) kann ich
> dann UDR wie eine variable verwenden?
>
> Hier nochmal der Code:
>
>
1
>       while (!(UCSRA & (1<<RXC)))   // warten bis Zeichen verfuegba
2
>     {
3
>     }
4
>     return UDR;
5
>


Im Grunde ja.
Aber du darfst (in diesem Fall) nicht auf UDR schreiben und du darfst 
nur einmal von UDR lesen.

Also verpack das in eine Funktion
1
uint8_t getc()
2
{
3
  while (!(UCSRA & (1<<RXC)))   // warten bis Zeichen verfuegba
4
  {
5
  }
6
  return UDR;
7
}

und benutze sie ganz einfach
1
int main()
2
{
3
  uint8_t c;
4
5
  c = getc();
6
7
  if( c == 'a' )
8
    mach was
9
10
  if( c == 'b' )
11
    mach was ganz anderes
12
13
  if( c == 8 )
14
    und jetzt was völlig anderes

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Alex Peterson schrieb:

> Hallo,
> nachdem ich ein zeichen empfangen habe (mit folgendem code) kann ich
> dann UDR wie eine variable verwenden?

Das Thema wird gerade hier diskutiert:
Beitrag "ATmega8, UART: UDR mehrmals auslesen?"

Besser ist es, UDR einmalig in eine Variable auszulesen oder aus einer 
Variable zu füllen. Wenn du UDR als Rückgabewert einer Funktion 
verwendest, machst du im Grunde genau dieses.

von Alex G. (alex94) Benutzerseite


Lesenswert?

Vielen Dank für eure sehr guten Antworten.

von Alex G. (alex94) Benutzerseite


Lesenswert?

Ok ich kann jetzt einzelne Zeichen über die serielle schnittstelle 
empfangen und verarbeiten. Wie kann ich jetzt mein Array über die 
serielle schnittstelle übertragen? Muss ich jedes Zeicehn einzeln senden 
und dann in das Array einsetzten?

Hier mal das Array:
1
unsigned char example[5][8] = {{0xFF,0xD9,0xD1,0x13,0xD4,0xD1,0xC9,0x9A},    
2
                                {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},     
3
        {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},    
4
        {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},    
5
        {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}};

mfg alex

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Alex Peterson schrieb:

> Muss ich jedes Zeicehn einzeln senden
> und dann in das Array einsetzten?

Ja. Und im Idealfall ergänzt du die Rohdaten (Arrayinhalt) mit Prüfdaten 
(Quersumme, CRC-Prüfsumme ö.ä.) und Steuerdaten (z.B. 
Zeilennummer/Spaltennummer). Mit deren Hilfe kannst du die übertragenen 
Daten beim Empfänger auf Fheler prüfen und brauchst ggf. nur wenige 
Feldelemente statt das ganze Feld nochmal zu übertragen.

von Alex G. (alex94) Benutzerseite


Lesenswert?

Kann ich dann das empfangene Zeichen c dan einfach in das Array so 
setzten:

example[1][2] = c;

würde das gehen?
Dann besteht aber doch noch das Problem das eine Variable des Array's 
doch aus mehreren zeichen besteht. Wie geht das besser?

von Alex G. (alex94) Benutzerseite


Lesenswert?

Könnte das so funktionieren?:
1
uint8_t uart_getc(void)
2
{
3
    while (!(UCSRA & (1<<RXC)))   // warten bis Zeichen verfuegbar
4
        ;
5
    return UDR;                   // Zeichen aus UDR an Aufrufer zurueckgeben
6
}
7
 
8
void uart_gets( char* Buffer, uint8_t MaxLen )
9
{
10
  uint8_t NextChar;
11
  uint8_t StringLen = 0;
12
 
13
  NextChar = uart_getc();         // Warte auf und empfange das nächste Zeichen
14
 
15
                                  // Sammle solange Zeichen, bis:
16
                                  // * entweder das String Ende Zeichen kam
17
                                  // * oder das aufnehmende Array voll ist
18
  while( NextChar != '\n' && StringLen < MaxLen - 1 ) {
19
    *Buffer++ = NextChar;
20
    StringLen++;
21
    NextChar = uart_getc();
22
  }
23
 
24
                                  // Noch ein '\0' anhängen um einen Standard
25
                                  // C-String daraus zu machen
26
  *Buffer = '\0';
27
}
28
29
30
int main () {
31
32
  char Line[40];      // String mit maximal 39 zeichen
33
 
34
  uart_gets( Line, sizeof( Line ) );
35
36
example[1][2] = Line; //empfangener String in das Array einsetzen
37
38
}

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Das geht so nicht.

1
#include <inttypes.h>
2
#include <avr/io.h>
3
4
#ifndef F_CPU
5
#warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 4000000"
6
#define F_CPU 8000000UL    // Systemtakt in Hz - Definition als unsigned long beachten >> Ohne ergeben Fehler in der Berechnung
7
#endif
8
 
9
#define BAUD 9600UL          // Baudrate
10
 
11
// Berechnungen
12
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
13
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
14
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
15
 
16
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
17
  #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! 
18
#endif
19
20
#define ZEILEN 5
21
#define SPALTEN 8
22
23
uint8_t example[ZEILEN][SPALTEN] = \
24
   {{0xFF,0xD9,0xD1,0x13,0xD4,0xD1,0xC9,0x9A}, \    
25
    {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, \    
26
    {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, \   
27
    {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, \   
28
    {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}  \
29
   }; 
30
31
/* 
32
   EIN Zeichen lesen 
33
 */
34
uint8_t uart_getc(void)
35
{
36
    while (!(UCSRA & (1<<RXC)))   // warten bis Zeichen verfuegbar
37
        ;
38
    return UDR; // Zeichen aus UDR an Aufrufer zurueckgeben
39
}
40
41
/*
42
   Hauptprogramm
43
*/
44
int main(void)
45
{
46
    UCSRB |= (1<<RXEN);                // UART RX einschalten
47
    UCSRC |= (1<<URSEL)|(3<<UCSZ0);    // Asynchron 8N1 
48
    UBRRH = UBRR_VAL >> 8;
49
    UBRRL = UBRR_VAL & 0xFF;
50
51
    // unendliche Arbeitsschleife
52
    while(1)
53
    {
54
      uint8_t zeichen;
55
56
      zeichen = uart_getc();
57
58
      // Wurde ein Startzeichen empfangen?
59
      if (zeichen == 'S')
60
      { 
61
        // ja, dann stur mit den folgenden empfangenen 
62
        // ZEILEN*SPALTEN Zeichen das Array füllen
63
        uint8_t i, j, summe;
64
65
        summe = 0;
66
        for (i = 0; i < ZEILEN; i++)
67
        {
68
           for (j = 0; j < SPALTEN; j++)
69
           {
70
             zeichen = uart_getc();
71
             summe += zeichen;
72
             example[i][j] = zeichen;
73
           }
74
         }
75
76
         // Prüfsumme (8-Bit Summe aller Arrayelemente) checken
77
         zeichen = uart_getc();
78
         if (zeichen != summe)
79
         {
80
            // Fehler!
81
         }
82
      }
83
    }
84
}

Das wäre eine Minimalversion mit BINÄREN Nutzdaten. In der Praxis würde 
man eher ASCII-Daten benutzen. Also nicht ein Zeichen 0xFF übertragen, 
sondern z.B. zwei "FF" oder gar vier "0xFF". Dann müssen nach dem 
Empfang die ASCII-Daten in Binärdaten umgerechnet werden, bevor in dem 
Array gespeichert wird.

von Hc Z. (mizch)


Lesenswert?

> C kennt keine Funktionen, die innerhalb von anderen Funktionen
> definiert werden.

Standard-C nicht, aber GCC und damit AVR-gcc schon.

von Alex G. (alex94) Benutzerseite


Lesenswert?

Danke Stefan für den Code.

aber wird das array nicht so gefüllt:

1 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0
0 0 1 0 0 0 0 0
0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0

0 = kein Eintrag
1 = ein Eintrag

wegen:
1
        for (i = 0; i < ZEILEN; i++)
2
        {
3
           for (j = 0; j < SPALTEN; j++)
4
           {
5
...

oder denke ich gerade nur falsch?

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Alex Peterson schrieb:

> oder denke ich gerade nur falsch?

Ja.

von Alex G. (alex94) Benutzerseite


Lesenswert?

Stefan B. schrieb:
> Alex Peterson schrieb:
>
>> oder denke ich gerade nur falsch?
>
> Ja.

Das ist gut :D

von Alex G. (alex94) Benutzerseite


Lesenswert?

So jetzt habe ich noch eine Frage.
Muss ich so Zeichen auf die serielle schnittstelle senden das sie von 
dem obigen Code angenommen werden?

S
0xFF
0xD9
0xC9
0x9A
.
.
.
0xD4
0xC6

und jetzt ist das Array voll und das Programm wird fortgesetzt.

ist das richtig?

mfg alex

von Karl H. (kbuchegg)


Lesenswert?

Alex Peterson schrieb:
> So jetzt habe ich noch eine Frage.
> Muss ich so Zeichen auf die serielle schnittstelle senden das sie von
> dem obigen Code angenommen werden?

Wer ist 'ich'?

Du in Persona, der vor einem Terminalprogramm sitzt
oder ein anderes Programm, welches deinen AVR füttert?

Im ersten Fall: Nein, das geht so nicht.
Du Übertragung, so wie Stefan sie entworfen hat, ist für den 2.ten Fall 
gedacht, wenn ein anderer Rechner die Daten binär sendet.

Du als Mensch hast das Problem, dass du nur sehr umständlich rein binäre 
Werte auf den Weg bringen kannst, hauptsächlich deshalb weil dein 
Terminalprogramm für die Eingabe von Texten konzipiert ist.
Wenn du auf deinem Terminal das hier eingibst
>
> S
> 0xFF
> 0xD9
> 0xC9
> 0x9A

Dann empfängt dein AVR nacheinander die ASCII-Zeichen

S \n 0 x F F \n 0 x D 9 \n 0 x C 9 \n 0 x 9 A . . . . . .

und dein Programm muss aus diesen Zeichen wieder das gewünschte 
rekonstruieren. Aber auch das folgt dem bekannten Muster: Ein Zeichen 
empfangen und entscheiden was damit zu tun ist.

von Alex G. (alex94) Benutzerseite


Lesenswert?

Ok. Ich (mein zukünftiges Programm)  muss also die zahlen in Binär 
senden also:

hex     binär
---     -----

0xD9 = 11011001

Also muss ich 11011001 für D9 auf die serielle schnittstelle schicken.

Richtig?

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Alex Peterson schrieb:

> Ok. Ich (mein zukünftiges Programm)  muss also die zahlen in Binär
> senden also:
>
> hex     binär
> ---     -----
>
> 0xD9 = 11011001
>
> Also muss ich 11011001 für D9 auf die serielle schnittstelle schicken.
>
> Richtig?

Nö ;-)

du hast noch ein "Problem" mit dem Verständnis, wie Zahlen im µC / PC 
repräsentiert werden.

Du hast eine Speicherstelle und darin steht sagen wir eine 8-Bit Zahl. 
Die Speicherstelle kannst du in einem Debugger ansehen. Je nach 
Darstellungsart (Jex, dez, bin) wird die gleiche Zahl anders 
angezeigt: 0xD9, 217, 0b11011001. Es sind aber immer die gleichen 8-Bit.

Bei der Übertragung vom PC zum µC kannst du jetzt die Zahl auch auf 
verschiedene Arten übertragen:

Binär als 8-Bit indem du ein unsigned char 0xD9 (oder 217 oder 
0b11011001) überträgst ala send(217) oder send(0xD9) oder 
send(0b11011001). send() wäre dabei eine Funktion die ein einzelnes 
8-Bit Zeichen überträgt.

Oder du kannst die Zahl ASCII übertragen, d.h. in der Form wie du sie 
am Bildschirm siehst.

Hex. ASCII z.b. als Folge von 2 ASCII-Zeichen send('D');send('9'); und 
aus denen muss der µC erst die 8-Bit Zahl 0xD9 zusammenbasteln: zahl = 
((erstes_zeichen - '0') << 4) + (zweites_zeichen - '0');

Oder bei einer Dezimalzahl sind es 3 ASCII-Zeichen (Ziffern): 
send('2');send('1');send('7'); gilt zahl = (erstes_zeichen - '0') * 100 
+ (zweites_zeichen - '0') * 10 + (drittes_zeichen -'0') * 1;

Die ASCII-Übertragung hat den Vorteil, dass du als Mensch die Eingabe 
einfach nachverfolgen und ggf. manuell tätigen kannst. Nachteilig ist, 
dass mehr Zeichen als nötig übertragen werden müssen.

von Karl H. (kbuchegg)


Lesenswert?

Alex Peterson schrieb:
> Ok. Ich (mein zukünftiges Programm)  muss also die zahlen in Binär
> senden also:
>
> hex     binär
> ---     -----
>
> 0xD9 = 11011001
>
> Also muss ich 11011001 für D9 auf die serielle schnittstelle schicken.

Nein.
Wenn du das tatsächlich tun möchtest, müsstest du dir im ASCII Code das 
Zeichen suchen, dessen Code-Wert D9 oder meinetwegen 11011001 ist.
Drückst du dann das Zeichen auf der Tastatur, dann sendet dein 
Terminalprogramm D9 (was 11011001 entspricht) zum AVR.

Auf der Leitung selbst gibt es ebenfalls nur Zahlen (=Bitmuster). Aber 
es gibt eine Vereinbarung, den sog. ASCII Code, dass zb. das Bitmuster 
0x41 als 'A' angezeigt wird. Das Bitmuster 0x42 wird als 'B' angezeigt 
usw.

Sendest du an ein Terminal das Bitmuster für 0x43, so pinselt es auf 
seinen Bildschirm ein 'C' hin. Und umgekehrt: Drückst du die Taste 'C', 
dann sendet das Terminal das Bitmuster 0x43 über die serielle 
Schnittstelle. Der Empfänger muss wissen, was mit diesem 0x43 gemeint 
ist. Ob das einfach nur eine Zahl ist, oder ob dieses Bitmuster als 'C' 
zu interpretieren ist oder ob das vielleicht einfach nur eine Bitfolge 
ist, welche Pins an einem Port ein oder auszuschalten ist.

Es obliegt dir als Programmierer zu definieren, wie das geschehen soll.

von Alex G. (alex94) Benutzerseite


Lesenswert?

Thank you for your answers!

Ok das mit dem ASCII hab ich jetzt verstanden.

Das heißt jetzt ich könnte mit  folgenden Programm schnipsel Daten an 
Stefans skript senden?
1
unsigned char Buff[]="0xFF";
2
3
write(fd, Buff, strlen(Buff)+1);
4
5
...
(dieses Programm läuft auf dem pc)

Würde das funktionieren?

mfg alex

man is C ne schwere Sprache :)

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Alex Peterson schrieb:

> Thank you for your answers!
>
> Ok das mit dem ASCII hab ich jetzt verstanden.
>
> Das heißt jetzt ich könnte mit  folgenden Programm schnipsel Daten an
> Stefans skript senden?
>
>
1
> unsigned char Buff[]="0xFF";
2
> 
3
> write(fd, Buff, strlen(Buff)+1);
4
> 
5
> ...
6
>
> (dieses Programm läuft auf dem pc)
>
> Würde das funktionieren?

Nö.

Mein Programmschnippsel verlangt BINÄRE Daten, also 8-Bit Werte z.B. 
0xFF.

In deinem Programmschnippsel legst du in einem Array aus char namens 
Buff einen String "0xFF" aus 5 Zeichen ab. Die Zeichen sind '0', 'x', 
'F', 'F' und 0. Mit dem write() sendest du auch die 5 Zeichen 
nacheinander auf den Dateibezeichner fd (angenommen das ist auf die 
RS232 Schnittstelle gerichtet).

Wenn du mit deinem Schnippsel und meinem Code arbeitest, sieht der 
Anfang deines Arrays anschliessend so aus:
1
uint8_t example[ZEILEN][SPALTEN] = \
2
   {{'0','x','F','F',0,?,?,?}, \    
3
...
4
   };

Die Lösung für die Sendeseite wäre z.B.
1
#define ZEILEN 5
2
#define SPALTEN 8
3
4
uint8_t example[ZEILEN][SPALTEN] = \
5
   {{0xFF,0xD9,0xD1,0x13,0xD4,0xD1,0xC9,0x9A}, \    
6
    {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, \    
7
    {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, \   
8
    {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, \   
9
    {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}  \
10
   }; 
11
12
/* 
13
   EIN Zeichen senden 
14
 */
15
void uart_putc(unsigned char zeichen)
16
{
17
  // fd: globaler Dateibezeichner für die RS232 Schnittstelle
18
  write(fd, &zeichen, sizeof(unsigned char));
19
}
20
21
/*
22
   Hauptprogramm
23
*/
24
int main(void)
25
{
26
   unsigned char zeichen;
27
   unsigned char i, j, summe;
28
29
   // Einfügen: RS232 öffnen und initialisieren
30
   
31
   uart_putc('S'); // Start
32
33
   summe = 0;
34
   for (i = 0; i < ZEILEN; i++)
35
   {
36
     for (j = 0; j < SPALTEN; j++)
37
     {
38
       zeichen = example[i][j];
39
       uart_putc(zeichen);
40
       summe += zeichen;
41
     }
42
   }
43
44
   // Prüfsumme (8-Bit Summe aller Arrayelemente) schicken
45
   uart_putc(summe);
46
47
   // Einfügen: Ende der RS232 Übertragung abwarten und schliessen
48
}

von Karl H. (kbuchegg)


Lesenswert?

Alex Peterson schrieb:

> man is C ne schwere Sprache :)

Das alles hat nicht das Geringste mit C  zu tun.
Es ist ein allgemeines Problem in der Kommunikation.

Stell dir 2 Fernschreiber vor die miteinander verbunden sind. Was du auf 
dem einen tippst erscheint beim anderen auf dem Papier und umgekehrt. 
Jetzt sitzen 2 Menschen vor dem Fernschreiber. Der eine spricht Deutsch, 
der andere Spanisch. Was immer du tippst, erscheint beim Spanier auf dem 
Papier und umgekehrt. Solange ihr euch auf keinen gemeinsamen Nenner 
einigt, wird keine Kommunikation zustandekommen. Ihr verwendet zwar die 
gleichen Buchstaben, aber dieselbe Buchstabenkombination die einen 
perfekten deutschen Satz ergibt, ist für den Spanier nur 
unverständliches Kauderwelsch. Du scheinst auf dem Standpunkt zu stehen, 
dass es da irgendwo einen Übersetzer geben sollte, der von Deutsch auf 
Spanisch und zurück übersetzt. Aber zumindest im Falle von Computern 
gibt es den einfach nicht. So wie der eine Computer seine Daten 
wegsendet, genauso empfängt sie auch der andere. Beide Computer müssen 
sich darüber einig sein, was denn die 'Buchstaben' bedeuten.

Nur gibt es keine Buchstaben. In einem Computer ist alles eine Zahl. 
Seien es Befehle, seien es Texte, seien es Messergebnisse, seien es 
Grafiken, alles sind letztendlich nur Zahlen.

Auch auf der seriellen Schnittstelle tummeln sich nur Zahlen. Zahlen im 
Bereich 0 bis 255

Die erste und wichtigste Frage, die es zu klären gilt ist: "Was hat es 
mit diesen Zahlen auf sich?"

ZB. könnte dein µC die Sequenz empfangen
41 46 46 45

Das könnten zb die Messwerte eines Temperatursensors sein, der 
nacheinander meldet: jetzt ist die Temperatur 41 Grad, jetzt 46 Grad, 
dann noch einmal 46 Grad und runter auf 45 Grad.

Wäre möglich.

In der Kommunikation nennen wir das eine binäre Übertragung (weil ja 
eigentlich nicht Zahlen sondern binäre Muster aus jeweils 8 Bit 
übertragen werden, abe das ist in diesem Zusammenhang egal. Sind ja nur 
verschiedene Schreibweisen und dezimal schreibt sich leichter und 
schneller als 8-Bit Binärzahlen). Die Zahlen sind also tatsächlich 
Zahlen (im Sinne von 'sie beschreiben einen Wert') und was sie bedeuten 
weiß der Empfänger, weil er weiß von wem sie kommen - in dem Beispiel 
von einem Temperatursensor und damit ist klar, dass es sich um 
Temperaturen handelt.

Mann kann diese Zahlen auch anders interpretieren.
Man könnte zb vereinbaren, dass 41 ein Code ist, der bedeutet: Motor 
einschalten, 45 der Code für 'Motor aus' und 46 soll bedeuten 'Nichts 
tun und warten'. Und schon bekommt die Sequenz

41 46 46 45

eine ganz andere Bedeutung.

Man kann aber auch eine 'Standardbedeutung' zu Hilfe nehmen. Zb könnte 
man vereinbaren, dass jede Zahl für einen Buchstaben steht.
Nun gibt es natürlich viele mögliche derartige Zuordnungen. Es macht 
daher Sinn sich auf eine bestimmte Zurdnung zu einigen. Im Laufe der 
Geschichte hat sich die ASCII Zurdnung durchgesetzt. Im Web findest du 
jede Menge derartige ASCII Tabellen. zb hier
http://www.torsten-horn.de/techdocs/ascii.htm

Wenn du jetzt in dieser ASCII Tabelle nachsiehst, dann findest du raus, 
dass man die Sequenz

41 46 46 45

als

 A F F E

lesen kann. Jede Zahl steht für einen Buchstaben und in der Tabelle 
findest du für welchen Buchstaben die Zahl steht.
Aber ist alleine durch diese Zahlen-Buchstaben Zuordnung schon eine 
Bedeutung festgelegt?

Nein!

Diese 4 'Buchstaben' sind weiterhin einfach nur 4 Buchstaben. Niemand 
sagt, dass damit unser Verwandter aus dem Tierreich gemeint ist. In 
Kisuaheli könnte AFFE ganz etwas anderes bedeuten als im Deutschen und 
im Englischen würde man überhaupt APE sagen.

Nur durch diese Codierung, welche Zahl für welchen Buchstaben steht, hat 
man deswegen noch lange keine Bedeutung in die Übertragung hineingelegt.

Man könnte zb ja auch vereinbaren, dass immer 2 Buchstaben 
zusammengehören und gemeinsam eine Hex-Zahl codieren. aus dem Affen 
werden so die beiden Hex-Zahlen
  AF  und   FE

und die wiederrum könnten für die Zahlen 175 ( = 0xAF) bzw. 254 ( = 
0xFE) stehen.

Erst beides zusammen ...
 * binär oder in textform codiert
 * eine Vorschrift die dir sagt, was du mit dem empfangenen Zahlen
   (vulgo Bytes) anstellen sollst
... ermöglicht dir ein Programm zu schreiben, welches die Kommunikation 
zwischen 2 Partnern ermöglicht.

Das alles hat nichts mit C an sich zu tun. C ist nur das Werkzeug, mit 
dem man die Kommunikation implementiert. C bietet dir lediglich die 
Transportschicht um die Zahlen (die Bytes) von A nach B zu bringen. Wie 
diese ausgewertet werden sollen bzw. was sie bedeuten ist einzig und 
alleine Sache des Programmierers. Die Sprache C mischt sich da in keiner 
Weise ein.

von Alex G. (alex94) Benutzerseite


Lesenswert?

Nochmals vielen Dank für eure Antworten.

Ich werede mich morgen nochmal damit beschäftigen :)

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.