Forum: Mikrocontroller und Digitale Elektronik AVR-UART-Ausgabe kommt oft aus dem Takt


von Sebastian (Gast)


Lesenswert?

Hallo,

in meinem AVR-Programm für einen ATmega16 möchte ich alle 20ms Werte 
über die Serielle Schnittstelle ausgeben. Das klappt vom Prinzip her 
auch. Nur manchmal hängt sich der AVR auf. Ich vermute mal, dass die 
while-Schleifen der UART-Ausgabe-Funktionen(siehe unten) schuldig sind 
(die restlichen Funktionen waren bis auf die Timer-ISR auskommentiert).

Gibt es eine geschickte Möglichkeit dieses Aufhängen zu verhindern?


Sebastian
1
// bei neueren AVRs andere Bezeichnung fuer die Statusregister, hier ATmega16:
2
int uart_putc(unsigned char c)
3
{
4
    while (!(UCSRA & (1<<UDRE)))  // warten bis Senden moeglich 
5
    {
6
    }                             
7
 
8
    UDR = c;                      // sende Zeichen 
9
    return 0;
10
}
11
 
12
 
13
// puts ist unabhaengig vom Controllertyp 
14
void uart_puts (char *s)
15
{
16
    while (*s)
17
    {  //  so lange *s != '\0' also ungleich dem "String-Endezeichen" 
18
        uart_putc(*s);
19
        s++;
20
    }
21
}

von Klaus (Gast)


Lesenswert?

Hi  Sebastian,

arbeitest Du mit einem Quarz?
Ich vermute eher das den PC aus dem Tackt kommt!

von Klaus (Gast)


Lesenswert?

edit:

Ich vermute eher das der PC aus dem Takt kommt!

von Sven '. (--j)


Lesenswert?

Sebastian wrote:
>     while (!(UCSRA & (1<<UDRE)))  // warten bis Senden moeglich
>     {
>     }
>
>     UDR = c;                      // sende Zeichen
>     return 0;

Fehlt da nicht ein NOP oder wenigstens ein Semikolon? Für mich sieht das 
so aus, als ob du Daten in das UDR schreibst, solange das Senden eben 
nicht möglich ist.

PS: Je länger ich mit {} angucke, desto unsicherer bin ich mir. 
Verwertet der Compiler dies als ;?

von Sebastian (Gast)


Lesenswert?

Der AVR arbeitet mit einem externen Quarz, nich mit dem internen 
Quarzosz..

Ich hab es auch ohne einen PC nur mit dem Scope angeschaut, da sieht man 
es deutlich, dass er da ein Kaffeepäuschen von ca. 300ms ab und an 
macht.

von Sebastian (Gast)


Lesenswert?

@Sven '\0':

Da hast du natürlich recht gehabt. nun hab ich des mal berichtigt:

while (!(UCSRA & (1<<UDRE)))  // warten bis Senden moeglich
{
  asm volatile("nop");
}

aber, er macht immer noch seine kleinen 300ms-Päuschen :-(

von Bensch (Gast)


Lesenswert?

> Der AVR arbeitet mit einem externen Quarz, nich mit dem internen
Quarzosz..

Was ist das denn? Sowas wie ein "schwarzer Schimmel"?

von Sebastian (Gast)


Lesenswert?

@Bensch:
Es gibt doch den iternen RC-Oszillator und nen externen Takteingang wo 
in der Regel ein Quarz angelötet wird.

von Oliver (Gast)


Lesenswert?

>PS: Je länger ich mit {} angucke, desto unsicherer bin ich mir.
>Verwertet der Compiler dies als ;?

Das eine ist leerer Block, das andere eine leere Anweisung. Der Effekt 
ist allerdings der gleiche.

Oliver

von Sebastian (Gast)


Lesenswert?

Kaum nimmt man die Optimierungsstufe des guten AVR-Studios bzw. des 
GNU-Compilers zurück und setzt die Timer Variablen auf volatile, schon 
gehts auch deutlich stabiler.

von Falk B. (falk)


Lesenswert?

@Sebastian (Gast)

>Kaum nimmt man die Optimierungsstufe des guten AVR-Studios bzw. des
>GNU-Compilers zurück und setzt die Timer Variablen auf volatile, schon
>gehts auch deutlich stabiler.

Dann liegt der Fehler wie vermutet bei dir. Poste mal vollständigen 
Code.

MFG
Falk

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.