Guten Abend, ich zerbreche mir im Moment meinen Kopf. Bin noch nicht sehr weit in der Materie des Programmierens eines Mikrocontrollers in GCC. Trotzdem versuche ich Momentan mit meinem ATMega32 an zwei LCD`s Werte auszugeben. Die Hardware steht soweit und seperat initialisieren klappt auch. Nur tue ich mich sehr schwer darin die LCD-Routine (lcd-pollin-jumper.h) so umzuschreiben, dass ich davon zwei in das Programm einbinden kann um die LCD`s nacheinander initialisieren zu können. Ich hatte also vor beispielsweise LCD1 mit LCD_Init() und LCD2 mit LCD_Init2() zu initialisieren. Ist diese Idee generell machbar? Oder kann mir einer zu etwas leichterem Raten? Ich hoffe mir kann einer weiterhelfen. Mit freundlichen Grüßen Carion
doch, das geht schon. Aber auch beim Schreiben musst du natürlich sagen, welches gerade gemeint ist. Falls du keine Angst vor C++ hast: ich habe hier irgendwann mal eine Version veröffentlicht, die ohne Änderungen mit mehreren LCDs umgehen kann.
Am einfachsten nimmst Du eine Routine für LCDs mit 2 Enable-Anschlüssen als Beispiel und paßt sie an. D.h. beide LCDs werden im Programm als ein LCD angesprochen, bloß mit doppelter Zeilenzahl. Peter
Daran hatte ich auch schon gedacht, Meinst du beispielsweise ein Routine für ein 4x20 Zeilen Display? Müsste ich dann die RS und RW auf eine Strippe legen oder kann ich das so lassen, dass diese jeweils einen eigenen Pin zugeordnet sind? Also momentan habe ich die RW, RS und E von LCD1 und LCD2 auf PortB Pin 0-6 Kennst du so eine Routine, die du mir empfehlen könntest? In C++ wollte ich eigentlich nicht arbeiten, da dass Programm zum größten Teil schon steht und es schon ca 3Jahre her ist dass ich letzte mal in C++ programmiert hatte.
Christian O. schrieb: > Meinst du beispielsweise ein Routine für ein 4x20 Zeilen Display? Müssten 4*40 (160 Zeichen) sein. Ich meine der HD-Controller kann 80 Zeichen. > Müsste ich dann die RS und RW auf eine Strippe legen oder kann ich das > so lassen, dass diese jeweils einen eigenen Pin zugeordnet sind? Natürlich lassen sich alle Pins bis auf EN übereinander legen, ist auch sinnvoll um Pins zu sparen.
Guten Abend Leute, ich habe mir jetzt ettliche Routinen angeguckt, aber die sind ja alle vom gleichen Autor. In der Routine kann man auch eintragen, wie viele Zeilen das Display hat, welches man verwendet. /** * @name Definitions for Display Size * Change these definitions to adapt setting to your display */ #define LCD_LINES 4 /**< number of visible lines of the display */ #define LCD_DISP_LENGTH 16 /**< visibles characters per line of the display */ #define LCD_LINE_LENGTH 0x40 /**< internal line length of the display */ #define LCD_START_LINE1 0x00 /**< DDRAM address of first char of line 1 */ #define LCD_START_LINE2 0x40 /**< DDRAM address of first char of line 2 */ #define LCD_START_LINE3 0x14 /**< DDRAM address of first char of line 3 */ #define LCD_START_LINE4 0x54 /**< DDRAM address of first char of line 4 */ #define LCD_WRAP_LINES 0 /**< 0: no wrap, 1: wrap at end of visibile line */ Hab irgendwie eine Denkblockade ... Ich benötige ja eine Routine, die zwei Enable eingänge hat. Ich kann in der Routine aber keine zwei Enables eintragen. #ifndef LCD_PORT #define LCD_PORT PORTC #endif #define LCD_DATA0_PORT PORTC /**< port for 4bit data bit 0 */ #define LCD_DATA1_PORT PORTC /**< port for 4bit data bit 1 */ #define LCD_DATA2_PORT PORTC /**< port for 4bit data bit 2 */ #define LCD_DATA3_PORT PORTC /**< port for 4bit data bit 3 */ #define LCD_DATA0_PIN 4 /**< pin for 4bit data bit 0 */ #define LCD_DATA1_PIN 5 /**< pin for 4bit data bit 1 */ #define LCD_DATA2_PIN 6 /**< pin for 4bit data bit 2 */ #define LCD_DATA3_PIN 7 /**< pin for 4bit data bit 3 */ #define LCD_RS_PORT PORTB /**< port for RS line */ #define LCD_RS_PIN 0 /**< pin for RS line */ #define LCD_RW_PORT PORTB /**< port for RW line */ #define LCD_RW_PIN 1 /**< pin for RW line */ #define LCD_E_PORT PORTB /**< port for Enable line */ #define LCD_E_PIN 2 /**< pin for Enable line */ Wie zum guckuck kann ich dann mit der Routine ein vierzeilen, bzw. zwei zweizeilen displays ansteuern
Ohhh Leute, was seit ihr kompliziert. Ich kann kein C und kein C++ aber wenn es sich um ein simples Display handelt sollte es doch wohl ausreichen den Enable PIn des Display über zwei verschiedene Pin des MC anzusteuern. Da muss der liebe Autor: Christian O. (carion) doch garnicht an der Software rumfummeln. Er Enabled Display-1 und macht Init dann enabled der Junge das Display 2 und initialisiert es. Wenn er nun noch einen simplen Transistor als Inverter einbaut benötigt er sonst garnix mehr. Ein einziger Portpin enabled das eine oder das andere Display. "If not High then low" Nach der INIT ist es doch sowieso gegessen. Dann schreibt man im Programm halt vor dem PRINT einfach einen befehl zusätzlich: LDC2 = false Print "hello World" oder eben LCD2 = true Print " Ich bin der 2te" Wo ist denn nun das Problem? Liegt es daran, dass Transistoren 3 Beine haben und das wiederum schlecht in Einklng zu bringen ist mit dem Leben. klaus de lisson
Nicht nur, daß du kein C und kein C++ kannst - du hast auch keine Ahnung, was das Enable macht. @Christian: lass dich nicht davon nicht verwirren, das hilft dir nicht weiter.
Hi Christian, vielleicht hab ich es übersehen. In welcher Programmiersprache willst du denn dein Programm schreiben. Assembler oder Basic (Bascom)? In Assembler ist das recht einfach. Im Grunde kannst du mehrere LCD's ansprechen. Wichtig ist hier tatsächlich das Enable Bit des angesprochenen LCD Displays. Es werden die entsprechenden Daten auf den Datenleitungen gelegt und mit dem Enable Bit (kurzer Impuls) in das gewünschte LCD eingelesen. Je nach dem welches LCD den Impuls bekommen hat werden die Daten auch dem entsprechenden LCD zugewiesen. Habe das bereits für einen Flugsimulator Autopiloten programmiert und das klappt tadellos. Schau dir hier einfach mal das Tutorial für Assembler an (LCD) dann wirst du das sicher verstehen. Gruß Frank
Dohle schrieb: > vielleicht hab ich es übersehen. Ja, ganz oben steht "gcc". Das ist dann wahrscheinlich nicht Assembler und nicht BASIC.
Hi Klaus, Hmmm.... mich irritierte der Satz von Christian : "In C++ wollte ich eigentlich nicht arbeiten, da dass Programm zum größten Teil schon steht und es schon ca 3Jahre her ist dass ich letzte mal in C++ programmiert hatte." Gruß Frank
Christian O. schrieb: > ich habe mir jetzt ettliche Routinen angeguckt, aber die sind ja alle > vom gleichen Autor. nein, nicht alle. Ich hatte dir oben schon mal einen Link zu der C++-Version gegegeben (der leider durch meinen Fehler nicht funktioniert hatte, das habe ich eben korrigiert). Damit kannst du ohne irgendwelche Fummeleien in Headerdateien sehr einfach mehrere LCD verwenden. Dafür muß man halt C++ nehmen, aber viel darüber wissen muß man dafür nicht. Dein restliches Programm darf C bleiben, macht ja nix. Beispiel für ein 4*20 und ein 2*16, die sich nur im Enable-Pin unterscheiden (B.5 bzw. B.6):
1 | #include "LCD44780.h" |
2 | ...
|
3 | AnyWare::LCD44780 lcd1( AnyWare::LCD44780::LCD_Type_4x20, |
4 | PORTB, 0, // Port, Pin LCD-DB4 |
5 | PORTB, 1, // Port, Pin LCD-DB5 |
6 | PORTB, 2, // Port, Pin LCD-DB6 |
7 | PORTB, 3, // Port, Pin LCD-DB7 |
8 | PORTB, 4, // Port, Pin LCD-RS |
9 | PORTB, 5 // Port, Pin LCD-Enable1 |
10 | );
|
11 | AnyWare::LCD44780 lcd2( AnyWare::LCD44780::LCD_Type_2x16, |
12 | PORTB, 0, // Port, Pin LCD-DB4 |
13 | PORTB, 1, // Port, Pin LCD-DB5 |
14 | PORTB, 2, // Port, Pin LCD-DB6 |
15 | PORTB, 3, // Port, Pin LCD-DB7 |
16 | PORTB, 4, // Port, Pin LCD-RS |
17 | PORTB, 6 // Port, Pin LCD-Enable1 |
18 | );
|
19 | |
20 | lcd1.printf( 0, 0, 20, "ich bin ein 4x20" ); |
21 | lcd2.printf( 0, 0, 16, "ich nur 2x16" ); |
22 | ...
|
Die Pinzuordnungen können praktisch beliebig gewählt werden soweit auf dem jeweiligen AVR möglich, die LCD-Typen können frei gemischt werden und die Verwendung ist ziemlich schlicht. Die gezeigte printf-Methode hat vorweg drei Parameter für x und y (ab 0 gezählt) und die maximale Ausgabelänge. Es gibt auch noch andere Ausgabefunktionen, siehe Headerdatei. Für ein 4*40 würde man noch zwei Parameter mehr beim Initialisieren angeben für den zweite Enable-Pin (Port und Bitnummer).
Dohle schrieb: > Hi Klaus, > > Hmmm.... mich irritierte der Satz von Christian : > > "In C++ wollte ich eigentlich nicht arbeiten, da dass Programm zum > größten Teil schon steht und es schon ca 3Jahre her ist dass ich letzte > mal in C++ programmiert hatte." > > Gruß Frank Dann würde ich mal darauf tippen, daß er in C arbeiten will. Dann soll er sich aber nicht daran stören, wenn die LCD-Ansteuerung in C++ gestrickt ist. Das muß er ja nicht verstehen sondern nur die Verwendung abkupfern und kann dann seinen ganzen restlichen Kram in C machen. Die Verwendung von C++-Libs ist ja sehr einfach, wesentlich einfacher als das Headergefummel in C.
Dieses C++ Programm hat allerdings den Nachteil, daß es die Codegröße verdoppelt. Es werden alle LCD-Funktionen doppelt angelegt. Nötig ist aber nur eine unterschiedliche Ansteuerung des E-Pins. Das kann man bequem über eine Variable enscheiden, die entsprechend der gewünschten Zeilennummer gesetzt wird.
1 | static uint8_t lcd_select; |
2 | |
3 | static void lcd_nibble( uint8_t d ) |
4 | {
|
5 | LCD_D4 = 0; if( d & 1<<4 ) LCD_D4 = 1; |
6 | LCD_D5 = 0; if( d & 1<<5 ) LCD_D5 = 1; |
7 | LCD_D6 = 0; if( d & 1<<6 ) LCD_D6 = 1; |
8 | LCD_D7 = 0; if( d & 1<<7 ) LCD_D7 = 1; |
9 | |
10 | if( lcd_select & 1<<0 ) |
11 | LCD_E0 = 1; |
12 | if( lcd_select & 1<<1 ) |
13 | LCD_E1 = 1; |
14 | _delay_us( 1 ); // 1us |
15 | LCD_E0 = 0; |
16 | LCD_E1 = 0; |
17 | }
|
Man kann das bis auf 8 LCDs erweitern, ohne das der Code 8-fach groß wird. Beim Init kann man lcd_select auf 0xFF setzen, damit alle LCDs zugleich initialisiert werden. http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=102296 Peter
Mhh ... Also ich schreibe in assambler, wollte damit auch weiter arbeiten. Bin da noch nicht so gut drin und weiß nicht, Wie ich da c++ einbauen soll. Kann ich nicht zwei gleiche Routinen in das Programm einbauen Und von einer Routine dann die Befehle Bsp.:printf und gotoxy mit einer 2 dahinter versehen und die dann im Programm so ansprechen?
Peter Dannegger schrieb: > Dieses C++ Programm hat allerdings den Nachteil, daß es die Codegröße > verdoppelt. Es werden alle LCD-Funktionen doppelt angelegt. Sicher?
Klaus Wachtler schrieb: > Sicher? Ist meine Vermutung, da ja alle Pins unterschiedlich definierbar sind und die Funktionen unterschiedlich heißen. Ich verstehe von C++ allerdings nur Bahnhof. Die Vermutung kann daher auch falsch sein. Peter
Es hat sich ja eh erledigt, weil er nach 2 Tagen verrät, daß er es in Assembler machen will. Trotzdem zur Info: Gegenüber deiner ursprünglichen Lösung braucht man natürlich etwas mehr Code, aber in erster Linie nur, weil die Pins vollkommen frei definierbar sind, und nicht auf demselben Port liegen müssen. Das hat aber mit C++ nichts zu tun. Abgesehen davon gibt es nicht mehrere Funktionen, die sich nur im Namen unterscheiden würden. lcd1 und lcd2 sind die Variablen, hinter denen sich die Konfiguration versteckt (Pinzuordnung, LCD-Typ, aktuelle Cursorposition etc.). Beide werden mit derselben Funktion bzw. Methode initialisiert, nämlich dem Konstruktor der Klasse LCD44780. Da unterscheiden sich nur jeweils die Parameter, aber nicht die Funktion. Je nachdem, wie kompliziert die Situation ist, werden die Funktionen eh inline eingebaut. Wenn man dieselbe Funktionalität (mehrere LCD unterschiedlichen Typs gleichzeitig möglich etc.) nutzt, erzeugt man in C oder Assembler auch entsprechend mehr Code. Nutzt man das dagegen alles nicht, hat der Compiler halt etwas mehr Spaß beim Optimieren.
Christian O. schrieb: > Kann ich nicht zwei gleiche Routinen in das Programm einbauen > Und von einer Routine dann die Befehle > Bsp.:printf und gotoxy mit einer 2 dahinter versehen und die dann im > Programm so ansprechen? Natürlich KANNST du. Wer sollte dich daran hindern? Die Frage ist aber eine andere: Wie sinnvoll ist es, 2 Funktionen gleichen Namens zu haben, die sich nur darin unterscheiden, dass letzten Endes ganz unten eine andere Funktion aufgerufen wird, die in dem einen Fall den (zb) PB3 Pin als Enable-Pin benutzt und im anderen Fall den (wieder beispielsweise) PD5. Genau dazu gibt es in C Funktionsargumente, damit man von aussen steuern kann, was genau eine Funktion tun soll. Und wenn man das nicht tun will, gibt es immer noch die Möglichkeit, die entsprechende Information über globale Variablen da quer einzubringen. Wie bei vielen anderen Dingen im Leben, hast du 2 Möglichkeiten: entweder du lässt deine Muskeln spielen und bereinigst die Situation durch Code-Duplizierung oder du benutzt deinen Verstand und strukturierst deinen Code so, dass er mit mehreren Displays gleichen Typs umgehen kann.
@ Peter Dannegger, Das was du da geschrieben hast scheint plausibel, Kann ich denn den Code als Routine verwenden und das Lcd_select Bit in dem normalen Programm setzen oder geht das dann nur in der Routine oder muss ich alles ins Programm schreiben? Tut mir leid für die ganzen unwissenden Fragen, aber ich Brauch da irgendwie gerade etwas länger um den roten Faden zu finden und ich bedanke mich für eure Geduld
Christian O. schrieb: > Kann ich denn den Code als Routine verwenden und das > Lcd_select Bit in dem normalen Programm setzen oder geht das dann nur in > der Routine oder muss ich alles ins Programm schreiben? Du kannst es so machen wie du das willst: Vor Aufruf einer Ausgabefunktion ein LCD durch Anwählen mit dem Lcd_select auswählen, oder eigene Funktion für beide LCD schreiben, die Lcd_select richtig stellen und dann in die gemeinsamen Ausgabefunktionen verzweigen. So wie es DIR angenehm ist. MÜSSEN tust du gar nichts. Du bist der 'Erfinder' und du machst das (im Rahmen der Möglichkeiten der Programmiersprache) so, wie du es für richtig befindest und was du programmieren kannst. Letzten Endes geht es nur darum, dass in der hierarchiemässig untersten Funktion, der Funktion die ein Nibble ausgibt, die Information bereit steht. Wie sie das macht - du entscheidest das.
Klaus Wachtler schrieb: > Nutzt man das dagegen alles nicht, hat der Compiler halt etwas mehr Spaß > beim Optimieren. Interessant wäre, kann er sowas überhaupt optimieren? Sich eine zusätzliche Hilfsvariable für den Unterschied zu nehmen, kann bestimmt nur ein Mensch. Der AVR-GCC macht auf mich nicht den Eindruck, als daß er besonders clever optimiert. Er moved gerne mal Register unnötig hin und her. Er optimiert einigermaßen brauchbar, aber nicht gut. Peter
Guten Abend nochmal, ich habe es geschafft ^^ Nach langem hin und her habe ich eine passende Routine gefunden, die 2 Enable-Eingänge hat. Ich habe dann noch die DB0-3,RW und RS vom LCD1 aufs LCD2 gebrückt und dann lief es. Also laufen meine beiden 2x16LCD`s nun theoretisch als ein 4x20LCD und das auch noch ganz gut ^^ Ich musste noch in die Routine den Befehl lcd_printf (um meine Fließkommazahlen ausgeben zu können) einbauen und jetzt steht dem weiteren programmieren des µC nichts mehr im weg. Ich bedanke mich für die ganzen Ratschläge und Hilfestellungen, auch wenn Ihr es schwer hattet mir diese zu erklären, geschweige denn schmackhaft zu machen :) Für alle die das gleiche Problem haben, ich habe die Routine winket2704.h verwendet einen schönen Abend noch allen und viel Spaß beim programmieren, ich werde ihn zumindest wieder haben ^^
Wenn ich den angezeigten Spannungswert im Display so sehe, kommt ja direkt meine eigene Kuriosität und Hochspannungs-Affinität durch... Da kann ich einfach nicht anders als zu fragen: Was ist das denn für ein Apparat, der mit 178.49kV läuft? Und wo kommen die her, wie sind sie stabilisiert (dreistellige Kilovolts mit zwei Nachkommastellen - Oida!) wie misst Du sie und wozu sind sie überhaupt da?! ...viele Fragen, aber wenn ich solche Spannungwerte lese siegt bei mir ganz schnell die Neugierde und ich habe direkt Ozongeruch in der Nase ;) Grüße Sascha
Die Werte sind im Moment noch unumgerechnet, ginge lediglich erstmal darum Werte auf beiden Displays auszugeben und diese in Fließkommazahlen darzustellen. Das ganze soll später mal ein Transformatoren Monitoringsystem werden und im idealfall unter anderem die Werte zwischen 9-11kV oder zwischen 110-123kV anzeigen. Der bekommt seine Werte später von einer SPS (Ja ich weiß, ginge auch direkt auf den Mikrocontroller, aber das soll noch weiterentwickelbar sein) und diese bekommt die Werte umgewandelt von einem Simeas. Aber das wird die nächsten Tage erst noch alles programmiert, die Displays waren zu hartnäckig und wollten einfach nicht so wie ich.
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.