Forum: Mikrocontroller und Digitale Elektronik Display Anzeige aktualisieren


von Isildur (Gast)


Lesenswert?

Servus,

ich versuche einmal mein Problem verständlich zu schildern:
ich habe eine Funktion realisiert, die 30 Stellen auf einem Display 
ausgeben kann. Nennen wir diese Funktion meinetwegen sendedisplay(). In 
dieser Funktion werden jetzt die jeweiligen Stellen auf dem Display 
abgefahren.
1
sendedisplay()
2
{
3
sende(stelle1);
4
sende(stelle2);
5
sende(stelle3);
6
...
7
}

Diese sende Funktion würde ich am liebsten immer aktualisieren lassen, 
beispielsweise in der while-Schleife und nur die Variablen stelle1, 
stelle2, stelle3 ... aktualisieren.

Ich hoffe das Problem einigermaßen verständlich erläutert zu haben. Wie 
lässt sich das realisieren. Ich verlange keine Komplettlösungen, sondern 
nur einige Anregungen und Links.

Besten Dank

von Conny G. (conny_g)


Lesenswert?

Na, so: :-)
1
sendedisplay()
2
{
3
   sende(stelle1);
4
   sende(stelle2);
5
   sende(stelle3);
6
...
7
}
8
9
main 
10
{
11
   while(1) {
12
      sendedisplay();
13
   }
14
}

Das ist natürlich nur ein Scherz, Du hast die Frage sicher anders 
gemeint. Und zwar, wie Du das PLUS weitere Aktionen auf dem 
Mikrocontroller unterbekommen kannst.

Das geht z.B. ungefähr so:
- über einen Interrupt passieren irgendwelche Dinge, sagen wir mal es 
werden Taster abgefragt
- dieser Interrupt setzt dann eine Variable, sagen wir ein "keyUp"-Flag
- in der Hauptschleife fragst Du das keyUp ab und erhöhst dann eine 
Variable, die dann wieder auf das Display ausgegeben werden soll

Dann sieht das ganze so aus:
1
volatile uint8_t keyUp;
2
volatile uint8_t counter;
3
4
_ISR(INT0_vect)
5
{
6
   if (pin = HIGH) {
7
      keyUp = 1;
8
   }
9
}
10
11
sendedisplay()
12
{
13
   sende(stelle1);
14
   sende(stelle2);
15
   sende(stelle3);
16
}
17
18
main 
19
{
20
   while(1) {
21
      if (keyUp) {
22
         counter++;
23
      }
24
      sendedisplay();
25
   }
26
}

ACHTUNG: das ist nur mal schnell runtergekippt und nicht 
notwendigerweise compilierbar!

Als wird in der Hauptschleife einerseits auf Ereignisse reagiert, 
andererseits immer das Display ausgegeben.
Das kannst jetzt auch noch erweitern und z.B. das Display nur jede 
Sekunde aktualisieren, indem ein Timer-Interrupt jede Sekunde ein Flag 
setzt, das Deiner Hauptschleife sagt, es soll das Display aktualisieren:
1
volatile uint16_t ticks;
2
volatile uint8_t sekunde;
3
volatile uint8_t keyUp;
4
volatile uint8_t counter;
5
6
_ISR(TIMER0_OVF)
7
{
8
    ticks++;
9
    if (ticks > 1000) {
10
      sekunde = 1;
11
    }
12
}
13
14
_ISR(INT0_vect)
15
{
16
   if (pin = HIGH) {
17
      keyUp = 1;
18
   }
19
}
20
21
sendedisplay()
22
{
23
   sende(stelle1);
24
   sende(stelle2);
25
   sende(stelle3);
26
}
27
28
main 
29
{
30
   while(1) {
31
      if (keyUp) {
32
         counter++;
33
      }
34
      if (sekunde) {
35
         sendedisplay();
36
         sekunde = 0;
37
      }
38
   }
39
}

(Btw, nachlesen, was das volatile bedeutet und wie man in der 
Hauptschleife "atomic" auf die Variablen zugreift!)

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Isildur schrieb:

> Diese sende Funktion würde ich am liebsten immer aktualisieren lassen,
> beispielsweise in der while-Schleife und nur die Variablen stelle1,
> stelle2, stelle3 ... aktualisieren.

Ja, dann mach das doch!
WO drückt denn jetzt der Schuh?

>
> Ich hoffe das Problem einigermaßen verständlich erläutert zu haben.

Nicht wirklich. Aber meine Glaskugel sagt, dass du wahrscheinlich haben 
willst, dass eine Stelle nur dann aktualisiert werden soll, wenn sich 
ihr anzuzeigender Wert auch tatsächlich verändert hat.
Na, dann musst du dir eben in Variablen speichern, was an der jeweiligen 
Stelle momentan gerade angezeigt wird und nur dann, wenn die neue 
Information davon abweicht, dann wird die Anzeige aktualisiert.

zb in C
1
void sendedisplay()
2
{
3
  static int aktuellStelle1 = -1;
4
  static int aktuellStelle2 = -1;
5
6
  if( stelle1 != aktuellStelle1  ) {
7
    sende( stelle1 );
8
    aktuellStelle1 = stelle1;
9
  }
10
11
  if( stelle2 != aktuellStelle2 ) {
12
    sende( stelle2 );
13
    aktuellStelle2 = stelle2;
14
  }
15
16
  ....

durch den Einsatz von Arrays kannst du dir übrigens noch eine Menge 
Tipparbeit ersparen.

von Bernd K. (prof7bit)


Lesenswert?

Conny G. schrieb:
> _ISR(INT0_vect)
> {
>    if (pin = HIGH) {
>       keyUp = 1;
>    }
> }

Dafür setzt man lieber ein Bit in nem GPIOR, da spart man sich im 
Interrupt ein Register (und das zugehörige push/pop) und ein STS und in 
der main spart man ebenfalls und im obigen Fall könnte man die ISR dann 
sogar naked machen.

von Conny G. (conny_g)


Lesenswert?

Bernd K. schrieb:
> Conny G. schrieb:
>> _ISR(INT0_vect)
>> {
>>    if (pin = HIGH) {
>>       keyUp = 1;
>>    }
>> }
>
> Dafür setzt man lieber ein Bit in nem GPIOR, da spart man sich im
> Interrupt ein Register (und das zugehörige push/pop) und ein STS und in
> der main spart man ebenfalls und im obigen Fall könnte man die ISR dann
> sogar naked machen.

Und das ist hilfreich für einen Anfänger? :-)

von Bernd K. (prof7bit)


Lesenswert?

Conny G. schrieb:
> Und das ist hilfreich für einen Anfänger? :-)

Naja, er könnte es sich frühzeitig angewöhnen diese GPIOR Register für 
sinnvolle Zwecke zu nutzen, das hat auch den Vorteil dass er wieder was 
neues gelernt hat, nämlich die Existenz derselben von der er bis vor ein 
paar Stunden vermutlich noch gar nichts ahnte ;-)

@Isildur: Der Vorteil eben dieser Register gegenüber einer volatile 
uint8_t ist der daß für erstere genau wie bei IO-Pins nur ein einziger 
Taktzyklus erforderlich ist um ein bit zu setzen, zu löschen oder zu 
prüfen während eine globale volatile Variable im RAM mindestens zwei 
Zyklen zum Lesen, 2 weitere zum Schreiben und ein oder zwei um ihren 
Wert zu prüfen oder zu ändern, also 5 oder 6 Zyklen mindestens und auch 
um den selben Faktor mehr Programmspeicher (Flash) benötigt. Wenn Du Dir 
den vom Compiler erzeugten Assemblercode anschaust wird Dir schwindlig 
werden von all der Verschwendung ;-)

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Bernd K. schrieb:
> Conny G. schrieb:
>> Und das ist hilfreich für einen Anfänger? :-)
>
> Naja, er könnte es sich frühzeitig angewöhnen diese GPIOR Register für
> sinnvolle Zwecke zu nutzen, das hat auch den Vorteil dass er wieder was
> neues gelernt hat

Das hat Zeit, bis er aus dem Stadium '0-Wissen' rausgekommen ist.
Ehe das Thema GPIOR relevant wird, gibt es tausende andere Dinge, die 
erst mal wichtiger sind.

von Isildur (Gast)


Lesenswert?

WOW,
super schon mal vielen Dank für den ganzen Input, werde das heute Abend 
alles mal ausprobieren.

Eine Frage noch vorab, ich habe hier auch nen paar Taster rumfliegen. 
Idee ist wirklich über die Tasten jeweils verschiedene Menüs anzuzeigen 
(vermutlich auch verschachtelt).

Fragt man die Taster standardmäßig übers Polling oder über Interrupts 
ab. Ziel ist in einiger Zeit (nach Einarbeitung natürlich) schon einige 
verschachtelte Menüführung mit dem Display zu realisieren.

Vielen Dank für die ganzen Antworten!

von Conny G. (conny_g)


Lesenswert?

Hi Isildur,

Tasten abfragen und Entprellen ist ein ganzes Thema für sich.
Genau genommen sollte man Taster nicht per pin change oder Flanken 
Interrupt abfragen (Gründe: such mal im Forum nach Taster und Interrupt, 
da kommen bestimmt wilde Diskussionen zutage), da war mein Beispiel oben 
ungeschickt.

Für die Entprellung von Tasten gibt es einen riesigen Artikel.
Als Methode kann ich diese empfehlen:

http://www.mikrocontroller.net/articles/Entprellung#Timer-Verfahren_.28nach_Peter_Dannegger.29

vg,
Conny

: Bearbeitet durch User
von Isildur (Gast)


Lesenswert?

ich habe versucht das Display Problem wie folgt zu lösen:
1
static unsigned char displaystelle1;
2
static unsigned char displaystelle2;
3
static unsigned char displaystelle3;
4
...

In einer Funktion setzevar() setze ich dann die zugehörigen 
Displaystellen, in etwa so:
1
void setzevar()
2
{
3
 displaystelle1 = H;
4
 displaystelle2 = a;
5
 displaystelle3 = l;
6
 ...
7
8
}

Wenn ich jetzt in der Funktion sendeDisplay() die zugehörigen Variablen 
ausgeben möchte funktioniert es nicht wie gewünscht:
1
void sendeDisplay()
2
{
3
sende(displaystelle1);
4
sende(displaystelle1);
5
sende(displaystelle1);
6
int main()
7
{
8
setzevar();
9
sendeDisplay();
10
}
11
}


Wenn ich jedoch direkt die Stellen über
1
sende(H);
2
sende(a);
3
sende(l);

ausgeben möchte funktioniert es in meinen Augen seltsamerweise.

Was mache ich falsch?

von Karl H. (kbuchegg)


Lesenswert?

Isildur schrieb:

> Wenn ich jedoch direkt die Stellen über
>
1
> sende(H);
2
> sende(a);
3
> sende(l);
4
>


Das funktioniert gan z sicher nicht, es sei denn du hast einen Haufen 
Variablen, für jeden Buchstaben einen. Das allerdings wäre komplett 
dämlich.


Zeige dein ganzes Programm. Aus den Schnipseln kann keiner was ableiten. 
Sehr wahrscheinlich sitzt das Problem ganz woanders.

von Isildur (Gast)


Lesenswert?

1
Display.h
2
3
#define A_buch         0b10101000
4
#define B_buch         0b10011011
5
#define C_buch         0b00100011
6
#define D_buch         0b00011011
7
8
9
10
Programm.h
11
static unsigned char displaystelle1;
12
static unsigned char displaystelle2;
13
static unsigned char displaystelle3;
14
static unsigned char displaystelle4;
15
16
menu.c
17
#include "Display.h"
18
#include "Programm.h"
19
#include "menu.h"
20
21
void senddisplay_menu1()
22
{
23
displaystelle1 = A_buch;
24
displaystelle1 = B_buch;
25
displaystelle1 = B_buch;
26
displaystelle1 = B_buch;
27
}
28
29
main.c
30
#include "Display.h"
31
#include "Programm.h"
32
#include "menu.h"
33
34
void sende()
35
{
36
sendekommando(displaystelle1);
37
sendekommando(displaystelle2);
38
sendekommando(displaystelle3);
39
sendekommando(displaystelle4);
40
}
41
42
int main()
43
{
44
senddisplay_menu1();
45
sende()
46
;
47
}

Die sendekommando() Funktion funktioniert dabei definitv. Wie gesagt, 
wenn ich direkrt ausgebe und nicht über die Funktionen dann funktioniert 
es

von Bitflüsterer (Gast)


Lesenswert?

Das ist wieder mal so eine Frage, bei der man dann antworten möchte: 
Lies ein C-Buch!

Da Du die Variablen static deklariert hast und sie über eine 
Header-Datei in zwei verschiedene C-Dateien einfügst, erhälst Du zwei 
Sätze gleichnamiger Variablen die jeweils "lokal" zu der entsprechenden 
C-Datei sind.
Dadurch initialisierst Du zwar die eine der beiden Modullkokalen 
Variablensätze mit senddisplay_menu1(), liest aber einen dritten Satz 
aus, denn ich vermute, Du includest die Header-Datei mit den 
Variablendefinition ein drittesmal.

Was mich zu noch einem Hinweis bringt: Poste komplette Programme. Die 
Meinung von Anfängern, dass das nicht gepostete schon korrekt sei, 
erweist sich in den meisten Fällen als falsch.

von Isildur (Gast)


Lesenswert?

Top,

vielen Dank!
einfach static weglassen und schon funzt es. Werde versuchen mich da 
etwas einzulesen!

von Peter D. (peda)


Lesenswert?

Isildur schrieb:
> sendekommando(displaystelle1);
> sendekommando(displaystelle2);
> sendekommando(displaystelle3);
> sendekommando(displaystelle4);

Das ist Copy&Paste-Code der übelsten Sorte.
Sowas kann man für die allerersten Schritte mal probieren.

Aber ein richtiges Programm kann man so nicht schreiben.
Das wird unübersichtlich, unwartbar, unverstehbar, fehlerträchtig und 
riesig.

Sachen, die mehr als einmal ähnlich benötigt werden, macht man mit 
Arrays und Schleifen.
Dann muß man sie nur einmal hinschreiben und einmal testen und kann sie 
beliebig erweitern.

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.