LCD-Display

Hi,
ich bin den halben Tag schon daran ein dämliches LCD-Display (2x16 4bit-ansteuerung)in betrieb zu nehmen, jedoch ohne erfolg.
Wenn ich Spannung darauf gebe, werden in der ersten Zeile nur dunkle Kästchen angezeigt.

Der code zum initialisieren des Displays

#define RS 8
#define EN 9
#define LED 10
#define LED2 13


void setup() {
  pinMode(RS,OUTPUT);
  pinMode(EN,OUTPUT);
  DDRD = 0xFF;
  pinMode(LED,OUTPUT);
  pinMode(LED2,OUTPUT);
  
  digitalWrite(RS,LOW);
  digitalWrite(EN,LOW);
  PORTD = 0x00;
  digitalWrite(LED,LOW);
  digitalWrite(LED2,LOW);
}

void loop() {
  LCD_Init();
  digitalWrite(LED2,HIGH);
  while(1)
  {
    
  }

}

void LCD_Init(void)
{
  delay(20);
  digitalWrite(RS,LOW);
  
  PORTD = 0x03;
  digitalWrite(EN,HIGH);
  delay(2);
  digitalWrite(EN,LOW);
  delay(2);
  digitalWrite(EN,HIGH);
  delay(2);
  digitalWrite(EN,LOW);
  
  delay(5);
  
  PORTD = 0x03;
  digitalWrite(EN,HIGH);
  delay(2);
  digitalWrite(EN,LOW);
  PORTD = 0x00;
  delay(2);
  digitalWrite(EN,HIGH);
  delay(2);
  digitalWrite(EN,LOW);
  
  delay(2);
  
  PORTD = 0x03;
  digitalWrite(EN,HIGH);
  delay(2);
  digitalWrite(EN,LOW);
  PORTD = 0x00;
  delay(2);
  digitalWrite(EN,HIGH);
  delay(2);
  digitalWrite(EN,LOW);
  
  delay(2);

  PORTD = 0x03;
  digitalWrite(EN,HIGH);
  delay(2);
  digitalWrite(EN,LOW);
  PORTD = 0x08;
  delay(2);
  digitalWrite(EN,HIGH);
  delay(2);
  digitalWrite(EN,LOW);  
  
  delay(2);

  PORTD = 0x00;
  digitalWrite(EN,HIGH);
  delay(2);
  digitalWrite(EN,LOW);
  PORTD = 0x08;
  delay(2);
  digitalWrite(EN,HIGH);
  delay(2);
  digitalWrite(EN,LOW); 
  
  delay(2);

  PORTD = 0x00;
  digitalWrite(EN,HIGH);
  delay(2);
  digitalWrite(EN,LOW);
  PORTD = 0x01;
  delay(2);
  digitalWrite(EN,HIGH);
  delay(2);
  digitalWrite(EN,LOW);   
  
  delay(2);

  PORTD = 0x00;
  digitalWrite(EN,HIGH);
  delay(2);
  digitalWrite(EN,LOW);
  PORTD = 0x07;
  delay(2);
  digitalWrite(EN,HIGH);
  delay(2);
  digitalWrite(EN,LOW);  
}

nach dem initalisieren hat sich leider nichts an der Darstellung geändert. Es wird immer noch die erste Zeile mit dunklen Kästchen gefüllt.

von PORTD sind nur die ersten 4 pins belegt (also 0-3)

Chandler

Hallo,

Du möchtest dafür keine Library nehmen und wirklich alles selbst programmieren?
Haste Dich streng an das Datenblatt gehalten?
Welches LCD haste denn überhaupt?

Hi
habe folgendes display

Bin nach der Initialisierung von Seite 5 durchgegangen. (wenn ich die richtig verstanden habe)

Ich möchte keine library dafür nehmen, da ich das Display bei funktion an einem anderen Controller verwenden möchte. Dies hat heute nicht funktioniert. hier habe ich allerdings nicht den Controller sondern das Arduino und wollte es daher so programmieren, damit ich dann so viel wie es geht übernehmen kann.

Soweit ich das sehe werden die Pins des Ports D nicht als Ausgänge definiert.

Du solltest außerdem den Zustand des Ports D einlesen, die Bits die Du willst ändern und dann Zurückschreiben und nicht einfach annehmen daß einige Bits immer LOW sind.

Grüße Uwe

Sieht katastrophal aus :o

Eine Libary muss nicht Arduino spezifisch sein, sowas kann man auch soweit auslagern, dass dieser für diverse Systeme verfügbar ist. Ich habe mir auch mal eine LCD Lib für den RPi geschrieben in GCC, die ich ohne weiteres auch auf andere Systeme portieren kann (zB AVR).

Des weiteren verstehe ich das ganze Mixed-System nicht. Entweder direkter Portzugriff, oder aber über die digitalWrite Variante.

PORTD wird doch durch DDRD=0xFF als ausgang definiert.

ich kann auch alles über Portzugriff erstellen

#define RS 8
#define EN 9
#define LED 10
#define LED2 13


void setup() {
  DDRB = 0xFF;
  DDRD = 0xFF;

  PORTB = 0x00;
  PORTD = 0x00;
}

void loop() {
  LCD_Init();
  PORTD = 0x00;  
  while(1)
  {
    
  }

}

void LCD_Init(void)
{
  delay(20);
  PORTB = 0x00;
  
  PORTD = 0x03;
  PORTB = 0x02;
  delay(2);
  PORTB = 0x00;
  PORTD = 0x00;
  delay(2);
  PORTB = 0x02;
  delay(2);
  PORTB = 0x00;
  
  delay(5);
  
  PORTD = 0x03;
  PORTB = 0x02;
  delay(2);
  PORTB = 0x00;
  PORTD = 0x00;
  delay(2);
  PORTB = 0x02;
  delay(2);
  PORTB = 0x00;
  
  delay(2);
  
  PORTD = 0x03;
  PORTB = 0x02;
  delay(2);
  PORTB = 0x00;
  PORTD = 0x00;
  delay(2);
  PORTB = 0x02;
  delay(2);
  PORTB = 0x00;
  
  delay(2);

  PORTD = 0x03;
  PORTB = 0x02;
  delay(2);
  PORTB = 0x00;
  PORTD = 0x08;
  delay(2);
  PORTB = 0x02;
  delay(2);
  PORTB = 0x00;
  
  delay(2);

  PORTD = 0x00;
  PORTB = 0x02;
  delay(2);
  PORTB = 0x00;
  PORTD = 0x08;
  delay(2);
  PORTB = 0x02;
  delay(2);
  PORTB = 0x00;
  
  delay(2);

  PORTD = 0x00;
  PORTB = 0x02;
  delay(2);
  PORTB = 0x00;
  PORTD = 0x01;
  delay(2);
  PORTB = 0x02;
  delay(2);
  PORTB = 0x00;
  
  delay(2);

  PORTD = 0x00;
  PORTB = 0x02;
  delay(2);
  PORTB = 0x00;
  PORTD = 0x07;
  delay(2);
  PORTB = 0x02;
  delay(2);
  PORTB = 0x00; 
}

jedoch finde ich das andere für mich übersichtlicher, da ich die Steuerpins so ansprechen kann, dass ich sofort sehe, welcher das ist.

aber auch diese SChreibweise bringt mich nicht zum erfolg.

Schau dir mal ein avr gcc Beispiel von Jurs aus einem anderem Forum an. Ich weiß immer noch nicht, was dein System bringt. Die Zeiten passen vermutlich auch noch nicht einmal zwingend.

https://www.mikrocontroller.net/topic/350554#3899961

Mein System bringt momentan auch noch nicht viel.
ich wollte einfach nur das Display benutzen können.
Das wollte ich nach dem Datenblatt machen, was ich aber nicht hinbekommen habe.

Wenn du derzeit mit dem Arduino testest, warum nicht dann die Lib von oben nutzen oder die in der IDE. Die sind alle simple (die Lib) selbst aufgebaut. Ggf. bei der aus der IDE den Klassenteil rausmachen.

Es ist komisch, immer heisst es man soll ins datenblatt schauen und es so machen wie es da steht. jetzt heisst es ich soll was anderes machen. Das soll jetzt nicht falsch verstanden werden, ich bin ja wirklich dankbar über deine hinweise.

habe jetzt das beispiel von mikocontroller.net angewendet. Dabei habe ich die header Datei wie folgt geändert

// Beispielbelegung für "LCD-Keypad-Shield an Arduino MEGA Boardd" 
#define LCD_RS 8,B
#define LCD_EN 9,B
#define LCD_DB4 4,D
#define LCD_DB5 5,D
#define LCD_DB6 6,D
#define LCD_DB7 7,D

in der hauptdatei habe ich noch eine setup-Funktion, sowie eine loop-funktion erstellt. Die loop Funktion habe ich zunächst lehr gelassen. Die Setup sieht wie folgt aus

void setup()
{
  lcd_init();
  lcd_clear();
  lcd_home();
}

aber selbst jetzt sehe ich nur schwarze Kästchen.

Ja natürlich soll man erst einmal das Datenblatt befragen. Das ist nicht falsch sondern eher richtig. Aber die Weise wie du an das Projekt rangehst, bzw. es zu verwirklichen willst, scheint mir kontraproduktiv.

Lege dich auf eine Schreibweise fest, entweder du nutzt die Arduino übliche Schreibweise, oder aber die direkte Portschreibweise (bevorzuge diese selber). Das kann ansonsten keiner mehr ohne Kommentare ohne weiteres lesen.

Mir ist aber nach deinem Code von oben nicht ersichtlich, auf welches Timings du dich berufst. Der Ablauf in meinen Teilen sieht da anders aus.

Sobald das Display mit Strom versorgt wird. (Start des µC) wird ~15ms gewartet. Danach wird ein weiteres mal ~4,1ms gewartet … 100µs gewartet. Das deckt sich irgendwie nicht mit deinem Code.

Oben in den codes habe ich immer mit delay(x) gewartet. hatte es zwischenzeitig auch mal so

void LCD_Init(void)
{
  delay(20);
  PORTB = 0x00;
  delay(20);
  
  lcd_write(0x30);
  delayMicroseconds(4200);
  lcd_write(0x30);
  delayMicroseconds(200);
  lcd_write(0x30);
  lcd_write(0x38);
  lcd_write(0x08);
  lcd_write(0x01);
  lcd_write(0x07);
}

void lcd_write(unsigned char cmd)
{
  PORTD = (cmd & 0xF0);
  PORTB = 0x02;
  delay(1);
  PORTB = 0x00;
//  delay(1);
  PORTD = ((cmd<<4) & 0XF0);
  PORTB = 0x02;
  delay(1);
  PORTB = 0x00;  
}

hier (ist ähnlich wie ich es am anfang hatte) warte ich immer 100us länger, da im datenblatt steht ‘wait for more than …’

aber das gab auch nichts.

fast befürchte ich, dass das display einen Defekt hat, obwohl es ganz neu ist.

Ich möchte das eigentlich auch nicht mit der Arduino-Schreibweise machen, da ich das ganze später mit einem PIC machen werde (sollte ich es zum laufen bekommen).

So, für heute ist dann doch feierabend. leider habe ich es doch nicht geschafft. schade, aber nicht änderbar.

bis dahin

Chandler_B:
PORTD wird doch durch DDRD=0xFF als ausgang definiert.

Entschuldige; hatte ich übersehen.
Uwe

Ich habe noch einmal eine Nachfrage.
also mit dem Sketch vom arduino funktioniert das display (ist also schon einmal nicht defekt)

wenn ich die header und code von LCD Keypad Shield zeigt nichts an - Mikrocontroller.net zum laufen bekommen würde, würde dieser dann auch einem kontroller der dspic30f-familie laufen? Damit soll es nämlich dann eigentlich laufen.

Chandler

Habe nie einen PIC programmiert, aber die Funktionen sind gut von der Hardware mit den Makros abgekoppelt. Soll heißen, es geht nicht direkt, aber es dürfte reichen, die entsprechenden h-Files nachzuladen für den Controller und die Makros anzupassen…

Chandler_B:
wenn ich die header und code von LCD Keypad Shield zeigt nichts an - Mikrocontroller.net zum laufen bekommen würde, würde dieser dann auch einem kontroller der dspic30f-familie laufen? Damit soll es nämlich dann eigentlich laufen.

Für einen PIC-Controller brauchst Du natürlich PIC-Code für den von Dir verwendeten PIC-Compiler.

Die auf www.mikrocontroller.net geposteten Library Routinen sind natürlich extrem hardwarenah programmiert und nur für AVR-Atmega Controller verwendbar.

Sowas wie diese ganz ausgefuchsten Makros zur Ansteuerung der internen Register funktioniert nur mit dem AVR-GCC Compiler und selbst mit diesem nur für Atmega Controllertypen:

// Einige Maktros für direkte Portprogrammierung definieren

/* Macro function to declare an output pin */
#define SETOUTPUT(x) _SETOUTPUT(x)
#define _SETOUTPUT(bit,port) DDR##port |= (1 << bit)

/* Macro function to declare an input pin */
#define SETINPUT(x) _SETINPUT(x)
#define _SETINPUT(bit,port) DDR##port &= ~(1 << bit)

/* Macro function to set an output pin high */
#define SETHIGH(x) _SETHIGH(x)
#define _SETHIGH(bit,port) PORT##port |= (1 << bit)

/* Macro function to set an output pin low */
#define SETLOW(x) _SETLOW(x)
#define _SETLOW(bit,port) PORT##port &= ~(1 << bit)

Diese Makros funktionieren bereits auf einem “Arduino DUE” nicht mehr, und natürlich erst Recht nicht nicht auf PIC Controllern mit einem anderen Compiler.

Auch die delay-Funktionen im Mikrosekundenbereich werden sicherlich anders gelöst werden müssen.

Also alles was hardwarenah ist:

  • Register auf OUTPUT oder INPUT setzen
  • Status eines INPUT Registers auslesen
  • Ausgang eines OUTPUT Registers auf HIGH oder LOW setzen
  • Mikrosekunden-Delay
    mußt Du an dem Code selbst neu schreiben. Passend für den Compiler und für den Controller.
    Alles andere kannst Du direkt übernehmen.

Statt so eine Library selbst zu programmieren, solltest Du aber wohl eher versuchen, Steuerroutinen für Deinen Ziel-Compiler und Ziel-Controller fertig im Internet zu finden. HD44780 kompatible LCD-Anzeigen sind nämlich ziemlicher Standard, so dass es fertige Routinen auch außerhalb der Welt von Arduino und AVR-Atmega geben sollte.

Wenn Du weder von Arduino- noch von AVR- oder PIC-Programmierung auch nur die leiseste Ahnung hast, wäre wahrscheinlich am vernünftigsten, mit der Arduino-IDE einzusteigen. Da ist Dein LCD-Display mit der zur IDE gehörenden LiquidCrystal-Library nämlich in genau der Zeitspanne in Betrieb zu nehmen, die Du benötigst, um ein Beispielprogramm zur LiquidCrystal-Library zu öffnen, kompilieren und auf das Arduino-Board zu laden. Ohne große Lernkurve und ohne ein Mikrocontroller-Studium.

Edit/Nachtrag:
Auch für PIC-Controller lassen sich fertige Codes im Internet finden.
Z.B. hier für einen PIC18F4520 controller.