Forum: Compiler & IDEs USART Fleruy lib auf ATMEGA88 - Problem bei hohen Datenraten


von Vo M. (vo_m)


Lesenswert?

Hallo zusammen,

ich habe die USART lib von Fleury auf einem ATMEGA88 mit 16MHz Quarz 
laufen. Der befeuert einen RS485 Transceiver (LT1785). Die Busleitungen 
sind mit einem VC 0805-14 Varistor geschützt.

Über einen USB - RS485 Converter (Digitus DA70157) gehe ich dann in den 
PC aufs Hyperterminal.

Das Ganze lief auf Anhieb, allerdings nur bis 115200 Bit/s. Bei höheren 
Datenraten gibts Datensalat.

Und ab da stehe ich auf dem Schlauch.
Ich muss für ein Projekt 1MBbit/s in den Controller einlesen, wollte das 
zumindest mal bis 921600Bit/s auf dem Rechner testen.

Meine Oszi Ausstattung lässt leider keine weitere Analyse zu. Wo könnte 
das Problem liegen?
- Kapazität auf der Leitung sollte Ok sein.
- Oh, ich seh grade, Terminierung könnte das Problem sein. Ich hab 
derzeit nichts dran, Leitung ist aber auch nur 20cm lang.
- sind irgendwelche Fallstricke in der lib vorhanden, die ich übersehen 
habe?
- andere Ideen?

Viele Grüße + herzlichen Dank für Eure Hilfe!
Volker

von Thomas S. (tosa)


Lesenswert?

Hi

die Probleme duerften an der Geschwindigkeit bzw. dem Quartz liegen.
Schau Dir mal den Artikel 
[[http://www.mikrocontroller.net/articles/Baudratenquarz]] an.

Diesen Code kannst Du verwenden um zu checken ob der gewaehlte Quartz 
auch passt. Er stammt aus dem sehr guten Tutorial auf 
mikrocontroller.net:
[[http://www.mikrocontroller.net/articles/AVR-Tutorial:_UART]]

1
#define F_CPU  7372800UL
2
// Berechnungen
3
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
4
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
5
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
6
 
7
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
8
  #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! 
9
#endif

Gruesse
Tosa

von Vo M. (vo_m)


Lesenswert?

Hallo Tosa,

herzlichen Dank für den Tip, das war es natürlich.

Jetzt habe ich leider ein neues Problem, vermutlich ähnlich trivial?!

Ich kann nun einen String, Char, alles was das Fleury Beispielprogramm 
hergibt, ausgeben.
Aber wenn ich einen Char einlese und dieses als Echo wieder ausgebe, 
kommt nur Murks im Terminal an.
Das Programm habe ich denke ich verstanden, unsigned int wird auf 
unsigned char gecastet, damit die Diagnosebits abgeschnitten werden und 
dann wird das Byte zurückgeschrieben.

Irgendwo beim einlesen muss ein Fehler drin sein, denn
1
uart_putc('x');
funktioniert ja.

Hat jemand eine Idee, wie da heranzugehen ist?

Grüße,
Volker

von Karl H. (kbuchegg)


Lesenswert?

Vo M. schrieb:

> Aber wenn ich einen Char einlese und dieses als Echo wieder ausgebe,
> kommt nur Murks im Terminal an.
> Das Programm habe ich denke ich verstanden, unsigned int wird auf
> unsigned char gecastet, damit die Diagnosebits abgeschnitten werden und
> dann wird das Byte zurückgeschrieben.

Ja.
Aber nur dann, wenn in den Diagnosebits auch steht, dass ein Zeichen 
vorhanden ist.

> Irgendwo beim einlesen muss ein Fehler drin sein, denn

Der Fleury Code funktioniert. Den haben viele im Einsatz.
Also muss der Fehler vorrangig mal in deinem Code zu suchen sein.

> Hat jemand eine Idee, wie da heranzugehen ist?

Ja.
Wie immer. Den Code posten.

von Peter D. (peda)


Lesenswert?

Vo M. schrieb:
> mit 16MHz Quarz

Vo M. schrieb:
> 921600Bit/s

Das ergibt 8,5% Fehler, viel zu hoch.
Bei hohen Baudraten mußt Du Quarze nehmen, die ganzzahlige Teiler 
bilden.

Bei 921600Baud geht daher nur 14,7456MHz.


Peter

von Gustav (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:

>Der Fleury Code funktioniert. Den haben viele im Einsatz.

Das kann nicht sein
Es gibt auch unzählige wo es nicht geht.
Leider gibt es auch kein Beispiel auch hier nicht ausser das 
mitgelieferte wo, zb. Daten ins Array geschrieben
werden.

von Chris L. (kingkernel)


Lesenswert?

http://www.gjlay.de/helferlein/avr-uart-rechner.html

Auf der Seite kannst du sehen, mit welchem Quarz du welche Baudrate 
hinbekommst, ohne das der Fehler zu gross wird.
RS232/485 verwendet asynchrone datenübertragung, sodass die Bitlänge auf 
2% genau sein muss, damit der Empfänger auch wirklich jedes bit 
mitbekommt und nichts verschluckt.

von Karl H. (kbuchegg)


Lesenswert?

Gustav schrieb:
> Karl Heinz Buchegger schrieb:
>
>>Der Fleury Code funktioniert. Den haben viele im Einsatz.
>
> Das kann nicht sein
> Es gibt auch unzählige wo es nicht geht.


Und wo ist dein Beispiel eines nicht funktionierenden Codes?
Erst mal ist nicht klar, warum es da überhaupt einen Unterschied geben 
soll. Der Fleury Code liefert die empfangenen Zeichen. Nicht mehr und 
nicht weniger. Wenn in der Weiterverarbeitung der Zeichen ein Fehler 
ist, dann kannst du das wohl schlecht dem Fleury Code anlasten. So 
gesehen ist es völlig egal, was du mit den Zeichen weiter machst - das 
ist erst mal dein Bier und bis zum Beweis des Gegenteils nicht dem 
Fleury Code anzulasten.

> Leider gibt es auch kein Beispiel auch hier nicht ausser das
> mitgelieferte wo, zb. Daten ins Array geschrieben
> werden.

Was genau stellt dich da vor Probleme?

1
char ReceivedLine[80];
2
uint8_t nextReceivedChar;
3
uint8_t receivedLineFinished;
4
uint8_t uartError;
5
6
uint8_t HandleUART()
7
{
8
  unsigned int c = uart_getc();
9
10
  if ( c & UART_NO_DATA )
11
    return;
12
13
  if ( (c & UART_FRAME_ERROR) ||
14
       (c & UART_OVERRUN_ERROR) ||
15
       (c & UART_BUFFER_OVERFLOW) ) {
16
    uartError = TRUE;
17
    return;
18
  }
19
20
  if ( nextReceivedChar >= sizeof( ReceivedLine ) - 1 ) {
21
    uartError = TRUE;
22
    nextReceivedChar  = 0;
23
  }
24
25
  ReceivedLine[ nextReceivedChar++ ] = c;
26
  ReceivedLine[ nextReceivedChar ] = '\0';
27
28
  if( c == '\n' )
29
    receivedLineFinished = TRUE;
30
  else
31
    receivedLineFinished  = FALSE;
32
33
  return receivedLineFinished ;
34
}

Was genau soll da jetzt in der Fleury Lib ein Problem machen?
Immer schön brav nach jedem uart_getc die Flags auswerten, dann kann es 
da keine Probleme mit der Lib geben. Eagl, wie man dann die Zeichen 
weiter auswertet und zb sukzessive in einem Array speichert.

von Karl H. (kbuchegg)


Lesenswert?

PS: Was reguläre Poster nicht sehen können.
Da gibt es noch einen gelöschten Post, indem Volker bestätigt, dass 
nicht der Fleury Code schuld war, sondern dass er vergessen hatte, die 
RS485 entsprechend umzustellen.

von Lernender (Gast)


Lesenswert?

Wie muss mann die "flags" in der Mainloop auswerten

von Karl H. (kbuchegg)


Lesenswert?

Lernender schrieb:
> Wie muss mann die "flags" in der Mainloop auswerten

Ähm.
Verarscht du mich jetzt?
Schon mal das Beispiel angesehen, welches Peter mitliefert?

Bzw. was könnte wohl das hier
1
  unsigned int c = uart_getc();
2
3
  if ( c & UART_NO_DATA )
4
    return;
5
6
  if ( (c & UART_FRAME_ERROR) ||
7
       (c & UART_OVERRUN_ERROR) ||
8
       (c & UART_BUFFER_OVERFLOW) ) {
9
    uartError = TRUE;
10
    return;
11
  }
sein, bzw. welche Aufgabe könnte das wohl im Zusammenhang mit dieser 
Funktion erfüllen?

von Lernender (Gast)


Lesenswert?

nein ich will hier niemand Verarschen

so hab ich das bei mir,
nach Peter Fleury seinem Beispiel
1
uint8_t getdata()
2
{ 
3
  uint8_t next= 0;
4
  uint16_t c;
5
  char Message[70];
6
     
7
8
  
9
10
     next= 0;                    //Zeichenzähler auf Null setzen
11
12
     c = uart1_getc(); 
13
14
    if ( c & UART_NO_DATA )
15
    {
16
    }
17
18
    else
19
    {
20
21
            /*
22
             * new data available from UART
23
             * check for Frame or Overrun error
24
             */
25
            if ( c & UART_FRAME_ERROR )
26
            {
27
                /* Framing Error detected, i.e no stop bit detected */
28
                //uart_puts_P("UART Frame Error: ");
29
      }
30
            if ( c & UART_OVERRUN_ERROR )
31
            {
32
                /* 
33
                 * Overrun, a character already present in the UART UDR register was 
34
                 * not read by the interrupt handler before the next character arrived,
35
                 * one or more received characters have been dropped
36
                 */
37
                //uart_puts_P("UART Overrun Error: ");
38
      }
39
            if ( c & UART_BUFFER_OVERFLOW )
40
            {
41
                /* 
42
                 * We are not reading the receive buffer fast enough,
43
                 * one or more received character have been dropped 
44
                 */
45
                //uart_puts_P("Buffer overflow error: ");
46
      }
47
            /* 
48
             * send received character back
49
             */
50
            //uart_putc( (unsigned char)c );
51
52
53
   Message[ next] = c;                  //erstes Zeichen speichern
54
   next= 1;
55
     
56
        while( ( c = uart1_getc() ) != 55 && next< sizeof(Message)  )
57
        {
58
         Message[ next++ ] = c;
59
        }
60
        
61
     Message[next] = '\0';
62
    }
63
_delay_ms(400);
64
}

von Thomas S. (tosa)


Lesenswert?

Lernender schrieb:
> nein ich will hier niemand Verarschen
>
> so hab ich das bei mir,
> nach Peter Fleury seinem Beispiel

Na so ganz ist das nicht das Beispiel :-)
Du pruefst zwar auf die Fehlerzustaende, am Ende verwendest Du aber 
dennoch 'c' um es in Dein Array zu packen. Egal ob ein Fehler 
aufgetreten ist oder nicht.

Mach es so wie Karl Heinz es vorgeschlagen hat:
1
  if ( (c & UART_FRAME_ERROR) ||
2
       (c & UART_OVERRUN_ERROR) ||
3
       (c & UART_BUFFER_OVERFLOW) ) {
4
    // Hier kommt eine vernueftige Fehlerbehandlung
5
  }
6
  else {
7
    // und hier machst Du was mit 'c'
8
  }

Gruesse

von Karl H. (kbuchegg)


Lesenswert?

Thomas hat ja zu einem Teil schon was gesagt.

Weiters
1
       while( ( c = uart1_getc() ) != 55 && next< sizeof(Message)  )
2
        {
3
         Message[ next++ ] = c;
4
        }

Welchen Teil des Satzes ...
"Immer schön brav nach jedem uart_getc die Flags auswerten, dann kann es
da keine Probleme mit der Lib geben."
... hast du jetzt nicht verstanden?

Da, in dieser Schleife, ist ein uart_getc (ok, ein uart1_getc). WO 
wertest du die Flags aus, ob dieser Aufruf von uart1_getc überhaupt ein 
Zeichen geliefert hat?

Du musst schon nach den Regeln spielen! Das kann man wohl kaum der 
Fleury Lib anlasten, wenn du nicht gewillt bist, dich daran zu halten 
oder nicht verstehst, dass uart_getc dir mit seinem Returnwert mehrere 
Dinge mitteilen kann. Unter anderem den, dass zur Zeit eben kein Zeichen 
an der UART vorlag. Du scheinst das überhaupt nicht verstanden zu haben, 
dass dieses uart_getc aus der Fleury Lib eben NICHT wartet, bis ein 
Zeichen vorliegt, sondern dem Aufrufer mit dem Returnwert schlicht und 
ergreifend mitteilt: "Ich hab (noch) nichts. Probiers später nochmal. In 
der Zwischenzeit kannst du ja ruhig was anderes rechnen, wenn du 
möchtest."

von Thomas S. (tosa)


Lesenswert?

Damit Du nicht noch ewig rumhampeln musst ...
1
do {
2
  c = uart1_getc();
3
  if ( (c & UART_FRAME_ERROR) ||
4
     (c & UART_OVERRUN_ERROR) ||
5
     (c & UART_BUFFER_OVERFLOW) ) {
6
    // Fehlerbehandlung. Z.B. eine Led blinken lassen
7
  }
8
  else if( c & UART_NO_DATA ) {
9
    // kein Fehler. Aber es gibt (noch) kein Zeichen.
10
    // Der Mc ist nunmal schneller als die Schnittstelle :-)
11
  }
12
  else {
13
    // kein Fehler und es liegt auch ein Zeichen vor.
14
    Message[next++]=c;
15
  }
16
} while (c!=55 && next<sizeof(Message));

Das ist kein schoener Code, aber er soll Schritt fuer Schritt beleuchten 
wie man es machen koennte. Eventuell solltest Du noch vorsehen das Du 
nur Fehler bekommst (falsche Baudrate z.B.). Dann hast Du eine 
Endlosschleife weil die Abbruchbedingung nie erfuellt wird.

von Lernender (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Thomas hat ja zu einem Teil schon was gesagt.
>
> Weiters       while( ( c = uart1_getc() ) != 55 && next< sizeof(Message)  )
>         {
>          Message[ next++ ] = c;
>         }
>
> Welchen Teil des Satzes ...
> "Immer schön brav nach jedem uart_getc die Flags auswerten, dann kann es
> da keine Probleme mit der Lib geben."
> ... hast du jetzt nicht verstanden?



Es wird so lange eingelesen bis das Ende-Zeichen 55  kommt.
oder ist das nicht richtig
1
//Mainlloop
2
dat = uint8_t getdata() //wird von von der Mainloop aufgerufen
3
4
5
 if (dat == 1)
6
  {
7
   // keine daten
8
  }
9
10
 if (dat == 2)
11
  {
12
   // Daten Fehlerhaft
13
  }
14
15
 if (dat == 3)
16
  {
17
   // Daten korrekt
18
   //weiter verarbeiten
19
  }
20
21
uint8_t getdata()
22
{ 
23
  uint8_t next= 0;
24
  uint16_t c;
25
  char Message[70];
26
     
27
28
  
29
30
     next= 0;                    //Zeichenzähler auf Null setzen
31
32
     c = uart1_getc(); 
33
34
    if ( c & UART_NO_DATA )
35
    {
36
    return 1;
37
    }
38
39
  if ( (c & UART_FRAME_ERROR) ||
40
       (c & UART_OVERRUN_ERROR) ||
41
       (c & UART_BUFFER_OVERFLOW) ) {
42
    return 2;
43
  }
44
 else 
45
  {
46
47
   Message[ next] = c;                  //erstes Zeichen speichern
48
   next= 1;
49
     
50
        while( ( c = uart1_getc() ) != 55 && next< sizeof(Message)  )
51
        {
52
         Message[ next++ ] = c;
53
        }
54
        
55
     Message[next] = '\0';
56
    }
57
return 3;
58
_delay_ms(400);
59
}

von Karl H. (kbuchegg)


Lesenswert?

Lernender schrieb:
> Karl Heinz Buchegger schrieb:
>> Thomas hat ja zu einem Teil schon was gesagt.
>>
>> Weiters       while( ( c = uart1_getc() ) != 55 && next< sizeof(Message)  )
>>         {
>>          Message[ next++ ] = c;
>>         }
>>
>> Welchen Teil des Satzes ...
>> "Immer schön brav nach jedem uart_getc die Flags auswerten, dann kann es
>> da keine Probleme mit der Lib geben."
>> ... hast du jetzt nicht verstanden?
>
>
>
> Es wird so lange eingelesen bis das Ende-Zeichen 55  kommt.
> oder ist das nicht richtig

Aber der springende Punkt ist, dass nicht jeder Aufruf von uart1_getc 
ein Zeichen liefert!

Der µC ist hunderte male schneller, als Zeichen auf der Schnittstelle 
übertragen werden können!

Ist wie bei deinem Postkasten.
Du kannst alle 2 Minuten zum Postkasten laufen. Aber das bedeutet NICHT, 
dass da jedesmal ein Brief drinnen ist!

Sieh dir doch mal das Fleury Beispiel GENAU(!) an.

   c = uart_getc();

   if( c & UART_NO_DATA )
   {
   }

   else
     ....



was könnte wohl UART_NO_DATA heissen?
No Data - keine Daten
"Ich hab momentan nichts! Da ist nichts was du verarbeiten könntest!"
Eben "No Data"

Das scheint dich aber nicht weiter zu stören. Du speicherst trotzdem 
irgendwas ab. Selbst wenn auf der UART die Zeichen noch gar nicht da 
sind.

von Lernender (Gast)


Lesenswert?

so geht es erstmal
aber ich muss _delay_ms(400); am ende reinschreiben ansonsten sind keine 
daten da
1
  c = uart1_getc();
2
  if ( (c & UART_FRAME_ERROR) ||
3
     (c & UART_OVERRUN_ERROR) ||
4
     (c & UART_BUFFER_OVERFLOW) ) {
5
    // Fehlerbehandlung. Z.B. eine Led blinken lassen
6
     return 1;
7
  }
8
  else if( c & UART_NO_DATA ) {
9
    // kein Fehler. Aber es gibt (noch) kein Zeichen.
10
    // Der Mc ist nunmal schneller als die Schnittstelle :-)
11
  }
12
  else
13
  {
14
    // kein Fehler und es liegt auch ein Zeichen vor.
15
    Message[next++]=c;
16
  
17
        while( ( c = uart1_getc() ) != 55 && next< sizeof(Message)  )
18
        {
19
         Message[ next++ ] = c;
20
        }
21
        
22
     Message[next] = '\0';
23
_delay_ms(400);
24
 return 4;
25
  }
26
27
28
}

von Karl H. (kbuchegg)


Lesenswert?

>        while( ( c = uart1_getc() ) != 55 && next< sizeof(Message)  )
                      ************


JEDER Aufruf von uart1_getc muss untersucht werden.

JEDER!

KEINE AUSNAHME!

ALLE!

ALL OF THEM!

TUTTI COMPLETI

(auf französisch kann ichs nicht)

ALLE!

DU HAST EINEN AUFRUF VON UART_GETC? DANN SIEH DIR IM ERGEBNIS DIE 
VERDAMMTEN FLAGS AN. WENN UART_NO_DATA GESETZT IST, DANN IST KEIN BYTE 
VORHANDEN! Noch nicht. Aber was noch nicht ist, kann ja noch werden.

alle? JAAAAA, ALLE!

aber .... KEIN 'ABER'. ALLE! JEDEN EINZELNEN!





Das ist doch nicht so schwer! Das ist eine ganz einfache Regel.

(Und ich glaube wir hatten das vor ein paar Monaten schon mal)

von Thomas S. (tosa)


Lesenswert?

@Lernender

Schau Dir noch mal das Beispiel aus dem Post von 20:09 an.
Das ist der komplette Code um die Daten einzulesen (ausser der 
Initialisierung der Schnittstelle).
Also nicht unten drunter wieder Deinen falschen Code einbauen.

Und reg Karl Heinz nicht so auf !

:-)

von Karl H. (kbuchegg)


Lesenswert?

> Und reg Karl Heinz nicht so auf !

Weils wahr ist.
Aber groß daherreden, dass die Lib nicht funktionieren würde.

von Lernender (Gast)


Lesenswert?

Entschuldigt bitte
Ihr habts ja mehrfach gesagt nun gehts auch bei mir.
War immer auf die While abfrage fixiert das war falsch.
Trotzdem nochmal danke.

von Lernender (Gast)


Lesenswert?

Leider geht das bei mir doch nicht so wies gedacht war.



1
  c = uart1_getc();
2
  if ( (c & UART_FRAME_ERROR) ||
3
     (c & UART_OVERRUN_ERROR) ||
4
     (c & UART_BUFFER_OVERFLOW) ) {
5
    // Fehlerbehandlung. Z.B. eine Led blinken lassen
6
  }
7
  else if( c & UART_NO_DATA ) {
8
    // kein Fehler. Aber es gibt (noch) kein Zeichen.
9
    // Der Mc ist nunmal schneller als die Schnittstelle :-)
10
  }
11
  else
12
  {
13
    // kein Fehler und es liegt auch ein Zeichen vor.
14
   Message[next++]=c;
15
     if ( c != 55 && next< sizeof(Message) )
16
      {
17
       TLED_ON();
18
       Message[next] = '\0'; 
19
      }
20
     else
21
      {
22
       TLED_OFF();
23
      }
24
 }

von Thomas S. (tosa)


Lesenswert?

Lernender schrieb:
> Leider geht das bei mir doch nicht so wies gedacht war.
>

Du schreibst nicht was nicht geht bzw. was Du hier machen willst.
Was auffaellt:
Du hast keine Schleife mehr und liest nur noch ein Zeichen von der 
Schnittstelle. Willst Du das?
Ansonsten fehlt ein while oder do-while. Poste doch mal Deinen 
kompletten Code.

von Lernender (Gast)


Lesenswert?

Das mit der do-while schleife blockiert ja dann das ganze Programm wenn 
mal kein zeichen kimmt.

Es sollen vom Slave Zeichen gelesen werden bis die Slave-Adresse =55 als 
Ende erkennung kommt.
Zeichen sehen wie folgt aus
zb. 889
zb.0010

Aber leider bekomme ich nur die ersten 3 zeichen.
1
  uint8_t next= 0;
2
  uint16_t c;
3
  char Message[70];
4
5
// Mainloop
6
  while (1)
7
  {
8
   getdata();
9
10
   DisplayText_s( 41, 35, Message);
11
12
  }
13
 }
14
15
16
uint8_t getdata()
17
{ 
18
19
  c = uart1_getc();
20
  if ( (c & UART_FRAME_ERROR) ||
21
     (c & UART_OVERRUN_ERROR) ||
22
     (c & UART_BUFFER_OVERFLOW) ) {
23
    // Fehlerbehandlung. Z.B. eine Led blinken lassen
24
  }
25
  else if( c & UART_NO_DATA ) {
26
    // kein Fehler. Aber es gibt (noch) kein Zeichen.
27
    // Der Mc ist nunmal schneller als die Schnittstelle :-)
28
  }
29
  else
30
  {
31
    // kein Fehler und es liegt auch ein Zeichen vor.
32
  
33
     if ( c != 55 && next< sizeof(Message) )
34
      {
35
       TLED_ON();
36
        Message[next++]=c;
37
      }
38
     else
39
      {
40
       Message[next] = '\0'; 
41
       next= 0;   // Zeichenzäühler auf null setzen
42
       TLED_OFF();
43
      }
44
 }
45
}

von Karl H. (kbuchegg)


Lesenswert?

Lernender schrieb:

>   while (1)
>   {
>    getdata();
>
>    DisplayText_s( 41, 35, Message);
>
>   }
>  }

Wenn du dir Message laufend ausgeben lässt, dann musst du auch dafür 
sorgen, dass Message nach jedem empfanegenen Zeichen wieder einen 
gültigen String ergibt. Im Moment tust du das nicht!

>      if ( c != 55 && next< sizeof(Message) )
>       {
>        TLED_ON();
>         Message[next++]=c;

        Message[next] = '\0';

>       }
>      else
>       {
>        Message[next] = '\0';
>        next= 0;   // Zeichenzäühler auf null setzen
>        TLED_OFF();
>       }
>  }
> }


Im übrigen: zeig alles!

von Karl H. (kbuchegg)


Lesenswert?

Moment.

Deine Messages: sind die überhaupt Text?
Oder sind das einfach nur eine Abfolge von Bytes?


Zeig doch bitte auch mal die Protokollbeschreibung nach der du 
programmierst. Das kommt mir ein wenig spanisch vor, dass jemand in 
einem binären Protokoll die Dezimal-Konstante 55 verwenden würde. 55 ist 
der ASCII COde für '7'. Und das wäre dann doch ein eher kurioses 'End Of 
Message' Zeichen.

von Lernender (Gast)


Lesenswert?

So hier hab ich erstmal alles.
1
//SLAVE
2
sprintf(msg,"%02d",sens );  
3
uart_puts(msg);              
4
sprintf(msg,"%+03d,%1d", Vorkommastelle, Nachkommastelle);    
5
uart_puts( msg); 
6
uart_putc(55);       // device_ID ausgeben 
7
//SLAVE
8
9
10
11
  char buffer[50]; 
12
  char Message[70];
13
  uint8_t next= 0;
14
15
  signed int Wert[19];                  
16
  int Wertkomma[19];
17
  uint8_t sensorNr;                        
18
19
 
20
21
// Mainloop
22
  while (1)
23
  {
24
   getdata();
25
26
   
27
28
  }
29
 }
30
31
32
void getdata(uint8_t second)
33
{
34
  uint16_t c;
35
36
    if (second== 1)
37
    {_delay_ms(1000);
38
     tempsend(T_mess,TEMPER_ADDR);    // Komando zum Temperratur messen schicken
39
  }
40
  c = uart1_getc();
41
  if ( (c & UART_FRAME_ERROR) ||
42
     (c & UART_OVERRUN_ERROR) ||
43
     (c & UART_BUFFER_OVERFLOW) ) {
44
    // Fehlerbehandlung. Z.B. eine Led blinken lassen
45
  }
46
  else if( c & UART_NO_DATA ) {
47
    // kein Fehler. Aber es gibt (noch) kein Zeichen.
48
    // Der Mc ist nunmal schneller als die Schnittstelle :-)
49
  }
50
  else
51
  {
52
    // kein Fehler und es liegt auch ein Zeichen vor.
53
  
54
     if ( c != 55 && next< sizeof(Message) )
55
      {
56
       TLED_ON();
57
        Message[next++]=c;
58
      }
59
     else
60
      {
61
       Message[next] = '\0'; 
62
       next= 0;   // Zeichenzäühler auf null setzen
63
       TLED_OFF();
64
      }
65
 }
66
67
68
      // ersten 2 stellen vorm komma mit Vorzeichen Speichern
69
      int messWert = atoi( &Message[3] );
70
      Wert[sensorNr] = messWert;    
71
      //nachkomma= n;
72
      int n= atoi( &Message[7]);
73
      Wertkomma[sensorNr] = n;
74
75
76
      if( sensorNr == 1 ) 
77
     {  
78
        outtValut( 41, 35, sensorNr,"%2d %+3d,%1d", Wert[sensorNr], Wertkomma[sensorNr]);
79
80
       }
81
82
      if( sensorNr == 2 ) 
83
     {  
84
        outtValut( 41, 60, sensorNr,"%2d %+3d,%1d", Wert[sensorNr], Wertkomma[sensorNr]);
85
86
      } 
87
88
89
      if( sensorNr == 3 ) 
90
     {  
91
        outtValut( 41, 85, sensorNr,"%2d %+3d,%1d", Wert[sensorNr], Wertkomma[sensorNr]);
92
93
     }
94
}
95
96
97
void outtValut(uint16_t x,uint16_t y,uint8_t sens ,char *name, signed int valu,int nachkomma )
98
99
{
100
101
  SetBrushColor(0, 0, 0);// Brush Color white
102
  SetPenColor(255, 165, 0); 
103
  SetFont(1);                  // Text and Number Font 1
104
    
105
  sprintf( buffer_t,name ,sens, valu, nachkomma  ); 
106
  DisplayText_s(x, y, buffer_t);
107
  SetFont(0);                  // Text and Number Font 1
108
109
}
110
111
112
113
114
115
116
117
118
// Comando und Adresse Schicken
119
void tempsend(uint8_t data,uint8_t adress)
120
{
121
  setTransmitMode();
122
  uart1_putc(data);      // Startkommando: Messen
123
  uart1_putc(adress);    // Adresse schicken
124
  setReceiveMode();
125
}

von Karl H. (kbuchegg)


Lesenswert?

Ähm

> uart_putc(55);       // device_ID ausgeben

Dir ist aber schon klar, dass 55 der ASCII Code für '7' ist?

d.h. sobald in deinen Daten

> sprintf(msg,"%02d",sens );
> uart_puts(msg);
> sprintf(msg,"%+03d,%1d", Vorkommastelle, Nachkommastelle);
> uart_puts( msg);

irgendwo eine 7 vorkommt, dann wird der Empfänger das mit der von dir 
angedachten Device-Id verwechseln!

Der Empfänger kriegst Bytes. Welche Bytes er als Codes für ASCII Zeichen 
auffassen soll und welche Bytes direkt einen numerischen Wert 
darstellen, kann er erst mal nicht unterscheiden. Das gibt dein 
'Protokoll' bzw. die Implementierung beim Empfänger nicht her.

von Lernender (Gast)


Lesenswert?

So habe die
> uart_putc(60);       // device_ID ausgeben
device_ID vonn 55 auf 60 geändert trotzdem bekomme ich nur den ersten 
wert!

von J.-u. G. (juwe)


Lesenswert?

Lernender schrieb:
> So habe die
>> uart_putc(60);       // device_ID ausgeben
> device_ID vonn 55 auf 60 geändert trotzdem bekomme ich nur den ersten
> wert!
Also ich verstehe es immer noch nicht. Was genau empfängst Du denn nun?
So wie ich das interpretiere, schickt Dir Dein Sensor einen String, 
bestehend aus 8 Zeichen. Die ersten beiden stehen für die Sensornummer, 
dann kommt das Vorzeichen des Messwerts, danach kommen zwei Zeichen, die 
den ganzzahligen Anteil des Messwerts darstellen, dann ein Komma, dann 
eine Nachkommastelle und dann noch ein Zeichen, dass die ID darstellt.

Mal ein Beispiel:
Der Sensor mit der Nummer "99" und der ID 60 sendet den Messwert "-9,8", 
d.h. die Übertragung lautet:
1
"99-09,8<"

Was davon "bekommst" Du denn nun?

Was mir an Deinem Code sonst noch aufgefallen ist:

Lernender schrieb:
> Wert[sensorNr] = messWert;

> Wertkomma[sensorNr] = n;

> if( sensorNr == 1 )

> if( sensorNr == 2 )

> if( sensorNr == 3 )

Der Variable "sensorNr", die Du hier mehrmals verwendest, wird nie ein 
Wert zugewiesen.

> // ersten 2 stellen vorm komma mit Vorzeichen Speichern
>       int messWert = atoi( &Message[3] );
Der Messwert (das Vorzeichen) beginnt bei Index "2" nicht bei "3".

> int n= atoi( &Message[7]);
Gleicher Fehler hier: die Nachkommastelle befindet sich bei Index "6", 
nicht "7".

von Thomas S. (tosa)


Lesenswert?

Lernender schrieb:
> So hier hab ich erstmal alles.
Alles ist das sicher nicht. Die includes fehlen z.B.


>
> // Mainloop
>   while (1)
>   {
>    getdata();
//hier rufst Du getdata ohne Parameter auf. Laut Definition weiter unten 
kommt hier ein Parameter hin. Nicht fein.
>
>
>
>   }
>  }
>
>
> void getdata(uint8_t second)
> {
>   uint16_t c;
>
// da Du den parameter second nicht uebergibst wird der Code auch nicht 
ausgefuehrt. Obwohl ich bezweifle das er sinnvoll ist...
>     if (second== 1)
>     {_delay_ms(1000);
>      tempsend(T_mess,TEMPER_ADDR);    // Komando zum Temperratur messen schicken
>   }

// Jetzt faengst Du an etwas sinnvolles zu machen
>   c = uart1_getc();
>   if ( (c & UART_FRAME_ERROR) ||
>      (c & UART_OVERRUN_ERROR) ||
>      (c & UART_BUFFER_OVERFLOW) ) {
>     // Fehlerbehandlung. Z.B. eine Led blinken lassen
>   }
>   else if( c & UART_NO_DATA ) {
>     // kein Fehler. Aber es gibt (noch) kein Zeichen.
>     // Der Mc ist nunmal schneller als die Schnittstelle :-)
>   }
>   else
>   {
>     // kein Fehler und es liegt auch ein Zeichen vor.
>
>      if ( c != 55 && next< sizeof(Message) )
>       {
>        TLED_ON();
>         Message[next++]=c;
>       }
>      else
>       {
>        Message[next] = '\0';
>        next= 0;   // Zeichenzäühler auf null setzen
>        TLED_OFF();
>       }
>  }
// und hier hoerst Du mit der Sinnhaftigkeit auf.

// Nun verwendest Du den Buffer obwohl ja nichts oder hoechstend 1 
Zeichen  drin steht.
//Wieder mal: wo ist Deine while oder do-while Schleife?
// Ab hier machst Du nur noch Quatsch. Sorry.

>       // ersten 2 stellen vorm komma mit Vorzeichen Speichern
>       int messWert = atoi( &Message[3] );
>       Wert[sensorNr] = messWert;
>       //nachkomma= n;
>       int n= atoi( &Message[7]);
>       Wertkomma[sensorNr] = n;
>
...

>So habe die
>> uart_putc(60);       // device_ID ausgeben
>device_ID vonn 55 auf 60 geändert trotzdem bekomme ich nur den ersten
>wert!
Wie kommst Du nun auf die 60? Ich sage nicht das es falsch ist, aber 
niemand ausser Dir weiss warum Du erst eine 55 und nun eine 60 
verwendest.
Welches Protokoll soll das sein?

Ich will Dich wirklich nicht aergern oder beleidigen, aber Du solltest 
definitv erst einmal ein C-Buch oder ein Tutorial durcharbeiten.
Mit Deinem Wissensstand wird das nix ...

von Lernender (Gast)


Lesenswert?

So bekomme ich nur den ersten Wert vom Sensor angezeigt

getdata(second); wird doch in der While (1) schleife doch ständig 
aufgerufen.
   while (1)
   {
    getdata(second);
   }
 }





Mit der
do {
  c = uart1_getc();
  if ( (c & UART_FRAME_ERROR) ||
     (c & UART_OVERRUN_ERROR) ||
     (c & UART_BUFFER_OVERFLOW) ) {
    // Fehlerbehandlung. Z.B. eine Led blinken lassen
  }
  else if( c & UART_NO_DATA ) {
    // kein Fehler. Aber es gibt (noch) kein Zeichen.
    // Der Mc ist nunmal schneller als die Schnittstelle :-)
  }
  else {
    // kein Fehler und es liegt auch ein Zeichen vor.
    Message[next++]=c;
  }
} while (c!=55 && next<sizeof(Message));

wird ja das ganze Programm angehalten wenn kein zeichen kommt.

1
//SLAVE
2
sprintf(msg,"%02d",sens );  
3
uart_puts(msg);              
4
sprintf(msg,"%+03d,%1d", Vorkommastelle, Nachkommastelle);    
5
uart_puts( msg); 
6
uart_putc(55);       // device_ID ausgeben 
7
//SLAVE
8
9
10
11
  char buffer[50]; 
12
  char Message[70];
13
  uint8_t next= 0;
14
15
  signed int Wert[19];                  
16
  int Wertkomma[19];
17
  uint8_t sensorNr;                        
18
19
 
20
21
// Mainloop
22
  while (1)
23
  {
24
   getdata();
25
26
   
27
28
  }
29
 }
30
31
32
void getdata(uint8_t second)
33
{
34
  uint16_t c;
35
36
    if (second== 1)
37
    {_delay_ms(1000);
38
     tempsend(T_mess,TEMPER_ADDR);    // Komando zum Temperratur messen schicken
39
  }
40
  c = uart1_getc();
41
  if ( (c & UART_FRAME_ERROR) ||
42
     (c & UART_OVERRUN_ERROR) ||
43
     (c & UART_BUFFER_OVERFLOW) ) {
44
    // Fehlerbehandlung. Z.B. eine Led blinken lassen
45
  }
46
  else if( c & UART_NO_DATA ) {
47
    // kein Fehler. Aber es gibt (noch) kein Zeichen.
48
    // Der Mc ist nunmal schneller als die Schnittstelle :-)
49
  }
50
  else
51
  {
52
    // kein Fehler und es liegt auch ein Zeichen vor.
53
  
54
     if ( c != 55 && next< sizeof(Message) )
55
      {
56
       TLED_ON();
57
        Message[next++]=c;
58
      }
59
     else
60
      {
61
       Message[next] = '\0'; 
62
       next= 0;   // Zeichenzäühler auf null setzen
63
       TLED_OFF();
64
      }
65
 }
66
67
 
68
    sensorNr = (Message_in1[1]-'0')*10 + (Message_in1[2]-'0'); 
69
 
70
71
    if( sensorNr != 255 ) {
72
73
      // ersten 2 stellen vorm komma mit Vorzeichen Speichern
74
      int messWert = atoi( &Message[3] );
75
      Wert[sensorNr] = messWert;    
76
      //nachkomma= n;
77
      int n= atoi( &Message[7]);
78
      Wertkomma[sensorNr] = n;
79
}
80
81
      if( sensorNr == 1 ) 
82
     {  
83
        outtValut( 41, 35, sensorNr,"%2d %+3d,%1d", Wert[sensorNr], Wertkomma[sensorNr]);
84
85
       }
86
87
      if( sensorNr == 2 ) 
88
     {  
89
        outtValut( 41, 60, sensorNr,"%2d %+3d,%1d", Wert[sensorNr], Wertkomma[sensorNr]);
90
91
      } 
92
93
94
      if( sensorNr == 3 ) 
95
     {  
96
        outtValut( 41, 85, sensorNr,"%2d %+3d,%1d", Wert[sensorNr], Wertkomma[sensorNr]);
97
98
     }
99
}
100
101
102
void outtValut(uint16_t x,uint16_t y,uint8_t sens ,char *name, signed int valu,int nachkomma )
103
104
{
105
106
  SetBrushColor(0, 0, 0);// Brush Color white
107
  SetPenColor(255, 165, 0); 
108
  SetFont(1);                  // Text and Number Font 1
109
    
110
  sprintf( buffer_t,name ,sens, valu, nachkomma  ); 
111
  DisplayText_s(x, y, buffer_t);
112
  SetFont(0);                  // Text and Number Font 1
113
114
}
115
116
117
118
119
120
121
122
123
// Comando und Adresse Schicken
124
void tempsend(uint8_t data,uint8_t adress)
125
{
126
  setTransmitMode();
127
  uart1_putc(data);      // Startkommando: Messen
128
  uart1_putc(adress);    // Adresse schicken
129
  setReceiveMode();
130
}


So bekomm ich alle 3 Werte angezeigt
1
c = uart1_getc(); 
2
3
   Message[ next] = c;                  //erstes Zeichen speichern
4
   next = 1;
5
     
6
    while( ( c = uart1_getc() ) != 60 && next< sizeof(Message)  )
7
        {
8
         Message[ next++ ] = c;
9
        }
10
        
11
     Message[next] = '\0';
12
     next= 0;                    //Zeichenzähler auf Null setzen

von uart (Gast)


Lesenswert?

Dann werde glücklich damit, aber verstanden hast Du nicht warum man vor 
dem uartget c den Status abfragen MUSS.

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.