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
die 48 bits sind nicht (!) für 6 7-segment-anzeigen. Es sind in Summe 4x7-Segment-Anzeigen plus Sonderzeichen (ph-Wert,°C,+,-,.....)
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:
1 | i++; |
und nicht anders. Peter
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 !
sorry Karl-Heinz, habe gerade erst deinen Thread gelesen. Danke für die Mühe!
johannes wrote: > sorry Karl-Heinz, habe gerade erst deinen Thread gelesen. > > Danke für die Mühe! Ich hoffe es hilft dir weiter.
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.
aber würde es denn auch so mit meinem Vorschlag gehen, den ich vorher geschrieben habe?! dieses X müsste wohl in die (klammern)
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 ??? Danke! #include <avr/io.h> int main (void) { DDRB=0xFF; PutZiffer(4, 1); PORTB = 0b00000100; //Load-Bit } //---------------------------------------------------------------------- ------------------------ 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 {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,0,0,0,0,1,1,0}, //1 {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,1,0,1,1,0,1}, //2 {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,0,0,1,1,1,1,1}, //3 {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,0,1,1,0,1,1,0}, //4 {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,0,1,1,1,0,1,0}, //5 {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,1,1,1,0,1,1}, //6 {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,0,0,0,1,1,1,0}, //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}, //8 {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,0,0,1,1,1,1,1} //9 }; int PutZiffer(uint8_t Ziffer, uint8_t Wo) { uint8_t i; int array[45]; for (i=0;i<7;i++) { array[Wo * 7+i] = Digit [Ziffer][i]; } }
>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.
1 | int PutZiffer(uint8_t Ziffer, uint8_t Wo) |
2 | {
|
3 | uint8_t i; |
4 | |
5 | int array[45]; |
6 | |
7 | for (i=0;i<7;i++) |
8 | {
|
9 | array[Wo * 7+i] = Digit [Ziffer][i]; |
10 | }
|
11 | }
|
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.
Fehlermeldung : -array undeclared -conflicting types for "PutZiffer" -previous implicit declaration of "PutZiffer" was here danke
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++
;-)
Hallo Leute! Hier mein Code: Es gibt keine compilier-Fehler mehr. Wie kann ich nun ansteuern? #include <avr/io.h> int PutZiffer(uint8_t Ziffer, uint8_t Wo); void clock(void); int main (void) { DDRB=0xFF; PutZiffer(4, 1); clock(); PutZiffer(3, 2); PutZiffer(2, 2); PutZiffer(1, 1); PORTB = 0b00000100; //Load-Bit } //---------------------------------------------------------------------- ------------------------ /*int Dsplshow(void) { int i; int Array[45]; for (i=0;i<45;i++) { PORTB = PORTB & Array[i]; PORTB = 0b00000010 | Array[i]; PORTB = 0b00000010; PORTB = 0b00000000; } } */ uint8_t Digit[10][7] = { {1,0,1,1,1,1,1}, //0 {0,0,0,0,1,1,0}, //1 {1,1,0,1,1,0,1}, //2 {0,0,1,1,1,1,1}, //3 {0,1,1,0,1,1,0}, //4 {0,1,1,1,0,1,0}, //5 {1,1,1,1,0,1,1}, //6 {0,0,0,1,1,1,0}, //7 {1,0,1,1,1,1,1}, //8 {0,0,1,1,1,1,1} //9 }; int array[45]; int PutZiffer(uint8_t Ziffer, uint8_t Wo) { uint8_t i; for (i=0;i<7;i++) { array[Wo * 7+i] = Digit [Ziffer][i]; } } void clock(void) { PORTB = 0b00000010|Digit; PORTB = 0b00000010; } Danke
Edit: Das ist das, was ich im moment habe: Am display werden schon manchmal zeichen angezeigt: #include <avr/io.h> int PutZiffer(uint8_t Ziffer, uint8_t Wo); void clock(void); int main (void) { DDRB=0xFF; PutZiffer(4, 1); clock(); PutZiffer(3, 2); PutZiffer(2, 2); PutZiffer(1, 1); PORTB = 0b00000100; //Load-Bit } //---------------------------------------------------------------------- ------------------------ /*int Dsplshow(void) { int i; int Array[45]; for (i=0;i<45;i++) { PORTB = PORTB & Array[i]; PORTB = 0b00000010 | Array[i]; PORTB = 0b00000010; PORTB = 0b00000000; } } */ uint8_t Digit[10][7] = { {1,0,1,1,1,1,1}, //0 {0,0,0,0,1,1,0}, //1 {1,1,0,1,1,0,1}, //2 {0,0,1,1,1,1,1}, //3 {0,1,1,0,1,1,0}, //4 {0,1,1,1,0,1,0}, //5 {1,1,1,1,0,1,1}, //6 {0,0,0,1,1,1,0}, //7 {1,0,1,1,1,1,1}, //8 {0,0,1,1,1,1,1} //9 }; int array[7]; int PutZiffer(uint8_t Ziffer, uint8_t Wo) { uint8_t i; for (i=0;i<7;i++) { array[Wo * 7+i] = Digit [Ziffer][i]; } } void clock(void) { PORTB = 0b00000010; }
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_t Schiebe[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 | void Ausgeben() |
28 | {
|
29 | uint8_t i; |
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 | int main() |
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 | void Ausgeben() |
10 | {
|
11 | uint8_t i; |
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 | int main() |
41 | {
|
42 | DDRB = DATEN | CLOCK | LOAD; // Daten, Clock und Latchpin vom |
43 | // PORT auf Ausgang setzen
|
@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. : )
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.