Hallo Liebe Leute!
Wer meinen Thread über das ansteuern des Schieberegister-LCDs gelesen
hat, weiß nun, was ich vorhabe.
Das Ansteuern hat dank euerer Hilfe super geklappt!
Nun möchte ich folgendermaßen fortfahren:
Ich möchte mit 3 Lichtschranken die Zeit messen, in der ein Wagen die
Lichtschranken durchfährt. Taster-1 soll dann auf dem Display die
verstrichene Zeit der ersten Lichtschranke, Taster-2...usw. auf dem
Display darstellen.
Ich habe es nun mit den Arrays gemacht, wie ihr vorgeschlagen habt. Ich
habe jetzt lauter Funktionen geschrieben, jede Funktion für eine Zahl in
einem Segment. Das es in Summe 4 x 7-Segment sind, und jeweils eine Zahl
von 0-9, habe ich so viele Funktionen geschrieben.
Geht das "hochzählen von Zahlen" auch einfacher? mit meiner bisherigen
variante muss ich ja für jede einzelne Zahl die "zahl"-Funktion aufrufen
und ich noch jede Menge funktionen für die einzelnen Bitkombinationen
schreiben
Vielen Dank!
Das klingt jetzt allerdings als hättest du eine enorme
Fleissaufgabe gemacht.
Zeig doch mal, das kann man mit Sicherheit auch in ein
paar Zeilen Code samt einer Tabelle abhandeln.
Johannes wrote:
> Ich habe es nun mit den Arrays gemacht, wie ihr vorgeschlagen habt.
Welches denn, Bits oder Bytes ?
> Ich> habe jetzt lauter Funktionen geschrieben, jede Funktion für eine Zahl in> einem Segment. Das es in Summe 4 x 7-Segment sind, und jeweils eine Zahl> von 0-9, habe ich so viele Funktionen geschrieben.
Ich dachte, Du weißt bereits, was ein Array ist.
Dann mach einfach ein Array aus 10 Bytes mit den 7-Segment-Mustern.
Ich nehme mal an, daß die 48 Bits = 6 * 7-Segment sind.
Dann nimmst Du jede Ziffer als Arrayindex und schreibst den Arraywert in
das Array mit den 6 Ausgabebytes.
> Geht das "hochzählen von Zahlen" auch einfacher?
Gerechnet wird C-intern immer Binär (8, 16 oder 32Bit breit).
Peter
johannes wrote:
> die 48 bits sind nicht (!) für 6 7-segment-anzeigen. Es sind in Summe> 4x7-Segment-Anzeigen plus Sonderzeichen (ph-Wert,°C,+,-,.....)
Ist auch kein Beinbruch.
Du solltest erstmal die komplette Segmentzuordnung rauskriegen.
Wenn eine Ziffer nicht in nur einem Byte liegt, muß man sie eben auf die
2 Byte aufteilen (schieben + maskieren).
Peter
ABER: wie kann ich dann aus den 48 Bits, 7 Bits herausnehmnen und diese
dann einzeln hochzählen lassen, sofern die 7 Bits so angeordnet sind,
dass sie wie Dualsystem-mäßig stehen.
danke
bei mir siehts so aus:
array[48] = {0,0,0,0,0,1.......} // Da steht momentan noch jeweils das
Bitmuster für jede einzelne zahl.
Jedes Array-Muster habe ich in eine Funktion gefasst:
bspl:
segment-1_zahl8();
Aber ich möchte C in dem Array-Muster hochzählen lassen. (Davon
ausgegangen, dass die letzten 7 Bits von den 48 für das letzte 7-Segment
steht)
Danke!
@johannes
>ABER: wie kann ich dann aus den 48 Bits, 7 Bits herausnehmnen und diese>dann einzeln hochzählen lassen, sofern die 7 Bits so angeordnet sind,>dass sie wie Dualsystem-mäßig stehen.
1.) Du musst dich DRINGEND mit den Grundlagen von Zahlendarstellungen
befassen!
2.) Du musst dich DRINGEND mit den Grundlagen von Zahlendarstellungen
befassen!
3.) Du musst dich DRINGEND mit den Grundlagen von Zahlendarstellungen
befassen!
4.) Du musst dich DRINGEND mit den Grundlagen von Zahlendarstellungen
befassen!
5.) Du musst dich DRINGEND mit den Grundlagen von Zahlendarstellungen
befassen!
.
.
.
99.) Du musst unterscheiden zwischen normalen variablen zur Speicherung
von Zählerständen, Messwerten etc. und Speichern zur Speicherung von
7-Segmentmustern.
Mit deinen Variablen für Zählerstände kan man ganz normal rechnen, in
jeder Programiersprache. Dann braucht du eine Funktion, die diese Zahl
in das 7-Segmentmuser umrechnet.
MfG
Falk
johannes wrote:
> bei mir siehts so aus:>> array[48] = {0,0,0,0,0,1.......} // Da steht momentan noch jeweils das>> Bitmuster für jede einzelne zahl.
Genau das habe ich natürlich kommen sehen, als ich sagte:
> Ich halte es im Gegenteil für komplizierter, die 48 Bits als monolitisch> verschweißten Block zu betrachten. Spätestens, wenn er dann die> einzelnen Ziffern drauf aufteilen will, wirds haarig.
Du must Dir die Antworten natürlich auch durchlesen:
Beitrag "Re: Schieberegister-LCD vereinfachen"> Aber ich möchte C in dem Array-Muster hochzählen lassen.
Das ist viel zu aufwendig. In C zählt man:
ja und was soll ich jetzt tun???
Könntet ihr mir einen Code-schnipsel zukommen lassen?
Soll ich nun die Funktionen für jede einzelne Zahl, die ich gestern
geschreieben habe, verwenden?!
zum Thema, "Thread anschauen",
wie ihr wisst, bin ich blutiger Anfänger in Sachen Mikrocontroller UND
C, darum lohnt es dann auch nicht die Threads anzuschauen, wenn es um
Makros geht und mir nicht mal mitgeteilt wird, was das überhaupt ist.
Somit waren die threads für mich auch keine Hilfe, denn, was bringt es
mir, den code herauszukopieren, und nicht zu verstehen?!
johannes wrote:
> zum Thema, "Thread anschauen",>> wie ihr wisst, bin ich blutiger Anfänger in Sachen Mikrocontroller UND> C, darum lohnt es dann auch nicht die Threads anzuschauen, wenn es um> Makros geht und mir nicht mal mitgeteilt wird, was das überhaupt ist.
Der Link, auf den ich verwies, hat gar keine Macros.
Hier nochmal der Linkinhalt direkt:
=======================================================================
Johannes wrote:
> Ich kann natürlich eine Funktion schreiben, in der ich> für jede einzelne Zahl auf dem Display von 1-1000 jeweils 48 Bitmuster> schreibe.
Sag bloß, Du hast in der Schule alle Zahlen 0...1000 auswendig gelernt.
Ich hab nur die Ziffern 0..9 gelernt und genau so macht man es eben in
der CPU:
- Zahl in Ziffern zerlegen
- Bitmuster pro Ziffer aus Tabelle lesen
- alle Bitmuster in die 6 Bytes reinschreiben
- die 6 Bytes rausschieben.
=======================================================================
Peter
johannes wrote:
> Makros geht und mir nicht mal mitgeteilt wird, was das überhaupt ist.
Dann mußt Du es lernen, C ohne Macros geht nicht.
Vielleicht soltest Du doch erstmal C aufm PC lernen.
Hier z.B. der Hilfetext aus Borland C++ zu Macros:
=======================================================================
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
#define (Anweisung)
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
Definiert ein Makro.
Syntax: #define <Bez1>[( <Bez2>, ... )] <Bezeichnerstring>
Makros stellen einen Mechanismus zum Ersetzen von Symbolen bereit, mit
oder
ohne funktionsähnlichen Parametern. Alle folgenden Vorkommen von <Bez1>
im
Quelltext werden durch den in <Bezeichnerstring> angegebenen Text
ersetzt.
Wenn unmittelbar auf <Bez1> eine runde Klammer folgt, behandelt der
Präprozessor folgende Bezeichner (<Bez2> usw.) nicht als Teil des
Bezeichnerstrings, sondern als Parameter einer Funktion.
Alle Vorkommen von <Bez2> im Bezeichnerstring werden durch den jeweils
dafür
definierten Text ersetzt, wenn <Bez1> im Quelltext referenziert ist.
Das Zeichen \ dient als »Zeilenverlängerung«.
Beispiel
▀▀▀▀▀▀▀▀
#define MAXINT 32767
#define ctrl(x) ((x) \
- 64) /* Fortsetzung der vorhergehenden Zeile */
Es ist legal, aber nicht sehr günstig Schlüsselwörter von Borland C++
als
Makrobezeichner zu verwenden. Beispielsweise ist
#define int long
legal, aber höchstwahrscheinlich katastrophal.
Die folgenden globalen Bezeichner dürfen nicht unmittelbar nach einer
#define- oder #undef-Anweisung angegeben werden:
_DATE__ __FILE__ __LINE__STDC__ __TIME_
Siehe auch:
#undef
#if
Symbole verbinden
========================================================================
=
Peter
@Peter Dannegger
>Dann mußt Du es lernen, C ohne Macros geht nicht.
Naja, am Anfang braucht man sie ne ganze Weile nicht. DIDAKTIK!
Du übberrennst einen blutigen Anfänger mit viel zu viel Details die er
im Moment nicht mal ansatzweise einordnen kann.
>Vielleicht soltest Du doch erstmal C aufm PC lernen.
Das kann man nur doppelt unterstreichen!!
Besorg die ein C-Buch, Kernighham & Ritchy oder so.
Lies es!
Mach ALLE Übungen im Buch!
Mach ein paar mehr Übungen!
Dann bist du bereit für LCDs und mehr. Im Moment fehlen die ELEMENTARE
Grundlagen!
MFG
Falk
Falk wrote:
> @Peter Dannegger>>>Dann mußt Du es lernen, C ohne Macros geht nicht.>> Naja, am Anfang braucht man sie ne ganze Weile nicht. DIDAKTIK!
Brauchen tut man sie, sobald man etwas includiert.
Es mag einem vielleicht nicht bewußt sein, aber Includes strotzen nur so
vor Macros.
Und es schadet auch nichts, zu wisssen, daß Includes lesbarer Quelltext
sind.
Z.B. wenn man mal nicht weiß, wie eine Funktion genau heißt und welche
Parameter sie benötigt, schaut man eben im Include nach.
Peter
@Peter Dannegger
>Brauchen tut man sie, sobald man etwas includiert.>Es mag einem vielleicht nicht bewußt sein, aber Includes strotzen nur so>vor Macros.
Schon klar, aber . . .
>>Und es schadet auch nichts, zu wisssen, daß Includes lesbarer Quelltext
sind.
>Z.B. wenn man mal nicht weiß, wie eine Funktion genau heißt und welche>Parameter sie benötigt, schaut man eben im Include nach.
Alles richtig, aber ich wiederhole mich. Der OP muss sich erstmal die
elmentaren Grundlagen erarbeiten und ist im Moment mit Macros (vor allem
in deiner umfassenden Darstellung) hoffnungslos überfordert!
Daran sieht man mal wieder, dass Grundschullehrer auch ein Knochenjob
ist!
MFG
Falk
Hallo Johannes,
Du musst 3 Sachen unterscheiden:
* Zahlen
* Ziffern
Eine Ziffer kann Werte zwischen "0" und "9" haben, sie ist der Wert
EINER Stelle in einer Zahl.
* Graphische Darstellung von Ziffern auf Deinem LCD
Wahrscheinlich werden die Ziffern auf Deinem LCD NICHT im Binärformat
angezeigt, sondern als eine (sehr einfache) graphische Darstellung.
Jedes Bit schaltet ein Segment an. Um eine Ziffer darzustellen, musst
Du das graphische Muster dieser Ziffer auf das LCD ausgeben.
Da ich Dein Display nicht kenne, ein Beispiel: Im Display seien die
Segmente so angeordnet:
00000
1 2
1 2
1 2
33333
4 5
4 5
4 5
66666 7
Um eine "1" auf Dein LCD zu "malen", musst Du die Segmente 2 und 5
einschalten.
Um eine "0" zu malen, die Segmente 0, 1, 2, 4, 5 und 6.
Wie Du siehst, hat das Ganze nichts mit einer Binärdarstellung zu tun!
Um Ziffern darzustellen, solltest Du nicht für jede Ziffer eine eigene
Funktion schreiben, sondern eine einzige Funktion, die als Parameter den
Wert der Ziffer bekommt und diese auf das LCD ausgibt:
void male_ziffer_auf_lcd(uint8_t ziffer){
...
}
Du solltest also so vorgehen:
* Funktion schreiben, um eine Ziffer auf dem LCD auszugeben
* Funktion so erweitern, dass eine Ziffer an alle 4 Positionen des LCD
geschrieben werden kann.
* Erst wenn Du an alle 4 Positionen des LCD Ziffern schreiben kannst,
kannst Du die Ausgabe Deiner Zahl angehen.
* Wenn Du weitere Hilfe brauchst, solltest Du posten, welches Display Du
verwendest und wie die einzelnen LCD-Segmente darin angeordnet sind.
Viele Grüße, Stefan
@Peter, Falk
Ich gehe mit Peter konform, dass eine Bit-Array Lösung
besser wäre. Allerdings sehe ich auch, dass Johannes damit
völlig überfordert wäre. Die Byte-Array Lösung hat einen
grossen Vorteil: Es sieht so aus als ob er sie verstehen würde.
Daher mach ich dort weiter.
@Johannes
> bei mir siehts so aus:>> array[48] = {0,0,0,0,0,1.......} // Da steht momentan noch> // jeweils das Bitmuster> // für jede einzelne zahl.>> Jedes Array-Muster habe ich in eine Funktion gefasst:> bspl:>> segment-1_zahl8();
Das war unnötig.
Mach dir eine Tabelle, in der für jede einzelne Ziffer,
das Muster enthalten ist.
uint8_t Digit[10][7] = {
{ 1, 0, 0, 1, 0, 1, 1 }, // Bitmuster für 0
{ 0, 1, 0, 1, 0, 1, 1 }, // Muster für 1
{ 0, 1, 0, 1, 1, 0, 0 }, // Muster für 2
....
{ 1, 1, 0, 0, 1, 1, 0 } // Muster für 9
};
Die 0-en und 1-en hab ich jetzt zufällig eingesetzt, da musst
du natürlich deine konkreten Werte einsetzen.
Soweit so gut.
Angenommen, da hast jetzt eine einzelne Ziffer (keine Zahl!)
und du willst diese Ziffer an einer bestimmten Stelle in deiner
Anzeige stehen haben. Dann musst du doch das jeweilge Muster
für diese Ziffer, welches du aus der Tabelle erhältst, in
dein 48-er Array an eine bestimmte Stelle schreiben.
Ich geh mal davon aus, dass das 48-Array so organisiert ist, das
ab Array Position 0 die erste Stelle beginnt, ab Array Position 7
die zweite Stelle, ab 14 die dritte Stelle, etc. Wenn das
bei dir nicht so ist, dann musst du etwas anpassen.
Gesucht ist also eine Funktion, die eine Ziffer übernimmt und
der man sagt an welcher Display-Position diese Ziffer aufscheinen
soll:
void PutZiffer( uint8_t Ziffer, utin8_t Wo )
{
Das Bitmuster welches in die Anzeige geschrieben werden muss,
erhält man ganz leicht: Dafür ist die Tabelle Digit zuständig.
Alles was du tun musst, ist mit Ziffer als Index in dieses
Array zu gehen und die Indexpositionen 0 bis 7 sagen dir dann
ob eine 0 oder eine 1 in das 48-er Array muss. Nur an welche
Stelle vom 48-er Array muss diese 0 oder 1? Das kann man sich
ausrechnen. Wir wissen ja, dass für jede Ziffer genau 7 Einträge
benötigt werden, also beginnt die n-te Ziffer an der Array-
Position n * 7. Und wir wissen natürlich auch, dass für
jede Ziffer genau 7 Einträge zu setzen sind.
In Summe ist das dann:
void PutZiffer( uint8_t Ziffer, utin8_t Wo )
{
uint8_t i;
for( i = 0; i < 7; ++i )
array[ Wo * 7 + i ] = Digit[ Ziffer][ i ];
}
Fertig. Um also die Zahl 0175 an die Display Stellen
3 4 5 und 6 zu schreiben, genügt es folgendes aufzurufen:
PutZiffer( 0, 3 );
PutZiffer( 1, 4 );
PutZiffer( 7, 5 );
PutZiffer( 5, 6 );
Jeder PutZiffer Aufruf schreibt das jeweilige korrekte 'Bitmuster'
für die übergebene Ziffer in das 48-er Array und zwar an
die jeweils richtige Position, sodass beim Raustakten die
0 oder 1 an der richtigen Stelle zu liegen kommt.
array ist übrigens ein denkbar schlechter Name für diese
Variable. Variablennamen werden nach der Funktion der Variable
gewählt, nicht nach dem Datentyp. Die Funktion dieser Variablen
ist es nicht Array zu sein, sondern als Zwischenspeicher für das
Hinaustakten der Bits zu dienen. 'BitBuffer' wäre in der
Tat ein wesentlich besserer Name dafür, da er beschreibt, wozu
diese Variable benutzt wird.
Soweit, so gut.
Du hast aber nicht einzelne Ziffern, sondern du hast eine
Zahl, die du darstellen möchtest. Die Frage ist daher,
wie man eine Zahl in einzelne Ziffern zerlegt.
Das geht ganz einfach mittels Division durch 10 und
entsprechende Restbildung.
7492 % 10 -> 2
7492 / 10 -> 749
749 % 10 -> 9
749 / 10 -> 74
74 % 10 -> 4
74 / 10 -> 7
7 % 10 -> 7
7 / 10 -> 0
Wenn du dir die rechte Spalte ansiehst, dann tauchen,
in umgekehrter Reihenfolge, die einzelnen Ziffern der
Zahl auf. Die Zahl war 7492. Die Ziffer sind 2 9 4 7
Um eine 4 stellige Zahl also in einzelne Ziffern zu
zerlegen und diese Ziffern in die Anzeige übertragen zu
lassen, kannst du eine Funktion machen:
void PutZahl( uint16_t Zahl, uint8_t Wo )
{
uint8_t Ziffer;
Ziffer = Zahl % 10;
PutZiffer( Ziffer, Wo + 3 );
Zahl = Zahl / 10;
Ziffer = Zahl % 10;
PutZiffer( Ziffer, Wo + 2 );
Zahl = Zahl / 10;
Ziffer = Zahl % 10;
PutZiffer( Ziffer, Wo + 1 );
Zahl = Zahl / 10;
Ziffer = Zahl % 10;
PutZiffer( Ziffer, Wo + 0 );
Zahl = Zahl / 10;
}
und jetzt hast du alles beisammen um zb. sowas
machen zu können:
int main()
{
uint16_t Zaehler = 0;
for( Zaehler = 0; Zahler < 2000; Zaehler += 5 ) {
PutZahl( Zaehler, 0 );
Das_48_Array_ausgeben();
}
}
Zaehler ist eine ganz normale int-Variable, mit der du rechnen
kannst, wie du lustig bist. Die Funktion PutZahl übernimmt
diese Zahl, zerlegt sie in die einzelnen Ziffern und benutzt
jeweils die Funktion PutZiffer um jede Ziffer an die korrekte
Position ausgeben zu lassen. Die Funktion PutZiffer wiederrum
erledigt die Umsetzung jeder einzelnen Ziffer in das entsprechende
Muster, welches in das 48-er Array an die jeweilig korrekte
Position geschrieben werden muss.
Falk hat recht: du solltest dir wirklich etwas Literatur
besorgen und vorab auf dem PC ein paar Übungen durchführen.
Arbeiten mit Arrays ist absolutes Grundlagenwissen.
Vielen Dank Stefan!
So lobe ich mir das :)
Also über das Display kann ich dir im Moment wiegesagt keine Auskunft
geben, selbst wenn ich dir eine gebe, wirst du schwer ein Datenblatt
herbekommen, dann geht es dir so wie mir vor einigen monaten eins
aufzutreiben ;-)
Das mit dem Display verstehe ich ja alles. Wie ich das Ansteuere und so
ist mir klar. Ich habe nur eben schon Funktionen geschrieben für
gemalte-Zahlen im Display von 0-6. das heißt, es sind 7 Funktionen, die
jeweils eine Array mit 48 Feldern beinhaltet, je Funktion eben ein
anderes Bitmuster in der Array. Anders wüsste ich eben nicht, wie ich
die Zahlen sonst nacheinander darstellen könnte.
Ich habe mir jedoch gerade was ausgedacht, weiß aber nicht ob das
funktionieren wird. Habe nämlich auch hier gerade nicht die Möglichkeit,
es auszuprobieren. und zwar.
Wenn ich jetzt meine bisherigen Arrays behalte:
int male_zahl-X(void) !!!An der Stelle von X eine Variable
Zahl!!
{
Array[48] = {0,0,0,0,0,1,0,1........} //Bitmuster für "9" im Display
}
Verstehst du? Dass ich eben die einzelnen darzustellenden Zahlen mit
einer Variablen im Funktionskopf anspreche. Will ich beispielsweise eine
"3" darstellen, so schreibe ich eine 3 an die Stelle von "X" und in
diese Funktion dann meine Array mit dem Bitmuster von "3".
Kann ich DIESE Idee von mir mit dem Vorschlag von Dir (Stefan) umsetzen?
Vielen dank !
ok,
ich werde es jetzt erstmal so machen, dass ich die Arrays für die
Darstellung der Ziffernstelle und die Array der Ziffer am display
erstelle.
Dafür kann ich ja dann die Arrays von meinen bisher angefertigten
Funktionen für die einzelnen Zahlen (Bitmuster) verwenden.
johannes wrote:
> aber würde es denn auch so mit meinem Vorschlag gehen, den ich vorher> geschrieben habe?! dieses X müsste wohl in die (klammern)
Selbst wenn das syntaktisch gehen würde (was es nicht tut):
Dann landest du wieder unnötigerweise bei einem
Haufen Funktionen.
>soo...habe jetzt mal nach dem Schema gearbeitet. Es tritt aber noch ein>Compilier-Fehler auf. Wo ist der ???
Die Frage stellen wir uns auch.
Normalerweise sagt der Compiler Dir, was nicht stimmt. Wenn Du das nicht
verstehst, solltest Du wenigstens die Fehlermeldung posten.
Stefan
> uint8_t Digit[10][7] => {>> {0,0,0,0,0,0,0,0,0,0,0,0,> 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,1},
//0
Wie bitte soll den der Compiler diese Zahlenwust in
7 Stück uint8_t unterbringen?
Du brauchst nur 7 Stück für das Muster für 1 Digit.
Vergiss doch mal die 48. Die 48 hast du erst dann
wenn alles zusammengestellt ist und fertig zum raustakten
auf das Schieberegister.
Wie soll das den funktionieren?
array kann keine lokale Variable sein. Du brauchst mehrere
PutZiffer Aufrufe um die komplette Zeile zusammenzusetzen.
Ergo muss das Array in dem alles zusammenkommt den Aufruf
von PutZiffer überleben. Ergo muss dieses Array eine
globale Variable sein.
ok sorry, wegen Prototypen am Anfang ....Habe ich vergessen einzufügen
^^
Was mir jetzt noch fehlt ist ein clock während die einzelnen Bits
reingeschoben werden.
danke
@johannes
Poste bitte deinen gesamten Quelltext (als ASCII im Anhang), dann kann
man dir auch gescheit helfen. Diese schlecht kopierten Fragmente sind
schlecht. Ebenso solltest du die Fehlermeldungen direkt und komplett
kopieren (CTRL-C CTRL-V).
MFG
Falk
@Gast:
Wenn Du mit Falk Probleme hast, dann trag das bitte in dem Thread aus,
in dem Deine Probleme begonnen haben.
Unter "Gast" so einen Müll zu posten ist peinlich und feige.
Stefan
@Gast
>Sehe ich ein, Entschuldigung; auch an Falk :)
Angenommen. Zumal ein Oberst wohl kaum "bitte" sagen würde. ;-)
MfG
Falk
P.S. Mein militärischer Rang ist WEIT über einem Oberst. ABGÄNGER!
Minus 4000++
;-)
So wird das nichts.
Fangen wir nochmal ganz am Anfang an.
Du hast also eine Anzeige die über ein
Schieberegister angeschlossen wird.
Das Schieberegister verfügt über 45 Stellen.
Angeschlossen ist das Schieberegister am Port B
und zwar so:
PORTB
Bit 0 Daten
Bit 1 Clock
Um ein Datenbit in das Schieberegister zu übernehmen,
wird der Dateneingang je nachdem mit einer 0 oder einer
1 belegt und danach ein Clock-Impuls erzeugt. Ein Clock
Impuls bedeutet: Die Clockleitung geht auf 1 und danach
wieder auf 0.
Stimmt das soweit? Welches Schieberegister ist das überhaupt
(IC Nummer). Hat das einen Latch Eingang?
Die 45 Stellen im Schieberegister, wie sind die belegt?
0 ... 7 Digit 1, Segmente a - g ( 0 ist a, 1 ist b, etc
8 Dezimalpunkt für Digit 1
9 .. 16 Digit 2, Segmente a - g ( 9 ist a, 10 ist b, etc
17 Dezimalpunkt für Digit 2
18 .. 25 Digit 3, Segmente a - g ( 18 ist a, 19 ist b, etc
26 Dezimalpunkt für Digit 3
27 .. 34 Digit 4, Segmente a - g ( 27 ist a, 28 ist b, etc
35 Dezimalpunkt für Digit 4
36 .. 45 andere Anzeigen, bzw. Led
Jedes einzelne Digit hat folgende Zuordnung
d
*********
c e
b
*********
a f
g
*********
Eine LED leuchtet auf, wenn der entsprechende Ausgang auf 1
gezogen wird.
Korregier für mich erstmal diese Anschlussbelegung, damit
wir mit konkreten Dingen arbeiten können.
ja, das stimmt soweit...
Nein es hat keinen Latch-Eingang; IC: M5219B
Belegung:
a
xxxxxxx
f x x b
x g x
xxxxxxx
x x
e x x c
xxxxxxx
d
Segmente:
4.Seg. 3.Seg ............................
xxxxxxx xxxxxxx
f x x b x x
x g x x x
xxxxxxx xxxxxxx
x x x x
e x x c x x
xxxxxxx xxxxxxx
wofür die einzelnen Bits stehen:
0...17. Bit interessiert nicht, das sind sonderzeichen auf dem Display
(ph-Wert, °C, +,-,....)
18.Bit - 4e
19.Bit - 4g
20.Bit - 4f
21.Bit - 4a
22.Bit - 4b
23.Bit - 4c
24.Bit - 4d
---
25.Bit - 3e
26.Bit - 3g
usw. wie oben, nur segment3, und das gleiche für Segment2 und 1
danke
Mal nachzählen:
0 bis 17 uninteressant
18 bis 24 Segment 4
25 bis 31 Segment 3
32 bis 38 Segment 2
39 bis 45 Segment 1
Das ( 0 bis 45 ) sind aber 46 Leitungen, nicht 45!
OK, nachdem jetzt die Hardware soweit geklärt ist:
fangen wir an.
Der erste Schritt ist mal irgendwas auf die Anzeigen zu
kriegen. Dazu bauen wir uns mal das Array auf und sehen
zu, dass dieses korrekt auf das Schieberegister rausgetaktet
wird.
1
#include<avr/io.h>
2
3
// a
4
// xxxxxxx
5
// f x x b
6
// x g x
7
// xxxxxxx
8
// x x
9
// e x x c
10
// xxxxxxx
11
// d
12
13
#define LEITUNGEN 46
14
15
#define DATEN 0x01
16
#define CLOCK 0x02
17
18
uint8_tSchiebe[LEITUNGEN]=
19
{0,0,0,0,0,0,0,0,0,// 0 bis 9: uninteressant
20
0,0,0,0,0,0,0,0,0,// 10 bis 17: uninteressant
21
0,0,0,0,0,0,0,// 4: e, g, f, a, b, c, d
22
0,0,0,0,0,0,0,// 3: e, g, f, a, b, c, d
23
0,0,0,0,0,0,0,// 2: e, g, f, a, b, c, d
24
0,0,0,0,0,0,0// 1: e, g, f, a, b, c, d
25
};
26
27
voidAusgeben()
28
{
29
uint8_ti;
30
31
for(i=0;i<LEITUNGEN;++i){
32
//
33
// Die Datenleitung korrekt setzen
34
//
35
if(Schiebe[LEITUNGEN-i-1]==0)
36
PORTB&=~DATEN;// Die Datenleitung zum SR auf 0
37
else
38
PORTB|=DATEN;// Die Datenleitung zum SR auf 1
39
40
//
41
// und einen Clock Puls nachschicken
42
PORTB|=CLOCK;
43
PORTB&=~CLOCK;
44
}
45
}
46
47
intmain()
48
{
49
DDRB=DATEN|CLOCK;// Daten und Clockpin vom PORT auf
50
// Ausgang setzen
51
52
Ausgeben();
53
54
while(1)
55
;
56
}
Das sollte mal alle Anzeigen löschen. Nichts darf leuchten.
Es geht nur darum, mal ein Anfangsprogramm zu haben. Wenn
du einen Messpark hast, müsstest du eigentlich am Clock
Ausgang die 46 Impulse sehen, die jeweils eine 0 durch
das Schieberegister treiben.
(Ich habe keinen gcc Compiler hier, kann hier also
nicht compilieren. D.h. es ist durchaus
moeglich, dass ich da einen oder zwei Syntaxfehler eingebaut
habe. Wenn dem so ist, dann sag mir Bescheid)
Jetzt wollen wir mal an den Anzeigen was sehen. Und zwar
wollen wir an der Anzeige 2 eine '0' anzeigen.
Dazu muessen laut Tabelle:
a
xxxxxxx
f x x b
x g x
xxxxxxx
x x
e x x c
xxxxxxx
d
die LEDs a, b, c, d, e und f auf 1 gesetzt werden.
Dies entspricht einem Schieberegister Array:
uint8_t Schiebe[LEITUNGEN] =
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 bis 9: uninteressant
0, 0, 0, 0, 0, 0, 0, 0, 0, // 10 bis 17: uninteressant
0, 0, 0, 0, 0, 0, 0, // 4: e, g, f, a, b, c, d
0, 0, 0, 0, 0, 0, 0, // 3: e, g, f, a, b, c, d
1, 0, 1, 1, 1, 1, 1, // 2: e, g, f, a, b, c, d
0, 0, 0, 0, 0, 0, 0 // 1: e, g, f, a, b, c, d
};
ändere das mal so um und lass das Programm laufen.
Ist die '0' an der Anzeige sichtbar?
(Das ist der erste Schritt. Getestet wird damit
* ob die Zuordnung der Arraypositionen zu den Hardwarepins
stimmt
* ob das Raustakten funktioniert
Prüfe das mal.
Eine Frage hab ich noch:
Wenn du sagst: 0.Bit
ist das dann das Bit am Eingang des Schieberegisters oder
am anderen Ende.
Daten
|
|
v
+--+--+--+--+--+--+--+--+--+- -+--+--+--+
| | | | | | | | | | | | | |
+--+--+--+--+--+--+--+--+--+- -+--+--+--+
^ ^
| |
Ist das hier das Bit 0 |
|
|
oder ist das hier das Bit 0
Ich bin jetzt mal davon ausgegangen, dass das Bit 0
an dem Ende liegt an dem die Daten eingespeist werden.
Daher auch:
1
if(Schiebe[LEITUNGEN-i-1]==0)
weil ja zuerst das am weitesten rechts liegende Bit
in das SR eingespeist werden muss, damit es nach
46 Clock-Takten ganz rechts zu liegen kommt.
Weshalb machst Du das alles per Hand, wenn es entsprechende ICs zur
Ansteuerung von LCD-Displays gibt ? Gerade als Anfänger solltest Du
nicht vom hundersten ins tausendste gehen, sondern Dich auf das
wesentliche konzentrieren.
P.S.: Es fehlt offensichtlich ein Artikel über BCD-Code ;-)
Matthias wrote:
> Weshalb machst Du das alles per Hand, wenn es entsprechende ICs zur> Ansteuerung von LCD-Displays gibt ?
Da kommt dann sowies noch ein dicker Hund auf ihn zu.
Ich sag nur: Gleichspannungsfreie Ansteuerung.
Im Moment hab ich noch keine Idee wie ich ihm das
naeher bringen werde.
:-)
Aber zur Übung wie man mit einem Scheiberegister umgeht
und ein bischen Programmierübung ist es schon ganz
brauchbar. So wie es aussieht kann er beides gut gebrauchen.
Karl heinz Buchegger wrote:
> Matthias wrote:>> Weshalb machst Du das alles per Hand, wenn es entsprechende ICs zur>> Ansteuerung von LCD-Displays gibt ?>> Da kommt dann sowies noch ein dicker Hund auf ihn zu.> Ich sag nur: Gleichspannungsfreie Ansteuerung.> Im Moment hab ich noch keine Idee wie ich ihm das> naeher bringen werde.
Das nehm ich wieder zurück:
Der 5219 ist ein kompletter LCD Ansteuerbaustein.
PS: Der hat sehr wohl einen Latch Eingang. Beim 5219
heist der "Load".
Johannes: Was hast du mit diesem Eingang gemacht?
Der muss auch angesteuert werden.
Ich geh mal davon aus, dass der ebenfalls am PORTB hängt
und zwar am Pin PB2
1
...
2
3
#define DATEN ( 1 << PB0 )
4
#define CLOCK ( 1 << PB1 )
5
#define LOAD ( 1 << PB2 )
6
7
...
8
9
voidAusgeben()
10
{
11
uint8_ti;
12
13
for(i=0;i<LEITUNGEN;++i){
14
//
15
// Die Datenleitung korrekt setzen
16
//
17
if(Schiebe[LEITUNGEN-i-1]==0)
18
PORTB&=~DATEN;// Die Datenleitung zum SR auf 0
19
else
20
PORTB|=DATEN;// Die Datenleitung zum SR auf 1
21
22
//
23
// und einen Clock Puls nachschicken
24
//
25
PORTB|=CLOCK;
26
PORTB&=~CLOCK;
27
}
28
29
//
30
// nachdem alles uebertragen wurde, einen Load Puls nach-
31
// schicken, damit die Werte auf die Anzeige uebernommen
32
// werden
33
//
34
PORTB|=LOAD;
35
PORTB&=~LOAD;
36
}
37
38
...
39
40
intmain()
41
{
42
DDRB=DATEN|CLOCK|LOAD;// Daten, Clock und Latchpin vom
@Johannes
Was ist los?
Mitlerweile musst du das doch am Laufen haben oder
sagen können das es nicht geht, bzw. was nicht geht.
Ich steh schon in den Startlöchern für den nächsten Schritt.
@Karl heinz Buchegger
>Ich steh schon in den Startlöchern für den nächsten Schritt.
Du hast den Beruf verfehlt. Hättest Lehrer werden sollen. ;-)
MFG
Falk
hallo!
sorry, dass ich nicht da war, mein Vater ist schwer krank und ich muss
ständig ins Krankenhaus fahren....
Vielen Dank für euere Antworten.
@karl-heinz:
Den Load-Eingang habe ich bisher mit PORTB = 0b00000100 angesteuert. Er
hängt also am PortB an Pin3. Der muss auf "1" geschaltet werden, wenn
alle Bits ins Schieberegister geschoben wurden, damit der Inhalt des
Schieberegisters auf das Display gemalt wird.
Wäre es denn nicht mit einem anderen Display (mit einem Hitachi
44780-Driver-Chip) einfacher? Weil bevor ich jetzt die Kirche ins Dorf
trage, kaufe ich mir lieber um 3 Euro ein anderes Display, das ohnehin
mehr "kann" als mein 7-Segment-Display.
Ich möchte schließlich auch nicht, dass ihr euch jetzt reinstresst wegen
mir ;-) Umso mehr freue ich mich natürlich, wie gut ihr mir helft, denn
, wie du schon sagtest, Programmierübung und Umgang mit µC kann ich gut
gebrauchen
Vielen dank
johannes wrote:
> Den Load-Eingang habe ich bisher mit PORTB = 0b00000100 angesteuert. Er> hängt also am PortB an Pin3.
OK.
Also genau so wie ich es angenommen habe.
(Noch was: Gewöhn dir an dass wir bei 0 anfangen zu zählen.
0b00000100 ist Pin 2, nicht Pin 3: 0, 1, 2
> Der muss auf "1" geschaltet werden, wenn> alle Bits ins Schieberegister geschoben wurden, damit der Inhalt des> Schieberegisters auf das Display gemalt wird.
Ganz genau.
Die Codeerweiterung, die ich zuletzt gemacht habe, macht genau das.
>> Wäre es denn nicht mit einem anderen Display (mit einem Hitachi> 44780-Driver-Chip) einfacher?
Von der Softwareseite her ist es auch nicht unbedingt
einfacher. AUch für so ein LCD muss man erst mal eine
Ansteuerung programmieren. Die ist, grade im Bereich der
Initialisierung, sogar etwas aufwändiger.
Allerdings ist so ein LCD dann universeller, da man auch
Zeichen damit anzeigen kann und vor allem: Es passt wesentlich
mehr aufs Display.
> Weil bevor ich jetzt die Kirche ins Dorf> trage, kaufe ich mir lieber um 3 Euro ein anderes Display, das ohnehin> mehr "kann" als mein 7-Segment-Display.> Ich möchte schließlich auch nicht, dass ihr euch jetzt reinstresst wegen> mir ;-)
Von 'reinstressen' kann keine Rede sein.
Ich halte es ja immer noch für einen Fehler 48 Bytes statt 48 Bits zu
nehmen.
Vielleicht sollte man erst mal lernen, daß ein Byte aus 8 Bits besteht
und wie man die Bits eines Bytes anspricht (AND, OR, Schieben).
Z.B. mit 8 Tasten und 8 LEDs (STK500).
Grundlagenwissen sollte man nicht überspringen.
Peter
Peter Dannegger wrote:
> Ich halte es ja immer noch für einen Fehler 48 Bytes statt 48 Bits zu> nehmen.>> Vielleicht sollte man erst mal lernen, daß ein Byte aus 8 Bits besteht> und wie man die Bits eines Bytes anspricht (AND, OR, Schieben).>> Z.B. mit 8 Tasten und 8 LEDs (STK500).>> Grundlagenwissen sollte man nicht überspringen.
Ich geb dir grundsätzlich recht.
Allerdings kommen dann auf Johannes einige Lektionen
in Bitpfriemelei zu. Und da steh ich eher auf dem Standpunkt:
eines nach dem anderen. Er hat so schon Schwierigkeiten, da jag
ich ihn nicht da auch noch hinein. 7 Bits in einem Array von
6 Bytes an eine beliebige Stelle einsetzen, ist nicht so ohne
wenn man gerade frisch angefangen hat. Er braucht ja auch ein
paar schnelle Erfolgserlebnisse :-)
Erst bringen wirs mal zum Laufen, dann optimieren wir den
Speicherverbrauch. Ob das jetzt 48 Bytes oder 48 Bits sind,
spielt ja ausserhalb dieser paar Funktionen keine grosse
Rolle (vom Speicherverbrauch mal abgesehen), das ist also
auch im Nachhinein, wenn er erst mal ein bischen Sicherheit
hat, noch austauschbar.
Peter. Nichts gegen dich. Ich hab im Bereich µC-Programmierung
viel von dir gelernt. Aber du tendierst dazu einem Neuling
zu komplexe Dinge in einem Rutsch an den Kopf zu werfen, weil
du ihm natürlich die elegantesten und sparsamsten Funktionen
zeigen willst. Nur: Einem Neuling ist damit selten geholfen.
Der hat (noch) ganz andere Probleme als ein paar Byte hier
und da, ein paar Zyklen hier und da einzusparen. Für Neulinge
sind if und for noch geheimnisvoll, von einem halbwegs
vernünftigen Programmaufbau mit sinnvollen Funktionen mal
gar nicht geredet. Überspitzt ausgedrückt gibst du gerne Tips
wie man an einen New York Marathon herangeht, wenn der Neuling
sich grade mal von allen Vieren erhoben und noch wackelig auf
2 Beinen steht.
Karl heinz Buchegger wrote:
> Überspitzt ausgedrückt gibst du gerne Tips> wie man an einen New York Marathon herangeht, wenn der Neuling> sich grade mal von allen Vieren erhoben und noch wackelig auf> 2 Beinen steht.
Ganz so eng würde ich es nicht sehen
Ob Top-down oder Bottom-up beides kann zielführend sein.
Und ich bin eben mehr für Bottom-up.
Peter
@Peter Dannegger
>Ob Top-down oder Bottom-up beides kann zielführend sein.
Ja.
>Und ich bin eben mehr für Bottom-up.
Aber deine Schrittweite ist zu gross. Du rennst immer mit
Siebenmeilenstiefeln.
;-)
MFG
Falk
ich finde es echt große klasse was der Karl hier macht! dickes lob an
dieser stelle!
pumpkin
p.s.: ich will mich zwar nicht einmischen, aber vllt ist es doch besser
wenn du ihn gleich an das "bit-gefriemel" ranlässt; imho sollte man
gleich an die unterschiedlichen zahlensysteme rangeführt werden weil man
damit eher ein 'feeling' für die digitaltechnik bekommt. : )