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


von Frank (Gast)


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ß

von Karl H. (kbuchegg)


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.

von Frank (Gast)


Lesenswert?

Empfiehlt sich denn eher die deelay Funktion oder eine Schleife?

von Dennis (Gast)


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.

von Markus N. (Gast)


Lesenswert?

Wieso willst du denn keinen Timer verwenden?
Is doch ideal dafür !!

von Karl H. (kbuchegg)


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.
  }
}

von Frank (Gast)


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?

von Karl H. (kbuchegg)


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.

von Frank (Gast)


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.

von Karl H. (kbuchegg)


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.

von Frank (Gast)


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.

von inoffizieller WM-Rahul (Gast)


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...).

von Rolf Magnus (Gast)


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.

von Läubi (Gast)


Lesenswert?

Du kannst auch ne fertige Blink LED nehmen, und dann gilt:

LED an = Blinken
LED aus= Aus

:)

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.