mikrocontroller.net

Forum: Compiler & IDEs LCD-Tutorial.:)


Autor: Warhammer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hi, ich bin gerade dabei das LCD-Tutorial zu testen.

ich bekomme das Display im 4Bit Modus ans laufen, heisst der Cursor 
blinkt an der ersten stelle, aber mehr auch nicht.
// Ansteuerung eines HD44780 kompatiblen LCD im 4-Bit-Interfacemodus
// http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial
//
// Die Pinbelegung ist über defines in lcd-routines.h einstellbar
 
#include <avr/io.h>
#include "lcd-routines.h"
#include <util/delay.h>
 
// sendet ein Datenbyte an das LCD
 
void lcd_data(unsigned char temp1)
{
   unsigned char temp2 = temp1;
 
   LCD_PORT |= (1<<LCD_RS);        // RS auf 1 setzen
 
   temp1 = temp1 >> 4;
   temp1 = temp1 & 0x0F;
   LCD_PORT &= 0xF0;
   LCD_PORT |= temp1;               // setzen
   lcd_enable();
 
   temp2 = temp2 & 0x0F;
   LCD_PORT &= 0xF0;
   LCD_PORT |= temp2;               // setzen
   lcd_enable();
   
   _delay_us(42);
}
 
// sendet einen Befehl an das LCD
 
void lcd_command(unsigned char temp1)
{
   unsigned char temp2 = temp1;
 
   LCD_PORT &= ~(1<<LCD_RS);        // RS auf 0 setzen
 
   temp1 = temp1 >> 4;              // oberes Nibble holen
   temp1 = temp1 & 0x0F;            // maskieren
   LCD_PORT &= 0xF0;
   LCD_PORT |= temp1;               // setzen
   lcd_enable();
 
   temp2 = temp2 & 0x0F;            // unteres Nibble holen und maskieren
   LCD_PORT &= 0xF0;
   LCD_PORT |= temp2;               // setzen
   lcd_enable();
   
   _delay_us(42);
}
 
// erzeugt den Enable-Puls
void lcd_enable(void)
{
   // Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers einfügen
   // http://www.mikrocontroller.net/topic/81974#685882
   LCD_PORT |= 1<<LCD_EN;
    _delay_us(1);                   // kurze Pause
   // Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers verlängern
   // http://www.mikrocontroller.net/topic/80900
   LCD_PORT &= ~1<<LCD_EN;
}
 
// Initialisierung: 
// Muss ganz am Anfang des Programms aufgerufen werden.
 
void lcd_init(void)
{
   LCD_DDR = LCD_DDR | 0x0F | (1<<LCD_RS) | 1<<LCD_EN ;   // Port auf Ausgang schalten
 
   // muss 3mal hintereinander gesendet werden zur Initialisierung
 
   _delay_ms(15);
   LCD_PORT &= 0xF0;
   LCD_PORT |= 0x03;            
   LCD_PORT &= ~(1<<LCD_RS);      // RS auf 0
   lcd_enable();
 
   _delay_ms(5);
   lcd_enable();
 
   _delay_ms(1);
   lcd_enable();
   _delay_ms(1);
 
   // 4 Bit Modus aktivieren 
   LCD_PORT &= 0xF0;
   LCD_PORT |= 0x02;
   lcd_enable();
   _delay_ms(1);
 
   // 4Bit / 2 Zeilen / 5x7
   lcd_command(0x28);
    
   // Display ein / Cursor aus / kein Blinken
   lcd_command(0x0C); 
 
   // inkrement / kein Scrollen
   lcd_command(0x06);
 
   lcd_clear();
}
 
// Sendet den Befehl zur Löschung des Displays
 
void lcd_clear(void)
{
   lcd_command(CLEAR_DISPLAY);
   _delay_ms(5);
}
 
// Sendet den Befehl: Cursor Home
 
void lcd_home(void)
{
   lcd_command(CURSOR_HOME);
   _delay_ms(5);
}
 
// setzt den Cursor in Zeile y (1..4) Spalte x (0..15)
 
void set_cursor(uint8_t x, uint8_t y)
{
  uint8_t tmp;
 
  switch (y) {
    case 1: tmp=0x80+0x00+x; break;    // 1. Zeile
    case 2: tmp=0x80+0x40+x; break;    // 2. Zeile
    case 3: tmp=0x80+0x10+x; break;    // 3. Zeile
    case 4: tmp=0x80+0x50+x; break;    // 4. Zeile
  }
  lcd_command(tmp);
}
 
// Schreibt einen String auf das LCD
 
void lcd_string(char *data)
{
    while(*data) {
        lcd_data(*data);
        data++;
    }
}


 
int main(void)
{
    lcd_init();
 
    lcd_data('T');
    lcd_data('e');
    lcd_data('s');
    lcd_data('t');
 
    set_cursor(0,2);
 
    lcd_string("Hello World!");
 
    while(1)
    {
    }
 
    return 0;
}


beim Compilen bekomme ich folgende Fehlermeldung:

"../lcd-routines.c:126: warning: 'tmp' may be used uninitialized in this 
function"

versteh ich nicht so ganz...

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Warhammer (Gast)

>ich bekomme das Display im 4Bit Modus ans laufen, heisst der Cursor
>blinkt an der ersten stelle, aber mehr auch nicht.

Was? Ausgabe von Zeichen nicht möglich?

Und du musst den Code des tutorials nicht in voller Länge hier posten, 
das ist sinnlos.

>beim Compilen bekomme ich folgende Fehlermeldung:

>"../lcd-routines.c:126: warning: 'tmp' may be used uninitialized in this
>function"

Kann man hier ignorien. Oder schreib einfach

uint8_t tmp=0;

Dann ist die Warnung weg.

MFG
Falk

Autor: Warhammer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
joa oaky...

aber wie bekomme ich jetzt zeichen auf das dingen?

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Warhammer (Gast)

>aber wie bekomme ich jetzt zeichen auf das dingen?

Das steht ja wohl idiotensicher im Tutorial. Hast du die Taktfrequenz 
richtig angegeben?

MfG
Falk

Autor: Warhammer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
joa hab ich...erst hatte ich da die flasche drinne, aber nun die 
richtige...
der cursor binkt an der ersten stelle...

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und die Zeichen? Hello World!

Autor: Warhammer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
nein nix...nur der cursor am blinken

Autor: Frank B_. (frank_b) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Cursor darf eigentlich auch nicht blinken; das Blinken wird im Code 
doch zusammen mit dem Cursor abgeschaltet.

Bist du wirklich 100% sicher, dass Du es richtig verdrahtet hast ?

Poste doch mal das Makefile.

Autor: Warhammer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
öööhm makefile?

ich hab im avr studio als device den atmega88 ausgewählt.(GCC)

dann habe ich ein lcd-routines.c datei erstellt, und den inhalt aus dem 
tutorial kopiert, und das main file unten dran gehängt.

dann habe ich im gleichen ordner noch ein lcd-routines.h erstellt und 
die frequenz auf 4Mhz gestellt, und die Ports auf PORTB.

...
#define F_CPU 4000000

#define CLEAR_DISPLAY 0x01
#define CURSOR_HOME   0x02

#define LCD_PORT      PORTB
#define LCD_DDR       DDRB
#define LCD_RS        PB4
#define LCD_EN        PB5;

dann alles Compeliert und an das STK 500 übertragen. Verbindungen hab 
ich schon 2mal durchgemessen.

achja fuse bits.

da ist nur SPIEN an
BODLEVEL steht auf protection disable
und SUT_CKSEL steht auf Ext. Crystal 3-8mhz,....+65ms

mehr hab ich nicht gemacht...

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tatsächlich genau so?
#define LCD_EN        PB5;
Ok bei dem Code geht das zufällig gut. Ist aber trotzdem falsch.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Andreas Kaiser (a-k)

>#define LCD_EN        PB5;

>Ok bei dem Code geht das zufällig gut. Ist aber trotzdem falsch.

Wie meinen das der Herr?

MfG
Falk

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ahhh, das Semikolon.

Autor: Warhammer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
joa okay...

aber ; draussen...aber trotzdem kein text-.-

Autor: Warhammer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
keiner noch ne idee?

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich an deiner Stelle würde das Datenblatt vom Display und vom darin 
genannten LCD-Controller peinlich genau lesen und 
Initialisierungssequenz und -timing checken. Hast du den Namen des 
Displays und Link zu den Datenblättern schon gepostet?

Das derzeitige Hochfahren kann das normale Hardware-Hochfahren vom 
Display nach Power-Up sein und deine ganzen Kommandos seitens des µC 
versickern im Silizium. Hast du Messmöglichkeiten, um Reaktionen des 
Displays zu checken (Busyflag) und das Power-up von µC und LCD zu 
überwachen/steuern?

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Warhammer wrote:
> keiner noch ne idee?

Ich habs mir angewöhnt, IO-Pins als Bitvariablen zu definieren.

Das mit dem |=,&= verleitet doch zu gerne zu Fehlern.

x = 0; x = 1; ist gut lesbar und eindeutig.

Hier mal ein (bulletproof) Beispiel:

http://www.mikrocontroller.net/attachment/30300/lcd_drv.zip


Peter

Autor: Warhammer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hrm,

also es handelt sich um dieses

Disply:
http://www.powertip.com.tw/products_2.php?product_...

ich hab da keine "zeiten" gefunden

ich bin echt verzweifelt...

Autor: Gerd G. (elektrikser)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der LCD-Controller sollte ein KS0066U (http://www.eio.com/ks0066u.pdf) 
sein. Ist eigentlich kompatibel zum HD44780.

Autor: Michael H* (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
lad dir doch mal die demo von proteus runter. da gibts libs für display 
und µc und auch ein virtuelles oszi.
http://www.labcenter.co.uk/download/prodemo_download.cfm
und wenn das da alles wunderbar funktioniert, hast du wohl irgendwo 
einen hardwarefehler.

Autor: Stefan B. (stefan) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
In den Datenblättern sind schon etwas unterschiedliche Init-Sequenzen 
drin.

Autor: Stefan B. (stefan) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Man erkennt, dass beim KS0066U der grünmarkierte Teil nicht vorhanden 
ist und dass zwischen den anderen Befehlen bestimmte Wartezeiten 
einzuhalten sind. Ähnliche Wartezeiten sind auch beim HD44780 vorhanden, 
allerdings sind diese in einer anderen Tabelle (table 6) aufgeführt.

Die nächste Aufgabe ist ein Vergleich mit dem Tutorial-Code.

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dies ist die originale lcd_init aus dem Tutorial

void lcd_init(void)
{
   LCD_DDR = LCD_DDR | 0x0F | (1<<LCD_RS) | 1<<LCD_EN ;   // Port auf Ausgang schalten
 
   // muss 3mal hintereinander gesendet werden zur Initialisierung
 
   _delay_ms(15);
   LCD_PORT &= 0xF0;
   LCD_PORT |= 0x03;            
   LCD_PORT &= ~(1<<LCD_RS);      // RS auf 0
   lcd_enable();
 
   _delay_ms(5);
   lcd_enable();
 
   _delay_ms(1);
   lcd_enable();
   _delay_ms(1);
 
   // 4 Bit Modus aktivieren 
   LCD_PORT &= 0xF0;
   LCD_PORT |= 0x02;
   lcd_enable();
   _delay_ms(1);
 
   // 4Bit / 2 Zeilen / 5x7
   lcd_command(0x28);
    
   // Display ein / Cursor aus / kein Blinken
   lcd_command(0x0C); 
 
   // inkrement / kein Scrollen
   lcd_command(0x06);
 
   lcd_clear();
}

Für das KS0066U würde man es z.B. so anpassen. Ich habe allerdings kein 
LCD mit KS0066U zur Hand, um das zu testen.

Beim Ändern der Wartezeiten unbedingt die Dokumentation zu _delay_ms 
beachten. Je nach Prozessortakt gibt es Grenzen für den erlaubten Wert 
und längere Wartezeiten müssen in mehrere kleinere Wartezeiten 
aufgeteilt werden. 30ms im Einzelaufruf funktioniert nur unterhalb von 
8,734 MHz!

Statt 30ms auch mal mit 100ms experimentieren.

#define KS0066U 

void lcd_init(void)
{
   LCD_DDR = LCD_DDR | 0x0F | (1<<LCD_RS) | 1<<LCD_EN ;   // Port auf Ausgang schalten

#ifdef KS0066U 
   // 30ms (Einzelaufruf nur unterhalb F_CPU 8,734 MHz möglich)
   _delay_ms(10);  // lt. Datenblatt längere Wartezeit nach Power-On 
   _delay_ms(10);
   _delay_ms(10);
#else
   _delay_ms(15);

   // muss 3mal hintereinander gesendet werden zur Initialisierung
   LCD_PORT &= 0xF0;
   LCD_PORT |= 0x03;            
   LCD_PORT &= ~(1<<LCD_RS);      // RS auf 0
   lcd_enable();
 
   _delay_ms(5);
   lcd_enable();
 
   _delay_ms(1);
   lcd_enable();
   _delay_ms(1);
#endif 
 
   // 4 Bit Modus aktivieren 
   LCD_PORT &= 0xF0;
   LCD_PORT |= 0x02;
   lcd_enable();
   _delay_ms(1);

   // 4Bit / 2 Zeilen / 5x7
   lcd_command(0x28);
    
   // Display ein / Cursor aus / kein Blinken
   lcd_command(0x0C); 

#ifdef KS0066U 
   _delay_ms(2);
#endif 
 
   // inkrement / kein Scrollen
   lcd_command(0x06);
 
   lcd_clear();
}

Autor: Warhammer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
joa erstmal vielen dank, das du dir soviel mühe gemacht hast.

funktioniert leider immernoch nicht.

was mit bis jetzt aufgefallen ist.

wenn ich die spannung zuschalte ist es totaler zufall was auf dem 
display erscheint...habs jetzt so 10mal gemacht und 3-4mal hatte ich 
wieder den cursor am blinken 2mal hatte ich an der sten stelle einen 
buchstaben, ein "F" und noch einen, und im restlichen gar nix.

ich habe gerade nochmal testweise ein programm für die datenübertragung 
mit rs232 übertragen und ausprobiert(wollte den takt von 4MHz testen) 
das funktioniert einwandfrei.

noch ne idee?

und noch ne frage, wo hast du die schönen blockdiagramme und das wissen 
über die verwendetetn controller her? ich hab in den datenblättern 
keinen hinweis gefunden(allerdings steht da auch nur die PIN belegung 
und die Abmessungen)

achja
_delay_ms(10);
hab ich am anfang 10x hinternanter eingetragen...
auch keine änderung

Autor: Michael H* (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
...simulieren! die tuts sind an sich idiotensicher.

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Datenblätter findet man, wenn man in dem Datenblatt des Displays den 
Namen des LCD-Controllers herausfischt und dann mit diesem Namen eine 
Datenblattsuche macht (einfach über Google mit Namen und filetype:pdf) 
oder auf den verlinkten Seiten beim Wikiartikel LCD

Das Buntmalen habe ich mit einem Grafikprogramm gemacht, hatte heute 
mittag Langeweile ;-)

Im Moment habe ich auch keine bessere Idee (Verlängerung der Wartezeit 
vor dem ersten Kommando hast du ja schon gemacht).

In meiner Praxis habe ich festgestellt, dass eine ungültige 
Initialisierung den LCD-Controller blockieren kann. Also vor einem neuen 
Versuch mit neuem Programm das Targetboard und das LCD-Display stromlos 
machen.

Autor: Warhammer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hrm okay, ich habe das display dierekt 2mal bestellt,

werde morgen den ganzen kram mal mit dem atmega 16 ausprobieren.

Autor: Warhammer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
und dem anderen display

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.