Forum: Compiler & IDEs C array über serielle schnittstelle emfangen
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
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.
ok vielen Dank, das wede ich mal versuchen.
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
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.
Vielen DAnk für deine ausfürliche Antwort.
Ich werde dann mal die ganzen Sachen klären.
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;
|
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.
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
|
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.
Vielen Dank für eure sehr guten Antworten.
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
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.
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?
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 | }
|
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.
> C kennt keine Funktionen, die innerhalb von anderen Funktionen
> definiert werden.
Standard-C nicht, aber GCC und damit AVR-gcc schon.
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?
Alex Peterson schrieb:
> oder denke ich gerade nur falsch?
Ja.
Stefan B. schrieb:
> Alex Peterson schrieb:
>
>> oder denke ich gerade nur falsch?
>
> Ja.
Das ist gut :D
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
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.
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?
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.
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.
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 :)
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 | }
|
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.
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.
|