Forum: Mikrocontroller und Digitale Elektronik LCD DEM16217


von Christian K. (christiankarle)


Lesenswert?

Guten Abend liebe Community,

ich habe ein kleines Verständnisproblem...

Vor 3 Tagen habe ich mir das LCD DEM16217 gekauft, ich verstehe nur 
leider nicht welche Schritte zur Initialisierung nötig sind und in 
welcher Reihenfolge diese abgearbeitet werden müssen. Ziel ist der 8-Bit 
Modus.

Programmierkenntnisse in C sind vorhanden.
Als Mikrocontroller setze ich den ATmega8515 ein.

Vielen Dank für Euere Hilfe im Voraus,

Christian :)

P.s: Dies ist mein erste Versuch mit einem LCD, also bitte seid etwas 
nachsichtig mit mir:)
Das Tutorial hier im Forum zum Thema LCD habe ich bereits 
durchgearbeitet.

von Jay W. (jayway)


Lesenswert?

In dem verlinkten PDF sind die entsprechenden Sequenzen gut zu erkennen.

http://www.gaw.ru/pdf/lcd/lcm/Display/char/DEM16217SYH-PY.PDF

von Christian K. (christiankarle)


Lesenswert?

Danke, dieses Datenblatt ist um einiges übersichtlicher, als das 
Datenblatt, dass ich hatte.

von Christian K. (christiankarle)


Lesenswert?

Noch eine Frage: Wenn ich ein Byte an das Display übertrage, muss währen 
der Übertragungszeit das LCD auf Write "stehen" und sobald die Pegel am 
LCD stimmen der EN-Pin auf H gesetzt werden. Theoretisch sollte doch 
dann ein Buchstabe auf dem LCD angezeigt werden. Wie kann ich dem LCD 
aber mitteilen, an welcher Stelle, der Buchstabe erscheinen soll?

von Christian K. (christiankarle)


Lesenswert?

Schiebt das LCD die Daten immer automatisch ein Feld weiter?

von Karl H. (kbuchegg)


Lesenswert?

Christian Karle schrieb:
> Schiebt das LCD die Daten immer automatisch ein Feld weiter?

Ja.
Ein derartiges LCD hat ein Konzept ähnlich einem Cursor, der angibt, wo 
das nächste Zeichen hinkommt und der nach der Ausgabe eines Zeichens um 
1 Stelle weitergestellt wird.

Ich denke, du hast die Datenblätter und/oder Tutorien und deren Code 
studiert?

Wenn du das LCD erst mal initialisiert hast, ist der wichtigste 
Abschnitt im oben verlinkten Datenblatt das Kapitel 9, in dem alle 
Kommandos beschrieben sind, die das LCD versteht. 'Den Cursor an eine 
bestimmte Position setzen' heißt dort 'Set DDRAM Address'. Das ist aber 
eigentlich auch schon die einzige Falle in den Kommandos, die man ev. 
nicht gleich versteht.

: Bearbeitet durch User
von Christian K. (christiankarle)


Lesenswert?

Dankeschön, jetzt ist denke ich alles klar :)

von Cyblord -. (cyblord)


Lesenswert?

Christian Karle schrieb:
> Dankeschön, jetzt ist denke ich alles klar :)

Wart erst mal ab bis der erste sinnvolle Text auf dem Display ist.

von picaxe (Gast)


Lesenswert?

Miese Peter ;-)

von Cyblord -. (cyblord)


Lesenswert?

picaxe schrieb:
> Miese Peter ;-)

Ein Pessimist ist nur ein Optimist mit Erfahrung. Wenig beschäftigt 
Anfänger mehr, als ein vermeintlich popeliges "Standard-LCD" Display.

von Christian K. (christiankarle)


Lesenswert?

:D

von loeti2 (Gast)


Lesenswert?

Ein Anfänger wäre aber mit einem controllerlosen LCD komplett 
überfordert,
also seid froh das ihr nur die Cursoradresse setzen müßt ;-)

von Christian K. (christiankarle)


Angehängte Dateien:

Lesenswert?

So...

Ich habe gerade die Zeit gefunden die Initialisierung zu schreiben.
Ich habe sie mit Absicht extrem ausführlich geschrieben und wollte euch 
nun fragen, ob diese Initialisierung so funktionieren wird.

Vielen Dank im Voraus,

Christian :)

von Christian K. (christiankarle)


Lesenswert?

P.s: Der PortA des µC ist der 8-Bit Datenbus für das Display.

     An PortE befinden sich die Steuerleitungen für das Display.

von Christian Karle (Gast)


Lesenswert?

Kann mir niemand helfen?

von Karl H. (kbuchegg)


Lesenswert?

Christian Karle schrieb:
> So...
>
> Ich habe gerade die Zeit gefunden die Initialisierung zu schreiben.
> Ich habe sie mit Absicht extrem ausführlich geschrieben und wollte euch
> nun fragen, ob diese Initialisierung so funktionieren wird.

Viellicht, vielleicht auch nicht.
Teil der Initialisierung ist auch, dass du dich an Timings halten musst, 
die von dieser Seite des Bilschirms nur schlecht zu kontrollieren sind.

Was aber auf jeden Fall in deinem Code ziemlicher Mist ist, das ist, 
dass du zb hier
1
  DDRA  |=   ( ( 1 << PA0 ) | ( 1 << PA1 ) | ( 1 << PA2 ) | ( 1 << PA3 ) | ( 1 << PA4 ) | ( 1 << PA5 ) | ( 1 << PA6 ) | ( 1 << PA7 ) );
2
  // PORTA als Ausgang.
3
  DDRE  |=   ( ( 1 << PE0 ) | ( 1 << PE1 ) | ( 1 << PE2 ) );

die Pinnummern direkt reingeschrieben hast.

Logisch, es ist schon klar, dass es in letzter Konsequenz darauf hinaus 
läuft, dass irgendwelche Pins an irgendeinem Port wie hier auf Ausgang 
geschaltet werden müssen, oder das Pins toggeln müssen.
Aber: Auch wenn es letzten Endes auf bestimmte Prozessorpins hinaus 
läuft, so ist die viel wichtigere Information die, welche Bedeutung 
dieser µC-Pin aus Sicht des LCD hat. Das heißt als Programmierer ist für 
dich wesentlich wichtiger, dass die den E-Anschluss vom LCD toggelst und 
nicht, dass die E-Leitung mit dem Pin PE1 am Port E verbunden ist. 
Letzteres ist ein technisches Detail, dass man beim Lesen und Verstehen 
des Codes nicht wissen muss.
D.h wenn du das so schreibst
1
#define LCD_CONTROL_PORT  PORTE
2
#define LCD_CONTROL_DDR   DDRE
3
#define LCD_RS            PE0
4
#define LCD_RW            PE1
5
#define LCD_E             PE2
6
7
....
8
9
10
   LCD_CONTROL_DDR |= ( 1 << LCD_RS ) | ( 1 << LCD_RW ) | ( 1 << LCD_E );
11
...

dann hat das eine ganz andere Codequalität. Jetzt steht im Code selber 
unmissverständlich und eindeutig, dass hier die Leitungen auf Ausgang 
gestellt werden, an denen die RS, RW und E Leitung vom LCD hängt. Das 
ist die viel wesentlichere Information, als die Information, dass die am 
Port E an irgendwelchen Pins hängen. Letzters ist ein notwendiges 
technisches Übel, aber im Grunde insofern uninteresant, als es auch 
jeder andere Port und jeder andere Pin an diesem Port sein könnte.
1
  _delay_ms(50);
2
  // Wait for more than 50 ms after VDD  rises to 4.5V.
3
  
4
  PORTA |=   ( ( 1 << PA3 ) | ( 1 << PA4 ) | ( 1 << PA5 ) );
5
  // 2-line mode; 5 x 7 dots.
6
  
7
  _delay_ms(1);
8
  // Wait for more than 1 ms.
9
  
10
  PORTA &= ~ ( ( 1 << PA0 ) | ( 1 << PA1 ) | ( 1 << PA2 ) | ( 1 << PA3 ) | ( 1 << PA4 ) | ( 1 << PA5 ) | ( 1 << PA6 ) | ( 1 << PA7 ) );
11
  // Alle Pins an PORTA auf Low setzen.
12
  PORTA |=   ( ( 1 << PA0 ) | ( 1 << PA1 ) | ( 1 << PA2 ) | ( 1 << PA3 ) );
13
  // Display on; Cursor on; Blink on.

nein.
Du hast eines noch nicht verstanden.
Die Reihenfolge ist: zuerst stellst du alle Daten und Steuerleitungen 
auf den Pegel den du brauchst. Sind die alle eingestellt, dann wird der 
E-Pin vom LCD einmal hoch gezogen und wieder auf 0 zurückgestellt.
Das lCD kann ja nicht wissen, wann du mit der Einstellung der Daten und 
der beiden Steuerleitungen fertig bist. Es muss also einen eindeutigen 
Zustand, ein eindeutiges Kennzeichen geben, an dem man dem LCD mitteilt: 
Jetzt gilt es - das was jetzt eingestellt ist, das ist dein nächstes 
Kommando.
Die E-Leitung erfüllt genau diesen Zweck.

Es ist wie die Befehlausgabe bei der Bundesweer. Alle stehen um den 
Befehlshaber rum. Der gibt seine Orders aus, revidiert die vielleicht 
noch ein paar mal, irgendjemand macht einen Einwand, dann drehen sich 
ein paar Details noch mal um. Aber irgendwann kommt der Ausspruch: 
"Alles fertig - durchführen!". Und erst dann legen alle los.
Hier genau das gleiche. Du kannst an den Datenleitungen umstellen so oft 
und so viel du willst, du kannst RS setzen oder löschen, du kannst RW 
umstellen, so oft und so viel du lustig bist. Erst wenn der Puls an der 
E-Leitung kommt - dann gilt die dann vorliegende Einstellung. Davor und 
danach ist alles uninteressant. Da kannst du die Dtaenleitungen auch im 
halbe Stunde Abstand nacheinander auf die richtigen Pegel bringen. Das 
interessiert das LCD nicht die Bohne. Aber wenn der E-Puls kommt, dann 
muss alles richtig eingestellt sein. Das ist dein 'Alles fertig - 
durchführen!'

In deinem Code sehe ich nicht, dass du mal an E toggeln würdest. Teil 
des Problems ist natürlich auch, dass du hier keine Abstaktionsebene (im 
obigen Sinne) eingebaut hast, sondern alles mit direkten 
Portbezeichnungen versehen hast. Und das ist nun mal unklug, weil man 
die wesentliche Information im Code nicht sieht. Die wesentliche 
Information ist nicht, dass am Port E der Pin PE2 auf 1 und wieder auf 0 
geht. Die wesentliche Information ist, dass das die E-Leitung vom LCD 
ist. Das will ich im Code sehen.

Ich sehe auch in deinem Code nicht, dass du dich um den Rest kümmern 
würdest.
Du du sowieso 8 Bit Ausgabe machen willst, brauchst du auch die 
eigentliche Ausgabe jedesmal aufs neue auskodieren. Du kannst dir ein 
für alle mal genau EINE Funktion schreiben, die einen bestimmten Wert an 
das LCD ausgibt. D.h. deine Init-Funktin wird vielleicht am Anfang an 
den Portbits ein wenig rumpfriemeln um den 8 Bit Modus sicher zu 
stellenb. Aber danach: Ob du das LCD löschen willst, oder einen anderen 
Font einstellst: immer läuft es darauf hinaus, einen 8 Bit Wert auf das 
LCD auszugeben. D.h. das lässt sich wunderbar trennen. Auf der einen 
Seite gibt es eine Funktion, die einen (beliebigen) WErt als Kommando an 
das LCD ausgibt, auf der anderen Seite ist die Init-Sequenz, die 
mithilfe genau dieser Funktion die Initialisierung durchführt, indem es 
die entsprechenden Kommandos zusammenstellt und mit Hilfe dieser 
Funktion an das LCD absetzt. Die Funktion kümmert sich also um die 
'Transportebene' und die logisch etwas höher angesiedelte Funktionalität 
teilt der Funktion mit, was sie zu transportieren hat.

Hast du denn keinen anderen LCD Code studiert, wie der aufgebaut ist? 
Man kann viel lernen, wenn man anderer Leute Code (allerdings sollten es 
schon die richtigen Leute sein) im Detail studiert. So Dinge wie 
Coding-Strategie lernt man so ganz gut. Vor allen Dingen am Anfang, wenn 
man selber noch wenig Erfahrung hat, wie man Code in Schichten aufbaut 
und sinnvoll in Baugruppen unterteilt.

Und nein: Code 3 mal von der Ferne überfliegen und 'schön' sagen, hat 
nichts mit Codestudium zu tun.
Und eines ist auch klar: Das alles setzt vorraus, das man mit seinem 
Werkzeug - der Programmiersprache - umgehen kann. Wer die Arbeiten eines 
Michelangelo studiert weil er Bildhauer werden will, und sich von ihm 
Details abschauen will, wie er bestimmte Dinge gemacht hat, von dem wird 
vorausgesetzt, dass er mit Hammer und Meissel umgehen kann. Wer gerade 
mal ein Ölbild anfertigen kann, wenn er in vorgefertigte Flächen auf der 
Leinwand nach einem Nummernschema Farben reinmalt, der muss erst mal aus 
dieser Malen nach Zahlen Phase rauskommen, ehe es Sinn macht, sich mit 
der Pinselführung eines Rembrandt zu beschäftigen.

: Bearbeitet durch User
von Christian K. (christiankarle)


Lesenswert?

Vielen Dank, ich werde den Code, sobald ich Zeit finde, in dieser 
Hinsicht verbessern. :)

Daumen hoch, für die tolle Antwort :)

von Christian K. (christiankarle)


Angehängte Dateien:

Lesenswert?

Neuer (überarbeiteter) Code:

Das Display hat sich auf den 2-line mode umgestellt und ein Cursor 
blinkt in der 1.Zeile links auf.

Ist das Display somit richtig Initialisiert und kann ich auf dieser 
Initialisierung weiter aufbauen?

Ich werde den Code natürlich noch kompakter schreiben.

LG Christian :)

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Christian Karle schrieb:
> Neuer (überarbeiteter) Code:
>
> Das Display hat sich auf den 2-line mode umgestellt und ein Cursor
> blinkt in der 1.Zeile links auf.
>
> Ist das Display somit richtig Initialisiert und kann ich auf dieser
> Initialisierung weiter aufbauen?

Sobald der defaultmässige dunkle Balken verschwindet, IST dein LCD 
sauber initialisiert.

> Ich werde den Code natürlich noch kompakter schreiben.

Tip: machs es doch gleich richtig. Du sparst dir eine Menge Arbeit und 
eine Menge Ärger.

Eine Funktion
1
void LCD_command( uint8_t Command )
2
{
3
  LCD_DATA_PORT = command;
4
5
  LCD_CONTROL_PORT |=    ( ( 1 << LCD_EN ) );
6
  _delay_ms(1);
7
  LCD_CONTROL_PORT &= ~ ( ( 1 << LCD_EN ) );
8
}
ist keine Hexerei, die dann in der Init benutzt wird
1
#define LCD_FUNCTION_SET     ( 1 << DB5 )
2
#define LCD_DISPLAY_CONTROL  ( 1 << DB3 )
3
#define LCD_ENTRY_MODE       ( 1 << DB2 )
4
5
#define LCD_8_BIT            ( 1 << DB4 )
6
#define LCD_2_LINES          ( 1 << DB3 )
7
#define LCD_1_LINE           0
8
#define LCD_FONT_5_11        ( 1 << DB2 )
9
#define LCD_FONT_5_8         0
10
#define LCD_CURSOR_INCREMENT 0
11
#define LCD_CURSOR_DECREMENT ( 1 << DB1 )
12
#define LCD_NO_SHIFT         0
13
#define LCD_SHIFT            ( 1 << DB0 )
14
15
16
void LCD_init()
17
{
18
  LCD_DATA_DDR = 0xFF;
19
  LCD_CONTROL_DDR  |=   ( ( 1 << LCD_EN ) | ( 1 << LCD_RS ) | ( 1 << LCD_RW )  );
20
21
  LCD_DATA_PORT = 0x00;
22
  LCD_CONTROL_PORT &= ~ ( ( 1 << LCD_EN ) | ( 1 << LCD_RS ) | ( 1 << LCD_RW ) );
23
24
  _delay_ms(50);
25
26
  LCD_command( LCD_FUNCTION_SET | LCD_8_BIT | LCD_2_LINES | LCD_FONT_5_8 );
27
  LCD_command( LCD_DISPLAY_CONTROL | LCD_ON | LCD_CURSOR_ON | LCD_CURSOR_POS_ON );
28
  LCD_command( LCD_ENTRY_MODE | LCD_CURSOR_INCREMENT | LCD_NO_SHIFT );
29
30
  LCD_clear();
31
}

(das einzige was man jetztr ankreiden könnte, das ist dass die Datenbits 
in aufsteigender Folge am Datenport angeordnet sein müssen. Mag sein, 
ist aber kein wirklicher Beinbruch, den wer das anders macht gehört 
sowieso mit dem nassen Fetzen erschlagen. Es ist allerdings auch nicht 
schwierig, in der Funktion LCD_command eine entsprechende Umsortierung 
noch nachzurüsten. Das Löschen und Setzen von einzelnen Bits kannst du 
dir allerdings in deinem Code sparen, denn auch in deinem Code müssen 
alle 8 Datenpins an ein und demselben Port angeschlossen sein. D.h. wenn 
diese Annahme nicht mehr hält, dann ist dein Code genauso im Arsch wie 
wenn du einfach das Byte an den Port ausgibst. So ein Fall würde so und 
so massive Codeänderungen nach sich ziehen)

So hat der Code doch gleich eine ganz andere Codequalität. Lies dir die 
Init Funktion durch. Da brauchst du kein Datenblatt um aus dem Code 
heruas zu verstehen was in welcher Reihenfolge wie initialisiert wird. 
Das steht alles sonnenklar und schon fast im Klartext dort.
Da braucht es auch keine Kommentare, weil alles wesentliche sowieso im 
Code selber steht. Deine Kommentare kannst du hingegen in der Pfeife 
rauchen. Wer bei
1
LCD_CONTROL_PORT |=    ( ( 1 << LCD_EN ) );
einen Kommentar
1
  // Enable auf High.
braucht, um zu sehen, dass hier ein Pin auf High gestellt wird, der soll 
sich sein C-Lehrgeld wiedergeben lassen - er hat offensichtlich seine 
Programmiersprache nicht gelernt. Wenn in einem Kommentar dasselbe wie 
im Code steht (nur in anderen Worten), dann ist das ein sinnloser 
Kommmentar. Er erzählt mir nichts neues. Das ein _delay_ms(5) eine 
Wartezeit von (mindestens) 5 Millisekunden realisiert, dazu brauch ich 
keinen Kommentar. Der wird höchstens falsch, wenn sich am Zahlenwert mal 
was ändert und vergessen wird, den Kommentar nachzuziehen
1
   _delay_ms( 10 );
2
   // Wait for more then 35 ms
was stimmt denn nun? Sind die 10ms richtig und ist der Kommentar falsch. 
Oder ist der Kommentar richtig und die 10 im Code stimmen nicht?
Lass so einen Kommentar weg. Das hier gewartet wird, sehe ich im Code 
genauso gut und auch dass es 10ms sind. Da bringt der Kommentar keine 
neuen Erkenntnisse.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

PS: Dafür vermisse ich in deinem Code die Behandlung des RS Bits.

Das ist jetzt noch kein Beinbruch, solange du keine Texte ausgibst. Aber 
irgendwann wird es soweit sein.
Daher: Besser jetzt gleich behandeln.
Mit einer 'command' Funktion ist das ja auch kein Problem
1
void LCD_command( uint8_t Command )
2
{
3
  LCD_CONTROL_PORT &= ~( 1 << LCD_RS );
4
5
  LCD_DATA_PORT = command;
6
7
  LCD_CONTROL_PORT |=    ( ( 1 << LCD_EN ) );
8
  _delay_ms(1);
9
  LCD_CONTROL_PORT &= ~ ( ( 1 << LCD_EN ) );
10
}

fettich. Ab sofort ist sicher gestellt, das bei allen Kommando-Ausgaben, 
das RS Bit auf 0 steht.
(Gleich eine Funktion gemacht -> wenig Arbeit bei der Behebung von 
Fehlern und was viel wichtiger ist: ich bin sicher, dass bei ALLEN 
Kommandos das RS Bit gelöscht ist und ich keine vergessen oder übersehen 
habe)

: Bearbeitet durch User
von Christian K. (christiankarle)


Lesenswert?

Ok, die Übersichtlichkeit sollte nur für mich sein um z.B. 
Leichtsinnsfehler besser zu vermeiden.

Das ist jetzt so ca. mein 10. Projekt in C :) und deshalb lieber erst 
ausführlich und unkompliziert :)


Zur weiteren Vorgehensweise:

Ich müsste nun ein Byte an das Display senden, LCD_EN auf High setzten 
und der Buchstabe, die Zahl oder das Zeichen würde auf dem Display 
erscheinen.

Ich möchte wirklich alles Schritt für Schritt durchgehen...

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Christian Karle schrieb:
> Ok, die Übersichtlichkeit sollte nur für mich sein um z.B.
> Leichtsinnsfehler besser zu vermeiden.
>
> Das ist jetzt so ca. mein 10. Projekt in C :) und deshalb lieber erst
> ausführlich und unkompliziert :)

Sieh dir deinen Code an und dann sieh dir meinen COde an
1
  LCD_command( LCD_FUNCTION_SET | LCD_8_BIT | LCD_2_LINES | LCD_FONT_5_8 );
2
  LCD_command( LCD_DISPLAY_CONTROL | LCD_ON | LCD_CURSOR_ON | LCD_CURSOR_POS_ON );
3
  LCD_command( LCD_ENTRY_MODE | LCD_CURSOR_INCREMENT | LCD_NO_SHIFT );

versus das ganze Portgefrickel in deinem Code.

Welcher Code ist komplizierter? Welcher ist leichter zu verstehen? 
Welcher ist einfacher zu erfassen? Welcher ist leichter zu verändern?

Dein Code ist eben nicht unkompliziert. Dein Code ist eben nicht so, 
dass man kaum Leichtsinnsfehler machen kann. Ganz im Gegenteil. Dein 
Code ist in die Länge gezogen und er versteckt die wesentliche 
Information hinter einem Wust an technischen Details, die sich in den 
Vordergrund drängen und alles andere überdecken. Da drinnen findest du 
keine Fehler mehr, weil du bei den ganzen Port-Manipulationen den 
Überblick verlierst, was wann und wo gesetzt bzw. gelöscht wird.

> Ich müsste nun ein Byte an das Display senden, LCD_EN auf High setzten
> und der Buchstabe, die Zahl oder das Zeichen würde auf dem Display
> erscheinen.

Geht genau so, wie ein Kommando an das LCD ausgeben. Nur das die RS 
Leitung auf 1 sein muss und nicht auf 0, wie bei Kommandos.

Hast du also eine Funktion die ein Kommando ausgeben kann
1
void LCD_command( uint8_t Command )
2
{
3
  LCD_CONTROL_PORT &= ~( 1 << LCD_RS );
4
5
  LCD_DATA_PORT = command;
6
7
  LCD_CONTROL_PORT |=    ( ( 1 << LCD_EN ) );
8
  _delay_ms(1);
9
  LCD_CONTROL_PORT &= ~ ( ( 1 << LCD_EN ) );
10
}
dann hast du mit einer kleinen Modifikation auch sofort eine 2.te 
Funktion, die ein Zeichen ausgeben kann
1
void LCD_data( uint8_t Data )
2
{
3
  LCD_CONTROL_PORT |= ( 1 << LCD_RS );
4
5
  LCD_DATA_PORT = Data;
6
7
  LCD_CONTROL_PORT |=    ( ( 1 << LCD_EN ) );
8
  _delay_ms(1);
9
  LCD_CONTROL_PORT &= ~ ( ( 1 << LCD_EN ) );
10
}

Wenn man wollte, könnte man beide Funktionen sogar zusammenziehen auf 
einen gemeinsamen Kern. Denn die eigentliche Ausgabe ist ja in beiden 
Fällen dieselbe. Lediglich die Behandlung des RS Bits ist 
unterschiedlich:
1
void LCD_out( uint8_t value )
2
{
3
  LCD_DATA_PORT = value;
4
5
  LCD_CONTROL_PORT |=    ( ( 1 << LCD_EN ) );
6
  _delay_ms(1);
7
  LCD_CONTROL_PORT &= ~ ( ( 1 << LCD_EN ) );
8
}
9
10
void LCD_Command( uint8_t Command )
11
{
12
  LCD_CONTROL_PORT &= ~( 1 << LCD_RS );
13
  LCD_out( Command );
14
}
15
16
void LCD_Data( uint8_t Data )
17
{
18
  LCD_CONTROL_PORT |= ( 1 << LCD_RS );
19
  LCD_out( Data );
20
}

>
> Ich möchte wirklich alles Schritt für Schritt durchgehen...

Was denkst du, warum ich dir das alles zeige?
Sicher nicht, weil ich denke das es sinnvoll ist, mit nicht mehr als 
Grundkentnissen in den Grundrechenarten in Integralrechnung 
einzusteigen.

Gewöhn dich daran. Funktionen zu schreiben und Funktionalität in 
Funktionen zu kapseln ist eine der Grundfertigkeiten in der 
Programmierung. Du kannst natürlich einen großen Bogen darum machen. 
Aber du wirst dann in der Programmierung nicht weit kommen. Genau wie 
jemand, der nicht multiplizieren will, weil er das ja durch eine 
entsprechende Anzahl an Additionen ersetzen kann. Ja, stimmt schon. Man 
kann anstelle von 2*3 auch 2+2+2 rechnen. Aber mach das mal bei 
1865*5623!

Das hier, ein LCD, ist leicht in Funktionen zu kapseln. Da passiert 
nirgends irgendetwas aussergewöhnliches. Das ist stink normales 
Handwerk, wie es jeder Programmierer beherrschen muss. ... Und 
irgendwann muss man eben auch damit anfangen, das zu tun. Noch ist kein 
Meister vom Himmel gefallen. Es bringt aber auch nichts, 
Grundfertigkeiten immer und immer wieder hinauszuzögern. Das bringt dir 
im Endeffekt nur Mehrarbeit, ohne das es dich in der Fertigkeit schult, 
von vorne herein gleich den einigermassen richtigen Programmansatz zu 
erkennen und auch durchzuziehen.

: Bearbeitet durch User
von tom (Gast)


Lesenswert?

Super werde ich gleich mal ausprobieren

von Rudi (Gast)


Lesenswert?

wo ist denn command und Data definiert?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.