PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Probleme mit EA DIP204-4 Display und ATMEGA 1260 - gelöst!!



wkrug
24.01.2011, 07:44
Hallo Leute,
ich hab ein Problem ein EA DIP204-4NLED Display von Electronic assembly zu laufen zu kriegen. Ich verwende CodeVision AVR zum proggen.

Ich hab schon die Original Librarys von CodeVision AVR und auch angeblich funktionierende lib's aus dem Internet probiert.
Ich hab d auch schon versucht die Initialisierungsroutine zu verändern - Kein Erfolg.
Manche lib's funktionieren gar nicht, andere zeigen die eingegebenen Zeichen an der falschen Stelle an.

Verkabelungsfehler hab ich auch keinen, hab die Leitungen schon ein paar mal durchgemessen.
Ein anderes EA DIP204 hab ich auch schon versucht - Gleiches Fehlerbild.

Ich häng euch mal die relevanten Codeteile rein, eventuell hatte ja schon jemand anderes ein ähnliches Problem.

Die Main Routine ( Ausschnitte ):



#include <mega1280.h>
#include <string.h>
#include <delay.h>

// Alphanumeric LCD Module functions
#asm
.equ __lcd_port=0x02 ;PORTA
#endasm
#include "lcddip.h"
....

void main (void)
{
....

// LCD module initialization
lcd_init(20);

// Watchdog Timer initialization
// Watchdog Timer Prescaler: OSC/256k
// Watchdog Timer interrupt: Off
#pragma optsize-
#asm("wdr")
//WDTCSR=0x1F; **** Watchdogtimer für Testzwecke deaktiviert !!!!
//WDTCSR=0x0F;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

// Global enable interrupts
#asm("sei")

while (1)
{
//*** Reset des Watchdog Timers
#asm("wdr");


//**** Test ****
lcd_gotoxy(0,0);
strcpyf(uc_line1,"Zeile 1 sollte hier");
lcd_puts(uc_line1);
lcd_gotoxy(0,1);
strcpyf(uc_line2,"Zeile 2 sollte hier");
lcd_puts(uc_line2);
lcd_gotoxy(0,2);
strcpyf(uc_line3,"Zeile 3 sollte hier");
lcd_puts(uc_line3);
lcd_gotoxy(0,3);
strcpyf(uc_line4,"Zeile 4 sollte hier");
lcd_puts(uc_line4);
delay_ms(300);
....
}

Die zum Display gehörende Header datei:

/* LCD driver routines

CodeVisionAVR C Compiler
(C) 1998-2000 Pavel Haiduc, HP InfoTech S.R.L.

BEFORE #include -ING THIS FILE YOU
MUST DECLARE THE I/O ADDRESS OF THE
DATA REGISTER OF THE PORT AT WHICH
THE LCD IS CONNECTED!

EXAMPLE FOR PORTB:

#asm
.equ __lcd_port=0x18
#endasm
#include <lcddip.h>
Copy the File LCDDIP204.lib into the entire folder

*/

#ifndef _LCD_INCLUDED_
#define _LCD_INCLUDED_

#pragma used+

void _lcd_ready(void);
void _lcd_write_data(unsigned char data);

// write a byte to the LCD character generator or display RAM
void lcd_write_byte(unsigned char addr, unsigned char data);

// read a byte from the LCD character generator or display RAM
unsigned char lcd_read_byte(unsigned char addr);

// set the LCD display position x=0..39 y=0..3
void lcd_gotoxy(unsigned char x, unsigned char y);

// clear the LCD
void lcd_clear(void);

void lcd_putchar(char c);

// write the string str located in SRAM to the LCD
void lcd_puts(char *str);

// write the string str located in FLASH to the LCD
void lcd_putsf(char flash *str);

// initialize the LCD controller
unsigned char lcd_init(unsigned char lcd_columns);

#pragma used-
#pragma library LCDDIP204.lib

#endif



Die Display library:


/* LCD driver routines

CodeVisionAVR C Compiler
(C) 1998-2004 Pavel Haiduc, HP InfoTech S.R.L.
*/

#asm
.equ __lcd_direction=__lcd_port-1
.equ __lcd_pin=__lcd_port-2
.equ __lcd_rs=0
.equ __lcd_rd=1
.equ __lcd_enable=2
.equ __lcd_busy_flag=7
#endasm

#pragma used+
static unsigned char _base_y[4]={0x80,0xc0};
unsigned char _lcd_x,_lcd_y,_lcd_maxx;
#pragma used-

void _lcd_ready(void)
{
#asm
in r26,__lcd_direction
andi r26,0xf ;set as input
out __lcd_direction,r26
sbi __lcd_port,__lcd_rd ;RD=1
cbi __lcd_port,__lcd_rs ;RS=0
__lcd_busy:
rcall __lcd_delay
sbi __lcd_port,__lcd_enable ;EN=1
rcall __lcd_delay
in r26,__lcd_pin
cbi __lcd_port,__lcd_enable ;EN=0
rcall __lcd_delay
sbi __lcd_port,__lcd_enable ;EN=1
rcall __lcd_delay
cbi __lcd_port,__lcd_enable ;EN=0
sbrc r26,__lcd_busy_flag
rjmp __lcd_busy
#endasm
}

#asm
__lcd_write_nibble:
andi r26,0xf0
or r26,r27
out __lcd_port,r26 ;write
sbi __lcd_port,__lcd_enable ;EN=1
rcall __lcd_delay
cbi __lcd_port,__lcd_enable ;EN=0
__lcd_delay:
ldi r31,15
__lcd_delay0:
dec r31
brne __lcd_delay0
ret
#endasm

void _lcd_write_data(unsigned char data)
{
#asm
cbi __lcd_port,__lcd_rd ;RD=0
in r26,__lcd_direction
ori r26,0xf7 ;set as output
out __lcd_direction,r26
in r27,__lcd_port
andi r27,0xf
ld r26,y
rcall __lcd_write_nibble ;RD=0, write MSN
ld r26,y
swap r26
rcall __lcd_write_nibble ;write LSN
sbi __lcd_port,__lcd_rd ;RD=1
#endasm
}

/* write a byte to the LCD character generator or display RAM */
#if funcused lcd_write_byte
void lcd_write_byte(unsigned char addr, unsigned char data)
{
_lcd_ready();
_lcd_write_data(addr);
_lcd_ready();
#asm
sbi __lcd_port,__lcd_rs ;RS=1
#endasm
_lcd_write_data(data);
}
#endif

#if funcused lcd_read_byte || funcused lcd_init
#asm
__lcd_read_nibble:
sbi __lcd_port,__lcd_enable ;EN=1
rcall __lcd_delay
in r30,__lcd_pin ;read
cbi __lcd_port,__lcd_enable ;EN=0
rcall __lcd_delay
andi r30,0xf0
ret
#endasm

static unsigned char lcd_read_byte0(void)
{
#asm
rcall __lcd_delay
rcall __lcd_read_nibble ;read MSN
mov r26,r30
rcall __lcd_read_nibble ;read LSN
cbi __lcd_port,__lcd_rd ;RD=0
swap r30
or r30,r26
#endasm
}
#endif

#if funcused lcd_read_byte
/* read a byte from the LCD character generator or display RAM */
unsigned char lcd_read_byte(unsigned char addr)
{
_lcd_ready();
_lcd_write_data(addr);
_lcd_ready();
#asm
in r26,__lcd_direction
andi r26,0xf ;set as input
out __lcd_direction,r26
sbi __lcd_port,__lcd_rs ;RS=1
#endasm
return lcd_read_byte0();
}
#endif

/* set the LCD display position x=0..39 y=0..3 */
#if funcused lcd_gotoxy || funcused lcd_putchar || funcused lcd_puts || funcused lcd_putsf
void lcd_gotoxy(unsigned char x, unsigned char y)
{
_lcd_ready(); // RS=0
_lcd_write_data(_base_y[y]+x+0x80);
_lcd_x=x;
_lcd_y=y;
}
#endif

// clear the LCD
#if funcused lcd_clear || funcused lcd_init
void lcd_clear(void)
{
_lcd_ready(); // RS=0
_lcd_write_data(2); // cursor home
_lcd_ready();
_lcd_write_data(0xc); // cursor off
_lcd_ready();
_lcd_write_data(1); // clear
_lcd_x=_lcd_y=0;
}
#endif

#if funcused lcd_putchar || funcused lcd_puts || funcused lcd_putsf
#pragma keep+
void lcd_putchar(char c)
{
#asm
push r30
push r31
ld r26,y
set
cpi r26,10
breq __lcd_putchar1
clt
#endasm
++_lcd_x;
if (_lcd_x>_lcd_maxx)
{
#asm("__lcd_putchar1:")
++_lcd_y;
lcd_gotoxy(0,_lcd_y);
#asm("brts __lcd_putchar0")
};
#asm
rcall __lcd_ready
sbi __lcd_port,__lcd_rs ;RS=1
ld r26,y
st -y,r26
rcall __lcd_write_data
__lcd_putchar0:
pop r31
pop r30
#endasm
}
#pragma keep-
#endif

// write the string str located in SRAM to the LCD
#if funcused lcd_puts
void lcd_puts(char *str)
{
#ifdef _MODEL_TINY_
#asm
clr r31
#endasm
#endif

#ifdef _MODEL_SMALL_
#asm
ldd r31,y+1
#endasm
#endif

#asm
ld r30,y
__lcd_puts0:
ld r26,z+
tst r26
breq __lcd_puts1
st -y,r26
rcall _lcd_putchar
rjmp __lcd_puts0
__lcd_puts1:
#endasm
}
#endif

// write the string str located in FLASH to the LCD
#if funcused lcd_putsf
void lcd_putsf(char flash *str)
{
#asm
ld r30,y
ldd r31,y+1
__lcd_putsf0:
#endasm
#if defined _CHIP_ATMEGA128_ || defined _CHIP_ATMEGA128L_
#asm("elpm")
#else
#asm("lpm")
#endif
#asm
tst r0
breq __lcd_putsf1
adiw r30,1
st -y,r0
rcall _lcd_putchar
rjmp __lcd_putsf0
__lcd_putsf1:
#endasm
}
#endif

#if funcused lcd_init
static void _long_delay(void)
{
#asm
clr r26
clr r27
__long_delay0:
sbiw r26,1 ;2 cycles
brne __long_delay0 ;2 cycles
#endasm
}

static void _lcd_init_write(unsigned char data)
{
#asm
cbi __lcd_port,__lcd_rd ;RD=0
in r26,__lcd_direction
ori r26,0xf7 ;set as output
out __lcd_direction,r26
in r27,__lcd_port
andi r27,0xf
ld r26,y
rcall __lcd_write_nibble ;RD=0, write MSN
sbi __lcd_port,__lcd_rd ;RD=1
#endasm
}

// initialize the LCD controller
unsigned char lcd_init (unsigned char lcd_columns)
{
#asm
cbi __lcd_port,__lcd_enable ;EN=0
cbi __lcd_port,__lcd_rs ;RS=0
#endasm
_lcd_maxx=lcd_columns;
_base_y[0]=0;
_base_y[1]=lcd_columns + 0x0C;
_base_y[2]=lcd_columns + 0x2C;
_base_y[3]=lcd_columns + 0x4C;
_long_delay();
_lcd_init_write(0x30);
_long_delay();
_lcd_init_write(0x30);
_long_delay();
_lcd_init_write(0x30);
_long_delay();
_lcd_init_write(0x20);
_long_delay();
_lcd_init_write(0x24);
_long_delay();
_lcd_write_data(0x09); // 4 Zeilen
_long_delay();

_lcd_write_data(0x28);
_long_delay();
_lcd_write_data(4);
_long_delay();
_lcd_write_data(0x85);//85
_long_delay();
#asm
in r26,__lcd_direction
andi r26,0xf ;set as input
out __lcd_direction,r26
sbi __lcd_port,__lcd_rd ;RD=1
#endasm
if (lcd_read_byte0()!=5) return 0;
_lcd_ready();
_lcd_write_data(6);
lcd_clear();
return 1;
}
#endif

Hubert.G
24.01.2011, 09:29
Hängt anscheinend mit den Zeilenadressen zusammen, siehe hier
https://www.roboternetz.de/phpBB2/viewtopic.php?t=56904

wkrug
24.01.2011, 10:05
Hallo Hubert,

ich hab die Startadressen auf folgende Werte geändert.
Line 1=0x00
Line 2=0x0C
Line 3=0x40
Line 4=0x4C

Den ausgegebenen Text hab ich verkürzt ( Zeile 1 usw. )
Jetzt wird Zeile 1 bis 4 korrekt angezeigt.
Zeile 2 wird aber auch auf Zeile 1 position 13 bis 20 angezeigt.
Ich könnte also so nur die ersten 12 Zeichen des Displys nutzen, was natürlich Blödsinn ist.

Wenn ich nicht wegen der kleinen Bauform so ein Display benötigen würde, würde ich mir ein anderes raussuchen - Es nervt schön langsam...

wkrug
24.01.2011, 11:58
Hallo Hubert,

das Problem ist anscheinend gelöst.
Die Original und auch meine bearbeitete Library sendeten während der initialisierungsphase nur das höherwertige Nibble an das Display.
Deshalb wurde es nicht richtig auf 4 Zeilen Modus initialisiert und machte diesen Quatsch.
Nachdem ich die Routine nun so geändert hab, das auch das lower Nibble übertragen wird funktionierts!

Die .lib pass für CodeVision AVR - Falls das Jemand braucht.

Hier die funktionierende Library LCDDIP204.c:


/* LCD driver routines

CodeVisionAVR C Compiler
(C) 1998-2004 Pavel Haiduc, HP InfoTech S.R.L.
*/

#asm
.equ __lcd_direction=__lcd_port-1
.equ __lcd_pin=__lcd_port-2
.equ __lcd_rs=0
.equ __lcd_rd=1
.equ __lcd_enable=2
.equ __lcd_busy_flag=7
#endasm

#pragma used+
static unsigned char _base_y[4]={0x80,0xc0};
unsigned char _lcd_x,_lcd_y,_lcd_maxx;
#pragma used-

void _lcd_ready(void)
{
#asm
in r26,__lcd_direction
andi r26,0xf ;set as input
out __lcd_direction,r26
sbi __lcd_port,__lcd_rd ;RD=1
cbi __lcd_port,__lcd_rs ;RS=0
__lcd_busy:
rcall __lcd_delay
sbi __lcd_port,__lcd_enable ;EN=1
rcall __lcd_delay
in r26,__lcd_pin
cbi __lcd_port,__lcd_enable ;EN=0
rcall __lcd_delay
sbi __lcd_port,__lcd_enable ;EN=1
rcall __lcd_delay
cbi __lcd_port,__lcd_enable ;EN=0
sbrc r26,__lcd_busy_flag
rjmp __lcd_busy
#endasm
}

#asm
__lcd_write_nibble:
andi r26,0xf0
or r26,r27
out __lcd_port,r26 ;write
sbi __lcd_port,__lcd_enable ;EN=1
rcall __lcd_delay
cbi __lcd_port,__lcd_enable ;EN=0
__lcd_delay:
ldi r31,15
__lcd_delay0:
dec r31
brne __lcd_delay0
ret
#endasm

void _lcd_write_data(unsigned char data)
{
#asm
cbi __lcd_port,__lcd_rd ;RD=0
in r26,__lcd_direction
ori r26,0xf7 ;set as output
out __lcd_direction,r26
in r27,__lcd_port
andi r27,0xf
ld r26,y
rcall __lcd_write_nibble ;RD=0, write MSN
ld r26,y
swap r26
rcall __lcd_write_nibble ;write LSN
sbi __lcd_port,__lcd_rd ;RD=1
#endasm
}

/* write a byte to the LCD character generator or display RAM */
#if funcused lcd_write_byte
void lcd_write_byte(unsigned char addr, unsigned char data)
{
_lcd_ready();
_lcd_write_data(addr);
_lcd_ready();
#asm
sbi __lcd_port,__lcd_rs ;RS=1
#endasm
_lcd_write_data(data);
}
#endif

#if funcused lcd_read_byte || funcused lcd_init
#asm
__lcd_read_nibble:
sbi __lcd_port,__lcd_enable ;EN=1
rcall __lcd_delay
in r30,__lcd_pin ;read
cbi __lcd_port,__lcd_enable ;EN=0
rcall __lcd_delay
andi r30,0xf0
ret
#endasm

static unsigned char lcd_read_byte0(void)
{
#asm
rcall __lcd_delay
rcall __lcd_read_nibble ;read MSN
mov r26,r30
rcall __lcd_read_nibble ;read LSN
cbi __lcd_port,__lcd_rd ;RD=0
swap r30
or r30,r26
#endasm
}
#endif

#if funcused lcd_read_byte
/* read a byte from the LCD character generator or display RAM */
unsigned char lcd_read_byte(unsigned char addr)
{
_lcd_ready();
_lcd_write_data(addr);
_lcd_ready();
#asm
in r26,__lcd_direction
andi r26,0xf ;set as input
out __lcd_direction,r26
sbi __lcd_port,__lcd_rs ;RS=1
#endasm
return lcd_read_byte0();
}
#endif

/* set the LCD display position x=0..39 y=0..3 */
#if funcused lcd_gotoxy || funcused lcd_putchar || funcused lcd_puts || funcused lcd_putsf
void lcd_gotoxy(unsigned char x, unsigned char y)
{
_lcd_ready(); // RS=0
_lcd_write_data(_base_y[y]+x+0x80);
_lcd_x=x;
_lcd_y=y;
}
#endif

// clear the LCD
#if funcused lcd_clear || funcused lcd_init
void lcd_clear(void)
{
_lcd_ready(); // RS=0
_lcd_write_data(2); // cursor home
_lcd_ready();
_lcd_write_data(0xc); // cursor off
_lcd_ready();
_lcd_write_data(1); // clear
_lcd_x=_lcd_y=0;
}
#endif

#if funcused lcd_putchar || funcused lcd_puts || funcused lcd_putsf
#pragma keep+
void lcd_putchar(char c)
{
#asm
push r30
push r31
ld r26,y
set
cpi r26,10
breq __lcd_putchar1
clt
#endasm
++_lcd_x;
if (_lcd_x>_lcd_maxx)
{
#asm("__lcd_putchar1:")
++_lcd_y;
lcd_gotoxy(0,_lcd_y);
#asm("brts __lcd_putchar0")
};
#asm
rcall __lcd_ready
sbi __lcd_port,__lcd_rs ;RS=1
ld r26,y
st -y,r26
rcall __lcd_write_data
__lcd_putchar0:
pop r31
pop r30
#endasm
}
#pragma keep-
#endif

// write the string str located in SRAM to the LCD
#if funcused lcd_puts
void lcd_puts(char *str)
{
#ifdef _MODEL_TINY_
#asm
clr r31
#endasm
#endif

#ifdef _MODEL_SMALL_
#asm
ldd r31,y+1
#endasm
#endif

#asm
ld r30,y
__lcd_puts0:
ld r26,z+
tst r26
breq __lcd_puts1
st -y,r26
rcall _lcd_putchar
rjmp __lcd_puts0
__lcd_puts1:
#endasm
}
#endif

// write the string str located in FLASH to the LCD
#if funcused lcd_putsf
void lcd_putsf(char flash *str)
{
#asm
ld r30,y
ldd r31,y+1
__lcd_putsf0:
#endasm
#if defined _CHIP_ATMEGA128_ || defined _CHIP_ATMEGA128L_
#asm("elpm")
#else
#asm("lpm")
#endif
#asm
tst r0
breq __lcd_putsf1
adiw r30,1
st -y,r0
rcall _lcd_putchar
rjmp __lcd_putsf0
__lcd_putsf1:
#endasm
}
#endif

#if funcused lcd_init
static void _long_delay(void)
{
#asm
clr r26
clr r27
__long_delay0:
sbiw r26,1 ;2 cycles
brne __long_delay0 ;2 cycles
#endasm
}

static void _lcd_init_write(unsigned char data)
{
#asm
cbi __lcd_port,__lcd_rd ;RD=0
in r26,__lcd_direction
ori r26,0xf7 ;set as output
out __lcd_direction,r26
in r27,__lcd_port
andi r27,0xf
ld r26,y
rcall __lcd_write_nibble ;RD=0, write MSN
ld r26,y
swap r26
rcall __lcd_write_nibble ;write LSN
sbi __lcd_port,__lcd_rd ;RD=1
#endasm
}

// initialize the LCD controller
unsigned char lcd_init (unsigned char lcd_columns)
{
#asm
cbi __lcd_port,__lcd_enable ;EN=0
cbi __lcd_port,__lcd_rs ;RS=0
#endasm
_lcd_maxx=lcd_columns;
_base_y[0]=0x00;
_base_y[1]=lcd_columns + 0x0C;
_base_y[2]=lcd_columns + 0x2C;
_base_y[3]=lcd_columns + 0x4C;

_long_delay();
_lcd_init_write(0x24); // 4 Bit Modus + RE Bit set
_long_delay();
_lcd_write_data(0x09); // 4 Zeilen
_long_delay();
_lcd_write_data(0x20); // 4 Bit Modus + RE Bit clear
_long_delay();
_lcd_write_data(0x0C); // Display On
_long_delay();
_lcd_write_data(0x01); // Clear Display
_long_delay();
_lcd_write_data(0x06); //Auto Increment on
_long_delay();

#asm
in r26,__lcd_direction
andi r26,0xf ;set as input
out __lcd_direction,r26
sbi __lcd_port,__lcd_rd ;RD=1
#endasm
if (lcd_read_byte0()!=5) return 0;
_lcd_ready();
_lcd_write_data(6);
lcd_clear();
return 1;
}
#endif




Und das dazugehörige Header File lcddip.h:


/* LCD driver routines

CodeVisionAVR C Compiler
(C) 1998-2000 Pavel Haiduc, HP InfoTech S.R.L.

BEFORE #include -ING THIS FILE YOU
MUST DECLARE THE I/O ADDRESS OF THE
DATA REGISTER OF THE PORT AT WHICH
THE LCD IS CONNECTED!

EXAMPLE FOR PORTB:

#asm
.equ __lcd_port=0x18
#endasm
#include <lcddip.h>
Copy the File LCDDIP204.lib into the entire folder

*/

#ifndef _LCD_INCLUDED_
#define _LCD_INCLUDED_

#pragma used+

void _lcd_ready(void);
void _lcd_write_data(unsigned char data);

// write a byte to the LCD character generator or display RAM
void lcd_write_byte(unsigned char addr, unsigned char data);

// read a byte from the LCD character generator or display RAM
unsigned char lcd_read_byte(unsigned char addr);

// set the LCD display position x=0..39 y=0..3
void lcd_gotoxy(unsigned char x, unsigned char y);

// clear the LCD
void lcd_clear(void);

void lcd_putchar(char c);

// write the string str located in SRAM to the LCD
void lcd_puts(char *str);

// write the string str located in FLASH to the LCD
void lcd_putsf(char flash *str);

// initialize the LCD controller
unsigned char lcd_init(unsigned char lcd_columns);

#pragma used-
#pragma library LCDDIP204.c

#endif