Forum: Mikrocontroller und Digitale Elektronik LCD zeigt Schrott an


von Stefan B. (Gast)


Angehängte Dateien:

Lesenswert?

Hi Leute!

Hab ein Problem mit dem Pollin-Evaluations-Board und dem dazugehörigen 
Addon-Board mit LC-Display. Hab die ganze Sache komplett selbst 
zusammengebaut und mit dem Demotool überprüft. Passt alles, Funktioniert 
einwandfrei.

Bei meinem eigenen Programm soll eine LED 5x Blinken und dann den Text 
"Hallo Welt" auf dem Display schreiben. Die LED blinkt dann weiter. Ich 
bekomme aber nur folgendes auf dem Display dargestellt:

H`}ln1Fu}d

Belegung des Displays:

DB0 FREI
DB1 FREI
DB2 FREI
DB3 FREI
DB4 PD4
DB5 PD5
DB6 PD6
DB7 PD7
E   PB2
NC  FREI
RS  PB0
R/W GND bzw. PB1 (hat keine Auswirkung)

Komm einfach nicht mehr weiter! Muss ich DB0-DB3 auf GND legen oder frei 
lassen. Stimmt mein Programm nicht? Display ist ein TC1602A-08
Hab ich falsche Ports genommen?Ich bin so langsam am verzweifeln.

Danke für eure Hilfe

von Andreas K. (derandi)


Lesenswert?

Dann zeig doch mal den Code deines eigenen Programmes.
Eventuell schon mal andere, fertige Libaries für die Ansteuerung 
benutzt?
Peter Fleury scheint da schon einen quasi-Standart etabliert zu haben.
Sehr einfach zu benutzen.

von Stefan B. (Gast)


Lesenswert?

So hier meine einzelnen Dateien mit dem Code. Wie gesagt, ich hatte mal 
das Demoprogramm von Pollin für dieses Board aufgespielt und es hat auch 
erst nach etlichen Versuchen geklappt, aber es hat 100% funktioniert. 
Ich glaub, damals hatte ich ein Masse-Problem bei den Steckbrücken. Das 
Schaltbild vom Board ist nicht gerade aussagekräftig. Auch wie ich 
welche Kontakte auf GND legen muss und welche nicht kann man hier nicht 
rauslesen. Müssen die freien Kontakte beim Display auf GND gelegt 
werden?

Ich hab es so weit hinbekommen, das ich "wenigstens" ein paar wirre 
Zeichen angezeigt bekomme. Also viel kann es doch jetzt nicht mehr sein.

Das untenstehende Programm haben wir von unserem Lehrer bekommen, sollte 
mit Port-Anpassungen auch für das Pollin-Board funktionieren. 
Funktioniert auf den ET Stamp- Boards einwandfrei.

Über Programmers Notepad und makefile wandel ich das ganze um. Auch die 
makefile Datei haben wir vom Lehrer


______________________________________________________________________ 
__

Datei hallowelt.c

// LED blinken lassen und Ausgabe "Hallo Welt" auf dem LC-Display

#include "led.h"
#include "lcd.h"

int main() {

  LED_init();
  LCD_init();

  LCD_instruction(LCD_DISP_ON);

  LED_blinken(5);
  LCD_puts("Hallo Welt");

  while(1) {
    LED_blinken(5);
  }
}

______________________________________________________________________ 
__

Datei led.c

#include <avr/io.h>
#include <util/delay.h>

#include "ledmap.h"
#define delaytime 500


void LED_init() {

  //PA1 als Ausgang setzen
  LED_DDR = LED_DDR | 1 << LED_PIN;
}

void LED_blinken() {
  int i;

for(i=1; i<=5; i=i+1) {
    LED_PORT = LED_PORT | (1 << LED_PIN);//LED an
    _delay_ms(delaytime);
    LED_PORT = LED_PORT & ~(1 << LED_PIN);//LED aus
    _delay_ms(delaytime);
  }

}

______________________________________________________________________ 
__

led.h
void LED_init ();
void LED_blinken(unsigned char anzahl);

______________________________________________________________________ 
__

Datei ledmap.h

// LED Verbindungen mit AVR


#define LED_DDR DDRA
#define LED_PORT PORTA
#define LED_PIN PA0

______________________________________________________________________ 
__

Datei lcd.c

/*********************************************************************** 
********
 File:    lcd.c
 Compiler:  AVR-GCC 3.3
 Hardware:  AVR
 Date:    04.06.2009

 Basic routines for interfacing a HD44780U-based text LC-Display
 4bit mode, microcontroller I/O port, write only (rw pin -> GND),
 dual- or single-line display
************************************************************************ 
*******/

#include <avr/io.h>
#include <avr/pgmspace.h>
#include <util/delay.h>

#include "lcd.h"
#include "lcdmap.h"


// execution time for instructions (LCD specific)
#define EXETIMELONG  1640  // execution time (us) for CLR and HOME 
instruction
#define EXETIMESHORT   40  // execution time (us) for all other 
instructions


/*********************************************************************** 
********
Low-level function to write byte to LCD controller
Input:   b    byte to write to LCD
     rs    1: data write
        0: instruction write
************************************************************************ 
*******/
static void write(unsigned char b, _Bool rs)
{
  if(rs) PORT(RS_PORT) |= (1 << RS); else PORT(RS_PORT) &= ~(1 << RS);

  // output high nibble
  PORT(EN_PORT) |= (1 << EN);
  if(b & 0x80) PORT(DB7_PORT) |= (1 << DB7); else PORT(DB7_PORT) &= ~(1 
<< DB7);
  if(b & 0x40) PORT(DB6_PORT) |= (1 << DB6); else PORT(DB6_PORT) &= ~(1 
<< DB6);
  if(b & 0x20) PORT(DB5_PORT) |= (1 << DB5); else PORT(DB5_PORT) &= ~(1 
<< DB5);
  if(b & 0x10) PORT(DB4_PORT) |= (1 << DB4); else PORT(DB4_PORT) &= ~(1 
<< DB4);
  PORT(EN_PORT) &= ~(1 << EN);

  // output low nibble
  PORT(EN_PORT) |= (1 << EN);
  if(b & 0x08) PORT(DB7_PORT) |= (1 << DB7); else PORT(DB7_PORT) &= ~(1 
<< DB7);
  if(b & 0x04) PORT(DB6_PORT) |= (1 << DB6); else PORT(DB6_PORT) &= ~(1 
<< DB6);
  if(b & 0x02) PORT(DB5_PORT) |= (1 << DB5); else PORT(DB5_PORT) &= ~(1 
<< DB5);
  if(b & 0x01) PORT(DB4_PORT) |= (1 << DB4); else PORT(DB4_PORT) &= ~(1 
<< DB4);
  PORT(EN_PORT) &= ~(1 << EN);
}


/*********************************************************************** 
********
Low-level function to write nibble to LCD controller
Input:   byte, high nibble is written to LCD
************************************************************************ 
*******/
static void write_nibble(unsigned char b)
{
  PORT(RS_PORT) &= ~(1 << RS);    // instruction

  // output high nibble
  PORT(EN_PORT) |= (1 << EN);
  if(b & 0x80) PORT(DB7_PORT) |= (1 << DB7); else PORT(DB7_PORT) &= ~(1 
<< DB7);
  if(b & 0x40) PORT(DB6_PORT) |= (1 << DB6); else PORT(DB6_PORT) &= ~(1 
<< DB6);
  if(b & 0x20) PORT(DB5_PORT) |= (1 << DB5); else PORT(DB5_PORT) &= ~(1 
<< DB5);
  if(b & 0x10) PORT(DB4_PORT) |= (1 << DB4); else PORT(DB4_PORT) &= ~(1 
<< DB4);
  PORT(EN_PORT) &= ~(1 << EN);
}


/*********************************************************************** 
********
Initialize display, see HD44780 data sheet
After initialisation the display is off!
************************************************************************ 
*******/
void LCD_init()
{
  // configure RW pin, if available
  #ifdef RW
  DDR(RW_PORT) |= (1 << RW);      // output
  PORT(RW_PORT) &= ~(1 << RW);    // write
  #endif

  // configure data pins as output
  DDR(DB7_PORT) |= (1 << DB7);
  DDR(DB6_PORT) |= (1 << DB6);
  DDR(DB5_PORT) |= (1 << DB5);
  DDR(DB4_PORT) |= (1 << DB4);

  // configure control pins as output
  DDR(RS_PORT) |= (1 << RS);
  DDR(EN_PORT) |= (1 << EN);

  _delay_us(15000);          // wait for more then 15ms

  write_nibble(0x30);
  _delay_us(4100);          // wait for more then 4.1ms

  write_nibble(0x30);
  _delay_us(100);            // wait for more then 100us

  write_nibble(0x30);
  _delay_us(EXETIMESHORT);

  write_nibble(0x20);          // Function Set: 4bit Mode
  _delay_us(EXETIMESHORT);

  #if DISPLAY_LINES == 1
  LCD_instruction(0x20);        // Function Set: 1 line, 5x8 dot 
character font
  #else
  LCD_instruction(0x28);        // Function Set: 2 lines, 5x8 dot 
character font
  #endif

  LCD_instruction(LCD_DISP_OFF);    // Display off, Cursor off, Blinking 
off

  LCD_instruction(LCD_CLR);      // Clear display

  LCD_instruction(LCD_ENTRY_INC);    // Entry Mode Set: Increment, no 
shift
}


/*********************************************************************** 
********
Load custom character. This function change the cursor position!
Input:   pointer to array of char
     character code (0x00 - 0x07)
************************************************************************ 
*******/
void LCD_loadCustomChar(unsigned char* customCharArray, unsigned char 
charCode)
{
  register unsigned char i;

  charCode = (charCode << 3);  // calculate CG RAM address

  // copy the 8 bytes into CG (character generator) RAM
  for(i=0; i<8; i++)
  {
    write(0x40 | (charCode + i), 0);        // set CG RAM address
    _delay_us(EXETIMESHORT);

    write(pgm_read_byte(customCharArray + i), 1);  // write character 
data
    _delay_us(EXETIMESHORT);
  }
}


/*********************************************************************** 
********
Send instruction to LCD unit
Input:   Instruction code (use predefined codes from lcd.h)
************************************************************************ 
*******/
void LCD_instruction(unsigned char cmd)
{
  write(cmd, 0);
  if (cmd==LCD_CLR || cmd==LCD_HOME)
    _delay_us(EXETIMELONG);
  else
    _delay_us(EXETIMESHORT);
}


/*********************************************************************** 
********
Set cursor to specified position
Input:   vertical position    (0: first line)
     horizontal position  (0: left most position)
************************************************************************ 
*******/
void LCD_setpos(unsigned char y, unsigned char x)
{
  if (y==0)              // first line
    write(0x80 | x, 0);
  else                // second line
    write(0x80 | (0x40+x), 0);

  _delay_us(EXETIMESHORT);
}


/*********************************************************************** 
********
Display character at current cursor position
Input:   character to be displayed
************************************************************************ 
*******/
void LCD_putchar(char c)
{
  write(c, 1);
  _delay_us(EXETIMESHORT);
}


/*********************************************************************** 
********
Display string without auto linefeed
Input:   string to be displayed
************************************************************************ 
*******/
void LCD_puts(const char *string)
{
  char c;

  while (c = *string++)
    LCD_putchar(c);
}
______________________________________________________________________ 
__

Datei lcd.h

/*********************************************************************** 
********
 File:    lcd.h
 Compiler:  AVR-GCC 3.3
 Hardware:  AVR
 Date:    04.06.2009

 Basic routines for interfacing a HD44780U-based text LC-Display
************************************************************************ 
*******/

// Clear enter display area, restore display from shift, and load 
address
// counter with DD RAM adress 0x00
#define LCD_CLR                  0x01

// Restore display from shift, and load address counter with DD RAM 
adress 0x00
#define LCD_HOME                 0x02

// Specify cursor advance direction and display shift mode
// This operation takes place after each data transfer
#define LCD_ENTRY_DEC            0x04  // cursor moves to the left
#define LCD_ENTRY_INC            0x06  // cursor moves to the right
#define LCD_ENTRY_DEC_SHIFT      0x05  // shift display to the left
#define LCD_ENTRY_INC_SHIFT      0x07  // shift display to the right

// Specify activation of display, cursor, and blinking of character
#define LCD_DISP_OFF             0x08  // display off
#define LCD_DISP_ON              0x0C  // display on
#define LCD_DISP_ON_CURSOR       0x0E  // display on, cursor on
#define LCD_DISP_ON_BLINK        0x0D  // display on, blink char
#define LCD_DISP_ON_CURSOR_BLINK 0x0F  // display on, cursor on, blink 
char

// Shift display or move cursor
#define LCD_MOVE_CURSOR_LEFT     0x10  // move cursor left  (decrement)
#define LCD_MOVE_CURSOR_RIGHT    0x14  // move cursor right (increment)
#define LCD_MOVE_DISP_LEFT       0x18  // shift display left
#define LCD_MOVE_DISP_RIGHT      0x1C  // shift display right


/*********************************************************************** 
********
Initialize display, see HD44780 data sheet
After initialisation the display is off!
************************************************************************ 
*******/
void LCD_init();


/*********************************************************************** 
********
Load custom character. This function change the cursor position!
Input:   pointer to array of char
     character code (0x00 - 0x07)
************************************************************************ 
*******/
void LCD_loadCustomChar(unsigned char* customCharArray, unsigned char 
charCode);


/*********************************************************************** 
********
Send instruction to LCD unit
Input:   Instruction code (use predefined codes from lcd.h)
************************************************************************ 
*******/
void LCD_instruction(unsigned char);


/*********************************************************************** 
********
Set cursor to specified position
Input:   vertical position    (0: first line)
     horizontal position  (0: left most position)
************************************************************************ 
*******/
void LCD_setpos(unsigned char, unsigned char);


/*********************************************************************** 
********
Display character at current cursor position
Input:   character to be displayed
************************************************************************ 
*******/
void LCD_putchar(char);


/*********************************************************************** 
********
Display string without auto linefeed
Input:   string to be displayed
************************************************************************ 
*******/
void LCD_puts(const char *);

______________________________________________________________________ 
__

Datei lcdmap.h

/*********************************************************************** 
********
 File:    lcdmap.h
 Compiler:  AVR-GCC 3.3
 Hardware:  AVR
 Date:    21.05.2009

 LCD hardware settings and pin connections
 Layout for olimex-board
************************************************************************ 
*******/

#define DISPLAY_LINES 1      // Display Lines (1 or 2)

#define RS_PORT B        // register select
#define RS PB0

#define RW_PORT B        // read/write
#define RW PB1

#define EN_PORT B        // enable
#define EN PB2

#define DB4_PORT D
#define DB4 PD4
#define DB5_PORT D
#define DB5 PD5
#define DB6_PORT D
#define DB6 PD6
#define DB7_PORT D
#define DB7 PD7

// extend register names with port characters
#define GLUE(a, b)    a##b
#define PORT(x)      GLUE(PORT, x)
#define PIN(x)      GLUE(PIN, x)
#define DDR(x)      GLUE(DDR, x)

von Stefan P. (form)


Lesenswert?

das
LED_blinken(5)
und das
void LED_blinken()

passt irgendwie nicht zusammen.

von Stefan B. (Gast)


Lesenswert?

Warum passt das nicht? Wie müsste das ganze heißen?
Hab kaum Erfahrung im Bereich der Mikrocontroller.

Die LED blinkt aber 5x und dann erscheint auf dem Display
"H`}ln1Fu}d"

Gruß

von bob (Gast)


Lesenswert?

Du wiederholst Dich...

von Hubert G. (hubertg)


Lesenswert?

Wenn du wirre Zeichen auf dem LCD hast, kommt das sehr oft von nicht 
passenden Wartezeiten. Ist die Taktfrequenz in dein Programm 
eingebunden.

von Andreas K. (derandi)


Lesenswert?

Schon mal drauf geachtet ob der Compiler irgendwelche Warnungen 
ausspuckt?
Ich hab nirgendwo ein #define F_CPU gefunden, aber vielleicht hat der 
Herr Lehrer das ja im Makefile versteckt.

von MeinerEiner (Gast)


Lesenswert?

Die nicht benötigten Datenleitungen DB0-DB3 sollten nicht "FREI" sein 
sondern definiert auf Masse liegen. Sonst is nämlich schnell passiert, 
dass sich die je nach Mondphase doch nen High-Pegel einfangen und dann 
wars das mit der 4-Bit-Ansteuerung.

von Z8 (Gast)


Lesenswert?

>dass sich die je nach Mondphase doch nen High-Pegel einfangen und dann
>wars das mit der 4-Bit-Ansteuerung.

huch,

hab ich da was übersehen? Hab schon zig verschiedene Displays verbaut
mit offenen unterm Nibble. Es gab noch nie Probleme damit.

Z8

von holger (Gast)


Lesenswert?

>hab ich da was übersehen? Hab schon zig verschiedene Displays verbaut
>mit offenen unterm Nibble. Es gab noch nie Probleme damit.

Hatte damit auch noch nie Probleme.

von MeinerEiner (Gast)


Lesenswert?

Normal schon... Dann warens bisher gute Displays, denen das entweder 
egal ist oder die selber nen kleinen Pulldown haben (wie auch immer der 
aussieht).

Selber hatt ich (leider) schon ein paar Billigteile aus nem asiatischen 
Land... da sucht man sich nen Wolf, wenn man eben auch die guten gewohnt 
ist,  und dann so ne Grütze kriegt, wo sogar Anatmen (!) bei offenen 
Datenleitungen was aufs Display zaubert.

Darum einfach vorsorglich runterziehen; schadet nie und vermeidet im 
Fall der Fälle Fehler.

von Z8 (Gast)


Lesenswert?

hab gerade mal nachgemessen, an den "offenen" Eingängen liegt
ein stabieler "H" Pegel. Offensichtlich haben die Dinger Pull-Up-Rs.
Es wär strommäßig kontraproduktiv die Eingänge auf Masse zu legen.
Wenn mans mag dann eher auf Vcc.

Z8 :)

von Benedikt K. (benedikt)


Lesenswert?

Wenn schon, dann nicht auf Masse, sondern auf Vcc ziehen. Zumindest alle 
HD44780 kompatibel Displays haben einen Pullup eingebaut. Und wenn ein 
Display keine Pullups hat, dann sollte es nicht als HD44780 kompatibel 
bezeichnet werden. Mir ist zumindest noch kein solches Display begegnet 
und ich habe noch keine kommerzielle Schaltung gesehen, die Pullups 
verwendet hat: Die Pins waren immer offen.

von Stefan B. (Gast)


Lesenswert?

So, danke erstmal für eure zahlreiche Hilfe. Ich habe das Ding heute zum 
laufen bekommen. Hab das originale Testprogramm überspielt und alles 
richtig verdrahtet. Als das Testprogramm lief, hab ich einfach

RS --> PB7
RW --> PB0
EN --> PB6
DB4--> PB2
DB5--> PB3
DB6--> PB4
DB7--> PB5

programmiert. Danach hat es geklappt. Hab dann die unnötigen Leitungen 
wieder entfernt. DB0 bis DB3 sind frei, liegen nicht auf GND. Klappt 
einwandfrei.

Kann es sein, das von alten Programmen noch im Speicher waren?

Im alten Programm waren
DB4 - DB7 auf PORTD
und
RS, RW und EN auf PORTB
Gibt es da irgendwelche komplikationen.
Wieso das Programm jetzt läuft kann ich mir einfach nicht erklären...

Danke für eure Hilfe

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.