PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : LCD - falsche ausgabe



Ineedhelp
15.07.2008, 18:21
hi

ich habe mal wieder ein problem - sry

ich habe das display LCD-Modul HLM8070 von Pollin (M50530 Controller).
Dank eurer Hilfe habe ich dazu auch einen code zum ansteuern gefunden.
Nun habe ich alles verdrahtet und den Code getestet.

Allerdings kommen komische Ausgaben auf dem Display...

erst hatte ich "@\\\p P\\p"

nun habe ich die Anzeigetexte geändert und er zeigt die ganze Zeit nur eine "0" an

die Kontakte und die richtige verdrahtung habe ich geprüft.

Ach ja, ich benutze einen Tiny2313 und steuere es über 4bit an.
Beim compilieren bekamm ich folgende Warnungen (vielleicht haben die damit zu tun)


main.c:20: warning: pointer targets in passing argument 1 of 'LCD_write' differ in signedness
main.c:22: warning: pointer targets in passing argument 1 of 'LCD_write' differ in signedness
main.c:24: warning: pointer targets in passing argument 1 of 'LCD_write' differ in signedness

der Code

main.c


#include <avr/io.h>
#include <lcd-m50530.h>


// Hauptprogramm
int main(void)
{
// wait for power up
delay(250);

// LCD initialisieren
LCD_init();
// Modus des LCDs ändern
LCD_setEntryMode(LCD_CURSOR_ADDRESS_INC_WD | LCD_DISPLAY_START_ADDRESS_NO_CHANGE);
// Cursor einschalten
LCD_setDisplay(LCD_DISPLAY_ON | LCD_CURSOR_ON | LCD_CURSOR_BLINK | LCD_CHARACTER_BLINK);


// ein paar Zeichen ausgeben
LCD_write("Hallo Welt");
LCD_setCursorPos(2,5);
LCD_write("Test");
LCD_setCursorPos(4, 0);
LCD_write("test successful");

while (1)
;

return 0;
}


lcd-m50530.c

/************************************************** *********

LCD-Routinen
für Samsung 2138a mit M50530-Controller
24 x 8 Zeichen

Copyright 2003-04 by Daniel Jelkmann


Zur Ansteuerung wird der 4Bit-Mode verwendet.
Neben den 4 Datenleitungen (Data0-3) werden 4 weitere
Steuerleitungen (Read/Write, Execute, OC1, OC2)
benötigt. Damit werden am AVR 8 Pins benötigt.


Anschluss:

Alle 8 LCD-Signale müssen an einem Port des AVR
angeschlossen werden. Gemäß folgender Tabelle müssen
die 4 Datenleitungen an den niederwertigsten Bits
anliegen. Die Reihenfolge der restlichen 4 Steuerleitungen
und der verwendete Port ist über die Konstanten im
Quellcode festgelegt und muss ggf. angepasst werden.
Die restlichen LCD-Signale sind in folgender Tabelle
zu finden.

LCD Beschreibung Anschluss
-------------------------------------------------------------------------
Pin 01 Masse Masse
Pin 02 Data0 nicht angeschlossen
Pin 03 Data1 nicht angeschlossen
Pin 04 Data2 nicht angeschlossen
Pin 05 Data3 nicht angeschlossen
Pin 06 Data4 AVR Port Bit 0
Pin 07 Data5 AVR Port Bit 1
Pin 08 Data6 AVR Port Bit 2
Pin 09 Data7 AVR Port Bit 3
Pin 10 EX (Execute) AVR Port Bit 4*
Pin 11 R/W (Read/Write) AVR Port Bit 5*
Pin 12 OC2 AVR Port Bit 7*
Pin 13 OC1 AVR Port Bit 6*
Pin 14 Kontrast-Regelung, ungefähr 8,2 Volt, am besten mittels Poti anschließen
Pin 15 Versorgungsspannung, +5 Volt
Pin 16 Masse Masse



* Die Reihenfolge dieser Leitungen kann über die
Konstanten im Quellcode angepasst werden.


Es wird keine Gewähr für die Vollständigkeit, Korrektheit,
Funktionsfähigkeit oder für sonstige Eigenschaften des
Codes übernommen. Haftung ausgeschlossen.

************************************************** ***********/


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

#include "lcd-m50530.h"

#include <stdlib.h>


/*
// wartet die angegebene Zeit in Millisekunden
// F_MCU muss entsprechend gesetzt sein
// (benötigt delay.h)
void delay(const unsigned int ms)
{
for (unsigned char i = ms; i > 0; --i)
// 4 cycles per loop * 250 = 1.000 cycles; 1.000 x F_MCU = 1 ms
_delay_loop_2(250*F_MCU);
}*/


// sendet den angelegten Befehl zum LCD
// setzt kurzzeitig das EX-Signal und nimmt es anschließend wieder zurück
void LCD_execute(void)
{
delay_short();
// EX-Signal setzen
LCD_PORT |= (1 << LCD_EX_PIN);
delay_short();
// EX-Signal löschen
LCD_PORT &= ~(1 << LCD_EX_PIN);
delay_short();
}


// wartet solange bis das Busy-Flag nicht mehr gesetzt ist
// und das LCD weitere Befehle entgegennimmt
void LCD_waitReady(void)
{
/*
READ BUSY FLAG & FUNCTION FLAGS (RB)
input:
OC1 0
OC2 0
RW 1
output:
DB7 busy-flag (1 = busy)
*/

// Datenleitungen auf Eingang schalten
// dazu die Bits der Datenleitungen auf 0 setzen
LCD_DDR &= 240;

// RB-Befehl senden
//LCD_PORT = (1 << LCD_OC1_PIN) | (1 << LCD_OC2_PIN) | (1 << LCD_RW_PIN);
LCD_PORT = 1 << LCD_RW_PIN;

unsigned char flags = 0;
while (1)
{
do
{
delay_short();
// EX-Signal setzen
LCD_PORT |= (1 << LCD_EX_PIN);
delay_short();
// flags einlesen
flags = LCD_PIN;
// EX-Signal löschen
LCD_PORT &= ~(1 << LCD_EX_PIN);
} while (bit_is_set(flags, 3));

if (flags & 6)
// bits 1 oder 2 gesetzt, also entweder sind wie im 8bit-mode oder wir haben gerade den zweiten Teil im 4bit-mode gelesen
break;
}


/* unsigned char busy;
do
{
delay_short();
LCD_execute();
// busy-Signal einlesen
busy = bit_is_set(LCD_PIN, 3);
LCD_execute();
} while (busy);
*/

// alle Leitungen als Ausgänge schalten
LCD_DDR = 0xFF;
}


// überträgt das übergebene Byte an das LCD
void LCD_sendByte(const unsigned char byte, unsigned char control)
{
LCD_waitReady();
// die unteren 5 Bits im Control-Byte ausblenden
control &= 224;
// oberes Nibble übertragen
LCD_PORT = (byte >> 4) | control;
LCD_execute();
// unteres Nibble übertragen
LCD_PORT = (byte & 15) | control;
LCD_execute();
}



// löscht die Anzeige und setzt die Display + Cursor-Adresse auf 0,0
void LCD_clear(void)
{
/*
CLEAR DISPLAY, MOVE DISPLAY/CURSOR ADDRESS HOME
input:
OC1 0
OC2 0
RW 0
DB7-DB1 0
DB0 1
*/
LCD_sendByte(1, 0); // DB0
delay(2);
}


// setzt 4-Bit-Mode und initialisiert das LCD
// muss als erstes aufgerufen werden, bevor das LCD angesteuert werden kann
void LCD_init(void)
{
// alle Leitungen auf Ausgang schalten
LCD_DDR = 0xFF;

// auf 4-Bit-Mode umschalten
/*
SET FUNCTION MODE
input:
OC1 0
OC2 0
RW 0
DB7,DB6 1
DB5 I/O 8/4 (1 = 8 bit, 0 = 4 bit)
DB4 FONT 8/12 (1 = 5x8 fonts, 0 = 5x12 fonts)
DB3,DB2 DUTY
DB1,DB0 RAM
*/
LCD_sendByte(216, 0); // DB7, DB6, DB4, DB3
LCD_clear();
}


// schreibt die übergebene Zeichenkette an die aktuelle Cursor-Position
void LCD_write(const unsigned char * c)
{
while (*c)
LCD_writeChar(*c++);
}


// schreibt die übergebene Zeichenkette an die aktuelle Cursor-Position (für String im ROM)
void LCD_write_P(const unsigned char * progmem_string)
{
register unsigned char c;
while ((c = pgm_read_byte(progmem_string++)))
LCD_writeChar(c);
}


// setzt den Cursor an die angegebene Position (y = Zeile, x = Spalte)
void LCD_setCursorPos(const unsigned char y, const unsigned char x)
{
// Adresse aus x und y berechnen
// Adressen sind wie folgt: Zeile 0 = 0; Zeile 1 = 64; Zeile 2 = 128; Zeile 3 = 192; Zeile 4 = 0+24; Zeile 5 = 64+24; Zeile 6 = 128+24; Zeile 7 = 192+24
unsigned char address = x + ((y % 4) << 6);
if (y > 3)
address += 24;
LCD_sendByte(address, (1<<LCD_OC1_PIN) | (1<<LCD_OC2_PIN));
}


lcd-m50530.h

/************************************************** *********

LCD-Routinen
für Samsung 2138a mit M50530-Controller
24 x 8 Zeichen

Copyright 2003 by Daniel Jelkmann


Zur Ansteuerung wird der 4Bit-Mode verwendet.
Neben den 4 Datenleitungen (Data0-3) werden 4 weitere
Steuerleitungen (Read/Write, Execute, OC1, OC2)
benötigt. Damit werden am AVR 8 Pins benötigt.


Anschluss:

Alle 8 LCD-Signale müssen an einem Port des AVR
angeschlossen werden. Gemäß folgender Tabelle müssen
die 4 Datenleitungen an den niederwertigsten Bits
anliegen. Die Reihenfolge der restlichen 4 Steuerleitungen
und der verwendete Port ist über die Konstanten im
Quellcode festgelegt und muss ggf. angepasst werden.
Die restlichen LCD-Signale sind in folgender Tabelle
zu finden.

LCD Beschreibung Anschluss
-------------------------------------------------------------------------
Pin 01 Masse Masse
Pin 02 Data0 nicht angeschlossen
Pin 03 Data1 nicht angeschlossen
Pin 04 Data2 nicht angeschlossen
Pin 05 Data3 nicht angeschlossen
Pin 06 Data4 AVR Port Bit 0
Pin 07 Data5 AVR Port Bit 1
Pin 08 Data6 AVR Port Bit 2
Pin 09 Data7 AVR Port Bit 3
Pin 10 EX (Execute) AVR Port Bit 5*
Pin 11 R/W (Read/Write) AVR Port Bit 4*
Pin 12 OC2 AVR Port Bit 7*
Pin 13 OC1 AVR Port Bit 6*
Pin 14 Kontrast-Regelung, ungefähr 8,2 Volt, am besten mittels Poti anschließen
Pin 15 Versorgungsspannung, +5 Volt
Pin 16 Masse Masse



* Die Reihenfolge dieser Leitungen kann über die
Konstanten im Quellcode angepasst werden.


Es wird keine Gewähr für die Vollständigkeit, Korrektheit,
Funktionsfähigkeit oder für sonstige Eigenschaften des
Codes übernommen. Haftung ausgeschlossen.

************************************************** ***********/

#ifndef LCD_M50530_H
#define LCD_M50530_H

#include <util/delay.h>


//#define F_MCU 5 /* Takt-Frequenz in MHz */


// wartet die angegebene Zeit in Millisekunden
// XTAL_CPU muss entsprechend gesetzt sein
// (benötigt delay.h)
//extern void delay(unsigned int ms);
#define delay(ms) for (unsigned int i = ms; i > 0; --i) \
_delay_loop_2(XTAL_CPU / 4000);
// _delay_loop_2(250*F_MCU);


/************************************************** **************
Ggf. hier den Port anpassen, an dem das LCD angeschlossen ist!
************************************************** **************/
// Data-Direction-Register, am dem das LCD angeschlossen ist
#define LCD_DDR DDRB
// Port-Register, am dem das LCD angeschlossen ist
#define LCD_PORT PORTB
// Pin-Register, am dem das LCD angeschlossen ist
#define LCD_PIN PINB

#define XTAL_CPU 5000000

/*************************************************
Ggf. hier die Bits der 4 Steuerleitungen anpassen!
*************************************************/
// Die Datenleitungen des LCDs müssen an den Pins 0-3 anliegen (Data0 auf Pin0, Data1 auf Pin1 usw.)
// Die anderen 4 Steuerleitungen sind hier einzustellen!
// Port-Pin, an dem der RW-Pin des LCDs liegt
#define LCD_RW_PIN 4
// Port-Pin, an dem der EX-Pin des LCDs liegt
#define LCD_EX_PIN 5
// Port-Pin, an dem der OC1-Pin des LCDs liegt
#define LCD_OC1_PIN 6
// Port-Pin, an dem der OC2-Pin des LCDs liegt
#define LCD_OC2_PIN 7


// ein paar Konstanten zur besseren Lesbarkeit des Quelltextes :-)
#define LCD_DISPLAY_ON 16
#define LCD_CURSOR_ON 8
#define LCD_UNDERLINE 4
#define LCD_CURSOR_BLINK 2
#define LCD_CHARACTER_BLINK 1


#define LCD_CURSOR_ADDRESS_NO_CHANGE 64
#define LCD_CURSOR_ADDRESS_INC_RD 72
#define LCD_CURSOR_ADDRESS_INC_WD 80
#define LCD_CURSOR_ADDRESS_INC_RDWD 88
#define LCD_CURSOR_ADDRESS_DEC_RD 104
#define LCD_CURSOR_ADDRESS_DEC_WD 112
#define LCD_CURSOR_ADDRESS_DEC_RDWD 120

#define LCD_DISPLAY_START_ADDRESS_NO_CHANGE 64
#define LCD_DISPLAY_START_ADDRESS_INC_RD 65
#define LCD_DISPLAY_START_ADDRESS_INC_WD 66
#define LCD_DISPLAY_START_ADDRESS_INC_RDWD 67
#define LCD_DISPLAY_START_ADDRESS_DEC_RD 69
#define LCD_DISPLAY_START_ADDRESS_DEC_WD 70
#define LCD_DISPLAY_START_ADDRESS_DEC_RDWD 71


#define LCD_SPECIAL_AE (char)144 // Ä, dezimal 144, oktal 220
#define LCD_SPECIAL_OE (char)145 // Ö, dezimal 145, oktal 221
#define LCD_SPECIAL_UE (char)197 // Ü, dezimal 197, oktal 305
#define LCD_SPECIAL_ae (char)160 // ä, dezimal 160, oktal 240
#define LCD_SPECIAL_oe (char)161 // ö, dezimal 161, oktal 241
#define LCD_SPECIAL_ue (char)17 // ü, dezimal 17, oktal 21
#define LCD_SPECIAL_ss (char)163 // ß, dezimal 163, oktal 243


// wartet einen kurzen Moment, 4 cycles per loop * 8 = 32 cycles, macht bei 16 MHz 2 µs
#define delay_short() _delay_loop_2(8)


// sendet den angelegten Befehl zum LCD
// setzt kurzzeitig das EX-Signal und nimmt es anschließend wieder zurück
extern void LCD_execute(void);


// wartet solange bis das Busy-Flag nicht mehr gesetzt ist
// und das LCD weitere Befehle entgegennimmt
extern void LCD_waitReady(void);


// überträgt das übergebene Byte an das LCD
extern void LCD_sendByte(const unsigned char byte, unsigned char control);


// setzt 4-Bit-Mode und initialisiert das LCD
// muss als erstes aufgerufen werden, bevor das LCD angesteuert werden kann
extern void LCD_init(void);

// löscht die Anzeige und setzt die Display + Cursor-Adresse auf 0,0
extern void LCD_clear(void);


// setzt den Entry-Mode des LCDs, also die automatische Erhöhung der Adresse nach einem Lese- oder Schreibbefehl
// man verwende die oben deklarierten Konstanten ;)
#define LCD_setEntryMode(mode) LCD_sendByte(mode, 0)


// schreibt das übergebene Zeichen an die aktuelle Cursor-Position
#define LCD_writeChar(c) LCD_sendByte(c, 1 << LCD_OC2_PIN)


// schreibt die übergebene Zeichenkette an die aktuelle Cursor-Position
extern void LCD_write(const unsigned char * c);

// schreibt die übergebene Zeichenkette an die aktuelle Cursor-Position (für String im ROM)
extern void LCD_write_P(const unsigned char * progmem_string);


// setzt den Display-Modus
// man verwende die oben deklarierten Konstanten ;)
#define LCD_setDisplay(mode) LCD_sendByte(mode | 32, 0)


// setzt den Cursor an die angegebene Adresse
#define LCD_setCursorAddress(address) LCD_sendByte(address, (1<<LCD_OC1_PIN) | (1<<LCD_OC2_PIN))


// setzt den Cursor an die angegebene Position (y = Zeile, x = Spalte)
extern void LCD_setCursorPos(const unsigned char y, const unsigned char x);

#endif


vielleicht findet ja jemand den Fehler
den code habe ich übrigens von hier mikrocontroller.net (http://www.mikrocontroller.net/topic/9903)
Danke für eure Hilfe

ragnar
15.07.2008, 22:35
Hier gibts einen alternativen Treiber für m50530 displays:

https://www.roboternetz.de/phpBB2/download.php?id=14191

Probiers damit mal. Im highlevel-Teil wirst du evtl. die Displaygröße ändern müssen, im *_config deine Pinzuordnung.

Ineedhelp
16.07.2008, 09:39
okay, danke
das werde ich gleich mal machen

Ineedhelp
16.07.2008, 10:30
wie kann ich denn mehrere .c dateien im makefile angeben
bei einer kann ich die ja einfach dahinter schreiben
so:

# List C source files here. (C dependencies are automatically generated.)
SRC = $(TARGET).c display_m50530_highlevel.c

das funktioniert

aber bei insgesamt 3 dateien will er das nicht

# List C source files here. (C dependencies are automatically generated.)
SRC = $(TARGET).c display_m50530_highlevel.c display_m50530.c

was muss ich tun?
habe auch schon gegoogelt, aber nichts gefunden

Ineedhelp
16.07.2008, 11:37
habe es jetzt so gemacht und die fehler scheinen ein anderes problem zu sein

# List C source files here. (C dependencies are automatically generated.)
SRC = $(TARGET).c
SRC += display_m50530_highlevel.c display_m50530.c