mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Blinklicht über UART ohne Timer


Autor: Frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich würde gern ein Blinklicht programmieren, welches ich über ein
gesendetes Zeichen per UART ein- und ausschalten kann. Das Blinklicht
soll jedoch ohne Timer programmiert werden.

Kann mir jemand einen Tip geben wie ich die Sache am besten angehe?

Vielen Dank!

Gruß

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

Bewertung
0 lesenswert
nicht lesenswert
Indem du dir mal überlegst, wie du ein Blinklicht alleine
hinkriegst. Vergiss erst mal das ein-/aus-schalten über
den UART und kümmere dich nur darum eine LED an einem
Port zum blinken zu kriegen.
Wenns denn ohne Timer sein soll, dann musst du halt
anderweitig dafür sorgen, dass zwischen ein und ausschalten
der Led ( nichts anderes ist ja blinken) eine gewisse
Zeit vergeht. Es gibt da mehrer Möglichkeiten: eine
davon ist eine vorgefertigte delay - Funktion (kommt
mit avr-gcc daher), eine andere ist es den µC ganz einfach
in einer Schleife Zeit vertrödeln zu lassen (nichts anderes
macht die delay Funktion).

Wenn du das hast, dann liest du erst mal alles, was du über
UART zum lesen auftreiben kannst und probierst mal ein
paar einfache Beispiele durch. zb. Der µC sendet über
die UART dasselbe Zeichen zurück, dass er empfängt.

Klappt das, dann überlegst du dir, wie du den Blinkcode
umbauen musst, damit du das Blinken selbst ein und aus-
schalten kannst. Das testest du am besten mal indem du eine
globale Variable benutzt, die das Blinken ein und ausschaltet.
Funktioniert das, dann kommt der UART dazu, der je nach
empfangegen Zeichen, die globale Variable auf den richtigen
Wert setzt.

Autor: Frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Empfiehlt sich denn eher die deelay Funktion oder eine Schleife?

Autor: Dennis (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die delay-Funktion ist auch nur eine Schleife, die Zeit vertrödelt.

Besser wäre allerdings ein Timer, aber den willst Du ja vermeiden.
Falls Deine Timer anderweitig belegt sind, mach ne Schleife, wenn Du
nur zu faul bist, dir die Timer-Funktion anzuschauen, solltest Du die
Faulheit überwinden, der Timer is nämlich ne praktische Sache, die Du
bestimmt noch öfter brauchen kannst.

Autor: Markus N. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wieso willst du denn keinen Timer verwenden?
Is doch ideal dafür !!

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

Bewertung
0 lesenswert
nicht lesenswert
Ich denke, Frank ist drauf und drann sein erstes Programm zu
schreiben. Dafür ist eine Zeitschleife, wie delay durchaus
ok. Auch Rom wurde nicht an einem Tag erbaut. Irgendwo
muss er mal anfangen.

@Frank
Mit avr-gcc kommt eine
_delay_ms
Funktion. Sie wartet die angegene Zeit in Millisekunden. Allerdings
hat das Ding einen Haken: Du kannst nicht beliebige Millisekunden
angeben. Die maximale Wartezeit hängt von der Taktfrequenz
ab und berechnet sich zu: 262ms / Taktfrequenz in Megahertz.
Ist aber kein Problem. Man kann ja delay_ms selbst wieder in
einer Schleife immer wieder aufrufen.

#define F_CPU 1000000  // hier musst du deine tatsächliche
                       // Taktfrequenz eintragen. Die wird von
                       // _delay_ms zur Berechnung der Schleifen-
                       // dauer benoetigt.
#include <avr/io.h>
#include <util/delay.h>

int main()
{
  unsigned char i;

  DDRB = 0xFF;    // angenommen an Port B haengt deine LED
                  // dann muss Port B mal als Ausgang definiert
                  // werden

  while( 1 ) {

    PORTB = 0xFF;    // am PORT B mal alle Pins auf 1

                     // danach warten
    for( i = 0; i < 50; i++ )
      _delay_ms( 10 );       // 50 mal 10 ms macht 0.5 Sekunden

                     // am PORT B alle Pins wieder auf 0
    PORTB = 0x00;

                     // und wieder warten
    for( i = 0; i < 50; i++ )
      _delay_ms( 10 );       // 50 mal 10 ms macht 0.5 Sekunden

                     // durch die while Schleife geht jetzt alles
                     // wieder von vorne los: Alle Pins auf 1,
                     // warten, alle Pins auf 0, warten, etc. etc.
  }
}

Autor: Frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Timer will ich leider anderweitig verwenden.

Mit nem Timer hab ich schon nen Blinklicht programmiert, das hat echt
gut funktioniert.

Wenn ich jetzt nen Blinker mit ner Schleife programmiere, z.B. ich
zähle in der Schleife bis zu einem bestimmten Wert und schalte dann den
Port um, dann kommt dieser Programmteil ja in die while(1) in der
main().

Wenn ich nun noch nen AD-Wandler benutze, wird dieser ja auch in der
while(1) in der main() initialisiert. Kommt es dabei dann vielleicht zu
Problemen, weil er ja für eine bestimmte Zeit in der Schleife für den
Blinker hängt?

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

Bewertung
0 lesenswert
nicht lesenswert
> Die Timer will ich leider anderweitig verwenden.

Das ist meist kein Hindernisgrund. Ein Timer kann ja
durchaus mehrere Aufgaben auf einmal durchführen.
Meist hat man in einem Programm sowieso einen
Basistimer, der einfach nur vor sich hintickt
und dem Programm einen Zeittakt vorgibt. Alle
zeitabhängigen Dinge sind dann einfach nur
ganzzahlige Vielfache dieses Basistaktes.

> while(1) in der main() initialisiert

ganz sicher nicht.
Initialisiert wird alles nur einmal, nicht öfter!

Was in der Schleife passiert ist, du gibst den ADC für
eine Messung frei. Der ADC kann sich dann zb. mit einem
Interrupt wieder melden, wenn er fertig ist.

Autor: Frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Karl Heinz,

vielen Dank für den Beispielcode!

Wäre es also möglich, den 8-Bit Timer mit dem ich ein PWM-Signal
erzeuge auch noch für den Blinker zu verwenden?

Aber dieser zählt doch nicht nur hoch und macht nen Overflow sondern
zählt auch wieder runter. Oder macht er den Overflow trotzdem? Weil
dann könnt ich ja den Overflow Interrupt nutzen.

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

Bewertung
0 lesenswert
nicht lesenswert
Kommt drauf an:
Welchen µC? welcher PWM Modus?

Sollte aber eigentlich im Datenblatt stehen, welcher
Interrupt ausgelöst werden kann. Beim Mega16 ist das zb.
ein Output Compare Interrupt am Timer0.

Autor: Frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ein Atmega88 im Fast PWM Mode.

Im Datenblatt steht, dass zwei Output Compare Interrupts zur Verfügung
stehen und ein Overflow Interrupt.

Nur ob diese auch im PWM Modus funktionieren, weiß ich nicht!

Da steht irgendwas mit Force Output Compare auf Seite 104 im
Datenblatt. Dieses Bit ist soweit ich das Verstanden habe im PWM Mode
nicht gesetzt.


Heißt das also dass auch der Interrupt nicht während des PWM Modus
läuft? Eigentlich ist doch das Bit OCIE0B für den Compare Interrupt
verantwortlich. Wie weit OCIE0A und FOC0A nun zusammenhängen kapier ich
nicht ganz.

Autor: inoffizieller WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bin mir jetzt nicht ganz sicher, aber auch beim Fast PWM-Mode müsste es
noch das Überlauf Interrupt geben.
Man könnte also in der Timer-Overflow-ISR einfach eine Variable in-
oder dekrementieren, die dann für ein Software-Interrupt sorgt (die
Variable von halt in der Main abgefragt...).

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Im fast PWM mode wird nix runtergezählt. Das passiert ausschließlich bei
phase correct PwM.
Das force outupt compare ist nie gesetzt. Das mußt du setzen, wenn du
ein compare-match-Ereignis manuell auslösen willst.
Die Interrupts werden ausgelöst, wenn die entsprechende Bedingung
gegeben ist. die Output-Compare-Interrupts werden immer beim
entsprechenden Compare-Match ausgeführt. Für den Overflow steht es . in
der Beschreibung der WGM-Bits (TOV flag set on... in der Tabelle). Wenn
der Overflow-Interrupt an ist, wird er immer ausgelöst, wenn das
TOV-Flag gesetzt wurde.

Autor: Läubi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du kannst auch ne fertige Blink LED nehmen, und dann gilt:

LED an = Blinken
LED aus= Aus

:)

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.