Forum: Mikrocontroller und Digitale Elektronik LCD: Text blinken


von Tobias K. (finswimmer)


Lesenswert?

Hallo,

der User soll wenn der Countdown eingestellt wird, sehen, ob er gerade 
bei der Stunde oder Minute ist.
Dazu dachte ich, ich lasse das LCD die jeweiligen 2 Stellen blinkend 
anzeigen.

Wenn ich es aber im einfachsten Falle mache
1
while(1){
2
lcd_clear();
3
lcd_home();
4
lcd_string(stunden);
5
lcd_string(":");
6
lcd_string(minuten);
7
_delay_ms(300);
8
lcd_clear();
9
lcd_home();
10
lcd_string("  ");
11
lcd_string(":");
12
lcd_string(minuten);
13
if debounce...(Tasterabfrage)
14
}
(Nicht getestet, aber Funktionsweise sollte klar werden)
Dann hänge ich in einer Endlosschleife fest, bei der auf 
Tasterereignisse nur alle 600ms reagiert wird.

Das ist also nicht ganz das, was ich haben will.

Ich habe mich gestern auch schon in Interrupts eingelesen.

Laut http://www.windmeadow.com/node/19
[quote]
The interrupts can detect four different types of pin changes:
1. pin goes low
2. any logical change in pin
3. falling edge (pin goes from high to low)
4. rising edge (ping goes from low to high)
[/quote]
bringt mir das nicht viel für einen Taster, oder?

Wäre für einen Denkanstoß sehr dankbar!

Vielen Dank
Tobi

von Der M. (steinadler)


Lesenswert?

Du solltest dich als nächstes in "Timer" einarbeiten.

Soviel Delay macht man nicht.

Das Schema ist hier so.

Man hat einen Timer-Interrupt, welchen man zu bestimmten Zeiten 
irgendwelche Bits setzen lässt.

In deiner Main-Loop fragst du dann einfach nur dieses eine Bit ab,
Und wenn es gesetzt ist, führst du deinen Blink-Befehl aus und setzt das 
Bit zurück.

Allerdings hängt er dann wieder in deiner Tastaturabfrage fest.
Hier müsstest du die Tastenabfrage auch aufbohren, dass sie dir nicht 
das ganze System lahm legt.
Also z.B. die Abfrage ständig im Hintergrund ausführen und nur ein Bit 
setzen, wenn eine gültige Eingabe (also mit ENTER oder so in etwa) 
empfangen wurde.

Der Interrupt für den Taster geht zum Spielen jetzt erstmal.
Allerdings, wenn du eine stabile Funktionsweise haben willst, solltest 
du dich mal mit "Entprellen von Tastern" auseinandersetzen.
In deinem jetzigen Fall (nur mit Interrupt), kann es passieren, dass 
dein Taster 10 statt nur einem Impuls abgibt.

von Sören H. (dersoe)


Lesenswert?

... wobei ich ja mal gehört habe, dass man Taster auch hardwareseitig 
entprellen kann ;-) Für den allerersten Anfang sollte wohl ein 
Kondensator reichen (so 1...100nF).
Ansonsten wirst du sicherlich hier noch fündig:
Beitrag "Taster Hardwaremäßig entprellen"
Gruß,
Sören

von Tobias K. (finswimmer)


Lesenswert?

1
inline uint8_t debounce(volatile uint8_t *port, uint8_t pin)
2
{
3
    if ( ! (*port & (1 << pin)) )
4
        {
5
                /* Pin wurde auf Masse gezogen, 100ms warten   */
6
        _delay_ms(50);  // max. 262.1 ms / F_CPU in MHz
7
        _delay_ms(50);
8
        if ( *port & (1 << pin) )
9
        {
10
                /* Anwender Zeit zum Loslassen des Tasters geben */
11
               _delay_ms(50);
12
               _delay_ms(50);
13
               return 1;
14
        }
15
        }
16
              return 0;
17
}
Klappt auch sehr gut, wie ich finde.

Mir gehts nochmal um die Funktionsweise vom Timer.
Dieser zählt von 0 bis 255 hoch. Wenn dieser dann wieder auf 0 springt, 
löst er einen Interrupt aus, mit dem man arbeiten kann.

Wie aber wird wo definiert, dass man nach dem Interrupt schaut?
Oder aktiviert der Interrupt selbst seine eigene Routine?

Kann ich dann nicht den Taster auf einen Interrupt legen? Sodass ich 
immer, wenn der Taster gedrückt wird, die dazugehörige Routine 
abgearbeitet wird?
Das hätte den Vorteil, dass nirgendswo "hängende" Endlosschleifen 
arbeiten.


Danke

Tobi

von Der M. (steinadler)


Lesenswert?

Den Vorteil, "dass nirgendwo hängende Endlosschleifen sind" sollte man 
sich sowieso von vorn herein angewöhnen.

Schau mal hier im Menü links unter AVR. Da sind ziemlich viele 
Anleitungen zu solchen Themen. Also einfach mal nach "Interrupts" 
suchen.

von Tobias K. (finswimmer)


Lesenswert?

So. Ich habe nun, laut http://www.windmeadow.com/node/19, einen 
Interrupt an PD2 angeschlossen.
ISC01=0
ISC00=1
ist "Any logical change on INT0 generates an interrupt request".

Das steht in main(void)
1
  // Set Pin 6 (PD2) as the pin to use for this example
2
PCMSK |= (1<<PIND2);
3
4
// interrupt on INT0 pin falling edge (sensor triggered)
5
MCUCR = (0<<ISC01) | (1<<ISC00);
6
7
// turn on interrupts!
8
GIMSK  |= (1<<INT0);
1
SIGNAL (SIG_INT0)
2
        {
3
        led_blink();
4
        }
steht außerhalb der Schleife.

Nun sollte doch bei einem Tastendruck die Spannung an PD2 kurzfristig 
von Low auf High gehen, somit ist das ein Kriterium für den Interrupt 
und die led sollte blinken?

Leider tut sich da nix...

Habe ich das System "Interrupt" noch nicht begriffen?

Danke
Tobi

von Falk B. (falk)


Lesenswert?

Die meisten LCDs können den Cursor alleine blinken lassen. Ist zwar nur 
ein Zeichen, reicht aber meist.

MFG
Falk

von Tobias K. (finswimmer)


Lesenswert?

Falk Brunner wrote:
> Die meisten LCDs können den Cursor alleine blinken lassen. Ist zwar nur
> ein Zeichen, reicht aber meist.
>
> MFG
> Falk

Nee, das ist nicht das, was ich haben möchte, da der Cursor dann meist 
an der falschen Stelle blinkt.
Wenn denn dann soll es richtig gut aussehen :)

Tobi

von holger (Gast)


Lesenswert?

>Nee, das ist nicht das, was ich haben möchte, da der Cursor dann meist
>an der falschen Stelle blinkt.

Das ist dann aber dein Fehler ;)

von Tobias K. (finswimmer)


Lesenswert?

holger wrote:
>>Nee, das ist nicht das, was ich haben möchte, da der Cursor dann meist
>>an der falschen Stelle blinkt.
>
> Das ist dann aber dein Fehler ;)

Klar, das kann ich auch umbauen. Aber dann habe ich immer noch das 
Problem, dass ich die Stunden einstelle, welche 2 Ziffern habe, aber nur 
bei 1Ziffer der Cursor blinkt.

Wie dem auch sei. Ich kenne diese Funktion, möchte aber auch etwas 
lernen und das Ganze ausgliedern und dann per Interrupts lösen.

Daher noch einmal die Frage, ob und wie ich diesen Taster mit Interrupts 
steuern kann?

Danke
Tobi

von Falk B. (falk)


Lesenswert?

@ Tobias Kaminsky (finswimmer)

>Daher noch einmal die Frage, ob und wie ich diesen Taster mit Interrupts
>steuern kann?

Den Taster kaum, aber das LCD. ;-)

Du must einen Timer Interrupt nutzen, z.B. auf 10ms eingestellt. 
Im Interrupt zählst du eine Variable hoch. Wenn sie z.B. 50 erreicht hat 
(1/2 s), dann musst du anhand einer weiteren Variable prüfen, ob du 
jetzt die Zahl darstellen willst (und welche) oder gerade "geblinkt 
wird", sprich du musst Leerzeichen, Vollzeichen oder invertiert 
darstellen. Wenn du das gemacht hast, musst du deine Zählvariable 
zurücksetzten und auch die Darstellungsvaribable ändern. Ungefähr so.
1
interrupt()
2
{
3
   zähler +1
4
   wenn zaähler=50 dann
5
   {
6
      wenn merker=0 dann
7
      {
8
         normal darstellen
9
         merker =1
10
      }
11
      anderenfalls
12
      {
13
         blinken darstellen
14
         merker =0
15
      }
16
      zaehler =0
17
   }
18
19
}

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.