Autor |
PIC16F877A + LCD Suche nach: lcd (4680) |
|
|
|
|
BID = 389926
marky Gerade angekommen
Beiträge: 6
|
|
Hallo,
bin neu hier und kenn mich außerdem noch nicht so gut mit der Programmierung von PICs aus.
Also folgendens, ich benutze einen PIC16F877A (20MHz Eingangstakt) und ein 16x2 LCD (AV1624)
Ich programmiere in C und benutze den CC5X-Compiler.
Ich habe schon kleine Testprogramme geschrieben, bei denen einfach ein Rechtecksignal an einem Pin des Ports ausgegeben wird. Hat alles super funktioniert.
Jetzt wollte ich mein LCD initialiseren. Hab dazu in der Beschreibung vom LCD nachgesehen. (LCD möchte ich im 4-BIT Mode betreiben)
So sieht mein Programm jetzt aus:
Zitat :
|
#include <C:\CC5\16F877A.h>
void pause(void)
{
OPTION=3;
TMR0=102;
while(TMR0);
}
void main(void)
{
PORTB=0x00;
TRISB=0b00000000;
pause();
pause();
pause();
pause();
pause();
pause();
pause();
pause();
pause();
pause();
pause();
pause();
pause();
pause();
pause();
pause();
pause();
pause();
pause();
pause();
PORTB=0b.00110100;
pause();
pause();
pause();
pause();
pause();
pause();
PORTB=0b.00110100;
pause();
PORTB=0b.00110100;
PORTB=0b.00100100;
PORTB=0b.11100100;
PORTB=0b.11000100;
PORTB=0b.00010100;
PORTB=0b.01100100;
}
|
Ich weiß sieht sehr stümperhaft aus. Mit pause erzeuge ich eine 1ms Pause.
Die Belegung der Pins vom LCD am PIC sieht so aus:
RB7...RB6...RB5...RB4...RB3..RB2..RB1..RB0..--> PIC
DB7...DB6..DB5...DB4.. R/W.. E.....RS.....-.....-->LCD
Normalerweise sollte doch nach der Initialisierung der Curser am LCD blinken oder?
Ein weiter Problem hab ich mit der Enable Leitung. Ich weißnicht ob diese 1 oder 0 sein muss. (Habs schon mit beiden ausprobiert - geht trotzdem nichts)
Könnt ihr mir vl helfen?
|
|
BID = 389964
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
|
1. Dein Code könnte optimierter sein.
2. Lies dir doch mal das Datenblatt genauer durch:
Wenn die E-Leitung 1 ist, passiert nix, erst bei der Flanke von 1 auf 0 (=fallende Flanke von E) werden die Daten an den Datenleitungen ins Register geschrieben.
Die Leitung RW legt fest, ob du lesen willst (also z.b. das Zeichen-RAM oder das Busyflag) und RS legt fest, ob die Daten als Befehl oder als Daten eben interpretiert werden.
Hinzu kommt im 4bit-Modus, dass die Datennibbles (á 4 Bit) auch getauscht werden müssen und man dem Controller exakt sagen muss, welches Display eigentlich angesteuert wird: ua. an eben, in welchem Modus das ganze läuft.
Weiters gibt es eine korrekte Initialisierungsabfolge, die ich hier zwar beschreiben könnte, aber das erstmal in deine Hände legen werde.
_________________
|
|
BID = 389966
marky Gerade angekommen
Beiträge: 6
|
Hallo,
also das mit der Flanke hab ich auch schon ausprobiert.
Habe nach jedem Befehl bei dem ich an PortB was ausgebe danach RB2(=Enable Leitung) auf 0 gesetzt.
Hat leider auch nicht funktioniert.
R/W liegt bei mir dauerhaft auf Masse, da ich nur schreiben will und nichts lesen.
Die Initialisierungabfolge für den 4Bit-Betrieb hab ich schon im Datenblatt zum LCD gefunden. Das Programm ist eigtl. schon so geschrieben, dass es das LCD initialisiert.
Hier hab ich die Initialisierung nochmal rauskopiert:
Keine Links zu Werbeschleudern - Um die Grafik passend zu verkleinern > paint verwenden! - imageshack.us
|
BID = 389968
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
Zitat :
|
PORTB=0b.00110100;
PORTB=0b.00100100;
PORTB=0b.11100100;
PORTB=0b.11000100;
PORTB=0b.00010100;
PORTB=0b.01100100;
|
Zitat :
|
Die Initialisierungabfolge für den 4Bit-Betrieb hab ich schon im Datenblatt zum LCD gefunden. Das Programm ist eigtl. schon so geschrieben, dass es das LCD initialisiert.
|
Ach?
Und wo sind die fallenden Flanken, das erneute setzen von E, das auswählen von Daten- und Befehlsregister und wo werden die Nibbles getauscht?
_________________
|
BID = 389973
marky Gerade angekommen
Beiträge: 6
|
Ok hier der neue Code. Hier wird nach jeder Ausgabe an PortB
das Enable Bit auf 0 gesetzt. Danach wieder auf 1.
Bei den Befehlen hab ich mich an die Initialisierung aus dem Datenblatt gehalten.
Aber da ich das mit den Nibbles nicht so ganz verstehe, könntest du mir das vl erklären?
Weiß bis jetzt nicht warum ich die tauschen muss. (Wie gesagt kenn mich noch nicht so gut aus)
Zitat :
|
#include <C:\CC5\16F877A.h>
void pause(void)
{
OPTION=3;
TMR0=102;
while(TMR0);
}
void main(void)
{
PORTB=0x00;
TRISB=0b00000000;
pause();
pause();
pause();
pause();
pause();
pause();
pause();
pause();
pause();
pause();
pause();
pause();
pause();
pause();
pause();
pause();
pause();
pause();
pause();
pause();
PORTB=0b.00110100;
PORTB.2=0;
pause();
pause();
pause();
pause();
pause();
pause();
PORTB=0b.00110100;
PORTB.2=0;
pause();
PORTB=0b.00110100;
PORTB.2=0;
PORTB=0b.00100100;
PORTB.2=0;
PORTB=0b.11100100;
PORTB.2=0;
PORTB=0b.11000100;
PORTB.2=0;
PORTB=0b.00010100;
PORTB.2=0;
PORTB=0b.01100100;
PORTB.2=0;
}
|
|
BID = 389980
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
1. Eine fallende Flanke kann nur erzeugt werden, wenn die Leitung vorher eine 1 hat; also Bit setzten, ein paar µs warten und Bit wieder löschen. Dann erst hat man einen Flankenwechsel von 1 auf 0!
2. Die Daten werden ja seriell zu je 4 Bits übertragen:
Im ersten Zyklus die oberen 4 Bit (also Bit4 bis Bit4) in den Port schreiben, E pulsen und dann das Byte umdrehen, sodass Bit0-3 dann an die Position von 4-7 gelangen und andersrum die Bits 4-7 nach 0-3 kommen.
Zwischen den beiden Übertragungen wird E auch kurz gepulst, um die Daten ins Daten-/Befehlsregister zu takten.
_________________
|
BID = 389984
marky Gerade angekommen
Beiträge: 6
|
Zu 1) Ahh alles klar, dann werde ich mal zwischen den Enable-Wechsel auch noch eine kurze Pause einfügen.
Zu 2) Verstehe ich jetzt auch. Nur in der Initialisierungroutine vom Datenblatt (siehe 2. Post von mir, da hab ichs angehängt) werden die unteren 4 Bit nie verwendet. Drum hab ich mich gewundert, dass ich diesen Nibble-Swap überhaupt brauche.
|
BID = 389992
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
Nachdem der Vierbitmodus eingestellt wurde, ist es wurscht, ob die oberen oder unteren Bits nicht gebraucht werden! Selbst wenn die oberen Bits alle 0 sind, müssen sie übertragen werden; ergo muss pro Zugriff nach dem Initialisieren im Vierbitmodus immer mit zwei Zyklen geschrieben werden.
_________________
|
BID = 390005
marky Gerade angekommen
Beiträge: 6
|
Dh. zusammengefasst: Meine Initialisierungsroutine stimmt bis auf die kurzen Pausen zwischen dem Enablewechsel.
Aber nach der Initialisierung muss ich dann immer beide Nibbles übertragen.
|
BID = 390010
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
Ich weiß nicht, wie dein aktueller Code aussieht, aber du hast im Obigen zumindest kein E gesetzt, sondern es immer nur gelöscht - das kann natürlich nicht klappen.
Desweiteren sagte ich, dass nach dem Einstellend des Vierbitmodus (siehe deine Anleitung) die nachfolgenden Daten im Vierbitmodus übertragen werden müssen, also musst du dein Programm entsprechend aufbereiten.
Weiterhin solltest du den Kram mit den Pausen lassen, sondern dir eine etwas effektivere Art ausdenken, x ms zu verzögern.
Außerdem rate ich dir dringend, alle Sachen, die mehrmals verwendet werden, in eine Funktion / Prozedur zu legen:
void lcd_data(char zeichen)
{
Datenregister per RS wählen
E setzen
Oberes Nibble zuerst ausgeben, andere Bits im Port unverändert lassen
E löschen -> Daten werden eingetaktet
Nibbles tauschen
E setzen
Unteres Nibble ausgeben, andere Bits im Port unverändert lassen
E löschen -> Daten eintakten
ca 100µs warten oder vieel besser: Busyflag pollen und so exakt feststellen, wenn der LCD-Controller fertig ist
}
Da die restlichen Bits im Port bis auf die Datenbits für das LCD nicht verändert dürfen werden (, damit man diese dann auch anderweitig nutzen kann), sollte man das mit OR-Maskierungen machen:
PORTB = Nibble | PORTB //in Nibble stehen die Werte drin, der Rest ändert sich nicht
Edit: Sry wegen der schlechten Formulierung teilweise. Bin ziemlich alle..
_________________
[ Diese Nachricht wurde geändert von: DonComi am 1 Dez 2006 18:47 ]
|
BID = 390015
marky Gerade angekommen
Beiträge: 6
|
Ja das mit den Pausen ist ein ziemlicher Pfusch , das muss ich auf jeden Fall ändern.
Und das mit der Funktion und der OR-Maskierung werde ich auf jeden Fall in mein Programm einbauen - Danke für den Tipp.
Jetzt nur noch eine Fragen wegen dem Enable.
Ich hätte es jetzt so gemacht:
Zitat :
|
PORTB=0b.00110100;
paar µS warten
PORTB.2=0;
|
Da das Enablebit ja eigentlich hier gesetzt wird: PORTB=0b.00110 100; (siehe 1. Post Pinbelegung
Oder liege ich hier falsch?
|
BID = 390027
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
Sollte so gehen, allerdings solltest du dir nohmals die Timing-Diagramme anschauen.
Es kommt auf jeden Fall auf die fallende Flnake an.
_________________
|