Hallo zusammen,
Ich habe mal wieder ne kleine Hirnblockade, und brauchte von euch einen
kleinen Wink mit dem Zaunpfahl.
Ich gebe den Inhalt des PIN C und B Register auf einem LCD aus, bzw
möchte zwischen den den PINs hin und herschalten über eine binäre
Auswertung.
Also drücke eine Taste und das LCD schaltet von PINC auf PINB und
umgekehrt.
also die Anzeige eines PIN funktioniert, allerdings bereitet mit das
löschen der Anzeige via lcd_clear() etwas Probleme weil die Anzeige
anfängt zu flackern. das ist der Grundcode :
1
#include<avr/io.h>
2
#include"lcd-routines.h"
3
#include<util/delay.h>
4
5
intmain(void)
6
{
7
8
lcd_init();// Initialisierung des LCD
9
10
//Beispiele für die LCD Ausgabe
11
/*
12
Beispiel für die Ausgabe auf dem LCD Display
13
14
lcd_setcursor(0, 1 );
15
lcd_string("Hello World");
16
lcd_setcursor(0, 2 );
17
lcd_string("Hello World");
18
lcd_setcursor(0, 3 );
19
lcd_string("Hello World");
20
lcd_setcursor(0, 4 );
21
lcd_string("Hello World");
22
23
Text in einzelnen Zeichen ausgeben
24
25
lcd_data( 'T' );
26
lcd_data( 'e' );
27
lcd_data( 's' );
28
lcd_data( 't' );
29
30
*/
31
DDRB=0x00;
32
PORTB=0xff;
33
DDRC=0x00;
34
PORTC=0xff;
35
36
while(1)
37
{
38
if(!(PINC&0x01))
39
{ausgabe_b();
40
if(!(PINC&0x02))
41
{ausgabe_c();}
42
43
44
}
45
46
return0;
47
}
48
voidausgabe_b(void)
49
{
50
inti=0;
51
charBuffer[20];
52
53
lcd_setcursor(0,1);//PB0
54
55
lcd_string("PB0 = ");
56
if(!(PINB&(1<<PB0)))
57
{i=0;}
58
else
59
{i=1;}
60
itoa(i,Buffer,10);
61
lcd_string(Buffer);
62
63
lcd_setcursor(8,1);//PB4
64
65
lcd_string("PB4 = ");
66
if(!(PINB&(1<<PB4)))
67
{i=0;}
68
else
69
{i=1;}
70
itoa(i,Buffer,10);
71
lcd_string(Buffer);
72
73
lcd_setcursor(0,2);//PB1
74
75
lcd_string("PB1 = ");
76
if(!(PINB&(1<<PB1)))
77
{i=0;}
78
else
79
{i=1;}
80
itoa(i,Buffer,10);
81
lcd_string(Buffer);
82
83
lcd_setcursor(8,2);//PB5
84
85
lcd_string("PB5 = ");
86
if(!(PINB&(1<<PB5)))
87
{i=0;}
88
else
89
{i=1;}
90
itoa(i,Buffer,10);
91
lcd_string(Buffer);
92
93
lcd_setcursor(0,3);//PB2
94
95
lcd_string("PB2 = ");
96
if(!(PINB&(1<<PB2)))
97
{i=0;}
98
else
99
{i=1;}
100
itoa(i,Buffer,10);
101
lcd_string(Buffer);
102
103
lcd_setcursor(8,3);//PB6
104
105
lcd_string("PB6 = ");
106
if(!(PINB&(1<<PB6)))
107
{i=0;}
108
else
109
{i=1;}
110
itoa(i,Buffer,10);
111
lcd_string(Buffer);
112
113
lcd_setcursor(0,4);//PB3
114
115
lcd_string("PB3 = ");
116
if(!(PINB&(1<<PB3)))
117
{i=0;}
118
else
119
{i=1;}
120
itoa(i,Buffer,10);
121
lcd_string(Buffer);
122
123
lcd_setcursor(8,4);//PB7
124
125
lcd_string("PB7 = ");
126
if(!(PINB&(1<<PB7)))
127
{i=0;}
128
else
129
{i=1;}
130
itoa(i,Buffer,10);
131
lcd_string(Buffer);
132
133
}
134
voidausgabe_c(void)
135
{
136
intj=0;
137
charBuffer_1[20];
138
139
lcd_setcursor(0,1);//PC0
140
141
lcd_string("PB0 = ");
142
if(!(PINC&(1<<PC0)))
143
{j=0;}
144
else
145
{j=1;}
146
itoa(j,Buffer_1,10);
147
lcd_string(Buffer_1);
148
149
lcd_setcursor(8,1);//PC4
150
151
lcd_string("PB4 = ");
152
if(!(PINC&(1<<PC4)))
153
{j=0;}
154
else
155
{j=1;}
156
itoa(j,Buffer_1,10);
157
lcd_string(Buffer_1);
158
159
lcd_setcursor(0,2);//PC1
160
161
lcd_string("PB1 = ");
162
if(!(PINC&(1<<PC1)))
163
{j=0;}
164
else
165
{j=1;}
166
itoa(j,Buffer_1,10);
167
lcd_string(Buffer_1);
168
169
lcd_setcursor(8,2);//PC5
170
171
lcd_string("PB5 = ");
172
if(!(PINC&(1<<PC5)))
173
{j=0;}
174
else
175
{j=1;}
176
itoa(j,Buffer_1,10);
177
lcd_string(Buffer_1);
178
179
lcd_setcursor(0,3);//PC2
180
181
lcd_string("PC2 = ");
182
if(!(PINC&(1<<PC2)))
183
{j=0;}
184
else
185
{j=1;}
186
itoa(j,Buffer_1,10);
187
lcd_string(Buffer_1);
188
189
lcd_setcursor(0,4);//PC3
190
191
lcd_string("PC3 = ");
192
if(!(PINC&(1<<PC3)))
193
{j=0;}
194
else
195
{j=1;}
196
itoa(j,Buffer_1,10);
197
lcd_string(Buffer_1);
198
199
}
So wenn ich jetzt am Ende der Unterprogramme ein lcd_clear setze dann
fängt die Anzeige an zu flimmern.
Ich bin leider noch sehr unerfahren das das programmieren angeht, daher
meine kleine Blockade.
Wie kann ich sowas an sinnvollsten lösen ?
Jörg Drösser schrieb:> So wenn ich jetzt am Ende der Unterprogramme ein lcd_clear setze dann> fängt die Anzeige an zu flimmern.> Ich bin leider noch sehr unerfahren das das programmieren angeht, daher> meine kleine Blockade.> Wie kann ich sowas an sinnvollsten lösen ?
indem du lcd_clear nur dann benutzt, wenn sich die komplette Anzeige
deines LCD ändert. In allen anderen Fällen willst du möglichst mittels
Überschreiben auskommen bzw. Teile die sich nicht geändert haben auch
nicht neu schreiben.
Du machst dir also ein Flag, welche der beiden PINB oder PINC gerade
angezeigt wird. Und nur dann, wenn das anzuzeigende von dem was
angezeigt wird unterscheidet, nur dann löscht du das LCD (wenn
überhaupt: PINB und PINC sind gleich lange Texte, wenn man den einen mit
dem anderen überschreibt, dann wird vollständig berschrieben).
lcd_clear ist eine Funktion, die du nicht verwenden willst. Es sei denn,
das generelle Layout deiner Anzeige ändert sich radikal. Aber ansonsten
willst du immer nur nach möglichkeit einen bereits angezeigten Wert
(oder Text) mit einem neuen überschreiben. Aber bitte so, dass auch
vollständig überschrieben wird und danach keine Artefakte sichtbar
bleiben.
Und formatier deinen Code besser. Da kriegt man ja Augenkrebs!
Der Code ist so absolut nicht zu lesen, weil sämtliche Einrückung fehlt.
Das hilft einem übrigens auch gerade als Anfänger selbst weiter. Wenn
man sich mangels Einrückung in seinem eigenen Code nicht mehr
zurechtfindet, fängt man irgendwann an, Code an zufällige Stellen
einzufügen bis es irgendwann klappt.
Im Übrigen fehlt dir wahrscheinlich bei "{ausgabe_b();" die schließende
geschweifte Klammer.
Jörg Drösser schrieb:> So wenn ich jetzt am Ende der Unterprogramme ein lcd_clear setze dann> fängt die Anzeige an zu flimmern.
Ich würde sagen, das liegt daran, dass das von der Hauptschleife aus
ohne jegliche Verzögerung immer wieder aufgerufen wird ohne irgendeine
Art von Delay dazwischen.
D.h. du siehst die Anzeige nur für die kurze Zeit, in der sie bereits
geschrieben, aber noch nicht gecleart wurde, und das liegt bestenfalls
im Millisekundenbereich.
Auf jeden Fall würde ich die Anzeige clearen, bevor du den Text
ausgibst, und nicht direkt nach der Ausgabe den Text wieder löschen.
> Wie kann ich sowas an sinnvollsten lösen ?
Ich würde außerdem irgendwo ein Delay o.ä. einbauen, da du den Text
ständig neu ausgibst solange du deinen Taster o.ä. gedrückt hältst
(wodurch auch ständig das Display gecleart werden muss, was sich in
Flackern äußern kann). Würde in der main nach den Aufrufen von
ausgabe_b/c ein _delay_ms(1) o.ä. einbauen.
ist ja wohl an kompliziertheit kaum noch zu überbieten.
Was ist falsch an
1
if(!(PINB&(1<<PB5)))
2
lcd_string("0");
3
else
4
lcd_string("1");
oder aber, wenn man realisiert, dass das eigentlich für alle Pins
ohnehin immer gleich ist: was ist falsch daran eine Funktion zu machen,
der man übergibt: einen Text, einen Wert der entweder 0 oder nicht 0
sein kann und eine Position an der das ganze anfangen soll.
80% Code eingespart. Übersichtlichkeit trotzdem (oder gerade deswegen?)
drastisch erhöht.
Wenn du Code schreibst, dann lehn dich immer wieder auch mal zurück und
frag dich: kann ich das ganze nicht einfacher formulieren?
Speziell wenn du Code immer einfach nur weiter kopierst und Einzelteile
durch andere ersetzt, dann solltest du dich fragen, ob es nicht
angebracht wäre das ganze in eine Funktion zu verpacken. Wie man sieht
kann das drastische Unterschiede ausmachen.
Danke schon mal für die Antworten.
Das mit der geschweiften Klammer habe ich auch gerade gemerkt. :-)
Im Bezug aufs Formatieren habe ich keinerlei Vorgaben wie man das
sinnvoll oder optisch besser gestaltet. bitte mal beispiele geben damit
ich weiss wie Ihr das meint dann ändere Ich gerne den Code ab.
@ Karl Heinz: Was meinst du mit Flag ( sorry für die Frage, aber das
sagt mir so jetzt nicht direkt was) Bin wie gesagt in der Thematik nicht
zuhause und stehe noch am Anfang.
@ Foo : Die Anzeige soll ja ständig aktuell sein. heisst ändert sich was
am PIN soll das direkt angezeigt werden, daher lasse ich das LCD
zyklisch schreiben. Das mit dem Delay habe ich schon versucht und das
flackert ebenfalls. Auch mit einem Delay von 100 ms
Jörg Drösser schrieb:> Danke schon mal für die Antworten.>> Das mit der geschweiften Klammer habe ich auch gerade gemerkt. :-)>> Im Bezug aufs Formatieren habe ich keinerlei Vorgaben wie man das> sinnvoll oder optisch besser gestaltet. bitte mal beispiele geben damit> ich weiss wie Ihr das meint dann ändere Ich gerne den Code ab.
Sieh dir einfach mal an, wie andere das machen.
Eine simple Regel
nach einer { wird grundsätzlich nicht in derselben Zeile
aweitergeschrieben. Jede Anweisung (auch wenn { jetzt in dem Sinn keine
'Anweisung' ist) kommt auf eine neue Zeile
nach einer { wird das im {} Block eingeschlossene eingerückt. Ob das
jetzt 2 oder 4 Zeichen sind, ist erst mal nicht so wichtig. Wichtig ist,
das eingerückt wird!
Die Einrückung wird bei der schliessenden } wieder aufgehoben. Die }
selber kommt wieder um die Einrückungstiefe weiter nach links.
Enthält ein {}-Block selbst wieder weitere {, dann wird
selbstverständlich auch weiter eingerückt.
Ob man bei if und lediglich einer einzigen abhängigen Anweisung
{}-Klammern macht oder nicht, ist in weiten Grenzen Geschmackssache. Ich
mach sie nicht oder selten, andere machen das generell.
Wichtig ist aber: die abhängige Anweisung kommt auf ihre eigene Zeile
und wird eingerückt.
Die Einrückung zeigt dir optisch an, welche Programmteile von anderen
Programmteilen abhängig sind. In
1
if(wert)
2
lcd_string("1");
3
else
4
lcd_string("0");
kann man aus 3 Meter Entfernung sehen (selbst wenn man es nicht lesen
kann), dass da 2 Anweisungen offenbar von irgendetwas abhängen.
> @ Karl Heinz: Was meinst du mit Flag ( sorry für die Frage, aber das> sagt mir so jetzt nicht direkt was) Bin wie gesagt in der Thematik nicht> zuhause und stehe noch am Anfang.
1
uint8_tmomentaneAnzeige;// 0 = jetzt wird gerade PINB angezeigt
2
// 1 = jetzt wird gerade PINC angezeigt
3
4
intmain()
5
{
6
uint8_tanzuzeigenIst=0;// selbe Bedeutung wie momentane Anzeige
7
8
....
9
10
while(1)
11
{
12
13
if(!(PINC&0x01))
14
anzuzeigenIst=0;// PINB soll angezeigt werden
15
16
if(!(PINC&0x02))
17
anzuzeigenIst=1;// PINC soll angezeigt werden
18
19
if(momentanteAnzeige!=anzuzeigenIst)
20
lcd_clear();
21
22
if(anzuzeigenIst==0)
23
ausgabe_b();
24
else
25
ausgabe_c();
26
27
momentaneAnzeige=anzuzeigenIst;
28
}
29
}
Der lcd_clear wird nur dann ausgeführt, wenn die Anzeige (auf
Benutzerwunsch) von B auf C wechselt oder umgekehrt.
Ein FLag ist einfach nur eine Variable, die mit ihrem Wert etwas über
eienn Zustand ausdrückt. So wie hier: die Bits welches PINx werden
gerade angezeigt.
Karl Heinz schrieb:>> Das mit der geschweiften Klammer habe ich auch gerade gemerkt. :-)
Sowas
1
while(1)
2
{
3
if(!(PINC&0x01))
4
{ausgabe_b();
5
if(!(PINC&0x02))
6
{ausgabe_c();}
7
8
9
}
geht gar nicht.
Wenn man das mal nach simplen FOrmatierregeln formatiert, dann erhält
man
1
...
2
while(1)
3
{
4
if(!(PINC&0x01))
5
{
6
ausgabe_b();
7
8
if(!(PINC&0x02))
9
{
10
ausgabe_c();
11
}
12
}
13
14
return0;
15
}
da die Funktion main() nach dem return zu Ende sein soll, die letzte
schliesende } aber nicht am linken Rand landet, muss daher irgendwo ein
Klammerfehler vorliegen.
Formatiert man das nach der (erkennbaren) Absicht
1
...
2
while(1)
3
{
4
if(!(PINC&0x01))
5
{
6
ausgabe_b();
7
8
if(!(PINC&0x02))
9
{
10
ausgabe_c();
11
}
12
}
13
14
return0;
15
}
dann landet die letzte } der Funktion zwar dort wo sie hingehört, aber
man sieht sofort, dass hier
1
if(!(PINC&0x01))
2
{
3
ausgabe_b();
4
5
if(!(PINC&0x02))
offenbar eine schliessende } Klammer fehlt. Denn das zweite if kann
nicht um 2 Zeichen ausgerückt sein, ohne das vorher eine schliessende }
kommt, wenn die Einrückung wegen einer { erfolgt ist. Auch sieht man,
indem man in derselben Spalte wie die öffnende { die Zeilen darunter
absucht, dass es die zugehörige } nicht gibt. Öffnende { und
schliessende } stehen immer in derselben Spalte und dazwischen kann es
keine Zeile geben, die in derselben Spalte anfängt.
D.h. man hat 2 optische Indizien für denselben Sachverhalt: du hast eine
} vergessen.
DAS ist der Wert einer ordentlichen Formatierung. Sie hilft dir Fehler
zu finden. Und zwar rein nur dadurch, dass die Optik 'nicht stimmt'.
Daher ist auch die oft gehörte Aussage "Formatierung mach ich nachher,
jetzt such ich erst mal den Fehler" Unsinn. Denn viele Fehler kann man
ganz einfach vermeiden, INDEM man ordentlich formatiert.
Jörg Drösser schrieb:> @ Foo : Die Anzeige soll ja ständig aktuell sein.
"Ständig aktuell" gibt es nicht, es wird mit Sicherheit immer einige
CPU-Takte hinterher hängen ;)
Immer aktuell (im Rahmen des technisch möglichen) und ohne überflüssige
Neuanzeigen würdest du mit der Lösung von Karl-Heinz (erste Antwort)
erreichen.
Der Vorschlag mit dem Delay war als Idee gedacht, falls eine leichte
Verzögerung ggf auch ausreicht, dann wäre das nämlich noch einfacher zu
implementieren gewesen.
> Das mit dem Delay habe ich schon versucht und das> flackert ebenfalls. Auch mit einem Delay von 100 ms
Entweder du hast das Delay nach dem Clear (dann hast du 100ms lang
nichts auf dem Display stehen -> flackert) oder du meinst das
Restflackern, welches bei einem Clear immer auftritt und sich nicht
vermeiden lässt, egal wie schnell das Display wieder neu beschrieben
wird. In letzterem Fall hilft dir auch wieder die erste Antwort von
Karl-Heinz: überschreibe den existierenden Inhalt nur.
ok ,
Ich danke schon mal für die Vielen hilfreichen Tipps.
Ich werde in den nächsten Zwei wochen im Urlaub nicht sonderlich oft
dazu kommen was auszuprobieren aber wenn doch bekommt Ihr natürlich
bescheid.
Danke schon mal
LG