PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Problem Initialisierung EA DIP204



Udam
09.08.2005, 16:20
Hallo Leute!

Versuche seit ein paar Tagen mein EA DIP204 Display an meinem ATM32 zum Laufen zu bringen. Der Controller läuft einwandfrei, Lötstellen ect. überprüft. Jede Ausgabe auf den Port ist auch gemessen und funktioniert, dh. vermute ich, dass das Problem an meiner Software liegt. Hab mich zwar an die Beiträge vom Forum und vom Netz gehalten, jedoch noch kein Erfolg. SW ist zwar noch in der Entwicklung (Funktion zum Command / Daten schicken kommt noch extra hinzu) jedoch sollte der Code mal funktionieren bis ich weitermache.

folgendes ist meine Routine zur initialisierung des Displays im 4 bit mod.

Pin belegung
D0-D3 GND
D4 PA0
D5 PA1
D6 PA2
D7 PA3
RS/CS PC4
R/W GND
E PC6



void init_lcd(void)
{
sleep_ms(100);

//Port A als Ausgang
DDRA=0xff;
PORTA=0x00;

//4 bit Mod, high Nibbel 0010
enable_lcd();
PORTA=0x02;
sleep_ms(10);
PORTA=0x00;
//4 bit Mod, low Nibbel RE=1 0100
enable_lcd();
PORTA=0x04;
sleep_ms(10);
PORTA=0x00;

//4 Line Mod, high Nib 0000
enable_lcd();
PORTA=0x00;
sleep_ms(10);
//low Nib 1001
enable_lcd();
PORTA=0x09;
sleep_ms(10);
PORTA=0x00;

//4 Bit Mod, RE=0; higt Nib 0010
enable_lcd();
PORTA=0x02;
sleep_ms(10);
PORTA=0x00;
//low Nib 0000
enable_lcd();
PORTA=0x00;
sleep_ms(10);

//Entry mod set, cursor auto increment, high nib 0000
enable_lcd();
PORTA=0x00;
sleep_ms(10);
//low nib 0110
enable_lcd();
PORTA=0x06;
sleep_ms(10);
PORTA=0x00;

//Clear Display, home cursor high nib 0000
enable_lcd();
PORTA=0x00;
sleep_ms(10);
//low nib 0001
enable_lcd();
PORTA=0x01;
sleep_ms(10);
PORTA=0x00;

//Display on, cursor on, blink on, high nib 0000
enable_lcd();
PORTA=0x00;
sleep_ms(10);
//low nib 1111
enable_lcd();
PORTA=0x0f;
sleep_ms(10);
PORTA=0x00;
}


Im main rufe ich die Fkt init_lcd auf. Code lässt sich kompilieren und übertragen, jedoch ist leider kein blinkender Cursor am Display zu erkennen.

Wäre toll wenn jemand die Lösung für das Problem finden würde.

mfg

SprinterSB
09.08.2005, 18:29
Hallo auch.



PORTA=0x04;
sleep_ms(10);
PORTA=0x00;

Wie sagst du dem Display-Controller, daß da 2 Nibbles unterwegs sind???

Ich verwende folgenden Code erfolgreich für ein LCD und ein VFD.
Ganz fertig bin ich noch nicht für das LCD, da stimmt noch was mit dem Kontrast nicht, aber der Code funktioniert.

Den Code setze ich zwar genauso ein, aber für dich ist es nur ein Pseudo-Code, weil dir einige Header fehlen, die nicht so ohne weiteres benutzbar sind.

Vielleicht gibt dir das ne Anregung, was bei der Initialisierung schief geht.
Wenn du Fragen hast zu Codestellen, werd ich versuchen das zu erklären was sie bedeuten.

vfd.c:


#include "use.h"
#include <AVR.h>
#include "ports.h"
#include "vfd.h"
#include "timer.h"

#if VFD
#define ONW_VFD_SYMBOLS 1
#else
#define ONW_VFD_SYMBOLS 0
#endif

#if ONW_VFD_SYMBOLS

static void vfd_write_symbol (vfd_symbol_t*);
#include "vfd-symbols.c"

#endif /* ONW_VFD_SYMBOLS */

static void vfd_wait_busy ();
static byte vfd_receive_byte_or_nibble ();
static void vfd_send_byte_or_nibble (byte b);

vfd_t vfd =
{
.cursor_on = 1,
.cursor_blink = 1,
.bright = 1,
.address_mode =1,
.shift_mode = 0
};

static void LOOP (byte b)
{
while (--b > 0);
}


void vfd_wait_busy()
{
byte busy, count=0;

do
{
CLR_FLAG (FLAG_VFD_RS);
busy = vfd_receive ();
}
while (busy & 0x80 && ++count<100);
}

void vfd_clear()
{
vfd_wait_busy();
vfd_send0 (0x01);
vfd_wait_busy();
}


void vfd_init ()
{
byte data;

vfd_wait_busy();
data = 1<<3;
if (vfd.cursor_blink) data |= 1<<0;
if (vfd.cursor_on) data |= 1<<1;
if (vfd.bright) data |= 1<<2;
vfd_send0 (data);

vfd_wait_busy();
#ifdef VFD_INTERFACE_4BIT
vfd_send0 (FUNCTION_SET_DATA4);
#endif /* VFD_INTERFACE_4BIT */

#ifdef VFD_INTERFACE_8BIT_PARALLEL
vfd_send0 (FUNCTION_SET_DATA8);
#endif /* VFD_INTERFACE_8BIT_PARALLEL */

vfd_send1 (4 - vfd.bright);

vfd_wait_busy();
data = 1<<2;
if (vfd.shift_mode) data |= 1<<0;
if (vfd.address_mode) data |= 1<<1;
vfd_send0 (data);

vfd_wait_busy();
}

void vfd_send0 (byte b)
{
CLR_FLAG (FLAG_VFD_RS);
#ifdef VFD_INTERFACE_4BIT
vfd_send_byte_or_nibble (b>>4);
#endif /* VFD_INTERFACE_4BIT */
vfd_send_byte_or_nibble (b);
}

void vfd_send1 (byte b)
{
SET_FLAG (FLAG_VFD_RS);
#ifdef VFD_INTERFACE_4BIT
vfd_send_byte_or_nibble (b>>4);
#endif /* VFD_INTERFACE_4BIT */
vfd_send_byte_or_nibble (b);
}

byte vfd_receive ()
{
byte result;

CLR (PORT_E);

VFD_IN_DB;
VFD_CLR_DB;

#ifdef VFD_INTERFACE_4BIT
result = vfd_receive_byte_or_nibble () << 4;
LOOP (100);
result |= vfd_receive_byte_or_nibble () & 0xf;
#endif /* VFD_INTERFACE_4BIT */

#ifdef VFD_INTERFACE_8BIT_PARALLEL
result = vfd_receive_byte_or_nibble();
#endif /* VFD_INTERFACE_8BIT_PARALLEL */

return result;
}

byte vfd_receive_byte_or_nibble ()
{
byte bibble = 0;

LOOP (10);
SET (PORT_RW);
LOOP (10);

CLR (PORT_RS);
if (IS_FLAG (FLAG_VFD_RS))
SET (PORT_RS);

LOOP (10);
SET (PORT_E);
LOOP (100);

#ifdef VFD_INTERFACE_4BIT
if (IS_SET (PORT_DB0)) bibble |= (1<<0);
if (IS_SET (PORT_DB1)) bibble |= (1<<1);
if (IS_SET (PORT_DB2)) bibble |= (1<<2);
if (IS_SET (PORT_DB3)) bibble |= (1<<3);
#endif /* VFD_INTERFACE_4BIT */

#ifdef VFD_INTERFACE_8BIT_PARALLEL
bibble = N_TO_PIN (PORT_VFD_ID);
#endif /* VFD_INTERFACE_8BIT_PARALLEL */

CLR (PORT_E);
CLR (PORT_RW);

return bibble;
}

void vfd_send_byte_or_nibble (byte b)
{
CLR (PORT_E);

VFD_OUT_DB;
CLR (PORT_RW);

CLR (PORT_RS);
if (IS_FLAG (FLAG_VFD_RS))
SET (PORT_RS);

VFD_CLR_DB;

#ifdef VFD_INTERFACE_4BIT
if (b & (1<<0)) SET (PORT_DB0);
if (b & (1<<1)) SET (PORT_DB1);
if (b & (1<<2)) SET (PORT_DB2);
if (b & (1<<3)) SET (PORT_DB3);
#endif /* VFD_INTERFACE_4BIT */

#ifdef VFD_INTERFACE_8BIT_PARALLEL
N_TO_PORT (PORT_VFD_ID) = b;
#endif /* VFD_INTERFACE_8BIT_PARALLEL */

SET (PORT_E);
LOOP (100);
CLR (PORT_E);

VFD_IN_DB;
}

void vfd_string (char *str)
{
while (*str)
{
vfd_send1 (vfd_replace_uml ((byte) *(str++)));
}
}

void vfd_set_cursor (byte pos)
{
vfd_wait_busy();
vfd_send0 (0x80|pos);
vfd_wait_busy();
}

void vfd_pos_string (byte pos, char *str)
{
// Cursor setzen
vfd_set_cursor(pos);

vfd_string/*_wait*/ (str/*,5*/);
}

void vfd_pos_char (byte pos, char c)
{
// Cursor setzen
vfd_set_cursor(pos);

vfd_send1 ((byte) c);
}



#if ONW_VFD_SYMBOLS
void vfd_write_symbol (vfd_symbol_t *sym)
{
byte i;
byte *pdata = (byte*) &(sym->dots);
byte id = eeprom_read_byte (&(sym->id));
id = 0x40 | ((byte) (id<<3)); // 0x40 | address

for (i=0; i<8; i++)
{
vfd_wait_busy();
vfd_send0 (id+i);
byte data = eeprom_read_byte (pdata++);

vfd_send1 (data);
}
}
#endif /* ONW_VFD_SYMBOLS */


void vfd_reset (byte bright)
{
#if VFD
CLR (PORT_RESET);
wait_10ms (10);
SET (PORT_RESET);
wait_10ms (10);
#endif
vfd_wait_busy();
CLR_FLAG (FLAG_VFD_RS);

#ifdef VFD_INTERFACE_4BIT
vfd_send_byte_or_nibble (FUNCTION_SET_DATA4>>4);
#endif /* VFD_INTERFACE_4BIT */

#ifdef VFD_INTERFACE_8BIT_PARALLEL
vfd_send_byte_or_nibble (FUNCTION_SET_DATA8);
#endif /* VFD_INTERFACE_8BIT_PARALLEL */

vfd_send1 (3-(bright & 3));
vfd_wait_busy();

#if ONW_VFD_SYMBOLS

vfd_write_symbol ((vfd_symbol_t*) &sym_szlig);
/*
vfd_write_symbol ((vfd_symbol_t*) &sym_euro);
vfd_write_symbol ((vfd_symbol_t*) &sym_check0);
vfd_write_symbol ((vfd_symbol_t*) &sym_check1);
vfd_write_symbol ((vfd_symbol_t*) &sym_heart);
vfd_write_symbol ((vfd_symbol_t*) &sym_circ2);
vfd_write_symbol ((vfd_symbol_t*) &sym_circ1);
vfd_write_symbol ((vfd_symbol_t*) &sym_all);
*/
#endif /* ONW_VFD_SYMBOLS */

}

#if 1

byte UML_MAP[][2] PROGMEM = {
{ 'ä', 0xe1},
#if VFD
{ 'ö', 0x87},
{ 'ü', 0x8b},
{ 'Ä', 0x80},
{ 'Ö', 0x86},
{ 'Ü', 0x8a},
#if // ONW_VFD_SYMBOLS
{ 'ß', 0x08},
#else // ONW_VFD_SYMBOLS
{ 'ß', 0xe2},
#endif // ONW_VFD_SYMBOLS
{ 'g', 0xe7},
#else // VFD
{ 'ö', 0xef},
{ 'ü', 0x8b},
{ 'Ä', 0x80},
{ 'Ö', 0x86},
{ 'Ü', 0x8a},
{ 'ß', 0xe2},
#endif // VFD
{ 0 , 0}

};


byte vfd_replace_uml (byte c)
{
byte c0;
byte *map = (byte*) UML_MAP;

do
{
c0 = pgm_read_byte (map);
if (c0 == c)
{
c = pgm_read_byte (map+1);
break;
}
map += 2;
} while (c0 != 0);

return c;
}

#else
byte vfd_replace_uml (byte c) { return c; }
#endif



vfd.h:


#ifndef _VFD_H_
#define _VFD_H_

#define VFD_INTERFACE_4BIT
//#define VFD_INTERFACE_8BIT_PARALLEL

#if !defined(VFD_INTERFACE_4BIT) && !defined(VFD_INTERFACE_8BIT_PARALLEL)
#error Define either 'VFD_INTERFACE_4BIT' or 'VFD_INTERFACE_8BIT_PARALLEL'
#endif
#if defined(VFD_INTERFACE_4BIT) && defined(VFD_INTERFACE_8BIT_PARALLEL)
#error Define either 'VFD_INTERFACE_4BIT' or 'VFD_INTERFACE_8BIT_PARALLEL'
#endif

extern void vfd_send0 (byte);
extern void vfd_send1 (byte);

extern byte vfd_receive ();
extern void vfd_pos_string (byte pos, char*);
extern void vfd_string (char*);
extern void vfd_string_wait (char*, char);
extern void vfd_reset (byte);
extern byte vfd_replace_uml (byte);

extern void vfd_pos_char (byte, char);

extern void vfd_clear();

typedef struct
{
unsigned char bright:3; // 0..4: 0=display off, 1-4=brighness > 0

unsigned char cursor_blink:1;
unsigned char cursor_on:1;

unsigned char shift_mode:1; // 0=shift cursor, 1=shift display
unsigned char address_mode:1; // 0=address decrement, 1=adddress increment
} __attribute__ ((packed)) vfd_t;

typedef struct
{
byte dot4:1;
byte dot3:1;
byte dot2:1;
byte dot1:1;
byte dot0:1;
byte :3;
} __attribute__ ((packed)) vfd_dots_t;

typedef struct
{
byte id;

vfd_dots_t dots[7];

byte :4;
byte underline:1;
byte :3;
} __attribute__ ((packed)) vfd_symbol_t;

extern vfd_t vfd;
extern void vfd_init ();
extern void vfd_set_cursor (byte);

#define FLAG_READ FLAG_RW
#define FLAG_WRITE 0

#define FLAG_RW (1<<1)

#define FUNCTION_SET_DATA8 0x30
#define FUNCTION_SET_DATA4 0x20

////////////////////////////////////////////////////////////

#ifdef VFD_INTERFACE_4BIT

#define VFD_OUT_DB \
do { \
MAKE_OUT (PORT_DB0); \
MAKE_OUT (PORT_DB1); \
MAKE_OUT (PORT_DB2); \
MAKE_OUT (PORT_DB3); \
} while (0)

#define VFD_IN_DB \
do { \
MAKE_IN (PORT_DB0); \
MAKE_IN (PORT_DB1); \
MAKE_IN (PORT_DB2); \
MAKE_IN (PORT_DB3); \
} while (0)

#define VFD_CLR_DB \
do { \
CLR (PORT_DB0); \
CLR (PORT_DB1); \
CLR (PORT_DB2); \
CLR (PORT_DB3); \
} while (0)

#endif /* VFD_INTERFACE_4BIT */

////////////////////////////////////////////////////////////

#ifdef VFD_INTERFACE_8BIT_PARALLEL

#define VFD_OUT_DB \
do { \
N_TO_DDR (PORT_VFD_ID) = 0xff; \
} while (0)

#define VFD_IN_DB \
do { \
N_TO_DDR (PORT_VFD_ID) = 0; \
} while (0)

#define VFD_CLR_DB \
do { \
N_TO_PORT (PORT_VFD_ID) = 0; \
} while (0)

#endif /* VFD_INTERFACE_8BIT_PARALLEL */


#endif /* _VFD_H_ */

fwallenwein
10.08.2005, 01:02
Hallo


Hallo Leute!

Versuche seit ein paar Tagen mein EA DIP204 Display an meinem ATM32 zum Laufen zu bringen.
.....
folgendes ist meine Routine zur initialisierung des Displays im 4 bit mod.



Kannst Du mal Deine enable_lcd(); veröffentlichen, damit man sehen kann was Du dort machst ?
Ich sehe zwar in den Kommentaren, dass Du das "RE" schaltest, kann das aber nirgends im Code entdecken. Wo machst Du das ?


Uebrigens
Das EA-DIP lässt sich ja auch seriell betrieben.
Ich habe es hier immer im seriellen Betrieb. D.h. man braucht nur 2 Leitungen und spart I/O Ports. SID (Serial Input Data) and SCLK (Clock Line)
Wenn Du dafür Sourcen / Ideen / Treiber brauchst, dann kannst Du sie gerne bekommen.
Einen Treiber für das Display im seriellen Betrieb - allerdings für ein Ethernut Board - kannst Du finden unter :
http://www.tklinux.de Dort auf Allg. Elektronik gehen.
Einen Treiber fuer den Mega32 lege ich hier mal bei. - Allerdings halt eben für den seriellen Betrieb.

Gruss
Frank

Udam
10.08.2005, 16:49
Danke für eure schnellen Antworten!

@SprinterSB


Wie sagst du dem Display-Controller, daß da 2 Nibbles unterwegs sind???

Hab mir das ganze vom Datenblatt, bzw von da genommen:
https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=10766
von Franks Posting

Danke für deinen Code werde ich vermutlich auch verwenden, jedoch will ich es zuerst mit meinem eigenen versuchen, um es besser zu verstehen.

@fwallenwein


Kannst Du mal Deine enable_lcd(); veröffentlichen, damit man sehen kann was Du dort machst ?
Ich sehe zwar in den Kommentaren, dass Du das "RE" schaltest, kann das aber nirgends im Code entdecken. Wo machst Du das ?

enable_lcd macht nichts anderes, als die Enable Leitung high zu setzten, kurz zu warten um sie dann wieder auf Low zu setzten.

Das mit dem RE bit ist mir ein bischen unklar, ich hab es so wie im o.g. link gemacht(versucht ;) )
zuerst 0010 0100
dann Zeilenanzahl
und dann 0010 0000 zu senden.

Laut dem link ist beim Oberen das RE=1 und beim unteren gleich 0, ich dachte das 3. Bit entspricht in diesem Fall dem RE und das war mir, wie gesagt sowieso unklar ob es so funktioniert.

Falls es so nicht richtig ist, wie sende ich dem Display das Extension bit?

mfg

fwallenwein
10.08.2005, 19:11
[quote="Udam"]Danke für eure schnellen Antworten!
[quote]

Was ich meinte war :

Du Sendest anscheinend Daten auf den Port A, und wartest ein bischen,
sendest dann neue Daten.


PORTA=0x02;
sleep_ms(10);
PORTA=0x00;

Woher weiss das LCD, das es die Daten uebernehmen soll ?

Du musst :

PORT E = HIGH
Daten auf Port A schreiben.
PIN "E" = LOW - Bei der fallenden Flanke von E werden die Daten ins LCD uebernommen.

also bei Dir

PC6 auf 1 setzen,
Daten ruasschreiben
PC6 auf 0 setzen.

ansonsten uebernimmt Dein LCD die Daten vom Port A nie.

Gruss
Frank

SprinterSB
10.08.2005, 20:38
Daß 2 Nibbles unterwegs sind, sagt man ihm im ersten Befehl:
Im meinen Code kannst du die Stellen zwischen

#ifdef VFD_INTERFACE_8BIT_PARALLEL
...
#endif /* VFD_INTERFACE_8BIT_PARALLEL */

überlesen, weil du das Display ja in 4 Bit-Modus betreiben willst.

Der erste Befehl den ich sende (in vfd_reset()) ist ein


// CLR () setzt das entsprechende Port-Pin auf 0
// SET () setzt das entsprechende Port-Pin auf 1
CLR (POTR_RS);

// FUNCTION_SET_DATA4>>4 ist gleich 0x2
vfd_send_byte_or_nibble (FUNCTION_SET_DATA4>>4);


Die wichtigsten Funktionen später sind (#ifdef hab ich schon aufgelöst)


void vfd_send0 (byte b)
{
CLR_FLAG (FLAG_VFD_RS);
vfd_send_byte_or_nibble (b>>4);
vfd_send_byte_or_nibble (b);
}

void vfd_send1 (byte b)
{
SET_FLAG (FLAG_VFD_RS);
vfd_send_byte_or_nibble (b>>4);
vfd_send_byte_or_nibble (b);
}

Aus diesen Funktionen ist später der ganze Kommande/Datenstrom aufgebaut. In FLAG_VFD_RS merke ich mir wie der PORT_RS im moment der Ausgabe zu stehen hat. Wie ich das genu umgesetzt habe ist egal, nur zum Verständnis.

Das ist nun die vfd_send_byte, wieder hab ich das Zeug rausgeworfen,
das nur 8-Bit-parallel-Modus verwendet wird.
Da bei dir die Ports nebeneinander liegen, kannst du das besser machen als ich in meinem Code. Wie, brauch ich dir ja nicht mehr zu erklären ;-)


void vfd_send_byte_or_nibble (byte b)
{
CLR (PORT_E);

// Alle Datenports als Ausgang
MAKE_OUT (PORT_DB0);
MAKE_OUT (PORT_DB1);
MAKE_OUT (PORT_DB2);
MAKE_OUT (PORT_DB3);

CLR (PORT_RW);

// Setzt PORT_RS wie im Flag gemerkt
CLR (PORT_RS);
if (IS_FLAG (FLAG_VFD_RS))
SET (PORT_RS);

// Alle Datenports auf 0
CLR (PORT_DB0);
CLR (PORT_DB1);
CLR (PORT_DB2);
CLR (PORT_DB3);

// Das Nibble ausgeben.
// Bei mir ist das etwas komplizierter, weil die Ports nicht nebenein
// ander liegen müssen. Wo PORT_DBx liegt wird zentral verwaltet,
// der genaue Wert ist hier egal.
if (b & (1<<0)) SET (PORT_DB0);
if (b & (1<<1)) SET (PORT_DB1);
if (b & (1<<2)) SET (PORT_DB2);
if (b & (1<<3)) SET (PORT_DB3);

// Daten raushauen
SET (PORT_E);
LOOP (100);
CLR (PORT_E);

// Wieder alle Daten-Ports als Eingang
// Das brauch ich nur um Kollisionen auf dem Bus zu vermeiden
MAKE_IN (PORT_DB0);
MAKE_IN (PORT_DB1);
MAKE_IN (PORT_DB2);
MAKE_IN (PORT_DB3);
}


Das wichtigste ist, daß du beim Initialisieren für den 4bit-Modus nicht 2 Nibbles schickst, sonder nur eines!

Mit den Erläuterungen kannst du auch den Rest meines Codes gut verstehen.

Udam
11.08.2005, 14:39
Danke nochmals es funktioniert.

Habe leider das Enable falsch verstanden, dachte nach der neg. Enable Flanke ist das Display bereit zu empfangen.

mfg