PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : LED blinken lassen während Programm normal weiterläuft



Steffen08
26.03.2009, 22:49
Hi :)
ich programmieren zur Zeit in C an einem Atmega8 rum.Und zwar möchte ich eine LED an einem PORT blinken lassen.Während diese LED blinkt,möchte ich mein Programm ganz normal weiterlaufen lassen.Es ließt z.b. nen Schalter ein,...etc... .Und während dem Programmablauf,würd ich dann gerne "sagen" so,..blinken Stopp!.Ist das irgendwie möglich?.Ich probiers jetzt schon seit 2 Tagen,aber ich komme auf keinen grünen Zweig.

Vielen Dank schonmal für Eure Hilfe!

gruss

vklaffehn
26.03.2009, 23:24
Moin!
Versuch es mal mit einem Timerinterrupt, ist z.B. hier im RN-Wissen erwähnt, glaube ich, ansonsten mal danach im forum suchen oder bis zum WE warten, dann kann ich Dir ein kleines Codebeispiel posten.
MfG
Volker

Steffen08
27.03.2009, 11:52
Das mit dem Codebeispiel wäre klasse.
ich werde mal das Forum weiter durchforsten und mir den Timerinterrupt mal ansehen und weiterprobieren.
ich möchte einfach das die LED immer blinkt und nebenzu ein Programm abläuft.Und irgendwann in diesem Programm kommt dann der Befehl "LED_AUS"

gruss und vielen Dank

oberallgeier
27.03.2009, 12:22
Hi Steffen08,

für (m)einen mega168 gebe ich Dir ein Codebeispiel. Du müsstest die Variablen noch selbst deklarieren und Dir die entsprechenden Timerregister (-namen und -werte) aus dem mega8-Datenblatt raussuchen. >>> Das ist eine mögliche Lösung <<< und vermutlich nicht mal die beste. Also fixiere Dich nicht zu sehr darauf.

Hintergrund: als vielfach nutzbares Zeitsignal habe ich in meiner Software einen 50µs-Takt aufgebaut. Die entsprechende ISR (Interrupt-Service-Routine) zählt beim Aufruf immer die Varible Izeit_1 um 1 rauf, bis Izeit_1 bei 20000 ist - dann ist eine Sekunde um. Jetzt könnte ich in der ISR natürlich noch nen Sekundenzähler einbauen (habe ich in dem hier vorgestellten Beispiel der Übersichtlichkeit halber gestrichen). Wenn Du für den Sekundenzähler ein uint16_t nimmst, dann hast Du bei unter 45 000 Sekunden schon mal einen halben Tag zu zählen . . . . .

Die (uint_8-) Variable LEDon ist Dein "Schalter" für LED ein oder aus. Bei JEDEM Wert ausser "1" ist die LED aus, bei "1" klickert sie im Sekundentakt . . . . ok?


/* ================================================== ============================ */
/* === Initialisierung fuer Timer2 mega168 ===================================== */
void TC2TMR_init(void) // Init Tmr/Cntr 2, 8-Bit auf 20 kHz = 50 µs
{
TCCR2A |= (1<<WGM21); // Timer im CTC-Mode, Top=OCR2A doc S 157
TCCR2B |= (1<<CS21); // Prescaler 1/8 / Clock <- CPU doc S 158
OCR2A = 124; // Preset 125 für 50µs bei 20Mhz
TIMSK2 |= (1<<OCIE2A); // Tmr/Cntr2 CompareA interrupt enabled
}
/* ================================================== ============================ */


/* ================================================== ============================ */
/* === Nicht unterbrechbare ISR für timer2 ===================================== */
/* Routine zählt hoch im Takt 20 kHz = 50 µs. Der Zählerwert wird von den ISR für
EXT_INT0 und -INT1 ausgelesen und den Werten Iz_yseci zugewiesen ...... */
ISR(TIMER2_COMPA_vect) // Vektor 7
{
if (Izeit_1 < 20000) //Interrupt-Timer = 20 000 ... (1 sec blink)
{
Izeit_1 ++; // war: alle Sekunden wird 20000 erreicht
} // und Izeit_1 bleibt in der uint16-Grenze
else
{
if ( LEDon == 1 ) // LED nur toggeln, wenn erlaubt
{
PORTC ^= (1<<PC5); // LED auf Port PC5/I2C/SCL toggeln
}
Izeit_1 = 1; // ansonsten: Zeit zurückstellen
}
}
/* ================================================== ============================ */

Die Initialisierung erfolgt durch Aufruf von "TC2TMR_init();", danach müsste noch ein sei(); kommen um die Interrupts zu erlauben - und sobald Du dann schreibst "LEDon = 1;" fängt die LED nach spätestens 50 µs an zu blinken, bei "LEDon = 0" oder einem anderen Wert geht sie nach spätestens 50 µs wieder aus . . . . ok?

Ach so, ja, die ISR läuft natürlich im "Hintergrund". Du merkst davon garnix, Dein restlicher Code ist davon nicht betroffen (der wird nur in seinem Ablauf alle 50 µs für ein paar Maschinenzyklen unterbrochen). Beim Auslesen von Izeit_1 bzw. einem 2-Byte-Sekundenwert im main oder einer Subroutine vermeidest Du Probleme wenn Du "cli();" - Wert auslesen - "sei();" vorsiehst. Denn die ISR kann natürlich mitten im Auslesen - zwischen den beiden Bytes (MSB und LSB) den Wert verändern!

Steffen08
27.03.2009, 14:59
super!Vielen Dank! werde ich nacher gleich mal ausprobieren!

gruss

Steffen08
30.03.2009, 21:47
super,habs zum laufen bekommen,...vielen,vilen Dank :)

gruss

oberallgeier
30.03.2009, 22:10
Hi Steffen08,


super,habs zum laufen bekommen ...Prima, mein Glückwunsch. Schön dass Dir geholfen wurde. Das Forum ist ja schliesslich zum Helfen da und als Drehtisch für Erfahrungen.

Viel Erfolg und Fortschritt mit Deiner Programmiererei