> init();> lcd_init();
Dein init() fummelt bereits an den PORTA Leitungen zum LCD. Die 1000ms
Wartezeit in lcd_init() bis das LCD aus dem Power-On-Reset kommt,
verpufft.
> void lcd_init()> {> delayms(1000);> send(0b01000011); // Function set
Das ist sehr unterschiedlich zu den bewährten LCD Routinen aus dem
Tutorial in der Artikelsammlung.
Dort wird eine Initialierung verwendet um Kommandomodus zu kommen, die
auch arbeitet, wenn das LCD im 8-Bit oder 4-Bit Modus ist.
> /* PA0 Data1> 1 2> 2 3> 3 4
Da kommst du nicht weiter. Du musst für das 4-Bit Interface am LCD auf
DB4-DB7 ankommen, die unteren Datenleitungen DB0-DB3 am LCD sind
wirkungslos!
PA0: AVcc AGND und ARef sind korrekt beschaltet?
> WriteChar(01011000);
Die Zahl 01011000 ist nicht die Zahl, die du meinst, dass sie ist.
ist beispielsweise kompletter Unsinn.
Du musst dir bewusst sein, dass eine Zuweisung an einen Port immer ALLE
Portpins ändert. Ein
PORTA=1<<En; // Enable
ändert nicht nur die Enable Leitung, sondern auch die Datenleitungen,
die am selben Port liegen. Ein
PORTA=VeeEnRsRWData4321; // Vee En Rs RW Data4-1
ändert ebenfalls alle Portbits. Du verlangst hier nicht mehr oder
weniger vom Aufrufer, als das er dir ein Datenbyte übergibt, in dem die
entsprechenden Bits für Enbale und Rs bereits richtig gesetzt sind.
Wozu? Um dieses Detail kann sich die Funktion problemlos selber kümmern
und du hast beim Aufruf der Funktion ein Detailproblem weniger, um dass
du dich beim Aufruf kümmern musst.
Das hier
PORTA=0<<En; // Werte übernehmen
.... no comment.
Auch hier ändern sich wieder ALLE Portpins. Sie werden alle zu 0. Was
das LCD sieht (sehen würde, wenn du die korrekten Datenpins am LCD
benutzt), wenn du genau im Umschalten des Enable Pins auch die
Datenleitungen auf 0 fallen lässt, das wissen nur die Götter.
> _delay_ms(x);> _delay_us(y);
Sabotiert die Funktionen; die arbeiten mit variablem Argument anders als
gedacht.
> PORTA=VeeEnRsRWData4321; // Vee En Rs RW Data4-1
Ignoriert IMHO die Timing Vorgaben aus dem Datenblatt. Die RS und RW
müssen vor und nach dem Toggle von EN gesetzt sein.
> PORTA=0<<En; // Werte übernehmen
Im Moment des Pegelwechsels werden so LOW-Pegel vom LCD übernommen. Die
Zeit tH (Data Hold Time, min. 10 ns) wird nicht eingehalten.
Möglicherweise gibt es weitere Timingprobleme; habe ich nicht weiter
kontrolliert.
Vielen Dank für die schnellen Antworten. Das mit dem init() werde ich
gleich mal ausprobieren. Die Datenleitungen sind schon korekt, hab sie
hier nur mit dem falschen Namen kommentiert. (Data1 entspricht Data4
usw.) Sorry das ich das nicht erwähnt hab.
Ich wollte mal das Programm selberschreiben, damit ich es auch komplett
verstehe und weiß was ich gemacht habe. Wenn es einmal Funktioniert
werde ich mich wahrscheinlich immer mehr der bewährten Art annähern bis
das Programm perfekt ist.
@ ernst:
Ne ich habs ausprobiert, auf diese Art braucht das Programm nur einen
drittel vom Speicherplatz dens zuvor gebraucht hat ;)
@ Joe:
Ich hab schon überprüft ob die Signale richtig ankommen und dort konnte
ich keine Probleme feststellen. :)
Ups, das stimmt. Hab das PORTA=1<<EN; jetzt auf PORTA|=1<<EN geändert,
jetzt ändert sich nur noch das Enable.
Die Funktion werde ich später noch verbessern, dass es jetzt etwas
undhandlich ist, ist noch egal.
Also zuerst RW und RS auf 0 setzen, dann EN auf 1, kurz darauf die Daten
setzten, während Daten gesetzt sind EN wieder auf 0 und Daten werden
übernohmen?
Pseudocode:
PORTA|=0<<RW,0<<RS
delay (tas=0-10ns)
PORTA|=1<<EN
PORTA|=Daten
delay (tpw=460ns)
PORTA|=0<<EN
delay (th=10ns)
Wie kann ich 4 bits gleichzeitig setzten?
Wenn Daten zB: Daten=0b0101
und ich möchte diese Daten auf PINA0-3 setzen:
PORTA|=Daten; ... setzt das dann die Daten auf
die niedrigsten Bits also 0bxxxx0101 ?
> PORTA|=0<<RW,0<<RS
Du schreibst jetzt hundert mal
* Mit einer Oder-Operation kann man keine Bits auf 0 setzen.
Mit einem Oder kann man Bits auf 1 ziehen, aber nicht umgekehrt.
Dazu braucht man ein Und.
* Eine 0 kann man nach links schieben so oft man will, sie bleibt
immer 0. (Oder was gleichwertig ist, da ein Linksschieben einer
Multiplikation mit 2 entspricht: 0 kann man mit jeder beliebigen Zahl
multiplizieren, das Ergebnis wird wieder 0 sein)
Bitmanipulation
Aber eigentlich sind das alles Dinge, die man mit seinen ersten
Programmen, bei denen es um Led-ein/Led-aus, Lauflicht, Blinklicht etc.
geht, alle aussortiert und bis zum Erbrechen übt. Danach ist das Thema
'Wie werden einzelne Pins bzw. Pingruppen an einem Port korrekt und
nebenwirkungsfrei angesprochen' durch und man wendet sich schwereren
Dingen zu. Das korrekte und sichere Hantieren mit bitweisem
Und/Oder/Nicht und den entsprechenden Maskenbytes (und wie man sie
konstruiert) ist sozusagen das Kleine-Einmaleins der µC Programmierung.
Hi Ralf,
hast du mal das LCD Beispiel aus dem Tutorial hier ausprobiert? So
könntest du wenigstens prüfen/eingrenzen, ob es am Display liegt oder
nicht.
Bei mir funktioniert der Code aus dem Tutorial einwandfrei.
Gruß