Forum: Mikrocontroller und Digitale Elektronik Veständnisfrage zur LCD-Routine in C+


von Norbert (Gast)


Lesenswert?

Programmiere seit einigen Jahren in Assembler und bin nun auf C++ im AVR 
Studio 6 umgestiegen. Komme auch ganz gut klar damit. Und es 
funktioniert auch das Meiste, bis jetzt. Nur wenn man die LCD Routinen 
vom AVR Tutorial vom Assembler 1:1 in C++ übersetzen tut. Würde man doch 
die Daten gleich direkt ans LCD-Port geben. Und in dem Beispiel für das 
LCD in C++ übergibt man es an eine statische Funktion und darüber erst 
ans LCD. Warum nicht gleich direkt ans LCD Port übergeben und einfach 
mit PIn_RS logisch verknüpfen ?

so zum beispiel:
1
void LCD_DATA(uint8_t data) //Daten an das LCD, 4 BIT MODUS, RS=1
2
{
3
  LCD_PORT=((data & 0xF0)>>4) | (1<<PIN_RS);   //die obersten 4 BIT senden
4
  lcd_enable();                 // PIN_E einschalten und ausschalten
5
6
  lcd_out(data & 0x0F) | (1<<PIN_RS);       // die untersten 4 BIT senden
7
  lcd_enable();               // PIN_E einschalten und ausschalten
8
  _delay_us(LCD_WRITEDATA_US);  //50 us Pause 
9
}

warum geht das so nicht ?
oder hab ich was falsch verstanden oder übersehen ?



Frage :
1. Warum so umständlich ?
2. Oder wird durch diese statische Funktion static void lcd_out(uint8_t 
data) in der LCD Routine eine Schnittstelle für das LCD definiert ?
3 . bei mir funktioniert die LCD Routine in C++, aus dem Tutorial , aber 
ab und zu spinnt mein LCD herum. Und stellt nur noch mist da ?

MFG...

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Norbert schrieb:

> ans LCD. Warum nicht gleich direkt ans LCD Port übergeben und einfach
> mit PIn_RS logisch verknüpfen ?

und wer sagt dir, dass der RS Pin und die Datenpins am gleichen Port 
sitzen?
Spricht ja nichts dagegen, dass die 4 Datenleitungen am Port D 
angeschlossen sind und die RS Leitung am Port B (oder wo halt sonst noch 
Platz war).
1
  LCD_PORT=((data & 0xF0)>>4) | (1<<PIN_RS);   //die obersten 4 BIT senden

du veränderst hier den kompletten Port. Du benutzt aber nur 5 Leitungen 
davon. Wer sagt dir, dass an den restlichen 3 Leitungen nicht irgendwas 
anderes angeschlossen ist.

Dein Problem: Du hast momentan nur das LCD im Auge. Schön. Aber in einem 
realen Programm hast du auch noch andere Komponenten im System. Zb ist 
da am selben Port ein Relais angeschlossen, das die Wasserpumpe eines 
Aquariums steuert. Du würdest dich schön bedanken, wenn jedesmal den 
Fischen ihre Pumpe ausgeschaltet wird, nur weil du einen Buchstaben ans 
LCD ausgibst.

Von Funktionen, die universell einsetzbar sein sollen, erwartet man ein 
bischen mehr. Zb. dass sie die, und NUR die Portpins manipulieren, die 
sie auch selbst benutzen und alle anderen in Ruhe lassen. Im Idealfall 
kann ich dann sogar noch völlig wahlfrei jeden beliebigen Portpin für 
eine Funktionalität benutzen, sebst wenn das heißt, dass dadurch 
Portpins sich über mehrere Ports verteilen. Denn manchmal geht das nicht 
anders. Dann muss man mit dem leben, was an Pins noch frei ist, wenn man 
ein LCD anschliesst. Denn die fixen Funktionen, die einzelnen Pins 
zugeordnet sind (Timer, PWM, UART, externe Interrupts) kann ich nicht 
ändern. Ein paar Drähte zum LCD kann ich aber dort anschliessen, wo noch 
was frei ist.

: Bearbeitet durch User
von Norbert (Gast)


Lesenswert?

Mein LCD hängt am PORT D, im 4 BIT MODUS, Pin 0-3 = DB4 -DB7 vom LCD,
PIN 4 = PIN RS, PIN 5 = PIN_E.

mein CODE war etwas falsch, sorry.

ich meinte so :
1
void LCD_DATA(uint8_t data) //Daten an das LCD, 4 BIT MODUS, RS=1
2
{
3
  LCD_PORT=((data & 0xF0)>>4) | (1<<PIN_RS);   //die obersten 4 BIT senden
4
  lcd_enable();                 // PIN_E einschalten und ausschalten
5
6
  LCD_PORT=(data & 0x0F) | (1<<PIN_RS);       // die untersten 4 BIT senden
7
  lcd_enable();               // PIN_E einschalten und ausschalten
8
  _delay_us(LCD_WRITEDATA_US);  //50 us Pause 
9
}

hab es schon so probiert, kommt aber nur mist am LCD an.
geht nicht korrekt.. ? WARUM ?

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Norbert schrieb:
> Mein LCD hängt ....

Deines!
Aber die Routinen im Tutorial sind allgemeine LCD-Routinen!

Wenn etwas allgemein einsetzbar sein soll, muss man eben ein wenig mehr 
Aufwand treiben.

> hab es schon so probiert, kommt aber nur mist am LCD an.
> geht nicht korrekt.. ? WARUM ?

Kann man so nicht sagen. Da fehlt zuviel.
Wo sind denn die Unterschiede zu den Tutorial-Funktionen. Achte auch 
darauf, wo die Tutoriumsfunktionen eine kleine Pause einlegen. Die 
machen das nicht ohne Grund.

von Norbert (Gast)


Lesenswert?

Danke erst mal....

Wie gesagt, mir geht es nur um das Verständnis.
Und wir gehen mal davon aus das ich nur ein LCD an Port D betreibe, an 
einem Atmega16.
Ich habe auch schon die Pausenzeiten etwas vergrößert, weil mein OLED 
doch etwas länger brauch um einen Befehl umzusetzten.
Aber mein eigener Code will halt nicht so Recht. Bzw. funktionirt das 
LCD nur kurzzeitig. Und dann stellt es nur noch Mist da.
Was mir unklar ist. Weil in Assembler das OLED bestens geht.

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.