Archiv verlassen und diese Seite im Standarddesign anzeigen : LCD (KS0066) 4Bit-Mode init brauche hilfe, PIC 18f4550
andi.studi
20.07.2008, 02:32
Hallo PIC freunde ich hoffe ihr seid dieses Thema noch nicht leid, und könnt mir weiterhelfen, ich versuch es schon seit einer Woche ohne erfolg.
Ich möchte ein 4x20 LCD im 4-Bit mode ansteuern LCD Treiber ist ein KS0066.
Ich bekomme einfach kein Zeichen auf das LCD und manchmal sieht es nach einem reset so aus als wenn er im 1-Zeilenmodus wäre.
Bitte helft mir ich komme nicht weiter ;(
/************************************************** ************
C18-compiler
PortPin: Display
RB0 = E
RB2 = RS
RB3 = R/W
RB4..RB7 = D4..D7
************************************************** ***************************/
/** I N C L U D E S ************************************************** ********/
#include <p18f4550.h>
#include <delays.h>
/** D E F I N I T I O N S ************************************************** **/
#define PORTLCD LATB
#define TRIS_LCD TRISB
#define LCD_E PORTBbits.RB0
#define LCD_RS PORTBbits.RB2
#define LCD_RW PORTBbits.RB3
//************************************************** **************************
#pragma code
void delay100us(unsigned char multiplikator)
// for PicLSBK (16MHz Taktzyklus = 4 MHz Befehlszyklus)
{
Delay10TCYx(40*multiplikator); //40*10*0,25µs = 100 µs
}
void LCD_BUSY(void)
{
unsigned char temp1;
// unsigned char temp2;
do
{
TRIS_LCD = 0xF0; // LCD-PORT = high nibbles:eingang; low nibbles:ausgang
//Display abfrage
LCD_RS = 0; // LCD im Befehls-Mode
LCD_RW = 1; // LCD im Lesen-Mode
LCD_E = 1; // Enable (LCD)
temp1 = PORTLCD;
temp1 = temp1 & 0xF0; // Niederw.Nibble (steuerbits) ausmaskieren
LCD_E = 0; // toggeln
LCD_E = 1; // Enable (LCD)
// temp2 = PORTLCD;
// temp2 = (temp2>>4)&0x0f;
// temp2 = temp1 | temp2; // Nibbles verbinden
LCD_E = 0; // toggeln
} while (temp1>=0x80);
delay100us(1);
LCD_RW = 0; // Busy = low: LCD im Schreiben-Mode
TRIS_LCD = 0x00; // LCD-PORT = Ausgänge
PORTLCD = 0x00; // Daten und Steuerleitungen LOW
}
void LCD_WriteZeichen(unsigned char zeichen)
{
unsigned char x;
LCD_BUSY(); // Warten bis LCD bereit ist
// LCD_RW = 0; // LCD im Schreiben-Mode
LCD_RS = 1; // LCD im Befehl-Mode
x = zeichen & 0xf0;
PORTLCD = x; //höherwertiges nibbel
LCD_E = 1; // Enable (LCD)
LCD_E = 0;
x = zeichen;
x = (x << 4)& 0xf0; //niederwertiges nibbel
PORTLCD = x;
LCD_E = 1; // Enable (LCD)
LCD_E = 0;
LCD_RS = 0;
}
void LCD_WriteString(char *String)
{
char zeichen;
zeichen = *String;
while(zeichen !='\0')
{
LCD_WriteZeichen(zeichen); // zeichen am LC-Display ausgeben
String++;
zeichen = *String;
}
}
void LCD_WriteRegister(char data)
{
unsigned char x;
LCD_BUSY(); // Warten bis LCD bereit ist
// LCD_RW = 0; // LCD im Schreiben-Mode
// LCD_RS = 0; // LCD im Befehl-Mode
x = data & 0xf0;
PORTLCD = x; //höherwertiges nibbel
LCD_E = 1; // Enable (LCD)
LCD_E = 0;
x = data;
x = (x << 4)& 0xf0; //niederwertiges nibbel
PORTLCD = x;
LCD_E = 1; // Enable (LCD)
LCD_E = 0;
}
void LCD_Init(void)
{
// LCD initialisieren
TRIS_LCD = 0x00; // LCD-PORT = Ausgänge
PORTLCD = 0x00; // Daten und Steuerleitungen LOW
delay100us (150);
delay100us (150); // warte über 30ms
delay100us (2);
PORTLCD = 0x30; // Interface auf 8-Bit setzen
LCD_E = 1; // Enable (LCD)
LCD_E = 0;
delay100us(45);
// Interface auf 8-Bit setzen
LCD_E = 1; // Enable (LCD)
LCD_E = 0;
delay100us(45);
// Interface auf 8-Bit setzen
LCD_E = 1; // Enable (LCD)
LCD_E = 0;
delay100us(45);
PORTLCD = 0x20; // Interface auf 4-Bit setzen
LCD_E = 1; // Enable (LCD)
LCD_E = 0;
LCD_WriteRegister(0x28); // 2-zeilig, 5x8-Punkt-Matrix
LCD_WriteRegister(0x08); // Display aus
LCD_WriteRegister(0x01); // Display löschen
LCD_WriteRegister(0x02); // Kursor nach rechts wandernd, kein Display-Shift
LCD_WriteRegister(0x0C); // Display ein [ 0x0C = ein, 0x08 = aus ]
}
void main (void)
{
LCD_Init();
LCD_WriteZeichen('t');
LCD_WriteZeichen('e');
LCD_WriteZeichen('s');
LCD_WriteZeichen('t');
}
radbruch
20.07.2008, 14:30
Hallo
...
LCD_E = 1; // Enable (LCD)
LCD_E = 0;
...
Sollte da nicht noch eine kleine Verzögerung dazwischen sein? Ich weiß nicht wie schnell so ein PIC ist, aber laut Datenblatt (http://www.datasheetcatalog.org/datasheets2/55/553815_1.pdf) (Seite 31ff) sollte E min. 230ns (tw) high sein.
Gruß
mic
andi.studi
20.07.2008, 14:41
habe schon einen nop zwischen gelegt entspricht 0,25 µs. klappt leider auch nicht.
und ich habe noch nen fehler in der LCD_WriteZeichen gefunden
jetzt wird LCD_RS auch auf 1 gesetzt,
früher wurde es mit 0 überschrieben.
leider immernoch ohne erfolg
radbruch
20.07.2008, 15:28
Hallo
Das nop würde ich auf jeden Fall mal drinlassen, eventuell (zum Testen) sogar ein zweites. Poste doch nochmal den aktuellen Code (in code-Tags), speziell wegen dem RS- und dem RW-Bit. Ich würde RS generell auf High setzen und nur während des Inits (und bei Steuerbefehlen wie clear) auf Low schalten.
Display off/on kannst du testweise auch weglassen. Ob deine Busy-Abfrage funktionert weis ich nicht, sicherheitshalber könntest du Zwangsverzögerungen nach den Befehlen ( bei display_clear z.B. 1,5ms!) einbauen.
Gruß
mic
andi.studi
20.07.2008, 15:46
hier der aktuelle code, leider immernoch ohne erfolg
aber danke schonmal für die hilfe.
habe die BUSY abfrage erstmal rausgenomen und 25ms eingesetzt.
/************************************************** *****************************
PortPin: Display
RB0 = E
RB2 = RS
RB3 = R/W
RB4..RB7 = D4..D7
************************************************** ***************************/
/** I N C L U D E S ************************************************** ********/
#include <p18f4550.h>
#include <delays.h>
/** D E F I N I T I O N S ************************************************** **/
#define PORTLCD LATB
#define TRIS_LCD TRISB
#define LCD_E PORTBbits.RB0
#define LCD_RS PORTBbits.RB2
#define LCD_RW PORTBbits.RB3
#define nop _asm nop _endasm
//************************************************** **************************
#pragma code
void delay100us(unsigned char multiplikator)
// for PicLSBK (16MHz Taktzyklus = 4 MHz Befehlszyklus)
{
Delay10TCYx(40*multiplikator); //40*10*0,25µs = 100 µs
}
void LCD_BUSY(void)
{
unsigned char temp1;
// unsigned char temp2;
do
{
TRIS_LCD = 0xF0; // LCD-PORT = high nibbles:eingang; low nibbles:ausgang
//Display abfrage
LCD_RS = 0; // LCD im Befehls-Mode
LCD_RW = 1; // LCD im Lesen-Mode
LCD_E = 1; // Enable (LCD)
temp1 = PORTLCD;
temp1 = temp1 & 0xF0; // Niederw.Nibble (steuerbits) ausmaskieren
LCD_E = 0; // toggeln
LCD_E = 1; // Enable (LCD)
// temp2 = PORTLCD;
// temp2 = (temp2>>4)&0x0f;
// temp2 = temp1 | temp2; // Nibbles verbinden
LCD_E = 0; // toggeln
} while (temp1>=0x80);
delay100us(1);
LCD_RW = 0; // Busy = low: LCD im Schreiben-Mode
TRIS_LCD = 0x00; // LCD-PORT = Ausgänge
PORTLCD = 0x00; // Daten und Steuerleitungen LOW
}
void LCD_WriteZeichen(unsigned char zeichen)
{
unsigned char x;
delay100us(250);
// LCD_BUSY(); // Warten bis LCD bereit ist
x = zeichen & 0xf0;
// LCD_RW = 0; // LCD im Schreiben-Mode
LCD_RS = 1; // LCD im Befehl-Mode
PORTLCD = x; //höherwertiges nibbel
nop;
LCD_E = 1; // Enable (LCD)
nop;
LCD_E = 0;
delay100us(50);
x = zeichen;
x = (x << 4)& 0xf0; //niederwertiges nibbel
LCD_RS = 1; // LCD im Befehl-Mode
PORTLCD = x;
LCD_E = 1; // Enable (LCD)
nop;
LCD_E = 0;
nop;
LCD_RS = 0;
}
void LCD_WriteString(char *String)
{
char zeichen;
zeichen = *String;
while(zeichen !='\0')
{
LCD_WriteZeichen(zeichen); // zeichen am LC-Display ausgeben
String++;
zeichen = *String;
}
}
void LCD_WriteRegister(char data)
{
unsigned char x;
delay100us(250);
// LCD_BUSY(); // Warten bis LCD bereit ist
// LCD_RW = 0; // LCD im Schreiben-Mode
// LCD_RS = 0; // LCD im Befehl-Mode
x = data & 0xf0;
PORTLCD = x; //höherwertiges nibbel
LCD_E = 1; // Enable (LCD)
nop;
LCD_E = 0;
delay100us(50);
x = data;
x = (x << 4)& 0xf0; //niederwertiges nibbel
PORTLCD = x;
LCD_E = 1; // Enable (LCD)
nop;
LCD_E = 0;
}
void LCD_Init(void)
{
// LCD initialisieren
TRIS_LCD = 0x00; // LCD-PORT = Ausgänge
PORTLCD = 0x00; // Daten und Steuerleitungen LOW
delay100us (150);
delay100us (150); // warte über 30ms
delay100us (100);
PORTLCD = 0x30; // Interface auf 8-Bit setzen
LCD_E = 1; // Enable (LCD)
nop;
LCD_E = 0;
delay100us(50);
// Interface auf 8-Bit setzen
LCD_E = 1; // Enable (LCD)
nop;
LCD_E = 0;
delay100us(2);
// Interface auf 8-Bit setzen
LCD_E = 1; // Enable (LCD)
nop;
LCD_E = 0;
delay100us(2);
PORTLCD = 0x20; // Interface auf 4-Bit setzen
LCD_E = 1; // Enable (LCD)
nop;
LCD_E = 0;
LCD_WriteRegister(0x28); // 2-zeilig, 5x8-Punkt-Matrix
LCD_WriteRegister(0x08); // Display aus
LCD_WriteRegister(0x01); // Display löschen
LCD_WriteRegister(0x02); // Kursor nach rechts wandernd, kein Display-Shift
LCD_WriteRegister(0x0c); // Display ein [ 0x0C = ein, 0x08 = aus ]
}
void main (void)
{
LCD_Init();
LCD_WriteZeichen('t');
LCD_WriteZeichen('e');
LCD_WriteZeichen('s');
LCD_WriteZeichen('t');
}
radbruch
20.07.2008, 16:16
Hallo
In LCD_WriteRegister() sollte die Verzögerung nach dem Schreiben des zweiten Nipples sein (delay100us(50);), sonst scheint mir das richtig zu sein.
Kannst du nun mehr als eine Zeile erkennen (mit max. Kontrast)?
In LCD_WriteZeichen() scheint mir noch ein Fehler zu sein:
...
x = zeichen & 0xf0;
// LCD_RW = 0; // LCD im Schreiben-Mode
LCD_RS = 1; // LCD im Befehl-Mode
PORTLCD = x; //höherwertiges nibbel
...
Nach &0xf0 sind die Bits 0-3 in x gelöscht, RS ist aber bit2 und wird mit PORTLCD = x; wieder gelöscht. Richtig wäre wohl entweder eine andere Reihenfolge:
PORTLCD = x; //höherwertiges nibbel
LCD_RS = 1; // LCD im Befehl-Mode
oder eine andere Formulierung:
PORTLCD = x | 4; //höherwertiges nibbel und Datenmode setzen
Ich bin aber leider auch kein LCD-Profi, wir tasten uns ran ;)
Gruß
mic
andi.studi
20.07.2008, 16:47
;) LCD_WriteZeichen() hab ich kurz nach absenden des codes auch gefunden.
habe jetzt eine verzögerung von 5 ms nach dem ersten und 2. nibble in den funktionen LCD_WriteZeichen und LCD_WriteRegister eingefügt.
aber leider immer noch ohne licht am ender des tunels:(
ja ich sehe alle 4 zeilen, wobei sie aber ganz komisch flackern auch wenn ich nur init aufrufe.
hier der neue code
/** I N C L U D E S ************************************************** ********/
#include <p18f4550.h>
#include <delays.h>
/** D E F I N I T I O N S ************************************************** **/
#define PORTLCD LATB
#define TRIS_LCD TRISB
#define LCD_E PORTBbits.RB0
#define LCD_RS PORTBbits.RB2
#define LCD_RW PORTBbits.RB3
#define nop _asm nop _endasm
//************************************************** **************************
#pragma code
void delay100us(unsigned char multiplikator)
// for PicLSBK (16MHz Taktzyklus = 4 MHz Befehlszyklus)
{
Delay10TCYx(40*multiplikator); //40*10*0,25µs = 100 µs
}
void LCD_BUSY(void)
{
unsigned char temp1;
// unsigned char temp2;
do
{
TRIS_LCD = 0xF0; // LCD-PORT = high nibbles:eingang; low nibbles:ausgang
//Display abfrage
LCD_RS = 0; // LCD im Befehls-Mode
LCD_RW = 1; // LCD im Lesen-Mode
LCD_E = 1; // Enable (LCD)
temp1 = PORTLCD;
temp1 = temp1 & 0xF0; // Niederw.Nibble (steuerbits) ausmaskieren
LCD_E = 0; // toggeln
LCD_E = 1; // Enable (LCD)
nop;
LCD_E = 0; // toggeln
} while (temp1>=0x80);
delay100us(1);
LCD_RW = 0; // Busy = low: LCD im Schreiben-Mode
TRIS_LCD = 0x00; // LCD-PORT = Ausgänge
PORTLCD = 0x00; // Daten und Steuerleitungen LOW
}
void LCD_WriteZeichen(unsigned char zeichen)
{
unsigned char x;
delay100us(200);
delay100us(200);
// LCD_BUSY(); // Warten bis LCD bereit ist
LCD_RW = 0; // LCD im Schreiben-Mode
LCD_RS = 1; // LCD im Befehl-Mode
x = zeichen & 0xf0;
x = x | LCD_RS;
PORTLCD = x; //höherwertiges nibbel
nop;
LCD_E = 1; // Enable (LCD)
nop;nop;
LCD_E = 0;
delay100us(50); //5ms warten nach den 1.nibble
x = zeichen;
x = (x << 4)& 0xf0; //niederwertiges nibbel
x = x | LCD_RS;
PORTLCD = x;
delay100us(50); //5ms warten nach den 2.nibble
LCD_E = 1; // Enable (LCD)
nop;nop;
LCD_E = 0;
nop;
LCD_RS = 0;
}
void LCD_WriteString(char *String)
{
char zeichen;
zeichen = *String;
while(zeichen !='\0')
{
LCD_WriteZeichen(zeichen); // zeichen am LC-Display ausgeben
String++;
zeichen = *String;
}
}
void LCD_WriteRegister(char data)
{
unsigned char x;
delay100us(200);
delay100us(200);
// LCD_BUSY(); // Warten bis LCD bereit ist
// LCD_RW = 0; // LCD im Schreiben-Mode
// LCD_RS = 0; // LCD im Befehl-Mode
x = data & 0xf0;
PORTLCD = x; //höherwertiges nibbel
LCD_E = 1; // Enable (LCD)
nop;nop;
LCD_E = 0;
delay100us(50); //5ms warten nach den 1.nibble
x = data;
x = (x << 4)& 0xf0; //niederwertiges nibbel
PORTLCD = x;
delay100us(50); //5ms warten nach dem 2.nibble
LCD_E = 1; // Enable (LCD)
nop;nop;
LCD_E = 0;
}
void LCD_Init(void)
{
// LCD initialisieren
TRIS_LCD = 0x00; // LCD-PORT = Ausgänge
PORTLCD = 0x00; // Daten und Steuerleitungen LOW
delay100us (150);
delay100us (150); // warte über 30ms
delay100us (100);
PORTLCD = 0x30; // Interface auf 8-Bit setzen
LCD_E = 1; // Enable (LCD)
nop;nop;
LCD_E = 0;
delay100us(50); //warte 5ms
LCD_E = 1; // Interface auf 8-Bit setzen
nop;nop; // Enable (LCD)
LCD_E = 0;
delay100us(2); //warte 200µs
LCD_E = 1; // Interface auf 8-Bit setzen
nop;nop; // Enable (LCD)
LCD_E = 0;
delay100us(2); //warte 200µs
PORTLCD = 0x20; // Interface auf 4-Bit setzen
LCD_E = 1; // Enable (LCD)
nop;nop;
LCD_E = 0;
LCD_WriteRegister(0x28); // 2-zeilig, 5x8-Punkt-Matrix
LCD_WriteRegister(0x08); // Display aus
LCD_WriteRegister(0x01); // Display löschen
LCD_WriteRegister(0x02); // Kursor nach rechts wandernd, kein Display-Shift
LCD_WriteRegister(0x0c); // Display ein [ 0x0C = ein, 0x08 = aus ]
}
void main (void)
{
LCD_Init();
}
radbruch
20.07.2008, 17:09
Hallo
Die Wartezeit nach dem zweiten Nipple muss nach der Übergabe der Daten mit E erfolgen. Datentyp für Parameter bei write_register wäre unsigned char schöner, aber sollte auch mit char funktionieren. Ich würde immer noch die Display off/on-Befehle zum Testen weglassen. Bei
LCD_WriteRegister(0x02); // Cursor nach rechts wandernd, kein Display-Shift
müßte der Wert doch 0x06 sein, oder?
Entry ModeSet 0 0 0 0 0 0 0 1 I/D SH Assign cursor moving direction and enable the shift of entire display.
Gruß
mic
andi.studi
20.07.2008, 17:09
und noch ein fehler, es muss
void LCD_WriteRegister(unsigned char data) nur char ist zu klein
klappt aber immer noch nicht
andi.studi
20.07.2008, 17:24
mensch du bist klasse;) so langsam sollten die fehler aber angst bekommen und verschwinden wenn wir so weitermachen ;)
die wartezeit nach dem 2. nibble ist jetzt auch nach dem 2. nibble (also nach enable).
hast recht es muss 0x06 heißen da hat sich bei sprut wohl ein fehler eingeschlichen und ich hab es bein abtippen nicht gemerkt.
Display off ist auch raus. // on muss doch drin bleiben, oder nicht, ist ja nach der internen init aus.
/** I N C L U D E S ************************************************** ********/
#include <p18f4550.h>
#include <delays.h>
/** D E F I N I T I O N S ************************************************** **/
#define PORTLCD LATB
#define TRIS_LCD TRISB
#define LCD_E PORTBbits.RB0
#define LCD_RS PORTBbits.RB2
#define LCD_RW PORTBbits.RB3
#define nop _asm nop _endasm
//************************************************** **************************
#pragma code
void delay100us(unsigned char multiplikator)
// for PicLSBK (16MHz Taktzyklus = 4 MHz Befehlszyklus)
{
Delay10TCYx(40*multiplikator); //40*10*0,25µs = 100 µs
}
void LCD_BUSY(void)
{
unsigned char temp1;
// unsigned char temp2;
do
{
TRIS_LCD = 0xF0; // LCD-PORT = high nibbles:eingang; low nibbles:ausgang
//Display abfrage
LCD_RS = 0; // LCD im Befehls-Mode
LCD_RW = 1; // LCD im Lesen-Mode
LCD_E = 1; // Enable (LCD)
temp1 = PORTLCD;
temp1 = temp1 & 0xF0; // Niederw.Nibble (steuerbits) ausmaskieren
LCD_E = 0; // toggeln
LCD_E = 1; // Enable (LCD)
nop;
LCD_E = 0; // toggeln
} while (temp1>=0x80);
delay100us(1);
LCD_RW = 0; // Busy = low: LCD im Schreiben-Mode
TRIS_LCD = 0x00; // LCD-PORT = Ausgänge
PORTLCD = 0x00; // Daten und Steuerleitungen LOW
}
void LCD_WriteZeichen(unsigned char zeichen)
{
unsigned char x;
delay100us(200);
delay100us(200);
// LCD_BUSY(); // Warten bis LCD bereit ist
LCD_RW = 0; // LCD im Schreiben-Mode
LCD_RS = 1; // LCD im Befehl-Mode
x = zeichen & 0xf0;
x = x | LCD_RS;
PORTLCD = x; //höherwertiges nibbel
nop;
LCD_E = 1; // Enable (LCD)
nop;nop;
LCD_E = 0;
delay100us(50); //5ms warten nach den 1.nibble
x = zeichen;
x = (x << 4)& 0xf0; //niederwertiges nibbel
x = x | LCD_RS;
PORTLCD = x;
LCD_E = 1; // Enable (LCD)
nop;nop;
LCD_E = 0;
delay100us(50); //5ms warten nach den 2.nibble
LCD_RS = 0;
}
void LCD_WriteString(unsigned char *String)
{
unsigned char zeichen;
zeichen = *String;
while(zeichen !='\0')
{
LCD_WriteZeichen(zeichen); // zeichen am LC-Display ausgeben
String++;
zeichen = *String;
}
}
void LCD_WriteRegister(unsigned char data)
{
unsigned char x;
delay100us(200);
delay100us(200);
// LCD_BUSY(); // Warten bis LCD bereit ist
// LCD_RW = 0; // LCD im Schreiben-Mode
// LCD_RS = 0; // LCD im Befehl-Mode
x = data & 0xf0;
PORTLCD = x; //höherwertiges nibbel
LCD_E = 1; // Enable (LCD)
nop;nop;
LCD_E = 0;
delay100us(50); //5ms warten nach den 1.nibble
x = data;
x = (x << 4)& 0xf0; //niederwertiges nibbel
PORTLCD = x;
LCD_E = 1; // Enable (LCD)
nop;nop;
LCD_E = 0;
delay100us(50); //5ms warten nach dem 2.nibble
}
void LCD_Init(void)
{
// LCD initialisieren
TRIS_LCD = 0x00; // LCD-PORT = Ausgänge
PORTLCD = 0x00; // Daten und Steuerleitungen LOW
delay100us (150);
delay100us (150); // warte über 30ms
delay100us (100);
PORTLCD = 0x30; // Interface auf 8-Bit setzen
LCD_E = 1; // Enable (LCD)
nop;nop;
LCD_E = 0;
delay100us(50); //warte 5ms
LCD_E = 1; // Interface auf 8-Bit setzen
nop;nop; // Enable (LCD)
LCD_E = 0;
delay100us(2); //warte 200µs
LCD_E = 1; // Interface auf 8-Bit setzen
nop;nop; // Enable (LCD)
LCD_E = 0;
delay100us(2); //warte 200µs
PORTLCD = 0x20; // Interface auf 4-Bit setzen
LCD_E = 1; // Enable (LCD)
nop;nop;
LCD_E = 0;
LCD_WriteRegister(0x28); // 2-zeilig, 5x8-Punkt-Matrix
// LCD_WriteRegister(0x08); // Display aus
LCD_WriteRegister(0x01); // Display löschen
LCD_WriteRegister(0x06); // Kursor nach rechts wandernd, kein Display-Shift
LCD_WriteRegister(0x0c); // Display ein [ 0x0C = ein, 0x08 = aus ]
}
void main (void)
{
LCD_Init();
LCD_WriteZeichen('t');
}
radbruch
20.07.2008, 18:03
Hallo
Tja, so langsam gehen mir die Ideen aus. Du könntest bei Display on (sollte doch besser drin bleiben) ein 0x0f übergeben, dann müßte der Cursor irgendwo sichtbar sein und blinken.
Was ich noch nicht nachvollziehen kann ist das Timeing mit den Verzögerungen. Vielleicht nochmal prüfen ob wirklich die erwartete Zeit gewartet wird. Wird bei Delay10TCYx() wirklich ein 16-bit-Wert erwartet (z.B. 40*200)? Im Zweifel eine kleine Blinksteuerung im Sekundentakt programmieren und mit Stoppuhr überprüfen:
void blink(void)
{
unsigned char temp;
while(1)
{
led_an;
for(temp=0; temp<50; temp++) delay100us(200); // 50*20ms=1sek
led_aus;
for(temp=0; temp<50; temp++) delay100us(200); // 50*20ms=1sek
}
}
(ungetestet)
Gruß
mic
andi.studi
20.07.2008, 18:51
hi
hast mal wieder recht
an Delay10TCYx() darf nur 0..255 sprich 8 bit
hab die funktion abgeändert leider viel mir auf dieschnelle nix beseres ein als eine long veriable zu verwende.
void delay100us(unsigned long multiplikator)
// for PicLSBK (16MHz Taktzyklus = 4 MHz Befehlszyklus)
{
unsigned long i;
for (i=0;i<(multiplikator*400);i++) // 400*nop=100µs
{nop;}
}
lcd flackert nicht mehr, aber zeichen sind auch nicht drauf zu erkennen ](*,)
HILFE ](*,)
radbruch
20.07.2008, 19:15
Hallo
Der multiplikator kann ja weiterhin 8 Bit haben, muß also nicht long sein.
Vielleicht wird die Schleife von Kompiler wegrationalisiert. Ich verzögere mit Dummy-Befehlen in der Zählschleife:
void delay(uint8_t d)
{
uint16_t d1, dummy;
for (d1=d*255; d1>0; d1--) dummy^=d1;
}
Eleganter wäre allerdings dies:
void delay100us(unsigned char multiplikator)
// for PicLSBK (16MHz Taktzyklus = 4 MHz Befehlszyklus)
{
while(multiplikator--) Delay10TCYx(40); //40*10*0,25µs = 100 µs
}
Wenn die Wartezeit zu kurz ist scheint mir der Clearbefehl kritisch, weil der recht lange zur Ausführung benötigt. Dann würden die nachfolgenden Einstellungen ins Nirwana gehen. Vielleicht mal testweise ohne clear initialisieren. Hast du das mit dem "Display on-Cursor on-Cursor blink" mal getestet?
Gruß
mic
andi.studi
20.07.2008, 19:18
erstes erfolgs erlebnis init scheint zu funktionieren, auch wenn nur seeeehr langsam.
hab zum test das display auf einzeilig umgestellt
LCD_WriteRegister(0x20); funktioniert
zudem bei LCD an courser an
LCD_WriteRegister(0x0f); fungtioniert auch
das komische
erst nach sa 5 sec ist 1 zeilen mode aktiv
nach weiteren 20 sec blinkt der courser an positon 1
nach 6 sec geht er wieder für 20 sec aus und kommt für 6 sec wieder.
von einem zeichen keine spur
andi.studi
20.07.2008, 19:32
deine while schleife gefällt mir sehr gut, ich war so frei sie gleich einzubauen.
courser blinkt nun an erster position aber im wechsel mit einem rechteck 5x8 dot's
radbruch
20.07.2008, 19:41
Hallo
...ich war so frei sie gleich einzubauen.
So war's auch gedacht :)
Schön, immerhin ein Fortschritt. Zeig doch nochmal deinen aktuellen (geputzten?) Code. Ich würde das Übernehmen der Daten in eine Funktion schreiben und nochmals die high-Zeit verlängern:
void strobe(void)
{
LCD_E = 1; // Daten übernehmen
delay100us(3);
LCD_E = 0;
}
Hast du ein Datenblatt für dein Display (oder eine genaue Typangabe)? Ich verwende das oben erwähnte KS0066U-Datenblatt (http://www.datasheetcatalog.org/datasheets2/55/553815_1.pdf) (war eine der ersten Fundstellen der Suchmaschine), vielleicht gibt's da Unterschiede.
Blockcursor 5x8 ist schon richtig. Ist das Init() und das Blinken immer noch so langsam?
Gruß
mic
andi.studi
20.07.2008, 20:01
link zum datenblatt meines LCD
http://www.zyscom.pl/katalog/ym2004a.pdf
verwende das gleiche controler datenblat wie du : http://www.datasheetcatalog.org/datasheets2/55/553815_1.pdf
init ist nun sehr schnell fertig :) und keine pausen danach, courser blinkt fröhlich an zeilen anfang ununterbrochen.
/** I N C L U D E S ************************************************** ********/
#include <p18f4550.h>
#include <delays.h>
/** D E F I N I T I O N S ************************************************** **/
#define PORTLCD LATB
#define TRIS_LCD TRISB
#define LCD_E PORTBbits.RB0
#define LCD_RS PORTBbits.RB2
#define LCD_RW PORTBbits.RB3
#define nop _asm nop _endasm // verzögerung 0,25µs
//************************************************** **************************
#pragma code
void delay100us(unsigned char multiplikator)
// for PicLSBK (16MHz Taktzyklus = 4 MHz Befehlszyklus)
{
while(multiplikator--) Delay10TCYx(40); //40*10*0,25µs = 100 µs
}
void LCD_BUSY(void)
{
unsigned char temp1;
// unsigned char temp2;
do
{
TRIS_LCD = 0xF0; // LCD-PORT = high nibbles:eingang; low nibbles:ausgang
//Display abfrage
LCD_RS = 0; // LCD im Befehls-Mode
LCD_RW = 1; // LCD im Lesen-Mode
LCD_E = 1; // Enable (LCD)
temp1 = PORTLCD;
temp1 = temp1 & 0xF0; // Niederw.Nibble (steuerbits) ausmaskieren
LCD_E = 0; // toggeln
LCD_E = 1; // Enable (LCD)
nop;
LCD_E = 0; // toggeln
} while (temp1>=0x80);
delay100us(1);
LCD_RW = 0; // Busy = low: LCD im Schreiben-Mode
TRIS_LCD = 0x00; // LCD-PORT = Ausgänge
PORTLCD = 0x00; // Daten und Steuerleitungen LOW
}
void LCD_WriteZeichen(unsigned char zeichen)
{
unsigned char x;
delay100us(200);
// LCD_BUSY(); // Warten bis LCD bereit ist
LCD_RW = 0; // LCD im Schreiben-Mode
LCD_RS = 1; // LCD im Befehl-Mode
x = zeichen & 0xf0;
x = x | LCD_RS;
PORTLCD = x; //höherwertiges nibbel
nop;
LCD_E = 1; // Enable (LCD)
nop;nop;
LCD_E = 0;
delay100us(50); //5ms warten nach den 1.nibble
x = zeichen;
x = (x << 4)& 0xf0; //niederwertiges nibbel
x = x | LCD_RS;
PORTLCD = x;
LCD_E = 1; // Enable (LCD)
nop;nop;
LCD_E = 0;
delay100us(50); //5ms warten nach den 2.nibble
LCD_RS = 0;
}
void LCD_WriteString(unsigned char *String)
{
unsigned char zeichen;
zeichen = *String;
while(zeichen !='\0')
{
LCD_WriteZeichen(zeichen); // zeichen am LC-Display ausgeben
String++;
zeichen = *String;
}
}
void LCD_WriteRegister(unsigned char data)
{
unsigned char x;
delay100us(200);
// LCD_BUSY(); // Warten bis LCD bereit ist
// LCD_RW = 0; // LCD im Schreiben-Mode
// LCD_RS = 0; // LCD im Befehl-Mode
x = data & 0xf0;
PORTLCD = x; //höherwertiges nibbel
LCD_E = 1; // Enable (LCD)
nop;nop;
LCD_E = 0;
delay100us(50); //5ms warten nach den 1.nibble
x = data;
x = (x << 4)& 0xf0; //niederwertiges nibbel
PORTLCD = x;
LCD_E = 1; // Enable (LCD)
nop;nop;
LCD_E = 0;
delay100us(50); //5ms warten nach dem 2.nibble
}
void LCD_Init(void)
{
// LCD initialisieren
TRIS_LCD = 0x00; // LCD-PORT = Ausgänge
PORTLCD = 0x00; // Daten und Steuerleitungen LOW
delay100us (150);
delay100us (150); // warte über 30ms
delay100us (100);
PORTLCD = 0x30; // Interface auf 8-Bit setzen
LCD_E = 1; // Enable (LCD)
nop;nop;
LCD_E = 0;
delay100us(50); //warte 5ms
LCD_E = 1; // Interface auf 8-Bit setzen
nop;nop; // Enable (LCD)
LCD_E = 0;
delay100us(2); //warte 200µs
LCD_E = 1; // Interface auf 8-Bit setzen
nop;nop; // Enable (LCD)
LCD_E = 0;
delay100us(2); //warte 200µs
PORTLCD = 0x20; // Interface auf 4-Bit setzen
LCD_E = 1; // Enable (LCD)
nop;nop;
LCD_E = 0;
LCD_WriteRegister(0x28); // 2-zeilig, 5x8-Punkt-Matrix
LCD_WriteRegister(0x08); // Display aus
LCD_WriteRegister(0x01); // Display löschen
LCD_WriteRegister(0x06); // Kursor nach rechts wandernd, kein Display-Shift
LCD_WriteRegister(0x0f); // Display ein [ 0x0C = ein, 0x08 = aus ]
}
void main (void)
{
LCD_Init();
LCD_WriteZeichen('t');
LCD_WriteZeichen('x');
}
andi.studi
20.07.2008, 20:13
noch mal mit funktion void enable (void)
/** D E F I N I T I O N S ************************************************** **/
#define PORTLCD LATB
#define TRIS_LCD TRISB
#define LCD_E PORTBbits.RB0
#define LCD_RS PORTBbits.RB2
#define LCD_RW PORTBbits.RB3
#define nop _asm nop _endasm // verzögerung 0,25µs
//************************************************** **************************
#pragma code
void delay100us(unsigned char multiplikator)
// for PicLSBK (16MHz Taktzyklus = 4 MHz Befehlszyklus)
{
while(multiplikator--) Delay10TCYx(40); //40*10*0,25µs = 100 µs
}
void enable(void)
{
LCD_E = 1; // Daten übernehmen
delay100us(3);
LCD_E = 0;
}
void LCD_BUSY(void)
{
unsigned char temp1;
// unsigned char temp2;
do
{
TRIS_LCD = 0xF0; // LCD-PORT = high nibbles:eingang; low nibbles:ausgang
//Display abfrage
LCD_RS = 0; // LCD im Befehls-Mode
LCD_RW = 1; // LCD im Lesen-Mode
LCD_E = 1; // Enable (LCD)
temp1 = PORTLCD;
temp1 = temp1 & 0xF0; // Niederw.Nibble (steuerbits) ausmaskieren
LCD_E = 0; // toggeln
enable();
} while (temp1>=0x80);
delay100us(1);
LCD_RW = 0; // Busy = low: LCD im Schreiben-Mode
TRIS_LCD = 0x00; // LCD-PORT = Ausgänge
PORTLCD = 0x00; // Daten und Steuerleitungen LOW
}
void LCD_WriteZeichen(unsigned char zeichen)
{
unsigned char x;
delay100us(200);
// LCD_BUSY(); // Warten bis LCD bereit ist
LCD_RW = 0; // LCD im Schreiben-Mode
LCD_RS = 1; // LCD im Befehl-Mode
x = zeichen & 0xf0;
x = x | LCD_RS;
PORTLCD = x; //höherwertiges nibbel
nop;
enable();
delay100us(50); //5ms warten nach den 1.nibble
x = zeichen;
x = (x << 4)& 0xf0; //niederwertiges nibbel
x = x | LCD_RS;
PORTLCD = x;
enable();
delay100us(50); //5ms warten nach den 2.nibble
LCD_RS = 0;
}
void LCD_WriteString(unsigned char *String)
{
unsigned char zeichen;
zeichen = *String;
while(zeichen !='\0')
{
LCD_WriteZeichen(zeichen); // zeichen am LC-Display ausgeben
String++;
zeichen = *String;
}
}
void LCD_WriteRegister(unsigned char data)
{
unsigned char x;
delay100us(200);
// LCD_BUSY(); // Warten bis LCD bereit ist
// LCD_RW = 0; // LCD im Schreiben-Mode
// LCD_RS = 0; // LCD im Befehl-Mode
x = data & 0xf0;
PORTLCD = x; //höherwertiges nibbel
enable();
delay100us(50); //5ms warten nach den 1.nibble
x = data;
x = (x << 4)& 0xf0; //niederwertiges nibbel
PORTLCD = x;
enable();
delay100us(50); //5ms warten nach dem 2.nibble
}
void LCD_Init(void)
{
// LCD initialisieren
TRIS_LCD = 0x00; // LCD-PORT = Ausgänge
PORTLCD = 0x00; // Daten und Steuerleitungen LOW
delay100us (150);
delay100us (150); // warte über 30ms
delay100us (100);
PORTLCD = 0x30; // Interface auf 8-Bit setzen
enable();
delay100us(50); //warte 5ms
// Interface auf 8-Bit setzen
enable(); // Enable (LCD)
delay100us(2); //warte 200µs
enable(); // Interface auf 8-Bit setzen
// Enable (LCD)
delay100us(2); //warte 200µs
PORTLCD = 0x20; // Interface auf 4-Bit setzen
enable(); // Enable (LCD)
LCD_WriteRegister(0x28); // 2-zeilig, 5x8-Punkt-Matrix
LCD_WriteRegister(0x08); // Display aus
LCD_WriteRegister(0x01); // Display löschen
LCD_WriteRegister(0x06); // Kursor nach rechts wandernd, kein Display-Shift
LCD_WriteRegister(0x0f); // Display ein [ 0x0C = ein, 0x08 = aus ]
}
void main (void)
{
LCD_Init();
LCD_WriteZeichen('t');
LCD_WriteZeichen('x');
}
andi.studi
20.07.2008, 20:55
wenn ich nach
ein 'E' ausgeben will. bekomme ich aufeinmal 2 blinkende courser einen in der ersten zeile an 1. stelle (wie gehabt) und einen 2 . in der 2. zeile an 5. stelle???
void main (void)
{
LCD_Init();
LCD_WriteZeichen('E');
}
radbruch
20.07.2008, 22:49
Hallo
Ein Verdacht:
'E' hat den Hexwert 0x45, das ist Binär 0b01000101. Wenn nun beim Schreiben der Daten das RS nicht gesetzt wäre, würde dies den Start des Usergraphik-Bereich definieren:
Set CGRAM Address 0 0 0 1 AC5 AC4 AC3 AC2 AC1 AC0 Set CGRAM address in address counter.
Alle weiteren Daten würden dann in den Grafikspeicher geschrieben werden, der Cursor würde aber vermutlich trotzdem im sichtbaren Bereich bewegt werden. Das ist allerdings reine Spekulation. Was ich in diesem Zusammenhang nicht weiß:
x = x | LCD_RS;
Funktioniert dies wie erwartet? Der Wert für LCD_RS ist doch 1, wir benötigen aber 4 (RS ist PortBit2) zum verodern, oder? Vielleicht mal sicherheitshalber doch diese Formulierung verwenden:
x = zeichen & 0xf0;
PORTLCD = x; //höherwertiges nibbel
LCD_RS = 1; // LCD Daten-Mode setzen
Gruß
mic
andi.studi
20.07.2008, 23:14
Der Wert für LCD_RS ist doch 1, wir benötigen aber 4 (RS ist PortBit2)
#define LCD_RS PORTBbits.RB2
sobald LCD_RS auf 1 gesetzt wird sollte auch RB2 high ein (wertigkeit 4)
werde es aber an einem einfacheren prog testen.
x = zeichen & 0xf0;
PORTLCD = x; //höherwertiges nibbel
LCD_RS = 1; // LCD Daten-Mode setzen
wersuch ich gleich mal...
void LCD_WriteZeichen(unsigned char zeichen)
{
unsigned char x;
delay100us(250);
// LCD_BUSY(); // Warten bis LCD bereit ist
LCD_RW = 0; // LCD im Schreiben-Mode
LCD_RS = 1; // LCD im Befehl-Mode
delay100us(1);
x = zeichen & 0xf0;
PORTLCD = x; //höherwertiges nibbel
LCD_RS=1;
delay100us(1);
enable();
delay100us(50); //5ms warten nach den 1.nibble
x = zeichen;
x = (x << 4)& 0xf0; //niederwertiges nibbel
PORTLCD = x;
LCD_RS=1;
delay100us(1);
enable();
delay100us(50); //5ms warten nach den 2.nibble
LCD_RS = 0;
}
=D> =D> =D> ich hab ein zeichen :)
leider sieht es so aus als wenn es ständig neu geschrieben würde es flackert etwas.
andi.studi
20.07.2008, 23:20
while (1);
nach LCD_WriteZeichen('X');
und das flackern ist weg
radbruch
20.07.2008, 23:32
Das bedeutet, es funktioniert? Juhu!
while(1); am Ende von main() ist ja klar, im Eifer des Gefechts glatt übersehen...
Viel Spass mit dem Display.
mic
andi.studi
20.07.2008, 23:56
hm schade das ich hier kein bild posten kann
sonst würdest du jetzt ein foto des LCD sehen, au dem steht
HaLLo Mic vielen dan
tuetzung !!!
k fuer Deine Unters
danke noch mal,
jetzt kann ich beruhigt ins bett, sitze schon seit einer woche daran.
jetzt fehlen noch die feinheiten, aber der anfang ist ja schonmal da;)
dank nochmal ohne dich hätte ich bestimmt noch ne weitere woche gebraucht um das zu erziehlen.
andi.studi
23.07.2008, 17:34
hallo mic,
und alle anderen microcontroller freunde.
weiß einer von euch wieso ich zwar folgendermassen einen string ans lcd senden kann:
.
.
.
.
void LCD_WriteString(unsigned char *string)
{
while(*string)
{
LCD_WriteZeichen(*string++); // zeichen am LC-Display ausgeben
}
void main (void)
{
unsigned char buffer[]="hallo";
LCD_Init();
LCD_WriteString(buffer);
while(1);
}
aber in der folgenden form:
void main (void)
{
LCD_Init();
LCD_WriteString("hallo..");
while(1);
}
diese compiler fehlermeldungen bekomme?
196:Warning [2054] suspicious pointer conversion
sie bezieht sich auf "LCD_WriteString("hallo..");"
LCD_WriteZeichen('H'); klappt doch auch.
ich ich müsste einem pointer wie *string ja auch in folgender vorm was zuweisen können:
string="hallo"; oder liege ich da falsch und er schickt <hallo> ins nirvana???
hoffe jemand kann mir helfen
Matzenerich
15.08.2008, 18:37
Hallo Andreas,
kann ich Dir so auch noch nicht sagen, aber hier tummelst Du Dich also rum!
Gruß
Matthias \:D/
andi.studi
15.08.2008, 18:51
hi Matthias,
bist du etwa auch fleißig?
dieses Thema kann aber geschlossen werden ;)
sehe https://www.roboternetz.de/phpBB2/viewtopic.php?t=41967
string an lcd senden, string in pointer speichern
const rom ist die lösung
void LCD_WriteString(const rom int8 *string)
{
while(*string)
{
LCD_WriteZeichen(*string++); // zeichen am LC-Display ausgeben
}
}
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.