www.mikrocontroller.net

Forum: Compiler & IDEs UART-Senden und LED-Blinken gleichzeitig


Autor: Peter G. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich bin grad dabei in die Welt der ATmegas und C einzusteigen und will 
ein wenig probieren.
Allerdings häng ich jetzt fest:
Ich möchte Messdaten eines Eingangs über RS232 an einen PC schicken, 
soweit kein Problem, das würde ja über etwas wie
    while(1)
    {
        for(i=0;i<6;i++)
        {
            uart_puti(adc(i));
            uart_putc(' ');
        }
        uart_putc('\n');
        _delay_ms(200);
    } 

gehen.
Gut, gut...Nun möchte ich aber auch gleichzeitig das eine LED 
blinkt...das würde ja nun so gehen
    DDRD |= (1 << PD0); 
    while(1) 
    {
        PORTD |= (1 << PD0);
        _delay_ms(50);
        PORTD &= ~(1 << PD0);
        _delay_ms(1000);
    } 

Nun gut, aber wie bekomme ich beides gleichzeitig hin? Denn, wenn ich 
das richtig verstanden habe, so werden doch die Schleifen nie verlassen, 
oder?
Ich hätte da so eine Idee wie es gehen würde, weiß aber nicht genau ob 
das sinnvoll ist und ob es denn überhaupt funktionieren würde. Meine 
Idee ist, dass in der Schleife mit dem Senden der Daten ja ein _delay_ms 
ist. Nun könnte ich ja folgendes machen, eine Funktion definieren die 
mir den Pin der LED toggelt, in der Schleife des uarts eine Variable 
hochzählen lasse, und wenn die Variable einen bestimmten Wert übersteigt 
wird die toogle funktion ausgeführt. Das würde doch aber eigentlich nur 
funktionieren wenn zwischen Ein- und Ausschalten der LED die gleiche 
Zeit liegen sollte, oder?

Ich hoffe ihr könnt mir helfen!
Grüße
Peter

Autor: Tom M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schau dir mal Multitasking an.

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

Bewertung
0 lesenswert
nicht lesenswert
Peter G. schrieb:

> wird die toogle funktion ausgeführt. Das würde doch aber eigentlich nur
> funktionieren wenn zwischen Ein- und Ausschalten der LED die gleiche
> Zeit liegen sollte, oder?

Probiers aus, dann weißt du es genauer :-)

> Ich hoffe ihr könnt mir helfen!

Im Idealfall wechselst du die Strategie.
Du musst weg von der Denkweise: Ich lese jetzt 6 mal den ADC ein, gib 
das aus und warte ein wenig. Warten ist sowieso generell schlecht und 
der Tod jedes Programms, welches mehrere Dinge scheinbar gleichzeitig 
machen soll.

Deine Denkweise muss sein:
Genau jetzt, zu diesem Zeitpunkt, was gibt es jetzt zu tun?

Dazu benötigt man des öfteren ein Art Basistakt, eine innere Uhr, im 
Programm. Die realisiert man zb mit einem Timer, der (hausnummer) alle 
10 Millisekunden einen Interrupt auslöst, in dem eine oder mehrere 
Variablen hochgezählt werden. Erreichen diese Variablen bestimmte Werte, 
dann setzen sei Jobflags, als Zeichen für die Hauptschleife: Jetzt gibt 
es etwas zu tun.

Die Hauptschleife sieht dann so aus
  ...

  while( 1 ) {

    if( needToSampleADC == 1 ) {
      uart_puti(adc(i));
      uart_putc(' ');
      needToSampleADC = 0;
    }

    if( needToToggleLED == 1 ) {
      PORTD |= (1 << PD0);
      needToToggleLED = 0;
    }
  }

Wenn jetzt die Timer-ISR (die [hausnummer] alle 10ms aufgerufen wird) 
dafür sorgt, dass needToSampleADC alle 200 Millisekunden, 
needToToggleLED alle 500 Millisekunden auf 1 geht, dann macht dein 
Programm scheinbar 2 Dinge 'gleichzeitig' in unterschiedlichen 
Zeitintervallen.

Dreh und Angelpunkt ist aber ein Timer mit einer ISR-Funktion, die in 
regelmässigen Zeitabständen von der Hardware automatisch aufgerufen 
wird.


> Grüße
> Peter

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

Bewertung
0 lesenswert
nicht lesenswert
Du könntest das Blinken im Timerinterrupt ablaufen lassen. Dann 
brauchst Du auch keine delay-Funktionen zu verwenden.

Die serielle Schnittstelle bedienst Du wie gewünscht in Deinem 
Hauptprogramm.

Alternativ könntest Du auch interruptgesteuert senden, d.h. die zu 
sendenden Daten in einen Puffer ablegen, der interruptgesteuert von der 
UART geleert wird.

Wenn Du beides kombinierst, kannst Du in Deinem Hauptprogramm sogar 
noch was anderes gleichzeitig machen.

Autor: Peter G. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Puh, das scheint ja doch komplizierter als ich dachte. Und ich versteh 
nur halb so viel wie ich gern möchte, trotzdem Danke für die Mühe.
Ich denke ich sollte mir die Howtos und Tutorials nocheinmal alle 
durchlesen, damit ich einigermaßen ne Ahnung habe.

Karl Heinz, kannst du mir nocheinmal erläutern wie das mit der Timer-ISR 
aussehen soll?

Rufus, kannst du mir auch nochmal erklären was du mit "im 
Timerinterrupt" meinst?

grüße
Peter

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Peter G. (Gast)

Schau dir erstmal das Beispiel im Artikel Multitasking an. Dort wird 
noch mit dem bösen _delay_ms() gearbeitet, das ist aber für den Anfang 
OK. Wenn du das Konzept WIRKLICH verstanden hast, bau es in dein 
Programm ein. Wenn das WIRKLICH solide läuft, kannst du dich mit dem 
Thema Interrupt und Timer beschäftigen. Und mit dem Thema 
Statemachine. Viel Holz fürs Erste.

MFG
Falk

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.