LCD zeigt 4 Balken an

Gast #1242199
Lesenswert?

Ich habe irgendwie das Gefühl, dass in dem ATMEGA8 die FuseBits noch 
falsch gesetzt sind. Habe folgende Port Belegung für den 4 Bit Modus:

#define LCD_RS_PORT    PORTB
#define LCD_RS_DDR    DDRB
#define LCD_RS_NR    0
#define LCD_RS_PIN    PB0

#define LCD_EN_PORT    PORTD
#define LCD_EN_DDR    DDRD
#define LCD_EN_NR    7
#define LCD_EN_PIN    PD7

#define LCD_DATA_4_PORT    PORTD
#define LCD_DATA_4_DDR    DDRD
#define LCD_DATA_4_NR    6
#define LCD_DATA_4_PIN    PD6

#define LCD_DATA_5_PORT    PORTD
#define LCD_DATA_5_DDR    DDRD
#define LCD_DATA_5_NR    5
#define LCD_DATA_5_PIN    PD5

#define LCD_DATA_6_PORT    PORTD
#define LCD_DATA_6_DDR    DDRD
#define LCD_DATA_6_NR    4
#define LCD_DATA_6_PIN    PD4

#define LCD_DATA_7_PORT    PORTD
#define LCD_DATA_7_DDR    DDRD
#define LCD_DATA_7_NR    3
#define LCD_DATA_7_PIN    PD3
Gast #1242266
Lesenswert?

Also die Routinen funktionieren auf zwei anderen Displays wunderbar, nur 
bei dem Sch.. Ding nicht:



#include <avr/io.h>
#include "lcd.h"
#include "mydefs.h"
#include <util/delay.h>

// sendet ein Datenbyte an das LCD

void LCD_data(unsigned char temp1)
{
   unsigned char temp2 = temp1;

   LCD_rs_enable();              // RS auf 1 setzen

   temp1 = temp1 >> 4;
   temp1 = temp1 & 0x0F;

   LCD_write_in_ports(temp1);

   LCD_enable();

   temp2 = temp2 & 0x0F;

   LCD_write_in_ports(temp2);

   LCD_enable();

   _delay_us(42);
}

// sendet einen Befehl an das LCD

void LCD_command(unsigned char temp1)
{
   unsigned char temp2 = temp1;

   LCD_rs_disable();            // RS auf 0 setzen

   temp1 = temp1 >> 4;              // oberes Nibble holen
   temp1 = temp1 & 0x0F;            // maskieren

   LCD_write_in_ports(temp1);

   LCD_enable();

   temp2 = temp2 & 0x0F;            // unteres Nibble holen und 
maskieren

   LCD_write_in_ports(temp2);

   LCD_enable();

    _delay_us(42);
}

// erzeugt den Enable-Puls
void LCD_enable(void)
{
   // Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers 
einfügen
   // Beitrag "Re: Bitte helft mir. Schon wieder AtMega16"
   sbi(LCD_EN_PORT,LCD_EN_NR);
    _delay_ms(10);                   // kurze Pause
   // Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers 
verlängern
   // Beitrag "LCD -> Probleme mit Optimierungsgrad"
   cbi(LCD_EN_PORT,LCD_EN_NR);
}

// Initialisierung:
// Muss ganz am Anfang des Programms aufgerufen werden.

void LCD_init(void)
{

   // Alle LCD PORTS auf Ausgang schalten
   sbi(LCD_RS_DDR,LCD_RS_NR);
   sbi(LCD_EN_DDR,LCD_EN_NR);
   sbi(LCD_DATA_4_DDR,LCD_DATA_4_NR);
   sbi(LCD_DATA_5_DDR,LCD_DATA_5_NR);
   sbi(LCD_DATA_6_DDR,LCD_DATA_6_NR);
   sbi(LCD_DATA_7_DDR,LCD_DATA_7_NR);

   // muss 3mal hintereinander gesendet werden zur Initialisierung

    _delay_ms(15);

   // Schreiben einer 0x03
   LCD_write_in_ports(0x03);

   LCD_rs_disable();

   LCD_enable();

   _delay_ms(5);
   LCD_enable();

   _delay_ms(1);
   LCD_enable();
   _delay_ms(1);

   // 4 Bit Modus aktivieren
   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_us(100);
}

// Sendet den Befehl: Cursor Home

void LCD_home(void)
{
   LCD_command(CURSOR_HOME);
   _delay_ms(100);
}

// setzt den Cursor in Zeile y (1..4) Spalte x (0..15)

void LCD_set_cursor(unsigned char x, unsigned char y)
{
  unsigned char tmp=0;

  switch (y) {
    case 1: tmp=0x80+x; break;    // 1. Zeile
    case 2: tmp=0xC0+x; break;    // 2. Zeile
    case 3: tmp=0x94+x; break;    // 3. Zeile
    case 4: tmp=0xD4+x; break;    // 4. Zeile
  }
  LCD_command(tmp);
}

// Schreibt einen String auf das LCD

void LCD_string(char *data)
{
    while(*data) {
        LCD_data(*data);
        data++;
    }
}
void LCD_rs_enable(void)
{
  sbi(LCD_RS_PORT,LCD_RS_NR);
}
void LCD_rs_disable(void)
{
  cbi(LCD_RS_PORT,LCD_RS_NR);
}

void LCD_write_in_ports(unsigned char data)
{
  unsigned char i = 0, data_temp=0;

  while(i < 4)
  {
    data_temp = data;
    data_temp = data_temp >> i;
    data_temp &= 0x01;
    if(data_temp && (i == 0))   sbi(LCD_DATA_4_PORT,LCD_DATA_4_NR);
    else            cbi(LCD_DATA_4_PORT,LCD_DATA_4_NR);

    if(data_temp && (i == 1))  sbi(LCD_DATA_5_PORT,LCD_DATA_5_NR);
    else            cbi(LCD_DATA_5_PORT,LCD_DATA_5_NR);

    if(data_temp && (i == 2))  sbi(LCD_DATA_6_PORT,LCD_DATA_6_NR);
    else            cbi(LCD_DATA_6_PORT,LCD_DATA_6_NR);

    if(data_temp && (i == 3))  sbi(LCD_DATA_7_PORT,LCD_DATA_7_NR);
    else            cbi(LCD_DATA_7_PORT,LCD_DATA_7_NR);

    i++;
  }
}
Gast #1242287
Lesenswert?

Vielleicht hilft das noch weiter, wenn die Initialisierungsroutine 
durchgelaufen ist, dann steht der Cursor in der ersten Zeile an der 
letzten Stelle blinkend. Wenn ich den Kontrast erhöhe, wird die erste 
Zeile mit schwarzen Balken gefüllt. Die Initioalisierung auf den 4 Bit 2 
Zeilen 16 Zeichen funktioniert so gar nicht.
Gast #1242405
Lesenswert?

cbi(LCD_EN_DDR,LCD_RW_NR);

Solltest auch noch hinzufügen. Wenn RW irgendwo ausversehen gestzt wird 
könnte es auch zu Problemen kommen.

Ansonsten liegt das am richtigen Timing würde ich sagen. Busy Flag wird 
ja nicht abgefragt.
Gast #1242417
Lesenswert?

Also RW ist auf Masse gelegt. Kurzschluss zwischen den Signalleitungen 
habe ich nicht, Softwareverdrahtungsfehler ist auszuschließen, bereits 
1000 mal überprüft, an der Hardware und an der Software. Beim Electronic 
Assemblies schreibt er immer dieses Zeichen "|||".
#1242635
Lesenswert?

So ein ähnliches 'Problem' hatte ich vor kurzem auch an einem LCD.
Mein Problem war, dass ich die Datenleitungen am LCD an D0 bis D3 
anstelle von D4 bis D7 angelötet habe.

Im Nachhinein war ich verblüfft, das das LCD überhaupt initialisiert 
wurde, aber das wurde es zweifellos. Aber anstelle von Zeichen kamen bei 
einem Test nur lauter ausgefüllte Rechtecke zum Vorschein.
Gast #1242702
Lesenswert?

Danke für die Anmerkungen,

da das Ding immer nur die selben Zeichen schreibt, egal welches Zeichen 
ich schicke, gehe ich von einem Hardwarefehler aus. Also habe ich 
zunächst überprüft ob Kurzschlüsse zwischen den Signalleitungen sind. 
Dann habe ich die einzelnen Verbindungen vom Steckverbinder des LCD zum 
uC gemessen und vom Steckverbinder zu den Anschlüssen am LCD. Dann habe 
ich mal die Funktion

LCD_write_in_ports(0x03) am Steckverbinder nachgemessen:

DB4 = 1,2 V
DB5 = 1,2 V
DB6 = 0 V
DB7 = 0 V

Das habe ich variiert, die Bits werden richtig geschrieben.
Dann habe ich die Delayzeiten hochgeschraubt.

Habe das alles nun mit drei Pollin Displays und mit einem Electronic 
Assembly Display durchgeführt. Der Cursor springt immer in der ersten 
Zeile an die letzte Stelle. Dann werden immer die selben Zeichen "|||" 
geschrieben.

Die Belegung der Pins habe ich wie folgt gemacht:

PIN 1 = GND
PIN 2 = VCC
PIN 3 = Schleifer von Poti zw. Vcc und GND
PIN 4 = RS = PB0
PIN 5 = R/W = GND
PIN 6 = EN = PD7
PIN 7 bis PIN10 = offen
PIN 11 = PD6
PIN 12 = PD5
PIN 13 = PD4
PIN 14 = PD3
PIN 15 = VCC
PIN 16 = 330 Ohm -> GND

Welche Infos benötigt ihr noch? Vielen Dank für die Hilfe.
Gast #1242797
Lesenswert?

So nun tut sich folgendes:

Ich schreibe nach der Initialisierung eine 0x03 mit der Funktion 
LCD_write_in_ports(); dann kann ich am Steckverbinder an den Ports

DB4 = 1,2 V
DB5 = 1,2 V
DB6 = 0 V
DB7 = 0 V

die Spannungen messen.

Schreibe ich nun danach ein LCD_enable() ohne das Display am 
Steckverbinder zu haben, liegen an allen Ports nur

DB4 = 0 V
DB5 = 0 V
DB6 = 0 V
DB7 = 0 V

an. Irgendetwas stimmt also mit der Enable Leitungen oder dem Code 
nicht.
Gast #1242853
Lesenswert?

Also wenn ich die Ports einzeln high setze mit der Funktion sbi(...) 
kommen da immer korrekte 5 V an. Nehme ich die write_in_ports() kommen 
da 1,2 V bei High an und wenn ich nach der write_in_ports ein enable 
mache, dann liegen nur 0 V an. Irgendwas stimmt komischerweise mit den 
Funktionen nicht.
Gast #1242873
Lesenswert?

Habs raus:

void LCD_write_in_ports(unsigned char data)
{
  unsigned char i = 0, data_temp=0;

  while(i < 4)
  {
    data_temp = data;
    data_temp = data_temp >> i;
    data_temp &= 0b00000001;

    if(data_temp)
    {
      if(i == 0)  sbi(LCD_DATA_4_PORT,LCD_DATA_4_NR);
      if(i == 1)  sbi(LCD_DATA_5_PORT,LCD_DATA_5_NR);
      if(i == 2)  sbi(LCD_DATA_6_PORT,LCD_DATA_6_NR);
      if(i == 3)  sbi(LCD_DATA_7_PORT,LCD_DATA_7_NR);
    }
    else
    {
      if(i == 0)  cbi(LCD_DATA_4_PORT,LCD_DATA_4_NR);
      if(i == 1)  cbi(LCD_DATA_5_PORT,LCD_DATA_5_NR);
      if(i == 2)  cbi(LCD_DATA_6_PORT,LCD_DATA_6_NR);
      if(i == 3)  cbi(LCD_DATA_7_PORT,LCD_DATA_7_NR);
    }
    i++;
  }
}

keine Ahnung warum, für mich ist die Logik die selbe
Gast #1242888
Lesenswert?

Mach das doch ohne Schleife dann sparst du Code:
1
void LCD_write_in_ports(unsigned char data)
2
{
3

4
    if(data & 0x01)   sbi(LCD_DATA_4_PORT,LCD_DATA_4_NR);
5
    else cbi(LCD_DATA_4_PORT,LCD_DATA_4_NR);
6

7
    if(data & 0x02))  sbi(LCD_DATA_5_PORT,LCD_DATA_5_NR);
8
    else            cbi(LCD_DATA_5_PORT,LCD_DATA_5_NR);
9

10
    if(data & 0x04)  sbi(LCD_DATA_6_PORT,LCD_DATA_6_NR);
11
    else            cbi(LCD_DATA_6_PORT,LCD_DATA_6_NR);
12

13
    if(data & 0x08)  sbi(LCD_DATA_7_PORT,LCD_DATA_7_NR);
14
    else            cbi(LCD_DATA_7_PORT,LCD_DATA_7_NR);
15

16
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren