PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Problem mit LCD-DIsplay



cantforget
13.07.2011, 16:05
Hallo,
ich habe ein Problem mit meinem Board (RN-MEGA8PLUS V1.5). Dazu habe ich noch den RN-LCD Adapter (BSLCDADAPT) und dieses LCD Display (EADIP204) auch aus dem RN Shop.
Nun habe ich alles angeschlossen (Display Adapter am Display Port), danach habe ich den aufgeführten Code aufgespielt. Jedoch funktioniert das Display Überhaubt nicht. Es blinkt mitsamt der Status Balkenanzeige.


$regfile = "m8def.dat"

'$crystal = 16000000 'Quarzfrequenz
$crystal = 7372800 'Alternative Quarzfrequenz

' Falls ein LCD Display angeschlossen ist
Config Portd = Output
Config Portc = Output
Config Lcd = 20 * 4
Config Lcdpin = Pin , Db4 = Portd.2 , Db5 = Portd.3 , Db6 = Portd.4 , Db7 = Portd.5 , E2 = Portd.7 , Rs = Portc.2
Config Lcdbus = 4
Cls
'Initlcd


Do
Locate 1 , 1
Lcd "Hallo Welt"
'Waitms 500
Loop

Gruß
Dennis

Thegon
13.07.2011, 21:26
Hallo Dennis,
ich habe auch einmal mit diesen Displays herumgefuchst und mir gings beim ersten Versuch genauso.
Dann hab ich ein bisschen herumprobiert und auf einmal hat es funktioniert. Ich habe damals die Zeile
config Lcdbus = 4
weggelassen. Dann hat es funktioniert. Ich habe nicht die geringste Ahnung warum, aber es hat dann auf anhieb funktioniert. Villeicht weiß ja jemand hier im Forum warum.
Das könntest du auch einmal ausprobieren, villeicht funktionier es dann ja.
Warum schreibst du eigentlich E2? reicht da nicht schon E für Enable?
Und du könntest alles mit anderen Output-pins versuchen, bei mir war nämlich einmal einer kaputt und dann hat auch alles nicht funktioniert.
Bin schon gespannt, ob das mit dem lcdbus = 4 weglassen auch bei jemandem anderen funktioniert.
Mfg Thegon

cantforget
13.07.2011, 22:19
Hallo Thegon,
Danke für deine Antwort. Ich werde deinen Vorschlag morgen direkt mal ausprobieren. Das E2 habe ich aus einem Beispielprogramm. Ich denke das LCD ist ein 2-Chip Display. Daher das 2. Enable. Werde dann morgen über den "hoffentlich" Erfolg berichten.

Schönen Abend noch
Dennis

wkrug
13.07.2011, 22:47
Ich denk mal, das es nicht funktionieren wird.
Das EA204DIP nutzt zwar ein ähnliches Protokoll wie die üblichen HD44780 Displays.
Im Prinzip geht es da beim 4 Zeiligen Display um ein Kommando und andere Adressen für die einzelnen Stellen.

In C sieht das so aus:

_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();
_long_delay();
_lcd_init_write(0x20); // 4 Bit Modus + RE Bit clear
_long_delay();

_lcd_init_write(0x24); // 4 Bit Modus + RE Bit set
_long_delay();

_lcd_init_write(0x09);
_long_delay();

_lcd_init_write(0x20); // 4 Bit Modus + RE Bit clear
_long_delay();

_lcd_init_write(0x0C); // Display On
_long_delay();

_lcd_init_write(0x01); // Clear Display
_long_delay();

_lcd_init_write(0x06); //Auto Increment on
_long_delay();

Beim HD44780 so:


_lcd_maxx=lcd_columns;
_base_y[2]=lcd_columns+0x80;
_base_y[3]=lcd_columns+0xc0;
_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_write_data(0x28);
_long_delay();
_lcd_write_data(4);
_long_delay();
_lcd_write_data(0x85);
_long_delay();

Wie das nun in BASCOM zu machen ist, kann ich Dir leider auch nicht sagen.
Eventuell hat da aber schon jemand eine fertige LIB für dieses Display.

cantforget
14.07.2011, 15:13
Hallo,
erstmal zu deiner Idee Thegon:
Ich es mal probiert das LCD durch weglassen der Bus-Configuration zum Sprechen zu bewegen, allerdings ohne Erfolg. Bist also noch der einzige mit disem Phänomen.
Nun zu dir wkrug:
Also mein Gedanke dahinter war, mal eben nen bisschen Bascom-Code zu Schreiben, um zu Testen ob das Display geht. Allerdings soll das Projekt, welches daraus entsteht in C programmiert werden. Morgen werde ich mal die Lib aus dem AVR-GCC-Tutorial ausprobieren um zu schauen ob es so geht. Kannst du mir vielleicht sagen was genau ich in der lcd-routines.h anpassen muss, damit es mit meinem 20*4 Zeichen Display funktioniert? Stehe da irgendwie wie ein Ochse vorm Berg mit den Adressen.

Gruß
Dennis

wkrug
14.07.2011, 16:30
Die Adressen und Ansteuer Sequenzen stehen im Datenblatt des Displays - Nur zur Info

Nicht für AVR GCC aber für CodeVision...
Hier die 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


Die dazugehörige 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();
_long_delay();
_lcd_init_write(0x20); // 4 Bit Modus + RE Bit clear
_long_delay();

_lcd_init_write(0x24); // 4 Bit Modus + RE Bit set
_long_delay();

_lcd_init_write(0x09);
_long_delay();

_lcd_init_write(0x20); // 4 Bit Modus + RE Bit clear
_long_delay();

_lcd_init_write(0x0C); // Display On
_long_delay();

_lcd_init_write(0x01); // Clear Display
_long_delay();

_lcd_init_write(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 die dazugehörigen Ports mit Adresszuweisung:
// Alphanumeric LCD Module functions
#asm
.equ __lcd_port=0x02 ;PORTA
#endasm
#include "lcddip.h"

Und die Init Sequenz mit ein wenig Text:
lcd_init(20);

lcd_gotoxy(0,0);
lcd_putsf("4 Chan. MiDi Merger\n");
lcd_putsf("Ver. 1.2\n");
lcd_putsf("Date: 10.Feb.2011");

Und die Anschlußbelegung:
RS (pin4) ------ bit 0
RD (pin 5) ------ bit 1
EN (pin 6) ------ bit 2
DB4 (pin 11) --- bit 4
DB5 (pin 12) --- bit 5
DB6 (pin 13) --- bit 6
DB7 (pin 14) --- bit 7

Eventuell kannst Du die GCC lib entsprechend anpassen.
Auch mit dieser lib zickt das Display ztw. rum. Die Zeile 3 und 4 lässt sich so bei jedem 20 Start nicht richtig ansprechen.
Ansonstan geht alles wie es soll.

cantforget
15.07.2011, 10:58
Hallo,
danke für deine schnelle Antwort wkrug. Habe das mal mit deiner Lib ausprobiert, allerdings funktioniert mein LCD immer noch nicht. Aber ich denke mal es liegt daran, dass ich das mit der Adressierung einfach nicht hinbekomme.
Ich habe es jetzt einmal mit nem anderen Board und LCD ausprobiert (Board und LCD von myAVR), das ganze mit der GCC-LCD-Tutorial Lib in C programmiert und siehe da es funktioniert.

Hier die lcd-routines.h:

// Ansteuerung eines HD44780 kompatiblen LCD im 4-Bit-Interfacemodus
// http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung
//

#ifndef LCD_ROUTINES_H
#define LCD_ROUTINES_H

////////////////////////////////////////////////////////////////////////////////
// Hier die verwendete Taktfrequenz in Hz eintragen, wichtig!

#ifndef F_CPU
#define F_CPU 3686400
#endif

////////////////////////////////////////////////////////////////////////////////
// Pinbelegung für das LCD, an verwendete Pins anpassen
// Alle LCD Pins müssen an einem Port angeschlossen sein und die 4
// Datenleitungen müssen auf aufeinanderfolgenden Pins liegen

// LCD DB4-DB7 <--> PORTD Bit PD0-PD3
#define LCD_PORT PORTD
#define LCD_DDR DDRD
#define LCD_DB PD4

// LCD RS <--> PORTD Bit PD4 (RS: 0=Data, 1=Command)
#define LCD_RS PD2

// LCD EN <--> PORTD Bit PD5 (EN: 1-Impuls für Daten)
#define LCD_EN PD3

////////////////////////////////////////////////////////////////////////////////
// LCD Ausführungszeiten (MS=Millisekunden, US=Mikrosekunden)

#define LCD_BOOTUP_MS 15
#define LCD_ENABLE_US 1
#define LCD_WRITEDATA_US 46
#define LCD_COMMAND_US 42

#define LCD_SOFT_RESET_MS1 5
#define LCD_SOFT_RESET_MS2 1
#define LCD_SOFT_RESET_MS3 1
#define LCD_SET_4BITMODE_MS 5

#define LCD_CLEAR_DISPLAY_MS 2
#define LCD_CURSOR_HOME_MS 2

////////////////////////////////////////////////////////////////////////////////
// Zeilendefinitionen des verwendeten LCD
// Die Einträge hier sollten für ein LCD mit einer Zeilenlänge von 16 Zeichen passen
// Bei anderen Zeilenlängen müssen diese Einträge angepasst werden

#define LCD_DDADR_LINE1 0x00
#define LCD_DDADR_LINE2 0x40
#define LCD_DDADR_LINE3 0x10
#define LCD_DDADR_LINE4 0x50

////////////////////////////////////////////////////////////////////////////////
// Initialisierung: muss ganz am Anfang des Programms aufgerufen werden.
void lcd_init( void );

////////////////////////////////////////////////////////////////////////////////
// LCD löschen
void lcd_clear( void );

////////////////////////////////////////////////////////////////////////////////
// Cursor in die 1. Zeile, 0-te Spalte
void lcd_home( void );

////////////////////////////////////////////////////////////////////////////////
// Cursor an eine beliebige Position
void lcd_setcursor( uint8_t spalte, uint8_t zeile );

////////////////////////////////////////////////////////////////////////////////
// Ausgabe eines einzelnen Zeichens an der aktuellen Cursorposition
void lcd_data( uint8_t data );

////////////////////////////////////////////////////////////////////////////////
// Ausgabe eines Strings an der aktuellen Cursorposition
void lcd_string( const char *data );

////////////////////////////////////////////////////////////////////////////////
// Definition eines benutzerdefinierten Sonderzeichens.
// data muss auf ein Array[5] mit den Spaltencodes des zu definierenden Zeichens
// zeigen
void lcd_generatechar( uint8_t code, const uint8_t *data );

////////////////////////////////////////////////////////////////////////////////
// Ausgabe eines Kommandos an das LCD.
void lcd_command( uint8_t data );


////////////////////////////////////////////////////////////////////////////////
// LCD Befehle und Argumente.
// Zur Verwendung in lcd_command

// Clear Display -------------- 0b00000001
#define LCD_CLEAR_DISPLAY 0x01

// Cursor Home ---------------- 0b0000001x
#define LCD_CURSOR_HOME 0x02

// Set Entry Mode ------------- 0b000001xx
#define LCD_SET_ENTRY 0x04

#define LCD_ENTRY_DECREASE 0x00
#define LCD_ENTRY_INCREASE 0x02
#define LCD_ENTRY_NOSHIFT 0x00
#define LCD_ENTRY_SHIFT 0x01

// Set Display ---------------- 0b00001xxx
#define LCD_SET_DISPLAY 0x08

#define LCD_DISPLAY_OFF 0x00
#define LCD_DISPLAY_ON 0x04
#define LCD_CURSOR_OFF 0x00
#define LCD_CURSOR_ON 0x02
#define LCD_BLINKING_OFF 0x00
#define LCD_BLINKING_ON 0x01

// Set Shift ------------------ 0b0001xxxx
#define LCD_SET_SHIFT 0x10

#define LCD_CURSOR_MOVE 0x00
#define LCD_DISPLAY_SHIFT 0x08
#define LCD_SHIFT_LEFT 0x00
#define LCD_SHIFT_RIGHT 0x04

// Set Function --------------- 0b001xxxxx
#define LCD_SET_FUNCTION 0x20

#define LCD_FUNCTION_4BIT 0x00
#define LCD_FUNCTION_8BIT 0x10
#define LCD_FUNCTION_1LINE 0x00
#define LCD_FUNCTION_2LINE 0x08
#define LCD_FUNCTION_5X7 0x00
#define LCD_FUNCTION_5X10 0x04

#define LCD_SOFT_RESET 0x30

// Set CG RAM Address --------- 0b01xxxxxx (Character Generator RAM)
#define LCD_SET_CGADR 0x40

#define LCD_GC_CHAR0 0
#define LCD_GC_CHAR1 1
#define LCD_GC_CHAR2 2
#define LCD_GC_CHAR3 3
#define LCD_GC_CHAR4 4
#define LCD_GC_CHAR5 5
#define LCD_GC_CHAR6 6
#define LCD_GC_CHAR7 7

// Set DD RAM Address --------- 0b1xxxxxxx (Display Data RAM)
#define LCD_SET_DDADR 0x80

#endif

Hier die lcd-routines.c:

// Ansteuerung eines HD44780 kompatiblen LCD im 4-Bit-Interfacemodus
// http://www.mikrocontroller.net/articles/HD44780
// http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung
//
// Die Pinbelegung ist über defines in lcd-routines.h einstellbar

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

////////////////////////////////////////////////////////////////////////////////
// Erzeugt einen Enable-Puls
static void lcd_enable( void )
{
LCD_PORT |= (1<<LCD_EN); // Enable auf 1 setzen
_delay_us( LCD_ENABLE_US ); // kurze Pause
LCD_PORT &= ~(1<<LCD_EN); // Enable auf 0 setzen
}

////////////////////////////////////////////////////////////////////////////////
// Sendet eine 4-bit Ausgabeoperation an das LCD
static void lcd_out( uint8_t data )
{
data &= 0xF0; // obere 4 Bit maskieren

LCD_PORT &= ~(0xF0>>(4-LCD_DB)); // Maske löschen
LCD_PORT |= (data>>(4-LCD_DB)); // Bits setzen
lcd_enable();
}

////////////////////////////////////////////////////////////////////////////////
// Initialisierung: muss ganz am Anfang des Programms aufgerufen werden.
void lcd_init( void )
{
// verwendete Pins auf Ausgang schalten
uint8_t pins = (0x0F << LCD_DB) | // 4 Datenleitungen
(1<<LCD_RS) | // R/S Leitung
(1<<LCD_EN); // Enable Leitung
LCD_DDR |= pins;

// initial alle Ausgänge auf Null
LCD_PORT &= ~pins;

// warten auf die Bereitschaft des LCD
_delay_ms( LCD_BOOTUP_MS );

// Soft-Reset muss 3mal hintereinander gesendet werden zur Initialisierung
lcd_out( LCD_SOFT_RESET );
_delay_ms( LCD_SOFT_RESET_MS1 );

lcd_enable();
_delay_ms( LCD_SOFT_RESET_MS2 );

lcd_enable();
_delay_ms( LCD_SOFT_RESET_MS3 );

// 4-bit Modus aktivieren
lcd_out( LCD_SET_FUNCTION |
LCD_FUNCTION_4BIT );
_delay_ms( LCD_SET_4BITMODE_MS );

// 4-bit Modus / 2 Zeilen / 5x7
lcd_command( LCD_SET_FUNCTION |
LCD_FUNCTION_4BIT |
LCD_FUNCTION_2LINE |
LCD_FUNCTION_5X7 );

// Display ein / Cursor aus / Blinken aus
lcd_command( LCD_SET_DISPLAY |
LCD_DISPLAY_ON |
LCD_CURSOR_OFF |
LCD_BLINKING_OFF);

// Cursor inkrement / kein Scrollen
lcd_command( LCD_SET_ENTRY |
LCD_ENTRY_INCREASE |
LCD_ENTRY_NOSHIFT );

lcd_clear();
}

////////////////////////////////////////////////////////////////////////////////
// Sendet ein Datenbyte an das LCD
void lcd_data( uint8_t data )
{
LCD_PORT |= (1<<LCD_RS); // RS auf 1 setzen

lcd_out( data ); // zuerst die oberen,
lcd_out( data<<4 ); // dann die unteren 4 Bit senden

_delay_us( LCD_WRITEDATA_US );
}

////////////////////////////////////////////////////////////////////////////////
// Sendet einen Befehl an das LCD
void lcd_command( uint8_t data )
{
LCD_PORT &= ~(1<<LCD_RS); // RS auf 0 setzen

lcd_out( data ); // zuerst die oberen,
lcd_out( data<<4 ); // dann die unteren 4 Bit senden

_delay_us( LCD_COMMAND_US );
}

////////////////////////////////////////////////////////////////////////////////
// Sendet den Befehl zur Löschung des Displays
void lcd_clear( void )
{
lcd_command( LCD_CLEAR_DISPLAY );
_delay_ms( LCD_CLEAR_DISPLAY_MS );
}

////////////////////////////////////////////////////////////////////////////////
// Sendet den Befehl: Cursor Home
void lcd_home( void )
{
lcd_command( LCD_CURSOR_HOME );
_delay_ms( LCD_CURSOR_HOME_MS );
}

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

void lcd_setcursor( uint8_t x, uint8_t y )
{
uint8_t data;

switch (y)
{
case 1: // 1. Zeile
data = LCD_SET_DDADR + LCD_DDADR_LINE1 + x;
break;

case 2: // 2. Zeile
data = LCD_SET_DDADR + LCD_DDADR_LINE2 + x;
break;

case 3: // 3. Zeile
data = LCD_SET_DDADR + LCD_DDADR_LINE3 + x;
break;

case 4: // 4. Zeile
data = LCD_SET_DDADR + LCD_DDADR_LINE4 + x;
break;

default:
return; // für den Fall einer falschen Zeile
}

lcd_command( data );
}

////////////////////////////////////////////////////////////////////////////////
// Schreibt einen String auf das LCD

void lcd_string( const char *data )
{
while( *data != '\0' )
lcd_data( *data++ );
}

////////////////////////////////////////////////////////////////////////////////
// Schreibt ein Zeichen in den Character Generator RAM

void lcd_generatechar( uint8_t code, const uint8_t *data )
{
// Startposition des Zeichens einstellen
lcd_command( LCD_SET_CGADR | (code<<3) );

// Bitmuster übertragen
for ( uint8_t i=0; i<8; i++ )
{
lcd_data( data[i] );
}
}

Und hier das Programm:

/*
* LCD_Test.c
*
* Created: 14.07.2011 08:08:53
* Author: Dennis
*/

#include <avr/io.h>
#include <avr/delay.h>
#include "lcd-routines.h"

int main(void)
{
// Initialisierung des LCD
// Nach der Initialisierung müssen auf dem LCD vorhandene schwarze Balken
// verschwunden sein
lcd_init();
// Text in einzelnen Zeichen ausgeben
lcd_data( 'T' );
lcd_data( 'e' );
lcd_data( 's' );
lcd_data( 't' );

// Die Ausgabemarke in die 2te Zeile setzen
lcd_setcursor( 0, 2 );

// erneut Text ausgeben, aber diesmal komfortabler als String
lcd_string("Hello World!");

while(1)
{

}

return 0;
}

Allerdings hat der Code (mit dem AVR-Studio 5 compiliert) eine Größe von 7036 Byte. Das kann doch nicht sein oder? Da is mein kleiner Mega8 ja schon voll. Kann es sein das er beim brennen der .hex Datei die .h und die .c der Lib auch auf den AVR schreibt?
Nun werde ich das ganze noch einmal mit dem RN-Mega8-plus Board und dem myavr-LCD ausprobieren, vielleicht ist ja doch nur ein Port kaputt.

Gruß
Dennis

radbruch
15.07.2011, 12:55
Allerdings hat der Code (mit dem AVR-Studio 5 compiliert) eine Größe von 7036 Byte.Dann machst du irgendetwas falsch:
19334

Kompiliert mit WinAVR-20100110.
delay.h befindet sich jetzt in util/

cantforget
15.07.2011, 13:20
Hallo,
aha danke dir Radbruch, ich habe den Fehler gefunden.
Im AVR-Studio 5 kann man im "Solution Explorer" bei "Solution 'Dateiname'" rechts klicken, danach wählt man den "Configuration Manager" an und stellt bei "Configuration" satt "Debug" "Release" ein. Danach hat mein Programm nun 486 Bytes. Wo allerdings der Unterschied zu deiner Größe kommt, kann ich mir nicht erklären.


Kompiliert mit WinAVR-20100110.
delay.h befindet sich jetzt in util/ Bei mir ging es erst nicht im util/, aber nun geht es seltsamer weise.

Sag mal Radbruch hast du eine Idee wie ich mein oben beschriebenes LCD mit der Lib die ich gepostet habe zum laufen bekomme?

Gruß
Dennis

radbruch
15.07.2011, 13:29
$crystal = 7372800
...
#ifndef F_CPU
#define F_CPU 3686400
#endif

? Bei falscher Taktfrequenz stimmt das Timeing durch delay.h nicht mehr. Ich muss mich erst mal einlesen (und die Datenblätter suchen) ...

P.S.: Schwäbisch sparsam kompiliert ;)

Hubert.G
15.07.2011, 13:30
Ich arbeite immer mit der Lib von P.Fleury, in der kann man den KS0073 einstellen. Es gibt da in der Init einen unterschied.

cantforget
15.07.2011, 13:49
Hallo,
also Radbruch ist nett von dir wenn du das für mich machst. Also der code sollte im Projekt schon in C geschrieben werden, also ich meinte das im Obersten Post beschriebene LCD und die Lib's aus Post nummer 7. Bei der Taktfrequenz sehe ich auch gerade da habe ich wohl was vertauscht, weil ich 2 Boards hier liegen habe. Die richtige ist 7372800 Hz.
Das Problem war halt, das ich das 20*4 LCD nicht mit dem RN-MEGA8-plus Board betreiben kann. Die Ports habe ich die von der Display-Buchse genommen.
Und Hubert.G hast du auch schon mit meinem LCD gearbeitet? Denn ich hatte es zuerst mit der Fleury lib probiert, allerdings kam ich damit auch nicht zu einer funktionierenden Lösung. >Ich sehe gerade, dass es ein paar änderungen in der lib gab, werde mir das später aber nocheinmal genauer ansehen.

Gruß
Dennis

Hubert.G
15.07.2011, 15:01
Mit deinem speziellen LCD habe ich noch nicht gearbeitet. Allerdings mit LCDs mit einem KS0073, diese haben nur mit der Einstellung für diesen Kontrollertyp funktioniert.

cantforget
15.07.2011, 16:54
Hallo,
@Hubert.G:
So habe die lib nun mal umgeschrieben bin mir aber mit der Adressierung unsicher könntest du mal schauen ob die richtig ist?

#define LCD_LINES 4 /**< number of visible lines of the display */
#define LCD_DISP_LENGTH 20 /**< visibles characters per line of the display */
#define LCD_LINE_LENGTH 0x20 /**< internal line length of the display */
#define LCD_START_LINE1 0x00 /**< DDRAM address of first char of line 1 */
#define LCD_START_LINE2 0x40 /**< DDRAM address of first char of line 2 */
#define LCD_START_LINE3 0x10 /**< DDRAM address of first char of line 3 */
#define LCD_START_LINE4 0x60 /**< DDRAM address of first char of line 4 */
#define LCD_WRAP_LINES 0 /**< 0: no wrap, 1: wrap at end of visibile line */
Das ist dieses LCD:
http://www.robotikhardware.de/download/eadip204_datenblatt.pdf
Ich hoffe mal ich bekomme das irgendwie nochmal hin. Finde das schon nicht so einfach ein LCD einzubinden.

Gruß
Dennis

Hubert.G
15.07.2011, 23:10
Die Startadressen der Zeilen sind für den Anfang nicht so wichtig, da hast du vielleicht verschobenen Text.
Viel wichtiger ist ob die Initialisierung funktioniert.

radbruch
16.07.2011, 12:48
Hallo

Ich habe nun die Datenblätter des RNMega8Plus und des RN-LCD-Adapters angeschaut und die Pinbelegungen der Steckverbindungen überprüft:


// Pinout LCD Display-Anschluß nach Roboternetznorm RN-LCD-Adapter
// Pin 1 LCD DB7
// Pin 2 LCD DB6
// Pin 3 LCD DB5
// Pin 4 LCD DB4
// Pin 5 Licht ein/aus per Port (da EN2 hier nicht benötigt wird)
// Pin 6 LCD EN
// Pin 7 LCD R/W
// Pin 8 LCD RS
// Pin 9 GND LCD GND und Licht Kathode
// Pin 10 +5V LCD VCC und Licht Anode// LCD DB4-DB7 <--> PORTD Bit PD0-PD3

// Pinout LCD Display-Anschluß nach Roboternetznorm RNMEGA8PLUS
// Pin 1 DB7 PD5
// Pin 2 DB6 PD4
// Pin 3 DB5 PD3
// Pin 4 DB4 PD2
// Pin 5 EN2 PD7 (wird nur bei manchen LCDs benötigt)
// Pin 6 EN PC3
// Pin 7 R/W PD6
// Pin 8 RS PC2
// Pin 9 GND
// Pin 10 +5V

#define LCD_PORT PORTD
#define LCD_DDR DDRD
#define LCD_DB PD4

// LCD RS <--> PORTD Bit PD4 (RS: 0=Data, 1=Command)
#define LCD_RS PD2

// LCD EN <--> PORTD Bit PD5 (EN: 1-Impuls für Daten)
#define LCD_EN PD3


Oben: Belegung des RN-LCD-Adapters. Laut Schaltplan stimmt auch die Verbindung zu den 2x9 Pins des aufsteckbaren LCD.
Mitte: Belegung des LCD-Ports auf dem RNMega8Plus. Stimmt mit der Abschluß am Adapter überein bis auf E2
Unten: Die Defines in lcd-routines.h passen nicht zu der Belegung vom RNMega8Plus!!!

Außerdem wird der R/W-Pin nicht definiert. Da beim Schreiben das Busy nicht geprüft wird und auch keine lesenden Funktionen vorhanden sind gehe ich davon aus, dass die Lib davon ausgeht, dass R/W low ist (Brücke zu GND. Ohne Brücke ist auch die jumperbare Verbindung der freien D0 bis D3 zu GND kritisch!).

Gruß

mic

http://www.robotikhardware.de/download/rnmega8plus.pdf
http://www.robotikhardware.de/download/rn_LCD_adapter.pdf

[Edit]

// Pinout LCD Display-Anschluß nach Roboternetznorm RNMEGA8PLUS
// Pin 1 DB7 PD5
// Pin 2 DB6 PD4
// Pin 3 DB5 PD3
// Pin 4 DB4 PD2
// Pin 5 EN2 PD7 (wird nur bei manchen LCDs benötigt)
// Pin 6 EN PC3
// Pin 7 R/W PD6
// Pin 8 RS PC2
// Pin 9 GND
// Pin 10 +5V

// Defines der Ports des RNMega8Plus für die LCD-Lib von Peter Fleury (http://www.jump.to/fleury)
// R/W geht auf PD6!

#define LCD_PORT PORTD /**< port for the LCD lines */
#define LCD_DATA0_PORT LCD_PORT /**< port for 4bit data bit 0 */
#define LCD_DATA1_PORT LCD_PORT /**< port for 4bit data bit 1 */
#define LCD_DATA2_PORT LCD_PORT /**< port for 4bit data bit 2 */
#define LCD_DATA3_PORT LCD_PORT /**< port for 4bit data bit 3 */
#define LCD_DATA0_PIN 2 /**< pin for 4bit data bit 0 */
#define LCD_DATA1_PIN 3 /**< pin for 4bit data bit 1 */
#define LCD_DATA2_PIN 4 /**< pin for 4bit data bit 2 */
#define LCD_DATA3_PIN 5 /**< pin for 4bit data bit 3 */

#define LCD_RS_PORT PORTC /**< port for RS line */
#define LCD_RS_PIN 2 /**< pin for RS line */
#define LCD_RW_PORT PORTD /**< port for RW line */
#define LCD_RW_PIN 6 /**< pin for RW line */
#define LCD_E_PORT PORTC /**< port for Enable line */
#define LCD_E_PIN 3 /**< pin for Enable line */

cantforget
19.07.2011, 08:40
Hallo,
entschuldigt bitte, dass ich so lange nicht geantwortet habe. Es kam leider wie immer wenn man basteln will etwas dazwischen. Danke für die Mühe des Vergleichs radbruch, verstehe ich das richtig, dass ich in der .h die Data_Pins 0 bis 3 in 4 bis 7 ändern muss und dem entsprechend auch die Pins in der .c Datei? Wenn ja wäre das ein ziemlicher Aufwand.

Gruß
Dennis

radbruch
19.07.2011, 09:18
Hallo

Du brauchst nur die Defines in der Headerdatei (.h) ändern bzw. anpassen. Später werden die Pins nur über die Defines angesprochen und die Anpassung wird so automatisch überall im Programm wirksam.

Die (ungetestete) Anpassung an die Lib von Peter Fleury habe ich oben ja schon gepostet. Diese Lib würde ich bevorzugen, weil sie die bei deiner Beschaltung vorhandene R/W-Leitung verwendet und deshalb das Busy-Signal des LCD auswerten kann.

Gruß

mic