mikrocontroller.net

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


Autor: Alex G. (alex94) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Alex G. (alex94) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok vielen Dank, das wede ich mal versuchen.

Autor: Alex G. (alex94) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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)
#include <inttypes.h>
#include <avr/io.h>



 
#ifndef F_CPU

 
#warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 4000000"
#define F_CPU 8000000UL    // Systemtakt in Hz - Definition als unsigned long beachten >> Ohne ergeben Fehler in der Berechnung
#endif
 
#define BAUD 9600UL          // Baudrate
 
// Berechnungen
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
 
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
  #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! 
#endif

void Usart_EnableRX(void)
{
    UCSRB |= ( 1 << RXEN );
}
 
 int main(void)
{
    UCSRB |= (1<<TXEN);                // UART TX einschalten
    UCSRC |= (1<<URSEL)|(3<<UCSZ0);    // Asynchron 8N1 
 
    UBRRH = UBRR_VAL >> 8;
    UBRRL = UBRR_VAL & 0xFF;
  
  uint8_t uart_getc(void)
{
    while (!(UCSRA & (1<<RXC)))   // warten bis Zeichen verfuegbar
        ;
    return UDR;                   // Zeichen aus UDR an Aufrufer zurueckgeben
}   
}


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

mfg alex

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was soll das denn sein?
 int main(void)
{
    UCSRB |= (1<<TXEN);                // UART TX einschalten
    UCSRC |= (1<<URSEL)|(3<<UCSZ0);    // Asynchron 8N1 
 
    UBRRH = UBRR_VAL >> 8;
    UBRRL = UBRR_VAL & 0xFF;
  
  uint8_t uart_getc(void)
{
    while (!(UCSRA & (1<<RXC)))   // warten bis Zeichen verfuegbar
        ;
    return UDR;                   // Zeichen aus UDR an Aufrufer zurueckgeben
}   
}


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.

Autor: Alex G. (alex94) Benutzerseite
Datum:

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

Autor: Alex G. (alex94) Benutzerseite
Datum:

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

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

Autor: Stefan Kunz (syliosha)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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:
>
>
>       while (!(UCSRA & (1<<RXC)))   // warten bis Zeichen verfuegba
>     {
>     }
>     return UDR;
> 


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
uint8_t getc()
{
  while (!(UCSRA & (1<<RXC)))   // warten bis Zeichen verfuegba
  {
  }
  return UDR;
}

und benutze sie ganz einfach
int main()
{
  uint8_t c;

  c = getc();

  if( c == 'a' )
    mach was

  if( c == 'b' )
    mach was ganz anderes

  if( c == 8 )
    und jetzt was völlig anderes

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Alex G. (alex94) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für eure sehr guten Antworten.

Autor: Alex G. (alex94) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
unsigned char example[5][8] = {{0xFF,0xD9,0xD1,0x13,0xD4,0xD1,0xC9,0x9A},    
                                {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},     
        {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},    
        {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},    
        {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}}; 


mfg alex

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Alex G. (alex94) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Alex G. (alex94) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Könnte das so funktionieren?:
uint8_t uart_getc(void)
{
    while (!(UCSRA & (1<<RXC)))   // warten bis Zeichen verfuegbar
        ;
    return UDR;                   // Zeichen aus UDR an Aufrufer zurueckgeben
}
 
void uart_gets( char* Buffer, uint8_t MaxLen )
{
  uint8_t NextChar;
  uint8_t StringLen = 0;
 
  NextChar = uart_getc();         // Warte auf und empfange das nächste Zeichen
 
                                  // Sammle solange Zeichen, bis:
                                  // * entweder das String Ende Zeichen kam
                                  // * oder das aufnehmende Array voll ist
  while( NextChar != '\n' && StringLen < MaxLen - 1 ) {
    *Buffer++ = NextChar;
    StringLen++;
    NextChar = uart_getc();
  }
 
                                  // Noch ein '\0' anhängen um einen Standard
                                  // C-String daraus zu machen
  *Buffer = '\0';
}


int main () {

  char Line[40];      // String mit maximal 39 zeichen
 
  uart_gets( Line, sizeof( Line ) );

example[1][2] = Line; //empfangener String in das Array einsetzen

}


Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das geht so nicht.

#include <inttypes.h>
#include <avr/io.h>

#ifndef F_CPU
#warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 4000000"
#define F_CPU 8000000UL    // Systemtakt in Hz - Definition als unsigned long beachten >> Ohne ergeben Fehler in der Berechnung
#endif
 
#define BAUD 9600UL          // Baudrate
 
// Berechnungen
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
 
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
  #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! 
#endif

#define ZEILEN 5
#define SPALTEN 8

uint8_t example[ZEILEN][SPALTEN] = \
   {{0xFF,0xD9,0xD1,0x13,0xD4,0xD1,0xC9,0x9A}, \    
    {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, \    
    {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, \   
    {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, \   
    {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}  \
   }; 

/* 
   EIN Zeichen lesen 
 */
uint8_t uart_getc(void)
{
    while (!(UCSRA & (1<<RXC)))   // warten bis Zeichen verfuegbar
        ;
    return UDR; // Zeichen aus UDR an Aufrufer zurueckgeben
}

/*
   Hauptprogramm
*/
int main(void)
{
    UCSRB |= (1<<RXEN);                // UART RX einschalten
    UCSRC |= (1<<URSEL)|(3<<UCSZ0);    // Asynchron 8N1 
    UBRRH = UBRR_VAL >> 8;
    UBRRL = UBRR_VAL & 0xFF;

    // unendliche Arbeitsschleife
    while(1)
    {
      uint8_t zeichen;

      zeichen = uart_getc();

      // Wurde ein Startzeichen empfangen?
      if (zeichen == 'S')
      { 
        // ja, dann stur mit den folgenden empfangenen 
        // ZEILEN*SPALTEN Zeichen das Array füllen
        uint8_t i, j, summe;

        summe = 0;
        for (i = 0; i < ZEILEN; i++)
        {
           for (j = 0; j < SPALTEN; j++)
           {
             zeichen = uart_getc();
             summe += zeichen;
             example[i][j] = zeichen;
           }
         }

         // Prüfsumme (8-Bit Summe aller Arrayelemente) checken
         zeichen = uart_getc();
         if (zeichen != summe)
         {
            // Fehler!
         }
      }
    }
}

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.

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> C kennt keine Funktionen, die innerhalb von anderen Funktionen
> definiert werden.

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

Autor: Alex G. (alex94) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
        for (i = 0; i < ZEILEN; i++)
        {
           for (j = 0; j < SPALTEN; j++)
           {
...


oder denke ich gerade nur falsch?

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alex Peterson schrieb:

> oder denke ich gerade nur falsch?

Ja.

Autor: Alex G. (alex94) Benutzerseite
Datum:

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

Das ist gut :D

Autor: Alex G. (alex94) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Alex G. (alex94) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Alex G. (alex94) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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?
unsigned char Buff[]="0xFF";

write(fd, Buff, strlen(Buff)+1);

...
(dieses Programm läuft auf dem pc)

Würde das funktionieren?

mfg alex

man is C ne schwere Sprache :)

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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?
>
>
> unsigned char Buff[]="0xFF";
> 
> write(fd, Buff, strlen(Buff)+1);
> 
> ...
> 
> (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:
uint8_t example[ZEILEN][SPALTEN] = \
   {{'0','x','F','F',0,?,?,?}, \    
...
   }; 

Die Lösung für die Sendeseite wäre z.B.
#define ZEILEN 5
#define SPALTEN 8

uint8_t example[ZEILEN][SPALTEN] = \
   {{0xFF,0xD9,0xD1,0x13,0xD4,0xD1,0xC9,0x9A}, \    
    {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, \    
    {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, \   
    {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, \   
    {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}  \
   }; 

/* 
   EIN Zeichen senden 
 */
void uart_putc(unsigned char zeichen)
{
  // fd: globaler Dateibezeichner für die RS232 Schnittstelle
  write(fd, &zeichen, sizeof(unsigned char));
}

/*
   Hauptprogramm
*/
int main(void)
{
   unsigned char zeichen;
   unsigned char i, j, summe;

   // Einfügen: RS232 öffnen und initialisieren
   
   uart_putc('S'); // Start

   summe = 0;
   for (i = 0; i < ZEILEN; i++)
   {
     for (j = 0; j < SPALTEN; j++)
     {
       zeichen = example[i][j];
       uart_putc(zeichen);
       summe += zeichen;
     }
   }

   // Prüfsumme (8-Bit Summe aller Arrayelemente) schicken
   uart_putc(summe);

   // Einfügen: Ende der RS232 Übertragung abwarten und schliessen
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Alex G. (alex94) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nochmals vielen Dank für eure Antworten.

Ich werede mich morgen nochmal damit beschäftigen :)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.