Forum: Compiler & IDEs uart_getc von Peter Fleury


von Uwe (Gast)


Lesenswert?

Ich nutze die UAART von Peter Fleury aber mit dem uart_getc komme ich 
nicht richtig klar es werden immer zeichen verschluckt.
Das Senden klappt wubderbar.

wenn ich den Empfang auf Polling umstelle bekomme ich jedes zeichen was 
Empfangen wird.

Vielleicht könntet ihr mir sagen wie ihr das macht mit dieser Lib,
ich bin noch Anfänger.
mfg
1
int main(void)
2
{
3
    unsigned int c;
4
    char buffer[7];
5
    int  num=134;
6
  
7
    uint8_t Linein[10];
8
    uint8_t j;
9
    
10
    /*
11
     *  Initialize UART library, pass baudrate and AVR cpu clock
12
     *  with the macro 
13
     *  UART_BAUD_SELECT() (normal speed mode )
14
     *  or 
15
     *  UART_BAUD_SELECT_DOUBLE_SPEED() ( double speed mode)
16
     */
17
    uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); 
18
    
19
    /*
20
     * now enable interrupt, since UART library is interrupt controlled
21
     */
22
    sei();
23
    
24
    /*
25
     *  Transmit string to UART
26
     *  The string is buffered by the uart library in a circular buffer
27
     *  and one character at a time is transmitted to the UART using interrupts.
28
     *  uart_puts() blocks if it can not write the whole string to the circular 
29
     *  buffer
30
     */
31
    uart_puts("String stored in SRAM\n");
32
    
33
    /*
34
     * Transmit string from program memory to UART
35
     */
36
    uart_puts_P("String stored in FLASH\n");
37
    
38
        
39
    /* 
40
     * Use standard avr-libc functions to convert numbers into string
41
     * before transmitting via UART
42
     */     
43
    itoa( num, buffer, 10);   // convert interger into string (decimal format)         
44
    uart_puts(buffer);        // and transmit string to UART
45
46
    
47
    /*
48
     * Transmit single character to UART
49
     */
50
    uart_putc('\r');
51
    
52
    for(;;)
53
    {
54
        /*
55
         * Get received character from ringbuffer
56
         * uart_getc() returns in the lower byte the received character and 
57
         * in the higher byte (bitmask) the last receive error
58
         * UART_NO_DATA is returned when no data is available.
59
         *
60
         */
61
        c = uart_getc();           
62
        //Hier wird doch schon ein zeichen
63
        //aus dem Puffer geholt somit fehlt doch schon
64
        //ein zeichen         
65
        if ( c & UART_NO_DATA )
66
        {
67
            /* 
68
             * no data available from UART 
69
             */
70
        }
71
        else
72
        {
73
            /*
74
             * new data available from UART
75
             * check for Frame or Overrun error
76
             */
77
              j = 0;
78
              while( ( c = uart1_getc() ) != '\r'&& j < sizeof(Linein)  )
79
              {
80
               Linein[ j++ ] = c;
81
              }
82
83
84
85
            if ( c & UART_FRAME_ERROR )
86
            {
87
                /* Framing Error detected, i.e no stop bit detected */
88
                uart_puts_P("UART Frame Error: ");
89
            }
90
            if ( c & UART_OVERRUN_ERROR )
91
            {
92
                /* 
93
                 * Overrun, a character already present in the UART UDR register was 
94
                 * not read by the interrupt handler before the next character arrived,
95
                 * one or more received characters have been dropped
96
                 */
97
                uart_puts_P("UART Overrun Error: ");
98
            }
99
            if ( c & UART_BUFFER_OVERFLOW )
100
            {
101
                /* 
102
                 * We are not reading the receive buffer fast enough,
103
                 * one or more received character have been dropped 
104
                 */
105
                uart_puts_P("Buffer overflow error: ");
106
            }
107
            /* 
108
             * send received character back
109
             */
110
            uart_putc( (unsigned char)c );
111
        }
112
    }
113
    
114
}

von Karl H. (kbuchegg)


Lesenswert?

Uwe schrieb:

> Vielleicht könntet ihr mir sagen wie ihr das macht mit dieser Lib,

Mit Sorgfalt!


>         c = uart_getc();
>         //Hier wird doch schon ein zeichen
>         //aus dem Puffer geholt somit fehlt doch schon
>         //ein zeichen
>         if ( c & UART_NO_DATA )
>         {
>             /*
>              * no data available from UART
>              */
>         }
>         else
>         {
>             /*
>              * new data available from UART
>              * check for Frame or Overrun error
>              */
>               j = 0;
>               while( ( c = uart1_getc() ) != '\r'&& j < sizeof(Linein)

wieso auf einmal uart1_getc (mit der Betonung auf 1!). Von der 1 weißt 
do doch an dieser Stelle gar nicht, ob da ein Zeichen gekommen ist oder 
nicht. Weiter oben hast du die andere UART befragt, ob sie was hat. Und 
die hat nicht mit UART_NO_DATA geantwortet und daher weißt du das DIESE 
Uart ein Zeichen vorrätig hat. Aber von der UART 1 weißt du an dieser 
Stelle erst mal nichts, bzw. du müsstest auch hier testen, ob da 
UART_NO_DATA gesetzt ist oder nicht.
Bei JEDEM Aufruf von getc() kann die Lib mit UART_NO_DATA  antworten! 
Dein Benutzer kann angefangen haben zu tippen und noch ehe er Return 
tippt, geht er aufs Klo. Die Fleury Lib liefert dann 20 Minuten lang bei 
jedem getc() Aufruf UART_NO_DATA, denn sie hat ja wirklich nichts 
gekriegt. Die lügt dich ja nicht an, oder schneidet sich was aus den 
Rippen. Erst dann, wenn der Benutzer zurück kommt und auf Return haut, 
dann liefert den auch das getc() ohne gesetztes UART_NO_DATA Bit.

von Uwe (Gast)


Lesenswert?

oje ein Fehler hat sich eingeschlichen,
in seiner Doku steht ja dazu;

Returns:  lower byte:  received byte from ringbuffer
          higher byte: last receive error

Müsste ich das dann nicht so machen, denn ich brauche doch nur die daten 
die im LowByte sind.
ich sitz da nun schon stunden dran und bekomme den empfang einfach nicht 
hin.
wie macht ihr denn das.
mfg

c = uart_getc();
   uint8_t HighByte = c >> 8;
   uint8_t LowByte  = c;
1
c = uart_getc();           
2
        //Hier wird doch schon ein zeichen
3
        //aus dem Puffer geholt somit fehlt doch schon
4
        //ein zeichen         
5
        if ( c & UART_NO_DATA )
6
        {
7
            /* 
8
             * no data available from UART 
9
             */
10
        }
11
        else
12
        {
13
            /*
14
             * new data available from UART
15
             * check for Frame or Overrun error
16
             */
17
              j = 0;
18
              while( ( c = uart_getc() ) != '\r'&& j < sizeof(Linein)  )
19
              {
20
               uint8_t HighByte = c >> 8;
21
               uint8_t LowByte  = c;
22
               Linein[ j++ ] = LowByte;
23
              }

von Uwe (Gast)


Lesenswert?

ich bekomme jetz meine zeichen bis das Return kommt, aber die hälfe 
fehlt.
scheinbar nutzten diese Lib nich viele.

vielleicht kann mir einer von euch noch weiterhelfen der diese LIB auch 
nutzt
mfg
1
c = uart_getc();           
2
        //Hier wird doch schon ein zeichen
3
        //aus dem Puffer geholt somit fehlt doch schon
4
        //ein zeichen         
5
        if ( c != UART_NO_DATA)
6
        {
7
        
8
         //Da ich ja vor der IF-Abfrage ja schon ein zeichen geholt habe
9
         //Fehlt mir ja schon ein zeichen
10
          
11
          Linein[ 0 ] = c ;
12
              j = 1;
13
              while( ( c = uart_getc() ) != '\r'&& j < sizeof(Linein)  )
14
              {
15
                Linein[ j++ ] = LowByte;
16
              }

von Karl H. (kbuchegg)


Lesenswert?

Uwe schrieb:
> ich bekomme jetz meine zeichen bis das Return kommt, aber die hälfe
> fehlt.
> scheinbar nutzten diese Lib nich viele.


Kein Wunder.
Dein Hauptproblem besteht immer noch

>               while( ( c = uart_getc() ) != '\r'&& j < sizeof(Linein)  )
>               {
>                 Linein[ j++ ] = LowByte;
>               }

Hast du das hier nicht gesehen?
Beitrag "Re: uart_getc von Peter Fleury"


Die Library kann nichts dafür, dass du sie nicht benutzen kannst. Das in 
der Fleury Lib enthaltene uart_getc() ist nun mal kein wartendes getc(). 
Du kannst dieses Faktum ignorieren, solange du willst. Das ändert nichts 
daran, dass es so ist.
(Allerdings ist es trivial, sich eine uart_getc_wait() Funktion zu 
machen, die tatsächlich solange Däumchen dreht, bis dann tatsächlich ein 
Zeichen über die UART reinkommt. Der Weg uart_getc() -> uart_getc_wait() 
ist trivial. Die Umkehrung aber nicht. Und genau aus dem Grund ist in 
der Fleury Lib ein nicht wartendes getc() enthalten und nicht anders 
rum)

von Uwe (Gast)


Lesenswert?

> Die Library kann nichts dafür, dass du sie nicht benutzen kannst.
Deshalb habe ich ja gefragt wie mann es richtig macht,
Aber durch das erste c = uart_getc();  geht mir doch schon ein zeichen 
verloren oder irre ich mich da.






1
j = 0;
2
3
c = uart_getc();           
4
        //Hier wird doch schon ein zeichen
5
        //aus dem Puffer geholt somit fehlt doch schon
6
        //ein zeichen         
7
        if ( c & UART_NO_DATA )
8
        {
9
            /* 
10
             * no data available from UART 
11
             */
12
        }
13
        else
14
        {
15
            /*
16
             * new data available from UART
17
             * check for Frame or Overrun error
18
             */
19
              c = uart_getc(); 
20
               Linein[ j++ ] = c;
21
               if( (c != '\r') ) 
22
               {
23
                j = 0;
24
               }
25
26
       }

von Michi (Gast)


Lesenswert?

Uwe schrieb:
> Deshalb habe ich ja gefragt wie mann es richtig macht,
> Aber durch das erste c = uart_getc();  geht mir doch schon ein zeichen
> verloren oder irre ich mich da.

Richtig, deshalb rufe uart_getc auch nur einmal auf! Teste ob 
UART_NO_DATA gesetzt ist und wenn nicht, dann nutze eben genau dieses 
einmal erhaltene c! Wo ist das Problem?

von Uwe (Gast)


Lesenswert?

>Wo ist das Problem?
es werden 2 Byte gesendet und das return zeichen,
die ersten  beiden Bytes sollten dann in Linein[0]  und Linein[1] .
aber ich muss doch auch überprüfen bis das Return zeichen kommt,
oader andersrum es soll sollange in Linein[] geschrieben werden bis das 
return zeichen kommt.
Aber das umzusetzten habe ich meine Probleme,Deshalb fragte ich ja hier.
mfg

von Michi (Gast)


Lesenswert?

Uwe schrieb:
> Aber das umzusetzten habe ich meine Probleme,Deshalb fragte ich ja hier.

Wieso machst du es nicht einfach so? (Beispielcode)
1
int n, c;
2
n = 0;
3
4
for (;;)
5
{
6
  c = uart_getc();
7
  if (!(c & UART_NO_DATA))
8
  {
9
    Linein[n++] = c;
10
    if ((c & 0xFF) == '\r')
11
    {
12
      break;
13
    }
14
  }
15
}

Sobald die Schleife verlassen wurde, steht alles, bis einschließlich des 
Returns, im Array.

von Uwe (Gast)


Lesenswert?

Michi schrieb:
> Uwe schrieb:
> Aber das umzusetzten habe ich meine Probleme,Deshalb fragte ich ja hier.
>
> Wieso machst du es nicht einfach so? (Beispielcode)

> Sobald die Schleife verlassen wurde, steht alles, bis einschließlich des
> Returns, im Array.
Vielen Dank,
Leider funktioniert das bei mir auch nicht,

von Michi (Gast)


Lesenswert?

Uwe schrieb:
> Leider funktioniert das bei mir auch nicht,

Was funktioniert nicht?

Zeig doch einfach mal deinen aktuellen Code und schreibe, was du 
erwartest und was tatsächlich geschieht. Woran machst du fest, dass es 
nicht funktioniert?

von Uwe (Gast)


Lesenswert?

also void Getin(void ) wird einmal aufgerufen und soll nun  die 2 Bytes 
empfangen aber leider klappts nich

1
void Getin(void )
2
{
3
  uint8_t Linein[10];
4
  uint8_t j;
5
  unsigned int c;
6
 
7
8
c = uart_getc();           
9
10
        if ( c & UART_NO_DATA )
11
        {
12
            /* 
13
             * no data available from UART 
14
             */
15
        }
16
        else
17
        {
18
            /*
19
             * new data available from UART
20
             * check for Frame or Overrun error
21
             */
22
23
               
24
               if( (c != '\r') ) 
25
               {
26
                j = 0;
27
               uart_puts (Linein[ 0]);
28
               uart_puts (Linein[ 1]);
29
               }
30
               else
31
               { 
32
                Linein[ j++ ] = c;
33
               
34
               }
35
       }
36
}

von Karl H. (kbuchegg)


Lesenswert?

Uwe schrieb:
> also void Getin(void ) wird einmal aufgerufen und soll nun  die 2 Bytes
> empfangen aber leider klappts nich

Wie soll denn das bei EINEM Aufruf ZWEI Bytes empfangen?
Da ist keine Form einer Schleife oder dergleichen in deinem Code. EIN 
Aufruf von uart_gets(), EIN empfangens Zeichen (wenn überhaupt).


ABer ich seh schon. Dz hast dich einfach nur schleicht ausgedrückt, denn 
natürlich existier die Schleife. Sie ist beim Aufrufer.

  ...

  while( 1 ) {
    GetIn();
  }

und damit wird dann GetIn tatsächlich öfter aufgerufen und wenn es etwas 
zu tun gibt, dann macht GetIn das auch.

Soweit ist das OK. Großes Lob. Du bist auf dem richtigen Weg.

Du hast nur etwas übersehen.
Und zwar deine Variablen j und LineIn.

Das sind lokale Variablen. Und als solche existieren sie nur, während 
die Funktion arbeitet. Geht der Programmfluss aus der Funktion heraus, 
dann wird j zerstört. Wird die Funktion durch den nächsten Aufruf erneut 
betreten, dann wird ein NEUES j angelegt, das nichts mit dem j vom 
vorhergehenden Aufruf zu tun hat. Das ist eine neue Variable!
Das bedeutet aber auch, du kannst derartige Variablen nicht dazu 
benutzen, um dir Werte von einem Aufruf zum nächsten zu merken!

Aber es gibt einen Ausweg daraus. Tatsächlich gibt es 2 Auswege.
* du könntest LinIn und j als globale Variablen anlegen.
  dann sind sie unabhängig vom Funktionsaufruf. Die Funktion kann etwas
  tun, oder auch nicht und die Programmausführung kann die Funktion
  verlassen. Wird GetIn das nächste mal aufgerufen, dann haben diese
  Variablen immer noch denselben Wert und du kannst dort weiter machen
  wo du aufgehört hast. Zum Beispiel eben damit, das nächste
  Zeichen dir zu holen (sofern eines existier) und es in LineIn zu
  speichern

* oder aber du kannst die beiden Variablen als 'static' Variablen
  ausführen. Dann werden sie ebenfalls von diesem "Variablen werden
  bei Verlassen einer Funktion zerstört" - Dingens ausgenommen und
  überleben, bis die Funktion erneut betreten wird.

So - your choice.

von Dieter (Gast)


Lesenswert?

Scheinbar haben doch viele schwierigkeiten  bei der benutzung der Lib 
auch hier.
Dieter

von Karl H. (kbuchegg)


Lesenswert?

Dieter schrieb:
> Scheinbar haben doch viele schwierigkeiten  bei der benutzung der Lib
> auch hier.

Eigentlich ist die ganz einfach zu benutzen.
Aber viele gehen von falschen Voraussetzungen aus. Das uart_getc() in 
der Fleury Lib ist ein nicht wartendes getc(). Das hat den Vorteil, dass 
es wunderbar in das übliche Konzept von "Wir warten auf niemanden und 
nichts" passt. Nur muss man dieses Konzept dann aber auch programmieren 
können.

Sich selbst damit ein wartendes getc() zu machen, ist trivial (wenn man 
Fehlerbehandlung weg lässt)
1
char uart_getc_wait()
2
{
3
  unsigned int c;
4
5
  do {
6
    c = uart_getc();
7
  } while( c & UART_NO_DATA );
8
9
  return c;
10
}

und schon kann er seine getline mit dieser Hilfsfunktion so 
programmieren, wie er das am Anfang vorhatte. (Ich hab die Funktion 
jetzt absichtlich in der 'ausführlichen Form geschrieben. Persönlich 
würde ich das für mich 'dichter' schreiben. Also: Kein Grund das jetzt 
zu reklamieren)

Was natürlich auch ein Problem ist: Das Vorwissen ist meistens viel zu 
mangelhaft. Viele glauben dann: "Ja, da nehm ich einfach etwas 
'Fertiges', dann hab ich keine Probleme.". Falsch. Auch wer auf 
vorgefertigte Baukästen setzt, muss immer noch wissen, wie die Teile 
funktionieren. Immerhin muss er ja die Einzelteile zusammenschrauben.

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.