Forum: Compiler & IDEs Ansteuern eines LCD über ATmega16


von Tobias Neumann (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,
da ich keinen richtigen Beispielcode für das Ansteuern eines LCD 
Displays über einen ATmega16 gefunden habe, habe ich diesen Beitrag 
erstellt. Ich habe einen LCD Displaytech 204B an den PORTA meines 
ATmega16 angeschlossen, so wie es im Datenblatt des LCD Displaytech 204B 
stand. Dort steht auch welche Ports ich schalten muss um ein bestimmtes 
Symbol auf den LCD zu bekommen. Da ich jedoch noch keine Erfahrungen mit 
LCD Displays habe, wollte ich euch um einen Beispielcode bitten, der 
irgend ein Zeichen auf den Bildschirm zaubert. Datenblatt habe ich 
angehangen.

Danke schonmal im voraus,
Tobias

von Karl H. (kbuchegg)


Lesenswert?

Tobias Neumann schrieb:
> Hallo zusammen,
> da ich keinen richtigen Beispielcode für das Ansteuern eines LCD
> Displays über einen ATmega16 gefunden habe, habe ich diesen Beitrag
> erstellt.

Für dein spezifisches LCD wirdsich wahrscheinlich nicht allzuviel 
finden. Aber für Standard-LCD findet sich jede Menge.

Dein Controller auf dem LCD ist ein KS0063B und so wie ich das auf die 
Schnelle sehe, funktioniert der sehr ähnlich einem HD7445.

> Ich habe einen LCD Displaytech 204B an den PORTA meines
> ATmega16 angeschlossen, so wie es im Datenblatt des LCD Displaytech 204B
> stand.

Was genau hast du wo angehängt. Ich glaube kaum, dass im Datenblatt 
exakt steht, welchen LCD Anschluss du an welchen Pin von deinem Port A 
angeschlossen hast.

> Symbol auf den LCD zu bekommen. Da ich jedoch noch keine Erfahrungen mit
> LCD Displays habe, wollte ich euch um einen Beispielcode bitten, der
> irgend ein Zeichen auf den Bildschirm zaubert.

Studiere die LCD Abschnitte in den Tutorials

http://www.mikrocontroller.net/articles/AVR-Tutorial:_LCD
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung

Auch wenn dein LCD nicht 100% identisch ist zu den dort gezeigten, ist 
es doch ähnlich genug, dass dieselben Prinzipien gehen.

von Tobias Neumann (Gast)


Lesenswert?

Hallo,
ich schreibe kurz nieder was ich wo angeschlossen habe:

VSS -> GND
VDD -> 5V
VO -> nicht angeschlossen
RS -> PD5
R/W -> PD6
E -> PD7
DB0-DB7 -> PA0-PA7
A -> nicht angeschlossen
K -> nicht angeschlossen

Ich lese mir mal die Tutorials durch und hoffe daraus schlauer zu 
werden.. danke schonmal :)

von Tobias Neumann (Gast)


Lesenswert?

Das Problem ist das ich den Controller in C programmiere und mit den 
Codebeispielen nicht anfangen kann.. =/

von Karl H. (kbuchegg)


Lesenswert?

Tobias Neumann schrieb:
> Das Problem ist das ich den Controller in C programmiere und mit den
> Codebeispielen nicht anfangen kann.. =/

1) Im AVR-GCC-Tutorial sind die Codebeispiele in C
2) Wenn du nichts weiter tun willst als Codebeispiele abtippen ohne
   verstehen zu wollen was da passiert, ok, dann versteh ich, dass
   dich der Link ins Assemblerbeispiel nicht weiterbringt.
   Andere lesen sich den trotzdem durch und holen sich aus dem Text
   Informationen raus, die so nicht oder in anderer Formulierung
   im C-Tutorial stehen.
   Auf die Art ergänzen sich manchmal mehrere Tutorien:
   Was im einen nicht steht, steht im anderen. Was im einen unklar
   bleibt, wird im anderen erklärt.

von holger (Gast)


Lesenswert?

VO -> nicht angeschlossen

Ohne Kontrastspannung ist die Programmiersprache auch egal.
Zeigt sowieso nix an;)

von Tobias Neumann (Gast)


Lesenswert?

Oh, ich habe den zweiten Link total vergessen gehabt. Dort ist das 
Tutorial mit C-Code Beispielen.. sorry.. Ich arbeite mich mal durch.

von Tobias Neumann (Gast)


Lesenswert?

Nur eine kleine Frage.. ist V0 = Vee?

von Christian D. (chris83)


Lesenswert?

Das Vee aus dem Tutorial, Ja. Damit kannst dann den Kontrast einstellen.

von Tobias Neumann (Gast)


Lesenswert?

So, also ich habe jetzt alles wie im Tutorial angeschlossen, die lcd 
routinen .h und .c erstellt und es wie folgt in mein Makefile 
eingetragen:

CC= avr-gcc

CFLAGS= -Wall -mmcu=atmega16 -Os
LDFLAGS=-mmcu=atmega16

all: $(f)

$(f): $(f).o lcd-routines.o

$(f).hex: $(f)
        avr-objcopy -j .text -j .data -O ihex $^ $@

brennen: $(f).hex
        avrdude -u -e -c avrispmkII -P usb -p m16 -U flash:w:$^

clean:
        $(RM) *.o $(f) *.hex

//////////////////////////////////7

Er kompiliert zwar ohne Probleme, jedoch wird nichts auf dem Bildschirm 
angezeigt. Habe das LCD Beispiel 1 gebrannt.

Ich glaube das ich es irgendwie im Makefile falsch eingetragen habe, das 
er als SRC die lcd-routine.c verwenden soll. Oder?

von Karl H. (kbuchegg)


Lesenswert?

Tobias Neumann schrieb:

> Er kompiliert zwar ohne Probleme, jedoch wird nichts auf dem Bildschirm
> angezeigt. Habe das LCD Beispiel 1 gebrannt.

Das war auch nicht unbedingt zu Erwarten.
Dein LCD-Controller ist ein anderer als der im Tutorial verwendete. 
Ähnlich aber doch anders. Da wird dir nichts anderes übrig bleiben als 
die Datenblätter zu vergleichen und in der Initialisierung Anpassungen 
an deinen Controller vorzunehmen.

von Tobias Neumann (Gast)


Lesenswert?

also habe ich es im Makefile richtig eingetragen?

Mein Display verwendet ja auch den HD44780. Du meinst also das ich die 
Initialisierung in der lcd-routine.h anpassen soll?

von Klaus (Gast)


Lesenswert?

Tobias Neumann schrieb:
> Mein Display verwendet ja auch den HD44780. Du meinst also das ich die
> Initialisierung in der lcd-routine.h anpassen soll?

Datenblatt!!! Datenblatt!!! Datenblatt!!! Datenblatt!!!

Nochmal: Schau bitte ins Datenblatt und vergleiche selber, ob die 
initialisierung im Code dazu passt.

von Tobias Neumann (Gast)


Lesenswert?

Sorry wenn ich mich dumm anstelle.. bin nunmal ein totaler Newbie in 
Sachen LCD. Ich habe ja das Datenblatt angehange.. kann mir einer sagen 
wo diese Initialisierungsdaten stehen?.. Ich nehme an auf Seite 6 aber 
ich werde daraus nicht so wirklich schlau :(

von Thomas B. (escamoteur)


Lesenswert?

wenn ich das richtig lese, dann musst Du eigentlich gar nichts 
initialisieren, das macht Dein Display nach dem Einschalten von alleine. 
Allerdings muss man mit dem Senden von Daten warten bis das Busy flag 
nicht mehr gesetzt ist.

Meine Vermutung, Du schickst zu schnell nach Power-On die ersten Daten. 
Warte da einfach mal ne Sekunde und schau was passiert.

Gruß
Tom

von James (Gast)


Lesenswert?

Leider fehlt der Anhang, bzw. das Datenblatt noch immer.

Aus leidvoller (Zeitverschwendung) Erfahrung weiß ich,
daß es sehr sinnvoll ist sich an die Init-Routine
des Datenblatt zu halten, und nicht blind der vom
Displayhersteller zu vertrauen. Glücklicherweise sind
die Namen der Steuerleitungen bei (fast) allen die gleichen.

Achte auf die Position der Steuerbits im Datenbyte!!
Hier fand ich schon Unterschiede, aus der Erklärung
der Steuerbits habe ich dann Unterschiede (fast 100% kompatibel)
gefunden.

Mach die Wartezeiten ruhig etwas größer, so 50% stören für
den Beginn keinen, ich nehme nach der Init immer den Busy-
Flag-Test, ist zuverlässiger, und schneller.

von Klaus (Gast)


Lesenswert?

James schrieb:
> Leider fehlt der Anhang, bzw. das Datenblatt noch immer.

Möge er im ersten Post schauen.

von Tobias Neumann (Gast)


Lesenswert?

Hallo Leute,
ich hab es leider immer noch nicht zum Laufen gebracht.. langsam 
verzweifele ich. Ich weiß nicht wo ich aus dem Datenblatt sehe welche 
Daten is wo in der lcd-routine.h reinschreiben muss. Ich denke mal das 
ihr meint das ich folgnde Initialisierungsgeschichten anpassen muss wie 
z.B:

// Clear Display -------------- 0b00000001
#define LCD_CLEAR_DISPLAY       0x02

// Cursor Home ---------------- 0b0000001x
#define LCD_CURSOR_HOME         0x02

// Set Entry Mode ------------- 0b000001xx
#define LCD_SET_ENTRY           0x04

#define LCD_ENTRY_DECREASE      0x00
#define LCD_ENTRY_INCREASE      0x02
#define LCD_ENTRY_NOSHIFT       0x00
#define LCD_ENTRY_SHIFT         0x01

Jedoch weiß ich nicht woher ich die richtigen Daten aus dem Datenblatt 
entnehmen soll..

von Thomas B. (escamoteur)


Lesenswert?

Guck mal auf Seite 5. Etwas ungewöhlich, aber die haben die Binärwerte 
statt mit 0  1 als l  h geschrieben.

Gruß
Tom

von Karl H. (kbuchegg)


Lesenswert?

Tobias Neumann schrieb:
> Hallo Leute,
> ich hab es leider immer noch nicht zum Laufen gebracht.. langsam
> verzweifele ich. Ich weiß nicht wo ich aus dem Datenblatt sehe welche
> Daten is wo in der lcd-routine.h reinschreiben muss.

Nimm die LCD-Routinen als ANHALTSPUNKT

Du hast einen K_irgendwas Controller auf dem LCD und keinen Standard 
HD44780.

Im Datenblatt auf Seite 6 ist die Initialisierungssequenz ausführlich 
angegeben.

> Ich denke mal das
> ihr meint das ich folgnde Initialisierungsgeschichten anpassen muss wie

Nein.
Was wir denken ist:
* du sollst dir am Tutorialcode grundsätzlich ansehen, wie LCD Routinen 
aussehen können und dann sollst du hergehen und deine eigenen schreiben.

* du solltest C lernen

* du solltest mit etwas einfacherem anfangen als mit einem LCD

* du solltest dein LCD auf 8 Datenbits umverkabeln, dann dann (laut 
Datenblatt Seite 6) brauchst du das LCD gar nicht explizit 
initialisieren, weil der Controller auf dem LCD schon eine brauchbare 
Basisinitialisierung macht

* du sollst die relevanten Teile im Datenblatt aufmerksam lesen, 
verstehen, ausprobieren und umsetzen und dich nicht darauf verlassen, 
dass dich hier im Forum irgendjemand da durchsprechen wird. Letzteres 
wird höchst wahrscheinlich schief gehen, weil hier niemand deine 
Hardware vor sich liegen hat und wir daher 'blind' arbeiten müssen.

* du sollst dein Programm so umbauen, dass du die LCD Initialisierung zb 
mit einem Tasterdruck um jeweils einen Schritt weiter laufen lassen 
kannst. Dies deshalb, weil du dann mit einem Voltmeter die Pegel an den 
einzelnen Pins ansehen und mit der Vorgabe im Datenblatt vergleichen 
kannst.



Edit: Beim Hochscrollen gesehen - du hast ja alle 8 Datenpins 
angeschlossen. Also vergiss die Sache mit dem Umverkabeln. AVcc vom 
Prozessor hast du beschaltet?

von Tobias Neumann (Gast)


Lesenswert?

Ja ich habe schon viele Sachen mit meinem Mikrocontroller gemacht. Es 
ist nicht so das ich gerade mit Mikrokontrollern angefangen habe.. und 
mit C arbeite ich auch schon seit 2 Jahren.

Ich habe jetzt wieder alle 8 Datenpins angeschlossen und versuche jetzt 
mit hilfe von Tutorial und Datenblatt mein eigenes kleines 
Beispielprogramm zu schreiben wo einfach nur einen Char auf dem 
Bildschirm ausgibt und es danach wieder cleared. Mal schauen ob ich das 
hin kriegen ;)

von Tobias Neumann (Gast)


Lesenswert?

Also ich habe nun ein Beispielprogramm geschrieben was leider nicth 
funktioniert. Ich habe auch eine lcd-routine.h geschrieben. Ich habe 
dabei alles berücksichtigt was auch in der lcd-routine.h vom Tutorial 
steht, außer diesen Teil:

#define LCD_SOFT_RESET          0x30

//Set CG RAM Address --------- 0b01xxxxxx  (Character Generator RAM)
#define LCD_SET_CGADR           0x40

#define LCD_GC_CHAR0            0
#define LCD_GC_CHAR1            1
#define LCD_GC_CHAR2            2
#define LCD_GC_CHAR3            3
#define LCD_GC_CHAR4            4
#define LCD_GC_CHAR5            5
#define LCD_GC_CHAR6            6
#define LCD_GC_CHAR7            7

// Set DD RAM Address --------- 0b1xxxxxxx  (Display Data RAM)
#define LCD_SET_DDADR           0x80

Diesen Teil kann ich aus meinem Datenblatt nicht wirklich entnehmen.. 
hat einer ne Idee was ich da laut Datenblatt angeben muss?

Mein Programm sollte den String "Hello World!" über die funktion 
lcd_string() ausgeben. Aber er er leuchtet nur jede einzelne Zelle des 
Displays mit verschiedenen grau stufen auf.. also es sind keine Zeichen 
auf dem Display zu sehen aber irgendwas passiert schonmal.. wenigstens 
was!

von Peter D. (peda)


Lesenswert?


von Tobias Neumann (Gast)


Lesenswert?

Hm, ich versteh nicht ganz wie mir das bei meinem Problem helfen soll.. 
:)

von Peter D. (peda)


Lesenswert?

Tobias Neumann schrieb:
> Hm, ich versteh nicht ganz wie mir das bei meinem Problem helfen soll..
> :)

Weil das ein ziemlich narrensicherer Code ist.

Er macht nicht ähnliche Sachen an 6 verschiedenen Stellen, sondern ist 
streng modular.
Außerdem erlaubt er beliebige Pinzuordnung.

Je nach LCD können kleinere Änderungen im Init oder in der 
Positionierung nötig sein, aber mehr nicht.


Peter

von Tobias Neumann (Gast)


Lesenswert?

Ich wollte mal meine Eigene lcd init posten und euch fragen ob ich das 
denn so richtig mache, weil mein Programm funktioniert immer noch nicht 
und ich hab immernoch nur die zwei Balken auf dem Display:

Also laut Datenblatt soll meine Initialisierung so aussehen:

----------------------------------------------------------------

- POWER On
- Wait for more then 15ms
- RS=0, R/W=0, DB7=0, DB6=0, DB5=1, DB4=1
- Wait for more then 4,1ms
- RS=0, R/W=0, DB7=0, DB6=0, DB5=1, DB4=1
- Wait for more then 100us
- RS=0, R/W=0, DB7=0, DB6=0, DB5=1, DB4=1
- RS=0, R/W=0, DB7=0, DB6=0, DB5=1, DB4=1, DB3=N, DB2=F
- RS=0, R/W=0, DB7=0, DB6=0, DB5=0, DB4=0, DB3=1, DB2=0 (Display off)
- RS=0, R/W=0, DB7=0, DB6=0, DB5=0, DB4=0, DB3=0, DB2=0,DB1=0, DB0=1
 (Clear)
-RS=0, R/W=0, DB7=0, DB6=0, DB5=0, DB4=0, DB3=0, DB2=1, DB1=I/D, DB0=Sh
 (Entry mode set)
- Initialisation Ends.

------------------------------------------------------------------

Programmtechnisch habe ich das so geloest:

------------------------------------------------------------------

void lcd_init( void )
{
        DATA_DDR = 0xFF;
        SET_DDR = 0xE0;

//-----Enable Display-------//
        _delay_ms(5000);
        lcd_enable();
        _delay_ms(200);

//--------1--Fset------------------//
        DATA_PORT |= (1<<PA4);
        DATA_PORT |= (1<<PA5);
        _delay_ms(500);

        DATA_PORT &= ~(1<<PA4);
        DATA_PORT &= ~(1<<PA5);
        _delay_ms(500);
//---------2-----Fset-----------------//
        DATA_PORT |= (1<<PA4);
        DATA_PORT |= (1<<PA5);
        _delay_ms(500);

        DATA_PORT &= ~(1<<PA4);
        DATA_PORT &= ~(1<<PA5);
        _delay_ms(500);
//---------3-----Fset-----------------//
        DATA_PORT |= (1<<PA4);
        DATA_PORT |= (1<<PA5);
        _delay_ms(500);

        DATA_PORT &= ~(1<<PA4);
        DATA_PORT &= ~(1<<PA5);
        _delay_ms(500);
//------------SET Funktion-------------//
        DATA_PORT |= (1<<PA3);
        DATA_PORT |= (1<<PA4);
        DATA_PORT |= (1<<PA5);
        _delay_ms(500);
        DATA_PORT &= ~(1<<PA3);
        DATA_PORT &= ~(1<<PA4);
        DATA_PORT &= ~(1<<PA5);
        _delay_ms(500);
//---------------Display Off-------------------------//
        DATA_PORT |= (1<<PA3);
        _delay_ms(15);
        DATA_PORT &= ~(1<<PA3);
        _delay_ms(15);
//--------Display on------//
        DATA_PORT |= (1<<PA0);
        DATA_PORT |= (1<<PA1);
        DATA_PORT |= (1<<PA2);
        DATA_PORT |= (1<<PA3);
        _delay_ms(15);
        DATA_PORT &= ~(1<<PA0);
        DATA_PORT &= ~(1<<PA1);
        DATA_PORT &= ~(1<<PA2);
        DATA_PORT &= ~(1<<PA3);
        _delay_ms(15);
//-----------Display clear------------//

        DATA_PORT |= (1<<PA0);
        _delay_ms(15);
        DATA_PORT &= ~(1<<PA0);
        _delay_ms(15);

//----------Entrymode set-------//
        DATA_PORT |= (1<<PA2);
        DATA_PORT |= (1<<PA1);
        DATA_PORT &= ~(1<<PA0);
        _delay_ms(15);
        DATA_PORT &= ~(1<<PA2);
        DATA_PORT &= ~(1<<PA1);
        DATA_PORT |= (1<<PA0);
        _delay_ms(15);

//--------Display on------//
        DATA_PORT |= (1<<PA0);
        DATA_PORT |= (1<<PA1);
        DATA_PORT |= (1<<PA2);
        DATA_PORT |= (1<<PA3);
        _delay_ms(15);
        DATA_PORT &= ~(1<<PA0);
        DATA_PORT &= ~(1<<PA1);
        DATA_PORT &= ~(1<<PA2);
        DATA_PORT &= ~(1<<PA3);
        _delay_ms(15);
}

----------------------------------------------------------------

In meinem Programm gebe ich einfach den String "Hello World!" an die 
Funktion lcd_string.

Die Syntax der Funktionen:

-----------------------------------------------------------------

//////////////////////////////////////////////////////////////////////// 
////////
// Sendet eine 4-bit Ausgabeoperation an das LCD
static void lcd_out( uint8_t data )
{
        data &= 0xFF;                       // Bits maskieren

        DATA_PORT |= data;
        lcd_enable();
}
//////////////////////////////////////////////////////////////////////// 
////////
// Sendet ein Datenbyte an das LCD
void lcd_data( uint8_t data )
{
    SET_PORT |= (1<<LCD_RS);    // RS auf 1 setzen

    lcd_out( data );            // zuerst die oberen,
    lcd_out( data<<4 );         // dann die unteren 4 Bit senden

    _delay_us( LCD_WRITEDATA_US );
}

void lcd_string( const char *data )
{
    while( *data != '\0' )
        lcd_data( *data++ );
}
//////////////////////////////////////////////////////////////////////// 
////////
// Erzeugt einen Enable-Puls
static void lcd_enable( void )
{
    SET_PORT |= (1<<LCD_EN);     // Enable auf 1 setzen
    _delay_us( LCD_ENABLE_US );  // kurze Pause
    SET_PORT &= ~(1<<LCD_EN);    // Enable auf 0 setzen
}

-----------------------------------------------------------------

Ich glaube das das Problem entweder an der Initialisierung liegt, oder 
daran das ich vielleicht mit 8 Datenpins arbeite und die Funktions 
lcd_data() angepasst werden muss. Ich hoffe ihr könnt mir dabei helfen.

Danke schonma und entschuldigt den extrem langen Post!

von Karl H. (kbuchegg)


Lesenswert?

Tobias Neumann schrieb:
> Ich wollte mal meine Eigene lcd init posten und euch fragen ob ich das
> denn so richtig mache, weil mein Programm funktioniert immer noch nicht
> und ich hab immernoch nur die zwei Balken auf dem Display:

Was soviel heißt wie:
Deine Initialisierung stimmt nicht.


> Programmtechnisch habe ich das so geloest:
>
> ------------------------------------------------------------------
>
> void lcd_init( void )
> {
>         DATA_DDR = 0xFF;
>         SET_DDR = 0xE0;
>
> //-----Enable Display-------//
>         _delay_ms(5000);
>         lcd_enable();
>         _delay_ms(200);
>


Der Enable Pin heißt nicht 'Enable', weil er das LCD einschaltet.
Er ist das Signal an das LCD, dass die restlichen Leitungen jetzt einen 
stabilen Zustand angenommen haben und daher vom LCD als gültig anzusehen 
sind. Wenn man will, kann man das so sagen: 'Jetzt gilts. Das was jetzt 
an den Leitungen anliegt, sind gültige Werte'


> //--------1--Fset------------------//
>         DATA_PORT |= (1<<PA4);
>         DATA_PORT |= (1<<PA5);
>         _delay_ms(500);
>
>         DATA_PORT &= ~(1<<PA4);
>         DATA_PORT &= ~(1<<PA5);
>         _delay_ms(500);


Warum denkst du, verweisen wir dich immer auf anderen Code? Damit du den 
ignorierst? Woher soll denn dein LCD wissen, dass genau jetzt die an PA4 
und PA5 anliegende 1 schon der endgültige Zustand ist? Weil dein 
Programm eine halbe Sekunde wartet?

Du musst schon mit den Steuer-Pins wackeln (konkret dem Enable) um dem 
LCD mitzuteilen: Jetzt gilts!

> oder
> daran das ich vielleicht mit 8 Datenpins arbeite und die
> Funktions lcd_data() angepasst werden muss. Ich hoffe ihr könnt mir
> dabei helfen.

Deine Funktion lcd_data + lcd_out ist ein einziger Schmarrn. Ein 
Mischmasch aus 4Bit und 8 Bit Anteuerung, wobei weder das eine noch das 
andere sauber durchgezogen ist.
Tu dir selbst einen Gefallen und studiere erst mal anderen Code! Aber 
wirklich studieren und nicht einfach nur drüberschauen! Anweisung für 
Anweisung durchgehen. Abklären welchen Einfluss das auf die Pins hat, 
mit dem Datenblatt abklären was da passiert und warum ausgerechnet jetzt 
dieser Pin auf den Zustand gebracht wird, der im Programm steht.

> Ja ich habe schon viele Sachen mit meinem Mikrocontroller gemacht.
> Es ist nicht so das ich gerade mit Mikrokontrollern angefangen habe..
> und mit C arbeite ich auch schon seit 2 Jahren.

Wenn ich deinen Code so ansehe: Ich mag es kaum glauben.

von MaWin (Gast)


Lesenswert?

> VO -> nicht angeschlossen


Da bist du recht lapidar drüber hinweggegangen.

So lange VO (VEE) nicht richtig bedient wird,

normalerweise also per Poti die passende Spannung zwischen 0V und 5V 
gefunden wird,
bei manchen Displays sogar eine negative Spannung (bei deinem nicht)
kannst du initialisieren wie du willst und nichts ist zu sehen.

Ganz abgesehen von den Problemen die die Anderen im Programm gefunden 
haben.

von Karl H. (kbuchegg)


Lesenswert?

Karl heinz Buchegger schrieb:

> Warum denkst du, verweisen wir dich immer auf anderen Code? Damit du den
> ignorierst? Woher soll denn dein LCD wissen, dass genau jetzt die an PA4
> und PA5 anliegende 1 schon der endgültige Zustand ist? Weil dein
> Programm eine halbe Sekunde wartet?
>
> Du musst schon mit den Steuer-Pins wackeln (konkret dem Enable) um dem
> LCD mitzuteilen: Jetzt gilts!

Es könnte sein, dass ich mich da in deinem Code verlesen habe.
Dein Mischmasch aus PA4 PA5 DATA_PORT SET_PORT und LCD_EN sucht aber 
auch seinesgleichen und ist hauptsächlich Eines: maximale Verwirrung!

Wobei aus dem Code immer noch nicht hervor geht:
Ist PA4 PA5 jetzt eine Steuerleitung oder sind das Datenleitungen? In 
deinem lcd_out kann man das auch nicht ablesen. Die gibt zwar laut 
Kommentar nur einen Nibble aus, verändert allerdings alle 8 Leitungen 
(und das auch nur in Richtung 0->1).

von Tobias Neumann (Gast)


Lesenswert?

Hallo,
habe die Initialisierung von diesem Beitrag hier und an meine 
Pinbelegung angepasst: Beitrag "Hilfe bei KS0076B"

MaWin schrieb:
>> VO -> nicht angeschlossen
>
>
> Da bist du recht lapidar drüber hinweggegangen.
>
> So lange VO (VEE) nicht richtig bedient wird,
>
> normalerweise also per Poti die passende Spannung zwischen 0V und 5V
> gefunden wird,
> bei manchen Displays sogar eine negative Spannung (bei deinem nicht)
> kannst du initialisieren wie du willst und nichts ist zu sehen.
>
> Ganz abgesehen von den Problemen die die Anderen im Programm gefunden
> haben.

V0 hab ich über einen Poti an 5V angeschlossen. Ich sehe zwei Balken, 
also müsste der Kontrast soin ordnung sein.

Karl heinz Buchegger schrieb:
> Der Enable Pin heißt nicht 'Enable', weil er das LCD einschaltet.
> Er ist das Signal an das LCD, dass die restlichen Leitungen jetzt einen
> stabilen Zustand angenommen haben und daher vom LCD als gültig anzusehen
> sind. Wenn man will, kann man das so sagen: 'Jetzt gilts. Das was jetzt
> an den Leitungen anliegt, sind gültige Werte'

Das mit lcd_enable habe ich jetzt verstanden, habe es jetzt aus der 
initialisierung genommen.

Karl heinz Buchegger schrieb:
> Warum denkst du, verweisen wir dich immer auf anderen Code? Damit du den
> ignorierst? Woher soll denn dein LCD wissen, dass genau jetzt die an PA4
> und PA5 anliegende 1 schon der endgültige Zustand ist? Weil dein
> Programm eine halbe Sekunde wartet?
>
> Du musst schon mit den Steuer-Pins wackeln (konkret dem Enable) um dem
> LCD mitzuteilen: Jetzt gilts!

Ich versteh nicht ganz was du damit meinst.. soll ich jetzt nach jeder 
Fset anweisung noch ein lcd_enable machen??

Karl heinz Buchegger schrieb:
> Deine Funktion lcd_data + lcd_out ist ein einziger Schmarrn. Ein
> Mischmasch aus 4Bit und 8 Bit Anteuerung, wobei weder das eine noch das
> andere sauber durchgezogen ist.

Ja, ich bin in diesen Bitverknüpfungsgeschichten noch sehr unsicher.. 
könntest du mir denn eine funktionierende lcd_data+lcd_out für eine 8 
Bit Datenübertragung schreiben?

Karl heinz Buchegger schrieb:
>> Ja ich habe schon viele Sachen mit meinem Mikrocontroller gemacht.
>> Es ist nicht so das ich gerade mit Mikrokontrollern angefangen habe..
>> und mit C arbeite ich auch schon seit 2 Jahren.
>
> Wenn ich deinen Code so ansehe: Ich mag es kaum glauben.

Ja ich habe davor mit den ganzen Interrupts gearbeitet und LEDs 
geschaltet, ein Zaehlrohr angeschlossen und solche Dinge. Ich arbeite 
jetzt vielleicht seit ung. 8 Wochen mit dem ATmega8. Mit C arbeite ich 
seit knapp 2 Jahren. Wobei ich erst vor kurzem mit diesen Bitoperationen 
angefangen habe... entschuldige bitte.

von Tobias Neumann (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Ist PA4 PA5 jetzt eine Steuerleitung oder sind das Datenleitungen?

PA0 - PA 7 sind meine Datenleitungen. Diese habe ich in meinem init 
direkt reingeschrieben.

RS = PD5
R/W = PD6
E = PD7

//  LCD RS      <-->  PORTD Bit PD5     (RS: 0=Data, 1=Command)
#define LCD_RS        PD5

//  LCD EN      <-->  PORTD Bit PD7     (EN: 1-Impuls für Daten)
#define LCD_EN        PD7

Sorry für meine Verwirrende schreibweise

von Tobias Neumann (Gast)


Angehängte Dateien:

Lesenswert?

Also Leute,
ich habe mein Programm jetzt nochmal komplett überarbeitet und den 
Quelltext nun leserlich gestalltet (hoffentlich :)). Ich habe im Anhang 
mein .c file angehängt. Ich habe immernoch ein Initialisierungsproblem, 
da die schwarzen Balken auf meinem Display nicht verschwinen. Irgendwas 
mach ich noch falsch. Wäre nett wenn einer mal meine Initialisiesung mit 
dem Datenblatt welches ich auch nochmal angehangen habe durchgeht und 
mir sagt was ich falsch mache.

Danke, Tobias.

von Karl H. (kbuchegg)


Lesenswert?

1
//Wait untill VDD rises to 4,5V
2
  _delay_ms(15);
3
//Function Set 1
4
  PORTA |= (1<<PA4);
5
  PORTA |= (1<<PA5);
6
  _delay_ms(5);
7
8
  PORTA &= ~(1<<PA4);    
9
  PORTA &= ~(1<<PA5);    
10
  _delay_ms(5);
11
//Function Set 2
12
        PORTA |= (1<<PA4);
13
        PORTA |= (1<<PA5);
14
        _delay_ms(1);

Ich seh immer noch keine Enable Pulse, die dem LCD mitteilen: Jetzt 
gilts.

OK. Analogie

Du und dein Kumpel Herbert habt eine ganz besondere Form der 
Kommunikation:
Vor jedem ist ein Schaltbrett mit Leuchten und darunter jeweils Schalter 
die entweder ein oder aus sein können.
Die Schalter sind jeweils mit den Leuchten der Gegenstelle verbunden, so 
dass wenn du bei dir den Schalter 0 auf 'ein' stellst, beim Herbert die 
Lampe 0 aufleichtet. Und natürlich umgekehrt, betätigt Herbert seinen 
Schalter, so leuchtet bei dir eine Lampe auf.

Ihr macht euch beide einen Code aus. Wenn die und die Lampenkombination 
aufleuchtet, dann bedeutet das irgendwas. Mit anderen Kombinationen 
natürlich auch, die eben dann was anderes bedeuten.

Also legt ihr los.
Du starrst auf deine Lampen.
Die leuchten nacheinander auf, gehen wieder aus, leuchten wieder etc. Du 
weisst nie, ob eine bestimmte Leuchtkombination jetzt gültig ist oder 
nicht, denn natürlich vertut sich Herbert auch mal ab und zu. Er 
schaltet eine Lampe ein, die eigentlich aus sein sollte und umgekehrt. 
Herbert bemerkt das auch und schaltet schnell die Lampe wieder aus.  mit 
seinen Wurstfingern kann er nicht alle Lampenschalter gleichzeitig 
betätigen, ab und zu muss er ins Codebuch schauen um die angestrebte 
Lampenstellung abzulesen. Kurz und gut: Woher sollst du denn als 
Beobachter der Lampen wissen, wann Herbert jetzt seine Schalter 
endgültig in der richtigen Stellung hat und das was bei dir aufleuchtet 
jetzt tatsächlich eine Nachricht von ihm ist?

Eben. Du kannst es nicht wissen.

Und daher macht ihr beide einen Zusatz:
Ihr verlegt noch einen zusätzlichen Schalter auf jeder Seite, der in 
einer elektrischen Glocke auf der Gegenseite mündet. Jedesmal, wenn 
einer seine Schalter so hat, wie er das haben möchte, betätigt er 
zusätzlich den Schalter der beim anderen die Glocke läuten lässt.

Und plötzlich geht alles wie geschmiert.
Du siehst wie auf deinem Brett Lampen an und ausgehen und ... 'Bimmel'
Die jetzt anliegende Lampenstellung ist die Nachricht
Weiter: die Lampen machen wieder einen Tanz, gehen an und aus, einmal 
kannst du sogar erkennen, wie sich Herbert vertan hat und eine Lampe 
zuerst ein und dann wieder ausgeschaltet hat. Aber das macht nichts. 
Solange Herbert nicht bimmelt, kann er mit den Lampen machen was immer 
er will.
'Bimmel' - Herbert hat seine Schalter kontrollier, hat sie für richtig 
befunden und hat gebimmelt. Damit gilt die zum Zeitpunkt des Bimmelns 
anliegende Lampenkonfiguration für dich. Alles dazwischenliegende ist 
egal. Nur die Lampen die zum Zeitpunkt des Bimmelns leuchten (oder nicht 
leuchten) gelten. Mit der Betonung auf 'zum Zeitpunkt des Bimmelns'.


Das ist die grundlegende Idee, die hinter dem Enable Pin des LCD steckt. 
Du kannst an den Datenpins umstellen soviel du willst, du kannst am R/W 
am Command/Data Pin rumstellen soviel du willst. Ist alles egal. Erst 
wenn der Puls am Enable kommt, dann gilt die zu diesem Zeitpunkt 
anstehende Einstellung und das LCD übernimmt die dann anliegende 
Pinkonfiguration und bearbeitet sie.


Ist doch nicht so schwer zu verstehen.

von roflkartoffel (Gast)


Lesenswert?

der TE sollte sich langsam darüber gedanken machen ob er programmieren 
WILL
das ist jetzt quasi eine grundsatzfrage ...

ohne weitere C kenntnisse und wie so ein µC sowie solche signale 
funktionieren kommt man hier nicht weiter
bzw ist es ein absoluter frust sich unwissend durch Code zu wühlen
ohne nur ansatzweise zu verstehen wie es funzt


wenn er will .. dann muss er lernen ...
wenn er nicht will ... kann er sich maximal projekte nachbauen die 
seinem anspruch genügen

alles andere führt nur dazu das hier elend lange threads entstehen wo zu 
90% geflamed wird ..

von Thomas B. (escamoteur)


Lesenswert?

Ich bewundere ja Kar Heinz für seine Geduld mit dem TE, aber ich stimme 
dem  roflkartoffel zu, wir können nicht jemandem, dem so elemtare 
Grundkenntnisse fehlen komplett Schritt für Schritt vorkauen wie er sein 
Programm zu schreiben hat.

Meine Meinung, Tom

von Karl H. (kbuchegg)


Lesenswert?

roflkartoffel schrieb:

> ohne weitere C kenntnisse und wie so ein µC sowie solche signale
> funktionieren kommt man hier nicht weiter
> bzw ist es ein absoluter frust sich unwissend durch Code zu wühlen
> ohne nur ansatzweise zu verstehen wie es funzt

Wobei man auch sagen muss, das 90% dieser Techniken in Wirklichkeit 
wahnsinnig simpel sind. Ich kann aber nicht ewig Beispiele konstruieren, 
die eine bestimmte Thematik losgelöst von Elektronik, Computern und 
Programmen beleuchten, um zu zeigen warum etwas so gemacht wird, so wie 
hier mit dem Enable Signal. Ob das jetzt Enable, Strobe (beim Centronics 
Druckerinterface), SCLK bei der Ansteuerung von Schieberegistern ... 
oder eben Herberts Bimmeln ist, es ist immer dieselbe Grundidee. Und es 
sind diese Grundideen, die man (neben natürlich technischem Handwerk, 
sprich Programmieren) verstehen muss, welches Problem sonst entsteht und 
wie die Idee genau dieses Problem eliminiert.

Irgendwann muss er soweit sein, solche Ideen aus dem Datenblatt 
herauszulesen, bzw. wenn schon fremder Code vorhanden ist, diese Idee im 
Code sehen. In allen Codevorlagen ist die Reihenfolge: Bits an den 
Datenbports, Bits an den Steuerleitungen und dann "Enable auf 1; Enable 
auf 0". Da muss ich mich doch irgendwann, wenn ich das im Code lese, 
fragen: Warum ist denn das so? Was steckt da dahinter?

> wenn er will .. dann muss er lernen ...
> wenn er nicht will ... kann er sich maximal projekte nachbauen die
> seinem anspruch genügen

Jup.
Der Unterschied zwischen 'Malen nach Zahlen' und 'Rausgehen in die Natur 
und das malen was man sieht'.


Edit: Timer sind auch so ein Kapitel.
Wahnsinnig simpel und trotzdem für Neueinsteiger so schwer zu verstehen. 
Ich weiß nicht warum, aber im relen Leben lösen Menschen genau dieselben 
Probleme ohne groß darüber nachzudenken. Nur wenn es um Computer und 
Programme geht, ist genau derselbe Sachverhalt plötzlich unendlich 
schwierig zu lösen.

von Thomas B. (escamoteur)


Lesenswert?

Völlig richtig! Daher kommt es auch überhaupt nicht darauf an, ob man 
eine bestimmte Programmiersprache kann oder nicht, die Grundprinzipien 
sind davon unabhängig.

Wenn er sich durch Beispielcode wühlt und dabei an einer Stelle nicht 
versteht warum dort etwas bestimmtes gemacht wird, dann kann er ja genau 
danach Fragen, aber dann hat er zumindest den Rest schon mal verstanden.
Tom

von Tobias Neumann (Gast)


Lesenswert?

Ganz ruhig bleiben.. Diejenigen die meinen mich hier beleidigen zu 
müssen sollen lieber mal garnichts schreiben. Ich versuche mein bestes 
und habe nunmal gerade erst mit LCD Displays angefangen und habe mich in 
der hinsicht vielleicht etwas schwer getan.

An diejenigen die mich unterstützen, wie z.B Karl Heinz:

Ich habe nun die Initialisierung ENDLICH hinbekommen.. nachdem du mir so 
anschaulich beschrieben hast wozu das ENABLE wirklich dient :). Danke 
schonmal dafür!

Meine Initialisierung sieht nun wie folgt aus:

void out_stat_reg (unsigned char command)
{
        PORTA=0;
        PORTD &= ~(1<<PD6);
        _delay_ms(5);
        PORTD |= (1<<PD7);              // Enable auf 1 setzen
        PORTA=command;
        PORTD &= ~(1<<PD7);             // Enable auf 0 setzen
        _delay_ms(70);
}

// Initialisierung:
void lcd_init( void )
{
//Pins auf schreiben schalten (PA0-PA7) (PD5-PD7)
        DDRA = 0xFF;
        DDRD = 0xE0;

//Pins alle low setzen
        PORTA = 0;
        PORTD = 0;

//Wait untill VDD rises to 4,5V
        _delay_ms(2000);
//Function Set 1
        PORTD |= (1<<PD7);              // Enable auf 1 setzen
        PORTA = 0x30;                   //Set PA4 und PA5 high
        PORTD &= ~(1<<PD7);             // Enable auf 0 setzen
        _delay_ms(2000);
//Function Set 2
        PORTD |= (1<<PD7);              // Enable auf 1 setzen
        PORTA = 0x30;                   //Set PA4 und PA5 high
        PORTD &= ~(1<<PD7);             // Enable auf 0 setzen
        _delay_ms(2000);
//Function Set 3
        PORTD |= (1<<PD7);              // Enable auf 1 setzen
        PORTA = 0x30;                   //Set PA4 und PA5 high
        PORTD &= ~(1<<PD7);             // Enable auf 0 setzen
        _delay_ms(2000);

        out_stat_reg(0x3c);                             //set Display 
lines
        out_stat_reg(0x08);                             //Display off
        out_stat_reg(0x01);                             //Display clear
        out_stat_reg(0x06);                             //cursor 
increase
        out_stat_reg(0x0c);                             //Display on
}

Ich hoffe das ist nun verständlicher und sieht mal n bisschen besser aus 
als das was ich vorher fabriziert habe ;)

Also es erscheinen nun die Zeichen "Lo<-" anstatt "Hello World!" auf dem 
Display. Aber wenigstens hat die Initialisierung schonmal funktioniert. 
Jetzt muss ich nurnoch rausfinden warum er nicht meinen gewünschten 
String ausgibt. Ich probier mal ein paar Dinge aus, wenn jemand n 
Vorschlag hat woran es liegen könnte kann er es ruhig hier posten.

Danke erstmal an die jenigen die so Geduldig mit mir waren.

von Tobias Neumann (Gast)


Lesenswert?

Hallo,
also ich kann jetzt einen beliebigen char an das Display übergeben.. 
weiß aber nicht wie ich den Curser bewege. Wie kann ich dem Display denn 
sagen, das er, nachdem er einen char geschickt bekommen hat eine 
curserposition nach rechts rücken soll?

Gruß, Tobias.

von Karl H. (kbuchegg)


Lesenswert?

Schaust du in dein Datenblatt, auf Seite 5 sind alle 
Konfigurationskommandos zusammengestellt.

Das LCD verändert die Cursor Position sowieso von sich aus nach jedem 
Zeichen. Mit der Konfiguration 'ENTRY MODE SET' kannst du dann noch 
festlegen, ob der Cursor nach Ausgabe eines Zeichens nach rechts oder 
nach links wandern soll.

von Karl H. (kbuchegg)


Lesenswert?

Bsp

Aus dem Datenblatt

                   RS R/W   7   6   5   4   3   2   1   0
ENTRY MODE SET      L   L   L   L   L   L   L   H   I/D SH

I/D   H = increase
      L = decrease

SH    H = Display is shifted
      L = Display is not shifted


Du willst: Cursor soll automatisch nach rechts ( = increase)
           Displayanzeige wird nicht verschoben

also I/D muss H (also 1) sein und sH muss L (also 0) sein.

Dein Commandobyte ist also

       LLLLLHHL

oder in gebräuchlicher 0/1 Schreibweise
      0b00000110

in Hex soviel wie 0x06

Dieses Kommando schickst du zum LCD und dann macht es das Gewünschte.


Edit: Seh gerade, dass das in deiner Init Sequenz sowieso enthalten ist.

Zeig mal dein Programm. Wahrscheinlich wimmelt es da wieder mal von 
Cursor Home bzw. LCD Clear Aufrufen.

von Tobias Neumann (Gast)


Lesenswert?

Ok.

Ich habe nur ein ganz einfaches Programm erstellt wo direkt in der main 
den char sendet. Wenn ich genau weiß wie das richtig funktioniert will 
ich dann meine eigene putchar funktion erstellen.

Meine init() kennst du ja.

Meine main:

int main(void)
{
        lcd_init();

        PORTD |= (1<<PD5); //RS auf 1
        PORTA = 0x54;      //send char 'T'
        lcd_enable();      //Jetzt gilts

        while(1)
        {
        }

        return 0;
}

von Karl H. (kbuchegg)


Lesenswert?

Und wo gibst du da jetzt mehrere Zeichen aus?

von Tobias Neumann (Gast)


Lesenswert?

Naja, ich frage mich halt grade wie das genau Funktioniert.

Ich habe jetzt versucht so zwei char nebeneinander zu senden:

int main(void)
{
        lcd_init();

        PORTD |= (1<<PD5);
        PORTA = 0x54;
        lcd_enable();

        PORTD |= (1<<PD5);
        PORTA = 0x4F;
        lcd_enable();

        while(1)
        {
        }

        return 0;
}

von Karl H. (kbuchegg)


Lesenswert?

Ohjemine
1
void putchar( char c )
2
{
3
  PORTD |= (1<<PD5);
4
  PORTA = c; 
5
  lcd_enable();
6
}
7
8
int main(void)
9
{
10
  lcd_init();
11
12
  putchar( 'H' );
13
  putchar( 'a' );
14
  putchar( 'l' );
15
  putchar( 'l' );
16
  putchar( 'o' );
17
18
  while(1)
19
  {
20
  }
21
22
  return 0;
23
}

UNd führ dir endlich für PORTA und PDirgendwas und was du sonst noch so 
an Konstnaten hast, vernünfitge #define ein!
1
#define LCD_DATA_PORT   PORTA
2
#define LCD_CTRL_PORT   PORTD
3
4
#define LCD_RW_PIN      PD6
5
#define LCD_RS_PIN      PD5
6
#define LCD_E_PIN       PD7
7
8
void putchar( char c )
9
{
10
  LCD_CTRL_PORT |= (1<<LCD_RS_PIN);
11
  LCD_CTRL_PORT &= ~(1<<LCD_RW_PIN);
12
13
  LCD_DATA_PORT = c; 
14
15
  LCD_CTRL_PORT |= (1<<LCD_E_PIN);
16
  _delay_ms( 1 );
17
  LCD_CTRL_PORT &= ~(1<<LCD_E_PIN);
18
}
19
20
void out_stat_reg (unsigned char command)
21
{
22
  LCD_DATA_PORT = 0;
23
  LCD_CTRL_PORT &= ~(1<<LCD_RW_PIN);
24
25
  _delay_ms(5);
26
  LCD_CTRL_PORT |= (1<<LCD_E_PIN);
27
  LCD_DATA_PORT = command;
28
  LCD_CTRL_PORT &= ~(1<<LCD_E_PIN);
29
  _delay_ms(70);
30
}
31
32
33
etc.....

erstens wird der Code dadurch sehr viel besser verständlich, als wie 
wenn man ständig im Hinterkopf behalten muss, welcher Pin am Port D dann 
jetzt welche Leitung ist und zweites hast du dann die Pinbelegung an 
einer Stelle beisammen, was bei Änderungen ja höchst vorteilhaft sein 
soll.

von Tobias Neumann (Gast)


Lesenswert?

Ok.. vielen dank!

von Tobias Neumann (Gast)


Lesenswert?

Er zeigt mir aber nur ein 'H' an, wenn ich es so mache :/

von Karl H. (kbuchegg)


Lesenswert?

Tobias Neumann schrieb:
> Naja, ich frage mich halt grade wie das genau Funktioniert.

Du gibst das Byte einfach auf dem Port aus. Allerdings muss die RS 
Leitung dazu High sein.
(Und natürlich, wie immer, hinten nach ein Enable Puls)

Siehe Datenblatt, Seite 5, in der Tabelle fast ganz unten, das 
'Kommando' Write Data

von Karl H. (kbuchegg)


Lesenswert?

Tobias Neumann schrieb:
> Er zeigt mir aber nur ein 'H' an, wenn ich es so mache :/

Wie sieht deine lcd_enable aus?
Hast du dir inzwischen ein paar #define gemacht, damit man nicht ständig 
mit PD5, PD6 und Konsorten durcheinanderkommt?
Hast du nach dem Enable Puls ein bischen gewartet? Laut Tabelle benötigt 
die Ausgabe auch Zeit (42µs)

....

von Thomas B. (escamoteur)


Lesenswert?

@Karl Heinz: Ich bewundere Dich für Deinen Langmut!!

von Tobias Neumann (Gast)


Lesenswert?

Ich habe grad irgend n kleinen bug drinnen, Nachdem ich die ganzen 
defines gemacht habe. Brauche noch kurz um den zu fixen.

von Tobias Neumann (Gast)


Angehängte Dateien:

Lesenswert?

JAAAAAAAAAAAAAAAAAAAAA!

Ich habs endlich geschafft!!!! DANKE Karl Heinz ich LIEBE DICH :D

Das Problem war das ich mal wieder zu "copy&paste" geil war und ich 
deine defines rauskopiert habe, wobei du RS = PD6 und RW = PD5 definiert 
hattest. Diese sind aber genau umgedreht.. das hat mich grad zur 
verzweiflung gebrahct.. aber jetzt gehts! DANKE DANKE DANKE

Ich hab mein Programm mal in den Anhang gemacht, falls du es dir nochmal 
anschauen willst.

Gruß, Tobias.

von Karl H. (kbuchegg)


Lesenswert?

Tobias Neumann schrieb:

> Ich hab mein Programm mal in den Anhang gemacht, falls du es dir nochmal
> anschauen willst.

Ich halt mich da jetzt raus.
Nur eines noch:
Du solltest anfangen auf Nomenklatur zu achten.

Die eine Funktion heisst lcd_init, die andere out_stat_reg, dann wieder 
eine lcd_enable und die letzte putchar

Was haben all diese Funktionsnamen gemeinsam?
Richtig. Bis auf lcd_init und lcd_enable, die die gemeinsame 'Vorsilbe' 
lcd benutzen:  Gar nichts

Alle diese Funktionen gehören aber zum selben Code-'Modul'. Nämlich der 
Ansteuerung des LCD!

Das sollte sich dann schon im Funktionsnamen niederschlagen.

Den irgenwann hast du dann 25 vrschiedene Zeichen-Sende Routinen und 
weißt nicht mehr welche jetzt für UART, welche für SPI, TWI, LCD etc. 
zuständig ist.


Und den Wildwuchs mit ENABLE solltest du auch beseitigen. Entweder von 
überall her wird lcd_enable aufgerufen, wenn man einen Enable Puls 
braucht, oder die Funktion fällt komplett weg. Aber nicht so wie jetzt.

von Tobias Neumann (Gast)


Lesenswert?

Ok. Ich werde in Zukunft darauf achten. Danke nochmal für alles.

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.