Forum: Mikrocontroller und Digitale Elektronik lcd_puts und lcd_putc funktioniert nicht


von Holger (Gast)


Lesenswert?

Hallo,

ich verwende den PIC16f877 und ein hd44780 kompatibles 4x20 LCD. Das 
Display ist funktionstüchtig und ich kann auch mit der routine 
lcd_cursor() den cursor bewegen.

Jedoch bekomme ich keinen Text auf das Display.

Hier sind die Routinen:

/* write a byte to the LCD in 4 bit mode */
void lcd_write(unsigned char c)
{  PORTB = (PORTB & 0xF0) |  (c >> 4);
  LCD_STROBE;
  PORTB = (PORTB & 0xF0) |  (c & 0x0F);
  LCD_STROBE;
  DelayUs(40);
}

/* write a string of chars to the LCD */
void lcd_puts(const char * s)
{
  LCD_RS = 1;  // write characters
  while(*s)
    lcd_write(*s++);
}

/* write one character to the LCD */
void lcd_putch(char c)
{  LCD_RS = 1;  // write characters
  PORTB = (PORTB & 0xF0) |  (c >> 4);
  LCD_STROBE;
  PORTB = (PORTB & 0xF0) |  (c & 0x0F);
  LCD_STROBE;
  DelayUs(40);
}


Hat jemand vielleicht einen Tip?
Vielen Dank
Holger

von Fernando Heitor (Gast)


Lesenswert?

Hi

Schau mal hier rein :

http://www.fernando-heitor.de

Dort findest du eine funktionierende Routine für die LCD-Anzeige.


MFG
Fernando

von Holger (Gast)


Lesenswert?

Leider funktioniert dieses Programm mit dem Hi-Tech PICC Lite compiler 
nicht.
Den möchte ich aber wegen einem anderen Programm verwenden.
Trotzdem danke für den Tip.

von Fernando Heitor (Gast)


Lesenswert?

Ich habe gerade bei deinem Source Code entdeckt, dass du den Enable Pin 
nicht auf 0 setzt.

Ich weiss auch nicht was unter LCD_STROBE steckt, aber versuch mal 
zuerst ENABLE Pin auf 0 bevor du die zum LCD-Controller schickst zum 
Schluss der Übertragung eines Nibbles setzt du ENABLE auf high , 
pausiert ein paar us und dann setzt du ihn auf low.
Dann müsste es vielleicht klappen.

MFG
Fernando

von Holger (Gast)


Lesenswert?

Hinter lcd_strobe verbirgt sich folgendes:

#define  LCD_STROBE  ((LCD_EN = 1),(LCD_EN=0))

Doch wie füg ich hier ne Pause ein?

Vielleicht so:
#define  LCD_STROBE   ((LCD_EN = 1),(DelayUs(10)),(LCD_EN = 0))

von Fernando Heitor (Gast)


Lesenswert?

Ja das mit der Pause müsste klappen.
Aber setzt noch ein LCD_EN=0; in der LCD_PUTCH Routine , nach LCD_RS=1; 
, ein.

Und danach solltest du vielleicht die Anzeige mit einem Zeichen testen 
z.B.:

lcd_putch("T");
(im Hauptprogramm)


MFG
Fernando

von Holger (Gast)


Lesenswert?

Es funktioniert leider immernoch nicht!
Der  cursor springt nur an den Anfang der vierte Zeile wenn ich ein T 
schicke.

Ich hab keine Ahnung woran es noch liegen könnte.

MFG Holger

von Fernando Heitor (Gast)


Lesenswert?

Hast du den PIN R/W auf Masse gelegt?
An welchen Pins am PIC sind für die Anzeige belegt und welche ?
Denn dann kann ich dir schnell ein HEX-File geben, mit dem du wenigstens 
prüfen kannst , ob die Hardware OK ist.


MFG
Fernando

von Holger (Gast)


Lesenswert?

R/W liegt auf Masse
RS liegt auf RA2
Enable liegt auf RA3
Daten liegen auf RB0-RB3

Ich hab grad noch ausprobiert die Zeichenfolge T U V W X Y Z zu 
schicken. Das Display springt dann bei T in die vierte Zeile und mit 
jedem fortlaufenden Buchstaben geht es dann ein Felde weiter.

Danke
Holger

von Fernando Heitor (Gast)


Lesenswert?

Dann liegt es an der Initialisierung der Anzeige.

Auf der folgenden Seite findest du ein Tool um die genaue 
Initialisierung für den HD44780 zu bestimmen:

http://www.bluebird-electronics.co.uk/download.html



MFG
Fernando

von Holger (Gast)


Lesenswert?

Ich hab jetzt sämtliche Einstellungen probiert, aber es wandert trotzdem 
nur der cursor rum und zeigt nichts an.

Kannst Du mir doch den HEX code schicken, daß ich von der Hardware auf 
jeden Fall sicher bin?

Danke
Holger

von Fernando Heitor (Gast)


Angehängte Dateien:

Lesenswert?

Hier im Anhang:
HEX-File,Source-Code


MFG
Fernando

von Fernando Heitor (Gast)


Lesenswert?

Sorry habe vergessen noch zu schreiben was das Programm macht und du 
benötigst:

Taktfrequenz 4MHz
Er zählt eine Variable von 0-254 hoch, und pausiert zwischen zwei 
Werten(200ms).Schreibt vorher aber noch ein Text.


MFG
Fernando

von Holger (Gast)


Lesenswert?

Vielen Dank,

hab aber schon wieder ne Frage.
Wie kann ich in MPLAB nur das hex-file hernehmen um den PIC zu
programmieren?

MFG
Holger

von Fernando Heitor (Gast)


Lesenswert?

Wenn du den PICSTART PLUS verwendest, ist dies kein Problem.
Denn es gibt ein Menüpunkt für den Programmierer.

Wenn du aber ein anderes Programmiergerät hast z.B. PONY,PBrenner,GALEP, 
usw., dann benutzt du die eigene Software vom jeweiligen 
Programmiergerät.

MPLAB brauchst du aber nicht unbedingt um das HEX-File in den PIC zu 
brennen.


MFG
Fernando

von Holger (Gast)


Lesenswert?

Jetzt hab ich es endlich geschafft den Pic mit Deinem Hex code zu 
brennen. Und es funktioniert auch.
Gibt es von dem ccs compiler (den hast Du doch hierfür verwendet?) eine 
Demo-version oder eine free-version?

Dann kann ich versuchen, ob mein anderes Programm vielleicht von dem ccs 
compiler compiliert werden kann.
Kann man den ccs wie den Hi-Tech compiler auch in MPLAB einbinden?

Ansonsten muß ich den Fehler in meiner LCD-Ansteuerung finden.

Danke nochmal für Deine Mühen!
MFG
Holger

von Fernando Heitor (Gast)


Lesenswert?

Hi
Es gibt eine Version, die man downloaden kann, jedoch ist die begrenzt 
und kann nur für bestimmte PICs verwendet werden.
Und dein PIC ist leider nicht dabei.

CCS Compiler kann wie der HITECH in MPLAB integriert werden.

Also sieht es so aus , dass du dein Programm nach dem Fehler suchen 
musst.

Du kannst ja wenn du willst das Programm als Anhang hier posten, 
besonders den Teil der Initialisierung der Anzeige.

Dann schau ich mal rein.


MFG
Fernando

von Holger (Gast)


Angehängte Dateien:

Lesenswert?

Super nett wenn Du das machst!

Danke
Holger

von Fernando Heitor (Gast)


Lesenswert?

Ich habe mir dein Programm angeschaut.
Deine Fehler liegen in der Initialisierung und im Schreiben der Anzeige. 
Denn die kleine Routine LCD_STROBE wird zu oft verwendet. Das Enable 
Signal wird immer nur beim Ende eines Schreibvorganges auf High und dann 
auf Low gesetzt.
Aber bei dir wird dies bei jedem Signal gemacht, das du der Anzeige 
schickst, so dass die Initialisierung fehlerhaft ist.

Hier habe ich dir die folgenden Routine in der LCD.C geändert, dadurch 
müsste das Programm dann funktionieren:

/* write a byte to the LCD in 4 bit mode */
void
lcd_write(unsigned char c)
{
  LCD_RS=0;
        Delay_ms(2);
        LCD_RS=0;
        LCD_EN=0;
        PORTB = (PORTB & 0xF0) |  (c >> 4);
  //LCD_STROBE;
  PORTB = (PORTB & 0xF0) |  (c & 0x0F);
  LCD_STROBE;
  //DelayUs(40);
}

/* write one character to the LCD */
void
lcd_putch(char c)
{
  LCD_RS = 0;  // write characters
        Delay_ms(2);
  LCD_RS=1;
  LCD_EN=0;
  PORTB = (PORTB & 0xF0) |  (c >> 4);
  //LCD_STROBE;
  PORTB = (PORTB & 0xF0) |  (c & 0x0F);
  LCD_STROBE;
  DelayUs(40);
}


/* initialise the LCD - put into 4 bit mode */
void
lcd_init(void)
{
  LCD_RS = 0;  // write control bytes
  LCD_EN=0;
        DelayMs(15);  // power on delay
  PORTB = 0x3;  // attention!
        Delay_MS(5);
  //LCD_STROBE;
  PORTB = 0x3;
  //LCD_STROBE;
  DelayMs(5);
        PORTB = 0x3;
        DelayMs(5);
  //LCD_STROBE;
  //DelayUs(100);
  //LCD_STROBE;
  //DelayMs(5);
  PORTB = 0x2;  // set 4 bit mode
  //LCD_STROBE;
  DelayUs(40);
       lcd_write(0x28);  // 4 bit mode, 1/16 duty, 5x8 font
        lcd_write(0xC);  // display on, blink curson on
  lcd_write(1);    //Display löschen
  lcd_write(6);    //Adresspointer
}




Danach kannst du wie im Programm schon gemacht hast, die Zeichen mit 
LCD_PUTCH() ausgeben.

Ich hoffe es funktioniert.
Viel Spaß


MFG
Fernando

von Holger (Gast)


Lesenswert?

Tut mir leid,
es funktioniert leider immernoch nicht!
Aber ich hab mir grad mal delay.c angeschaut und festgestellt, dass da 
nach XTAL abgefragt wird, jedoch verwende ich den RC OSC. Wenn das nicht 
stimmt funktionieren die Pausen nicht richtig.
Kann das das Problem sein?
Wenn ja, wie änder ich dann die Funktion?
P.S.:
Tschuldige, daß ich Dich immer mit vielen Fragen bombadier!

von Fernando Heitor (Gast)


Lesenswert?

Mir ist gerade eingefallen, woran es liegen könnte.
Diesen Fehler habe ich früher auch mal gehabt, bei den PIC16F8XX. Du 
musst den Modus LVP ausschalten. Denn Pin RB3 wird dafür reserviert und 
kann dann nicht als I/O -Pin benutzt werden.
Das heisst schalte den LVP aus (LVP_DISABLED ich weiss ob es eine 
Funktion im HITECH dafür gibt, aber im def.h ist sie drin), das wird es 
wunderbar funktionieren.

P.S. Wenn du dich für bestimmte "tipps und Tricks" oder häufige Fehler 
bei der Mikrocontrollerprogrammierung interessierst, dann schau mal bei 
mir rein unter der Rubrik "Tipps und Tricks":

        http://www.fernando-heitor.de



MFG
Fernando

von Holger (Gast)


Lesenswert?

LVP hab ich schon von vornherein bei den ICD options disabled.
Ich hab mittlerweile auch einen XTAL angeschlossen, hilft aber auch 
nichts.

Nach Deinen Änderungen in lcd_init() ist der cursor auch nicht mehr 
gelaufen. Schon merkwürdig, dass der Cursor läuft wenn ich verschiedene 
Buchstaben schicke.

MFG
Holger

von Holger (Gast)


Lesenswert?

Ich hab grad gesehen, dass Du ausser nur Port A und B als Ausgang zu 
setzen auch noch andere Einstellungen gleich am Anfang von main() in 
lcd.c machst, muß ich da auch noch irgendwas einstellen?

Im Prinzip sind ja Deine Einstellungen richtig. Ich müsste also nur die 
gleichen machen und dann müsste es funktionieren.

MFG
Holger

von Fernando Heitor (Gast)


Lesenswert?

Die Sache mit dem Cursor liegt daran, dass die Option "Adresspointer 
inkrementieren und Displayinhalt nicht verschieben" nicht aktiviert war.

Tja bald weiss auch nicht mehr weiter.
Versuch mal meine Headerdateien lcd.h lcd16x2.h in dein Programm zu 
integrieren. Ausser der Spezial Funktionen #use , #fuses muss der HITECH 
die Routinen problemlos compilieren.

Die Einstellungen bei mir in main() sind nur bestimmte Vorkehrungen , 
die du hier aber nicht benötigst.
Das einzige worauf du achten musst, ist das du den LVP ausschaltest und 
den Port A definierst ( Standardzustand Port ist analog).

Das ist die einzige Möglichkeit, die ich sehe, ist dein Fehler in deinem 
zu suchen (habe selbst keinen mehr bei dir gefunden) oder du integrierst 
Stück für Stück mein Programm.

Sorry.


MFG
Fernando

von Holger (Gast)


Lesenswert?

Hi,

hab grad versucht Deine Routinen zu verwenden, kommen jedoch jede Menge 
Fehler.
Z.B.: Bei  byte CONST LCD_INIT_STRING[4] = {0x20 | (lcd_type 
<< 2),0xc, 1, 6};
kommt dieser Fehler
C:\PICCLITE\LCD.C: 29:missing basic type:int assumed (warning)
C:\PICCLITE\LCD.C: 29: , expected (error)
C:\PICCLITE\LCD.C: 29: , expected (error)

oder bei byte
kommt
C:\PICCLITE\LCD.C:44: argument redeclared: byte (error)

auch weiß ich nicht wie ich portb.lcddata=n ersetzen soll.



MFG
Holger

von Fernando Heitor (Gast)


Lesenswert?

Hi

Du kannst anstatt LCD_INIT_STRING, die Konstanten manuell angeben.
In der LCD_INIT() kannst du mit dem LCD_SEND_BYTE() die Werte angeben, 
z.B. LCD_SEND_BYTE(0,0x28) . Der Wert 0x28 ist diesem Beispiel das 
gleiche wie 0x20 | (lcd_type << 2)

Der Befehl #byte gibt es glaube ich nicht im HITECH.
Mit diesem Befehl (#byte portb=6) definiere den Port B mit Hardware 
Adresse 6. Im HITECH muss es sowas auch geben, vielleicht mit Zeigern 
oder so. Den struct Befehl muss HITECH können, ist ein ANSI C Befehl.


MFG
Fernando

von Holger (Gast)


Lesenswert?

Habe porta.enable und porta.rs mit folgendem ersetzt.
// Register select
static bit LCD_RS  @ ((unsigned)&PORTA*8+2);

// Enable
static bit LCD_EN  @ ((unsigned)&PORTA*8+3);

Wie kann ich aber portb.lcddata ersetzen?

von Fernando Heitor (Gast)


Lesenswert?

Du kannst doch den STRUCT-Befehl anwenden:


struct {
unsigned lcddata:4;  //PIN RB0-RB3
unsigned pinb4:1;
unsigned pinb5:1;
unsigned pinb6:1;
unsigned pinb7:1;
} portb;

Danach versuch entweder:

byte portb = 0x6

oder:

static unsigned char PORTB @ 0x6;
(Das muss vor dem struct-Befehl)

Dann wird es funktionieren, da bin ich mir sicher.


MFG
Fernando

von Holger (Gast)


Lesenswert?

Juhu,
Juhu, jetzt klappt es endlich.
Ich musste noch ADCON1 richtig setzen.
Jetzt geht es auch mit meinem alten Programm.

Trotdem nett, wie Du Dich darum gekümmert hast.


Mein nächstes Problem ist es nun den Wert einer Variablen auszugeben.Mit 
der Funktion printf(putch,"\fWert= %03u", wert)
funktioniert das bei meinem Programm nicht. Und einfach mit putch(wert) 
funktioniert auch nicht. Du hast nicht zufällig auch da eine Lösung 
parat?

MFG
Holger

von Fernando Heitor (Gast)


Lesenswert?

Super das es klappt, lag es nur an ADCON1? War er aktiviert?

Mit dem Wert ausgeben, kannst du printf verwenden.
Du hast es fast richtig:

printf(putch,"Wert= %03u",wert);


Die Option \f ist bei mir in der Routine eingebaut, damit lösche ich das 
Display.


MFG
Fernando

von Holger (Gast)


Lesenswert?

Ja es lag nur an ADCON.
Irgendwie muß er wohl bei PortA von Haus aus aktiviert sein.

Jetzt funktioniert auch noch die Ausgabe von Werten.
Was für ein Tag.

MFG
Holger

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.