Forum: Mikrocontroller und Digitale Elektronik LCD mit Infineon Entwicklungsboard


von Ronald (Gast)


Lesenswert?

Hallo zusammen,

ich bin neu hier und habs noch nicht so drauf, also gleich mal sorry für 
evt. einfache Fragen.

Ich versuche mit einem Infineon XC164CM Easy Kit ein ANAG VISION AV0820 
8x2 (KS0066) anzusteuern. Leider scheitere ich bereits bei der 
Initialisierung.
Die Pins sind alle richtig belegt (hab alle nachgemessen).
Mein Versuch zur Initialisierung über Port1
1
typedef unsigned char ubyte;
2
  typedef unsigned int uword;
3
  typedef unsigned long ulong;
4
5
  #include <XC164.h>
6
 
7
  volatile uword reload;
8
  uword i;
9
10
  void delay(){
11
    for(i=reload;i<=0xEFFF;i++){}
12
    for(i=reload;i<=0xEFFF;i++){}
13
    for(i=reload;i<=0xEFFF;i++){}
14
    for(i=reload;i<=0xEFFF;i++){}
15
    for(i=reload;i<=0xEFFF;i++){}
16
    for(i=reload;i<=0xEFFF;i++){}
17
    for(i=reload;i<=0xEFFF;i++){}
18
    for(i=reload;i<=0xEFFF;i++){}
19
    for(i=reload;i<=0xEFFF;i++){}
20
    for(i=reload;i<=0xEFFF;i++){}
21
    for(i=reload;i<=0xEFFF;i++){}
22
    for(i=reload;i<=0xEFFF;i++){}
23
    for(i=reload;i<=0xEFFF;i++){}
24
    for(i=reload;i<=0xEFFF;i++){}
25
    for(i=reload;i<=0xEFFF;i++){}
26
    for(i=reload;i<=0xEFFF;i++){}
27
    for(i=reload;i<=0xEFFF;i++){}
28
    for(i=reload;i<=0xEFFF;i++){}
29
    for(i=reload;i<=0xEFFF;i++){}
30
    for(i=reload;i<=0xEFFF;i++){}
31
  }
32
33
 
34
 
35
  void main(void){
36
37
  reload = 0xEEEE;
38
  
39
  DP1L = (DP1L & ~(uword)0x00FF) | 0x00FF; //Die letzten 8 Bits auf Ausgangs setzten
40
  DP1H = (DP1H & ~(uword)0x00FF) | 0x003F; //Die letzten 8 Bits auf Ausgangs setzten
41
  
42
  delay();
43
44
  //Initialisierung
45
  P1H = (P1H & ~(uword)0x00FF) | 0x00C0;       
46
  delay();
47
  P1H = (P1H & ~(uword)0x00FF) | 0x00C0;
48
  delay();
49
  P1H = (P1H & ~(uword)0x00FF) | 0x00C0;
50
  delay();
51
  
52
53
  P1H = (P1H & ~(uword)0x00FF) | 0x000D;
54
  P1L = (P1L & ~(uword)0x00FF) | 0x00C0;
55
  
56
  P1H = (P1H & ~(uword)0x00FF) | 0x0002;
57
  P1L = (P1L & ~(uword)0x00FF) | 0x00C0;
58
  
59
  P1H = (P1H & ~(uword)0x00FF) | 0x0000;
60
  P1L = (P1L & ~(uword)0x00FF) | 0x0040;
61
  
62
  P1H = (P1H & ~(uword)0x00FF) | 0x0000;
63
  P1L = (P1L & ~(uword)0x00FF) | 0x0040;
64
65
66
  while (1){}
67
68
}

Vielleicht kann mir evt. jemand helfen.
Vielen Dank schon mal für eure Antworten.

MfG Ronald

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Funktioniert dein delay?

Eine funktionierende Delayfunktion ist das A und O beim LCD. Da ist ein 
striktes Timing einzuhalten, das auch im Datenblatt des LCD-Controllers 
angegeben ist. Hast du ein solches Datenblatt für den KS0066?

Die Delayfunktion kann man mit einem einfachen LED-Blinkprogramm grob 
testen.

Der Rest deines Quellcodes kann kaum kontrolliert werden, weil dem 
Zuschauer nicht klar ist, welche Spieler auf dem Platz stehen ähm 
Leitungen des LCD an welche Pins des µC gehen. Ein Schaltplan (auch 
handgezeichnet) wäre da sehr hilfreich.

Was am Quellcode auffällt ist, dass anscheinend die essentiellen RS und 
E (und ggf. die RW, sieht man nicht weil Schaltplan fehlt) Leitungen des 
LCD zusammen mit den Datenleitungen D0..D7 gesetzt werden (Veroderung?) 
oder komplett fehlen. Das entspricht überhaupt nicht dem einzuhaltenden 
Timing aus dem Datenblatt!

von abc (Gast)


Lesenswert?

verwendest du eine codeoptimierung? dann würde ich drauf tippen, dass 
der optimierer deine ganzen leeren (und daher für ihn sinnfreien) 
zählschleifen rauswirft ;-)

von Ronald (Gast)


Lesenswert?

Hallo,

danke für die Antworten. Ja ich glaub es liegt am Timing. Ich werde mal 
einen Schaltplan erstellen und das Programm umstellen.

Eine Frage hätte ich aber noch: bei einem Infineon XC164 40MHz, wie kann 
ich mir ein passendes delay basteln? 1/Takfrequenz sind 25ns....aber wie 
gehts weiter? Ich verwende Keil (Compiler).

Nochmals danke für die Anworten

MfG Ronald

von Oliver J. (skriptkiddy)


Lesenswert?

Ronald schrieb:
> Eine Frage hätte ich aber noch: bei einem Infineon XC164 40MHz, wie kann
> ich mir ein passendes delay basteln?

Wenn man es professionell machen willl, nimmt man nen timer. Ich mache 
es es aber der einfachheit halber immer so:

1
#include <REG164.H>
2
3
4
#define LED_PORT P1L
5
#define LED_MASK 0xFF  
6
#define LED_DIR  DP1L
7
8
#define led_init()  LED_DIR  |= LED_MASK
9
#define led_on()    LED_PORT &=~LED_MASK
10
#define led_off()   LED_PORT |= LED_MASK
11
12
#define COUNTER_1MS 2000UL         // muss noch so verändert werden, dass ca. 1Hz Blinktakt herauskommt
13
14
void _delay_ms(int ms)
15
{
16
 int count_ms;        
17
 long int counter;     
18
 
19
 for(count_ms=0 ; count_ms<ms ; count_ms++)
20
  for(counter=0 ; counter<COUNTER_1MS ; counter++);   // Schleife für einzelne Millisekunden
21
}
22
23
int main(void)
24
{
25
 led_init();
26
 
27
 while(1)
28
 {
29
  led_on();
30
  _delay_ms(500);
31
  led_off();
32
  _delay_ms(500);
33
 }
34
}

Jetzt muss nur noch COUNTER_1MS angepasst werden, dass eine LED im 
Sekundentakt blinkt. Damit hat man ne Verzögerungsschleife für Vielfache 
einer Millisekunden. Die sollte eigentlich reichen, um das LCD zu 
initialisieren, auch wenn an manchen Stellen Mikrosekunden reichen 
würden. Länger darfs immer sein.

Gruß
Skriptkiddy

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Der klassische weg:

Schreibe dir eine Funktion, die im µs Bereich warten kann.

Dazu in einer Schleife so viele Nichtstun-Assembler-Anweisungen benutzen 
wie nötig.

Es hängt vom Instruction Set des µC ab, wie diese Anweisung heisst. 
Bei anderen µC heisst sie üblicherweise NOP
http://www.keil.com/dd/docs/datashts/infineon/c166sv2um.pdf

Und es hängt von deiner Entwicklungssoftware (Kein µVision3?) ab, wie 
man die Nichtstun-Assembler-Anweisung in C verwendet (inline Assebler).

Und eine die im ms Bereich warten kann. Die ms wartefunktion kann die us 
Wartefunktion benutzen.

Wie man das implementieren kann (bei anderem Prozessor)
http://www.keil.com/forum/1940/

Diese Funktionen sind so grundlegend, dass ich mir nicht verstellen 
kann, dass es diese noch nicht gibt.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Skript Kiddy schrieb:

>   for(counter=0 ; counter<COUNTER_1MS ; counter++);   // Schleife für

Gleicher Fall den abc schon angesprochen hat. Manche Compiler 
optimieren solche Zeilen gnadenlos weg, wenn Codeoptimierung 
eingeschaltet ist. Wenn das der Fall ist: counter volatile machen.

von Oliver J. (skriptkiddy)


Lesenswert?

Stefan B. schrieb:
> Manche Compiler
> optimieren solche Zeilen gnadenlos weg, wenn Codeoptimierung
> eingeschaltet ist. Wenn das der Fall ist: counter volatile machen.

Ok dann gehen wir auf Nummer Sicher.
1
...
2
3
void _delay_ms(int ms)
4
{
5
 int count_ms;        
6
 volatile long int counter;     
7
 
8
 for(count_ms=0 ; count_ms<ms ; count_ms++)
9
  for(counter=0 ; counter<COUNTER_1MS ; counter++);   // Schleife für einzelne Millisekunden
10
}
11
12
...

Gruß
Skriptkiddy

von Ronald (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

nochmals danke für eure tolle Hilfe! Ich habs nun wie folgt modifiziert:
(Schaltplan + Dokumentation fürs Display + Beschreibung des Ports ist 
auch dabei). ...leider funktionierts immer noch nicht :(
Das Delay funktioniert (habs mit einer Diode ausprobiert)
1
  typedef unsigned char ubyte;
2
  typedef unsigned int uword;
3
  typedef unsigned long ulong;
4
5
  #include <XC164.h>
6
  #define COUNTER_1MS 2700UL
7
8
  
9
 void delay(uword ms)
10
{
11
 uword count_ms;        
12
 ulong counter;     
13
 
14
 for(count_ms=0 ; count_ms<ms ; count_ms++)
15
  for(counter=0 ; counter<COUNTER_1MS ; counter++);   // Schleife für einzelne Millisekunden
16
}
17
18
 
19
 void main(void){
20
21
  DP1L = (DP1L & ~(uword)0x00FF) | 0x00FF; //Die letzten 8 Bits auf Ausgangs setzten
22
  DP1H = (DP1H & ~(uword)0x00FF) | 0x003F; //Die letzten 6 Bits auf Ausgangs setzten
23
  P1L = (P1H & ~(uword)0x00FF) | 0x0000; //Startwert alles auf 0
24
  P1L = (P1H & ~(uword)0x00FF) | 0x0000; //Startwert alles auf 0
25
26
  delay(40);
27
28
  //Initialisierung laut Datenblatt....die delay`s sind immer ein Bisschen länger
29
  P1H = (P1H & ~(uword)0x00FF) | 0x000C;
30
  P1L = (P1L & ~(uword)0x00FF) | 0x0000;     
31
  delay(1);
32
  P1H = (P1H & ~(uword)0x00FF) | 0x000C;
33
  P1L = (P1L & ~(uword)0x00FF) | 0x0000;  
34
  delay(1);
35
  P1H = (P1H & ~(uword)0x00FF) | 0x000C;
36
  P1L = (P1L & ~(uword)0x00FF) | 0x0000;
37
  delay(1);
38
39
  P1H = (P1H & ~(uword)0x00FF) | 0x000E;    
40
  P1L = (P1L & ~(uword)0x00FF) | 0x0000;
41
  delay(1);
42
  P1H = (P1H & ~(uword)0x00FF) | 0x0002;
43
  P1L = (P1L & ~(uword)0x00FF) | 0x0000;
44
  delay(1);
45
  P1H = (P1H & ~(uword)0x00FF) | 0x0000;
46
  P1L = (P1L & ~(uword)0x00FF) | 0x0040;
47
  delay(1);
48
  P1H = (P1H & ~(uword)0x00FF) | 0x0001;
49
  P1L = (P1L & ~(uword)0x00FF) | 0x0080;
50
51
   while (1){}
52
}

Das Datenblatt ist hier zu finden:
http://www.conrad.at/ce/de/product/181647/LCD-MOD-STN-BLAU-NEGLED-WEISS-8X2/SHOP_AREA_17651&promotionareaSearchDetail=005

Bitte nochmals um Hilfe,

MfG Ronald

von Ronald (Gast)


Lesenswert?


von Stefan B. (stefan) Benutzerseite


Lesenswert?

Die korrekte Kontrastspannung Vee muss entsprechend dem Datenblatt 
angeschlossen werden.

Extrem ungünstige Verkabelung von Port 1, weil alle Bitmuster aus dem 
LCD-Controller Datenblatt verwurstet werden müssen.

Kannst du nicht die DB0 bis DB7 komplett auf P1H legen und zwar so, dass 
Bit 0 von P1H auch DB0 entspricht? Und P1L für RS, E und RW nehmen?

Arbeitet die delay jetzt korrekt? Kannst du damit eine LED im 1s 
(1000ms) Abstand blinken lassen? Exakt 60 "Herzschläge" pro Minute?

von Ronald (Gast)


Lesenswert?

Hallo Stefan,

leider kann ich DB0-DB0 nicht auf P1H legen, da P1H nur 6 Bits zur 
Verfügung stellt. Ich könnte jedoch evt. DB0 - DB7 auf P1L setzten und 
die anderen auf P1H wenn das besser ist. Bei Vee bin ich mir nicht 
sicher (häng ich da Vref vom Controller dran?). Beim Delay hab ich für 
10000ms mitgestoppt, und komm ziemlich genau auf 10s.

MfG Ronald

von Ronald (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

so hab jetzt alles mal umgestellt, dass man leichter programmieren kann. 
Im Anhang nochmal der vereinfachte Schaltplan. Evt. kann mir nun jemand 
weiterhelfen.
Vielen Dank schon mal:
1
 typedef unsigned char ubyte;
2
  typedef unsigned int uword;
3
  typedef unsigned long ulong;
4
5
  #include <XC164.h>
6
  #define COUNTER_1MS 2700UL
7
8
  
9
 void delay(uword ms)
10
{
11
 uword count_ms;        
12
 ulong counter;     
13
 
14
 for(count_ms=0 ; count_ms<ms ; count_ms++)
15
  for(counter=0 ; counter<COUNTER_1MS ; counter++);   // Schleife für einzelne Millisekunden
16
}
17
18
 
19
 void main(void){
20
21
  DP1L = (DP1L & ~(uword)0x00FF) | 0x00FF; //Die letzten 8 Bits auf Ausgangs setzten
22
  DP1H = (DP1H & ~(uword)0x00FF) | 0x003F; //Die letzten 6 Bits auf Ausgangs setzten
23
  P1L = (P1L & ~(uword)0x00FF) | 0x0000; //Startwert alles auf 0
24
  P1H = (P1H & ~(uword)0x00FF) | 0x0001; //Startwert alles auf 0
25
26
  delay(40);
27
 
28
  //Initialisierung laut Datenblatt....die delay`s sind immer ein Bisschen länger
29
  P1L = (P1L & ~(uword)0x00FF) | 0x0003;
30
  P1H = (P1H & ~(uword)0x00FF) | 0x0000;     
31
  delay(1);
32
  P1L = (P1L & ~(uword)0x00FF) | 0x0003;
33
  P1H = (P1H & ~(uword)0x00FF) | 0x0000;  
34
  delay(1);
35
  P1L = (P1L & ~(uword)0x00FF) | 0x0003;
36
  P1H = (P1H & ~(uword)0x00FF) | 0x0000;
37
  delay(1);
38
39
  P1L = (P1L & ~(uword)0x00FF) | 0x001C;
40
  P1H = (P1H & ~(uword)0x00FF) | 0x0000;    
41
  delay(1);
42
  P1L = (P1L & ~(uword)0x00FF) | 0x0008;
43
  P1H = (P1H & ~(uword)0x00FF) | 0x0000;
44
  delay(1);
45
  P1L = (P1L & ~(uword)0x00FF) | 0x0001;
46
  P1H = (P1H & ~(uword)0x00FF) | 0x0000;
47
  delay(1);
48
  P1L = (P1L & ~(uword)0x00FF) | 0x0006;
49
  P1H = (P1H & ~(uword)0x00FF) | 0x0000;
50
  
51
   while (1){}
52
}

..und auch nochmal der Link zum Datenblatt:
http://www.google.at/#hl=de&&sa=X&ei=flXVTM70G4WXOuT_9NQJ&ved=0CBUQBSgA&q=datenblatt+anag+vision+av0820&spell=1&fp=b0a2e91333c3fe0a

ach ja, wie war das nochmal mit Vee?
MfG Ronald

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Ronald schrieb:

> leider kann ich DB0-DB0 nicht auf P1H legen, da P1H nur 6 Bits zur
> Verfügung stellt. Ich könnte jedoch evt. DB0 - DB7 auf P1L setzten und
> die anderen auf P1H wenn das besser ist.

Das wäre deutlich besser als die Anfangsverkabelung! Über P1L setzt du 
dann ausschliesslich die Datenleitungen und über P1H ausschliesslich die 
Steuerleitungen.

Im Moment bin ich fit für die Falle. Morgen mehr.

> Bei Vee bin ich mir nicht
> sicher (häng ich da Vref vom Controller dran?).

Das ist wahrscheinlich ein zu hohes Spannungspotential. Du brauchst dort 
so um die typ. 0.7V. Muss ich aber im Datenblatt nachsehen und dafür ist 
es mir zu spät.

Um die Vee runter zu setzen: Hast du 10K oder 25K Potentiometer in der 
Bastelkiste oder auf dem Board? Mit dem kannst du einen 
Spannungsteiler aufbauen:
1
Vcc --###-- Gnd
2
       ^
3
       |
4
       +--- Vee

> Beim Delay hab ich für
> 10000ms mitgestoppt, und komm ziemlich genau auf 10s.

Das ist schon gut. Damit hättest du die delay_ms Funktion. Kannst du 
auch eine delay_us Funktion schreiben, also eine Funktion, die im 
Microsekunden-Bereich wartet.

Die delay_us ist nicht unbedingt nötig, aber bestimmte Timings speziell 
beim Enable An/Aus können im us Bereich liegen und mur mit delay_ms 
würde man da immer mindestens 1 ms verbraten.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Das folgende orientiert sich stark am Artikel
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung

Dort geht es um einen anderen µC, aber ich werde auf deinen µC Rücksicht 
nehmen.

Zunächst wird die Pinzuordnung in Makros definiert, damit der Quellcode 
später lesbarer wird.
1
#define LCD_RS        4
2
#define LCD_RW        5
3
#define LCD_EN        6
4
5
#define LCD_DATAPORT  P1L
6
#define LCD_CTRLPORT  P1H
7
#define LCD_DATADIR   DP1L
8
#define LCD_CTRLDIR   DP1H

Damit kann die "1<<BITNUMMER Schreibweise" zur Bitmanipulation 
verwenden.

Dann die wichtigsten LCD Funktionen. Fehlende Funktionen (lcd_clear) und 
Definitionen (LCD_Makros) aus dem Artikel holen. Bei den Zeiten aus dem 
Artikel (Bsp. LCD_ENABLE_US) im Datenblatt des eigenen LCD nachsehen, ob 
die so passen.
1
void _delay_us(unsigned int us)
2
{
3
  // us Microsekunden warten alternativ: _delay_ms(1) aufrufen
4
  // zu implementieren...
5
}
6
7
void _delay_ms(unsigned int ms)
8
{
9
  // ms Millisekunden warten
10
  // zu implementieren...
11
}
12
13
// Erzeugt einen Enable-Puls
14
static void lcd_enable( void )
15
{
16
    LCD_CTRLPORT |= (1<<LCD_EN);     // Enable auf 1 setzen
17
    _delay_us( LCD_ENABLE_US );      // kurze Pause
18
    LCD_CTRLPORT &= ~(1<<LCD_EN);    // Enable auf 0 setzen
19
}
20
 
21
// Sendet eine 8-bit Ausgabeoperation an das LCD
22
static void lcd_out8( unsigned char data )
23
{
24
    LCD_DATAPORT = data;     // Bits setzen
25
    lcd_enable();
26
}
27
 
28
// Initialisierung: muss ganz am Anfang des Programms aufgerufen werden.
29
void lcd_init( void )
30
{
31
    // verwendete Pins auf Ausgang schalten
32
    unsigned char pins = (1<<LCD_RW) |           // R/W Leitung
33
                         (1<<LCD_RS) |           // R/S Leitung
34
                         (1<<LCD_EN);            // Enable Leitung
35
36
    LCD_CTRLDIR  |= pins;
37
    LCD_CTRLPORT &= ~pins;
38
    LCD_DATADIR  |= 0xFF;
39
    LCD_DATAPORT &= ~0xFF;
40
 
41
    // warten auf die Bereitschaft des LCD
42
    _delay_ms( LCD_BOOTUP_MS );
43
    
44
    // Soft-Reset muss 3mal hintereinander gesendet werden 
45
    // zur Initialisierung
46
    lcd_out8( LCD_SOFT_RESET );
47
    _delay_ms( LCD_SOFT_RESET_MS1 );
48
 
49
    lcd_enable();
50
    _delay_ms( LCD_SOFT_RESET_MS2 );
51
 
52
    lcd_enable();
53
    _delay_ms( LCD_SOFT_RESET_MS3 );
54
55
    // 8-bit Modus / 2 Zeilen / 5x7
56
    lcd_command( LCD_SET_FUNCTION |
57
                 LCD_FUNCTION_8BIT |
58
                 LCD_FUNCTION_2LINE |
59
                 LCD_FUNCTION_5X7 );
60
 
61
    // Display ein / Cursor aus / Blinken aus
62
    lcd_command( LCD_SET_DISPLAY |
63
                 LCD_DISPLAY_ON |
64
                 LCD_CURSOR_OFF |
65
                 LCD_BLINKING_OFF); 
66
 
67
    // Cursor inkrement / kein Scrollen
68
    lcd_command( LCD_SET_ENTRY |
69
                 LCD_ENTRY_INCREASE |
70
                 LCD_ENTRY_NOSHIFT );
71
 
72
    lcd_clear();
73
}
74
  
75
// Sendet ein Datenbyte an das LCD
76
void lcd_data( unsigned char data )
77
{
78
    LCD_CTRLPORT |= (1<<LCD_RS);    // RS auf 1 setzen
79
    lcd_out8( data );
80
    _delay_us( LCD_WRITEDATA_US );
81
}
82
 
83
// Sendet einen Befehl an das LCD
84
void lcd_command( unsigned char data )
85
{
86
    LCD_CTRLPORT &= ~(1<<LCD_RS);    // RS auf 0 setzen
87
    lcd_out8( data );
88
    _delay_us( LCD_COMMAND_US );
89
}

Das Demoprogramm sieht dann so aus:
1
void main(void)
2
{
3
  lcd_init();
4
  while (1)
5
  {
6
    lcd_data('4');
7
    lcd_data('2');
8
    lcd_data(' ');
9
  }
10
}

von Ronald (Gast)


Lesenswert?

Hallo Stefan,

vielen vielen Dank, dass du deine Zeit opferst. Vee hab ich mit einem 
Poti mit 0.7V belegt. Nun versuch ich gleich mal mit deiner Vorlage das 
ding zum Laufen zu kriegen.
Bis später, und nochmals danke!

MfG Ronald

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Ronald schrieb:

> vielen vielen Dank, dass du deine Zeit opferst.

Keine Ursache, bin sowieso hier :-)

von Ronald (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Stefan,

das mit den 0.7V hat gut funktioniert. Vorweg, es funktioniert leider 
immer noch nicht. Folgendes hab ich am Code geändert:

Stefan B. schrieb:
> #define LCD_RS        4
> #define LCD_RW        5
> #define LCD_EN        6

...ich glaube da hast du dich vertippt (siehe Schaltplan)
E = Pin3
RW = Pin2
RS = Pin1
Vee = Pin0

..also müsste es doch so passen...?
#define LCD_RS        1
#define LCD_RW        2
#define LCD_EN        3

Komisch ist auch, dass die Hintergrundbeleuchtung nicht 
funktioniert...!?!
Port1 kann man als Input und als Output betreiben.
DP1L und DP1L muss man zuerst auf 0xFF setzten. Wenn ich das probiere, 
kommt eine Fehlermeldung: redefinition...
Macht man das jedoch nicht, kommen bei jedem Pin nur 3,5V Statt 4.8 raus 
(da noch andere Funktionen am Port laufen, oder so). Im Anhang hab ich 
nochmal das gesamte Datenblatt zu Port1.

Langsam bin ich echt am Verzweifeln.
Ich bitte nochmals um Hilfe.

MfG Ronald

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Ronald schrieb:

> ...ich glaube da hast du dich vertippt (siehe Schaltplan)
> E = Pin3
> RW = Pin2
> RS = Pin1
> Vee = Pin0
>
> ..also müsste es doch so passen...?
> #define LCD_RS        1
> #define LCD_RW        2
> #define LCD_EN        3

Stimmt, gut aufgepasst. Ich hatte falsch an der LCD Seite die Pinnummern 
abgeschrieben.

Vee gehort nicht an den µC, sondern an den Schleifer des 
Potentiometers.
Beitrag "Re: LCD mit Infineon Entwicklungsboard"
Aber mit Vee bist du ja durch bzw. das klappt.

> Komisch ist auch, dass die Hintergrundbeleuchtung nicht
> funktioniert...!?!

Das ist ein komplett anderes Thema.

Die Hintergrundbeleuchtung hat getrennte Anschlüsse (K und A an der 
Seite der Platine),

Die legt man über einen Vorwiderstand zur Begrenzung des 
Durchflußstromes der Hintergrund-LED an Vcc2 und GND. Bei manchen LCDs 
kann Vcc2 gleich Vcc sein, bei anderen nicht.

In deinem Datenblatt stehen die Werte zur Berechnung (s. Artikel 
LED) des Vorwiderstandes bei LED Forward Voltage und LED Forward 
Current. Dabei auf die Unterschiede weisse Hintergrund-LED vs. andere 
Hintergrund-LED achten! Vcc 5V können für die Hintergrundbeleuchtung 
benutzt werden.

Aufpassen wenn du auf die Idee kommst hier einen Potentiometer zu 
verwenden, um die Beleuchtung zu dimmen! Unbedingt einen 
Mindestwiderstand in Serie dazuschalten. Ohne passiert es sehr leicht, 
dass der Potentiometer in Richtung 0 Ohm gedreht wird und die 
Hintergrund-LED geröstet wird!

> Port1 kann man als Input und als Output betreiben.
> DP1L und DP1L muss man zuerst auf 0xFF setzten. Wenn ich das probiere,
> kommt eine Fehlermeldung: redefinition...

Achso das betrifft vielleicht diesen Teil:

#define LCD_DATADIR   DP1L
#define LCD_CTRLDIR   DP1H

und die folgenden Stellen mit LCD_DATADIR und LCD_CTRLDIR.

Um das exakt zu klären, müsste man sich die Definitionen von DP1L und 
DP1H in deinen µC spezifischen Includefiles und die exakte Fehlermeldung 
(oder Warnung?) des Compilers betrachten, also die berühmten fehlenden 
Teile bei ...

Die Schnelllösung sieht so aus, dass du die beiden Redefinitionen 
entfernst (auskommentierst) und im restlichen Quellcode direkt DP1L und 
DP1H statt der beiden Makronamen LCD_*DIR einsetzt.

> Macht man das jedoch nicht, kommen bei jedem Pin nur 3,5V Statt 4.8 raus
> (da noch andere Funktionen am Port laufen, oder so). Im Anhang hab ich
> nochmal das gesamte Datenblatt zu Port1.

> Langsam bin ich echt am Verzweifeln.
> Ich bitte nochmals um Hilfe.

Brauchst du nicht zu verzweifeln. Das ist noch die ganz normale Härte im 
Geschäft.

von Ronald (Gast)


Lesenswert?

Juhuuuuuuuuu!!!!!!!!!!!!!!!!!!!!!!
\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/

Man erkennt die 4 und die 2 am Display (Sie laufen von links nach 
rechts).
Vielen Danke für die Hilfe!
Danke danke danke! Who`s the man? --> Stefan :)

Ist es normal, dass die 2te Zeile nicht aktiv ist?

MfG Ronald

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Klasse. Das ist schon mal ein Start.

Die Zeile in der aktuell ausgegeben werden soll, musst du gezielt 
ansteuern (oder du initialisierst anders und zwar mit eingeschaltetem 
Scrollmodus, wird aber seltener gemacht).

Die Zeilenpositionierung kannst du mit der

> void lcd_setcursor( uint8_t spalte, uint8_t zeile );

machen (s. Artikel 
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung).

Dafür musst du diese Makrodefinitionen mit Hilfe des Datenblatts des LCD 
kontrollieren:

> #define LCD_SET_DDADR           0x80
>
> // 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

Soweit ich das Datenblatt interpretiere kannst du den Wert 0x80 für 
LCD_SET_DDADR übernehmen.

LCD_DDADR_LINE1 und LCD_DDADR_LINE2 passen auch bei deinem 8x2 Display. 
Zeile 3 und 4 gibt es nicht, d.h. LCD_DDADR_LINE3 und LCD_DDADR_LINE4 
ist egal was dort steht.

von Ronald (Gast)


Lesenswert?

Hallo,

ich musste leider uint8_t auf unsigned int ändern, da Keil uVision 
gemeint hat, dass das ein alter identifyer ist. Die erste Zeile 
funktioniert toll,
jedoch bekomm ich nichts auf die 2te Zeile. Die Werte für line 2 hab ich 
mit dem Datenblatt auch nochmal überprüft (die müssten eigentlich 
stimmen).
Ist die 2te Zeile evt. hinüber?

MfG Ronald

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Ronald schrieb:

> Ist die 2te Zeile evt. hinüber?

Sehr unwahrscheinlich.

Möglicherweise geht die 8-Bit Initialisierung in lcd_init() schief und 
die Hardware-Initialisierung in den Einzeilenmodus wird wirksam.

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

1. Mach vor und nach diesem Block je eine Wartezeit von 5ms.

2. Hast du die Definitionen der Wartezeiten nach deinem Datenblatt 
vorgenommen? Also die LCD_BOOTUP_MS aus dem Artikel von 15 ms auf 
mindestens 30 ms hochgesetzt? Zur Sicherheit auch mal auf 300ms 
hochsetzen. Längere Zeiten "schaden" nie, kürzere immer.

von Ronald (Gast)


Lesenswert?

Hallo,

hab das mal probiert:
1
#define LCD_FUNCTION_2LINE      0x08
...fragwürdig..
1
#define LCD_SET_DDADR           0x80
2
#define LCD_DDADR_LINE1         0x00
3
#define LCD_DDADR_LINE2         0x40
1
    delay_ms( 5 );
2
    // 8-bit Modus / 2 Zeilen / 5x7
3
    lcd_command( LCD_SET_FUNCTION |
4
                 LCD_FUNCTION_8BIT |
5
                 LCD_FUNCTION_2LINE |
6
                 LCD_FUNCTION_5X7 );
7
   _delay_ms( 5 );
1
void lcd_setcursor( unsigned int x, unsigned int y )
2
{
3
    unsigned int data;
4
 
5
    switch (y)
6
    {
7
        case 1:    // 1. Zeile
8
            data = LCD_SET_DDADR + LCD_DDADR_LINE1 + x;
9
            break;
10
 
11
        case 2:    // 2. Zeile
12
            data = LCD_SET_DDADR + LCD_DDADR_LINE2 + x;
13
            break;
14
 
15
         default:
16
            return;                                   // für den Fall einer falschen Zeile
17
    }
18
 
19
    lcd_command( data );
20
}
1
lcd_setcursor( 0, 2 );
2
3
  lcd_data('T');
4
  lcd_data('e');
5
  lcd_data('s');
6
  lcd_data('t');

Hab die Wartezeit auf 300ms raufgesetzt. Es sieht tatsächlich so aus, 
als würde nur in dein einzeilenmodus geschalten, da man eine leichte 
hinterlegung nach dem Start in der ersten Zeile erkennt. Trotz der 
Anpassung funktioniert jedoch nur die erste Zeile.

MfG Ronald

von Stefan B. (stefan) Benutzerseite


Angehängte Dateien:

Lesenswert?

Die sind IMHO nicht fragwürdig.

Im Datenblattausschnitt (Anhang) geht es mit N, F und L etwas kreuz und 
quer zu, aber es sollten letztendlich diese Definitionen (= die gleichen 
wie im AVR Artikel) vorhanden sein:

#define LCD_SET_FUNCTION     0x20
#define LCD_FUNCTION_8BIT    0x10 // Bit DL
#define LCD_FUNCTION_2LINE   0x08 // Bit N bzw. L
#define LCD_FUNCTION_5X7     0x00 // Bit F

Im Moment gehen mir die Ideen für die Ferndiagnose aus. Ich melde mich, 
wenn mir was einfällt.

von Ronald (Gast)


Lesenswert?

Danke dir!

MfG

von spess53 (Gast)


Lesenswert?

Hi

>#define LCD_FUNCTION_5X7     0x00 // Bit F

Eher 0x04

MfG Spess

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Ich habe nur wenige weitere Projekt im Netz gefunden, bei dem dieses 
Display verwendet wurde.

Eines davon hatte auch Sourcecode, leider kein öffentlicher, sondern mit 
Copyright von Elektor, deshalb hier nachprogrammiert:
1
void lcd_init( void )
2
{
3
    // verwendete Pins auf Ausgang schalten
4
    unsigned char pins = (1<<LCD_RW) |           // R/W Leitung
5
                         (1<<LCD_RS) |           // R/S Leitung
6
                         (1<<LCD_EN);            // Enable Leitung
7
8
    // hier deine Anpassung für die Ausgabe an den Pins...
9
 
10
    // warten auf die Bereitschaft des LCD
11
    _delay_ms( LCD_BOOTUP_MS ); // 15ms bzw. 30ms default ggf. erhöhen
12
    
13
    // Soft-Reset muss 3mal hintereinander gesendet werden 
14
    // zur Initialisierung
15
    lcd_out8( LCD_SOFT_RESET );
16
    _delay_ms( LCD_SOFT_RESET_MS1 ); // 5ms default ggf. erhöhen
17
 
18
    lcd_enable();
19
    _delay_ms( LCD_SOFT_RESET_MS2 ); // 1ms default ggf. erhöhen
20
 
21
    lcd_enable();
22
    _delay_ms( LCD_SOFT_RESET_MS3 ); // 1ms default ggf. erhöhen
23
24
    // 8-bit Modus / 2 Zeilen / 5x7
25
    lcd_command( LCD_SET_FUNCTION |
26
                 LCD_FUNCTION_8BIT |
27
                 LCD_FUNCTION_2LINE |
28
                 LCD_FUNCTION_5X7 );
29
30
    // Modifizierte Sequenz für LCD ANAG VISION AV0820 angelehnt an
31
    // Elektor.DE 1/2004 "Uhr mit Mehrfach-Alarm"
32
33
    lcd_command( LCD_SET_DISPLAY | 
34
                 LCD_DISPLAY_OFF ); // auch im Datenblatt
35
36
    lcd_command( LCD_SET_DISPLAY | 
37
                 LCD_DISPLAY_ON |
38
                 LCD_CURSOR_ON |
39
                 LCD_BLINKING_ON ); // zusätzlich bei Elektor
40
41
    lcd_command( LCD_CLEAR_DISPLAY ); // auch im Datenblatt
42
    delay_ms( LCD_CLEAR_DISPLAY_MS ); // 2ms default ggf. erhöhen
43
44
    lcd_command( LCD_CURSOR_HOME ); // zusätzlich bei Elektor
45
    delay_ms( LCD_CURSOR_HOME_MS ); // 2ms default ggf. erhöhen
46
47
    // Cursor inkrement / kein Scrollen
48
    lcd_command( LCD_SET_ENTRY |
49
                 LCD_ENTRY_INCREASE |
50
                 LCD_ENTRY_NOSHIFT ); // auch im Datenblatt
51
52
    // hier ist die Initialisierung laut Datenblatt zu Ende
53
54
    lcd_command( LCD_SET_DISPLAY | 
55
                 LCD_CURSOR_OFF ); // zusätzlich bei Elektor 
56
}

von Stefan B. (stefan) Benutzerseite


Lesenswert?

@ Spess

Kann man probieren, worst-case hat man 5x10 bit große Zeichen, kaputt 
gehen kann nix, aber ich denke das ist ein Fehler mit der 0x04.

Die Legende zum Bit F fehlt im Datenblatt. Bei dem roten Kreuz ist aber 
eine Legende zu Bit N, die IMHO eigentlich die Legende zu F sein soll. 
Und Bit N definiert die Wunschanzahl der Zeilen...

Im Tutorial 
(http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung) 
steht auch

#define LCD_FUNCTION_5X7        0x00
#define LCD_FUNCTION_5X10       0x04

von Ronald (Gast)


Lesenswert?

Hallo,

hab

#define LCD_FUNCTION_5X7 0x04

ausprobiert. Das funktioniert leider nicht (aber danke für den Versuch). 
Jetzt probier ich mal die neue lcd_init.
Meld mich dann gleich.

MfG

von Ronald (Gast)


Lesenswert?

Hallo,
1
void lcd_init( void )
2
{
3
    // verwendete Pins auf Ausgang schalten
4
    unsigned char pins = (1<<LCD_RW) |           // R/W Leitung
5
                         (1<<LCD_RS) |           // R/S Leitung
6
                         (1<<LCD_EN);            // Enable Leitung
7
8
    // hier deine Anpassung für die Ausgabe an den Pins...
9
    DP1H  |= pins;
10
    P1H &= ~pins;
11
    DP1L  |= 0xFF;
12
    P1L &= ~0xFF;
13
14
    // warten auf die Bereitschaft des LCD
15
    _delay_ms( 300 ); // 15ms bzw. 30ms default ggf. erhöhen
16
    
17
    // Soft-Reset muss 3mal hintereinander gesendet werden 
18
    // zur Initialisierung
19
    lcd_out8( LCD_SOFT_RESET );
20
    _delay_ms( 10 ); // 5ms default ggf. erhöhen
21
 
22
    lcd_enable();
23
    _delay_ms( 10 ); // 1ms default ggf. erhöhen
24
 
25
    lcd_enable();
26
    _delay_ms( 10 ); // 1ms default ggf. erhöhen
27
28
29
    // 8-bit Modus / 2 Zeilen / 5x7
30
    lcd_command( LCD_SET_FUNCTION |
31
                 LCD_FUNCTION_8BIT |
32
                 LCD_FUNCTION_2LINE |
33
                 LCD_FUNCTION_5X7 );
34
35
    // Modifizierte Sequenz für LCD ANAG VISION AV0820 angelehnt an
36
    // Elektor.DE 1/2004 "Uhr mit Mehrfach-Alarm"
37
38
    lcd_command( LCD_SET_DISPLAY | 
39
                 LCD_DISPLAY_OFF ); // auch im Datenblatt
.....LCD_DISPLAY_OFF 0x08....
1
    lcd_command( LCD_SET_DISPLAY | 
2
                 LCD_DISPLAY_ON |
3
                 LCD_CURSOR_ON |
4
                 LCD_BLINKING_ON ); // zusätzlich bei Elektor
5
6
    lcd_command( LCD_CLEAR_DISPLAY ); // auch im Datenblatt
7
    _delay_ms( 10 ); // 2ms default ggf. erhöhen
8
9
    lcd_command( LCD_CURSOR_HOME ); // zusätzlich bei Elektor
10
    _delay_ms( 10 ); // 2ms default ggf. erhöhen
11
12
    // Cursor inkrement / kein Scrollen
13
    lcd_command( LCD_SET_ENTRY |
14
                 LCD_ENTRY_INCREASE |
15
                 LCD_ENTRY_NOSHIFT ); // auch im Datenblatt
16
17
    // hier ist die Initialisierung laut Datenblatt zu Ende
18
19
    lcd_command( LCD_SET_DISPLAY | 
20
                 LCD_CURSOR_OFF ); // zusätzlich bei Elektor 
21
}

mit dieser Initialisierung funktionierts leider nicht. Habs noch mal mit 
der urpsrünglichen gegengecheckt. Ich nehme an, dass die Verdrahtung 
passt (sonst würd ja die Initialisierung und die erste Zeile nicht 
funktionieren).

MfG Ronald

MfG Ronald

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Die Funktion der lcd_init kann man so nicht nachweisen. Leider steht im 
Datenblatt nicht wie die Hardware-Initialisierung nach dem Power on des 
Displays aussieht.

Bei anderen LCD ist üblich, dass die HW-Init sich in einen einzeiligen 
Modus mit 8-Bit-Ansteuerung hochschafft. Die Software-Initialisierung 
mit lcd_init() soll dann erst in den mehrzeiligen Modus umschalten.

Du merkst die Beobachtung spricht dafür, dass die SW-Init nicht 
funktioniert. Vermutlich könntest du zum jetzigen Stand lcd_init() auch 
weglassen und nur das delay_ms() machen (mit Textausgaben zu warten bis 
das LCD hardwaremäßig initialisiert ist).

Ich versuche mal Mitte bis Ende der Woche ein solches LCD aufzutreiben.

von Ronald (Gast)


Lesenswert?

Hey Danke! Sollte das Ding jemals komplett laufen, stell ich eine 
komplette Anleitung ins Internet (Schaltpläne, Bilder vom Aufbau, 
Erklärungen usw..), damit auch andere profitieren können.

MfG Ronald

von Ronald E. (ronald_1)


Lesenswert?

So,
hab mir jetzt auch einen Account gemacht. Leider war Ronald schon 
vergeben.
MfG

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Dauert etwas länger: das LCD ist nicht vorrätig.

von Ronald E. (ronald_1)


Lesenswert?

Kein Problem, ich bin dankbar dass mir jemand hilft.

von Stefan B. (stefan) Benutzerseite


Angehängte Dateien:

Lesenswert?

So, das Display ist da.

Und funktioniert auch beim Setzen des Cursors in eine andere Zeile mit 
dem lcd_init() Code aus 
Beitrag "Re: LCD mit Infineon Entwicklungsboard"
Die ganzen folgenden Änderungen ala Elektor waren also unnötig.

Diesem Satz von dir habe ich zu wenig Beachtung gegeben:

>> DP1L und DP1L muss man zuerst auf 0xFF setzten. Wenn ich das probiere,
>> kommt eine Fehlermeldung: redefinition...

bzw. auf die Nachfrage

> Um das exakt zu klären, müsste man sich die Definitionen von DP1L und
> DP1H in deinen µC spezifischen Includefiles und die exakte Fehlermeldung
> (oder Warnung?) des Compilers betrachten, also die berühmten fehlenden
> Teile bei ...

kam nach dem ersten Erfolgserlebnis keine Antwort.

Im Anhang ist der komplette Quellcode. Dabei habe ich die Definitionen 
bei Keil nachgesehen und wegen deren SFR Schreibweise meine die 
LCD_*PORT und LCD_*DIR Definitionen zurück gebaut.

Im Code kann man auch zwei Definitionen AVR oder XC164 sehen. Die AVR 
Definition habe ich benutzt, um das Display an einem AVR zu testen. Du 
musst die AVR Definition entfernen und dafür XC164 definieren (ist schon 
gemacht)

Probiere den Quellcode aus und wenn der Compiler Warnungen rausgibt, die 
mit Copy&Paste hier zeigen. Ebenso wenn du Anpassungen machst.

von Ronald E. (ronald_1)


Lesenswert?

Hallo Stefan,

derzeit bin ich auf Besuch bei der Omi (bis Montag). Danach werd ich's 
gleich ausprobieren und das Ergebnis sofort online stellen. Schon mal 
vielen Dank!

MfG Ronald

von Ronald E. (ronald_1)


Angehängte Dateien:

Lesenswert?

Hallo Stefan,

folgende Anpassung habe ich gemacht:
1
 DP1L = (DP1L & ~(unsigned int)0x00FF) | 0x00FF; //Die letzten 8 Bits auf Ausgangs setzten
2
 DP1H = (DP1H & ~(unsigned int)0x00FF) | 0x003F; //Die letzten 6 Bits auf Ausgangs setzten

Ich dachte der Tag wird nie kommen, aber das Ding läuft! Anbei zwei 
Bilder vom Aufbau im Betrieb.
Who's the man? Stefan is the man!
Danke danke danke.
Nun werd ich gleich mal probieren das alles nochmal ganz alleine 
hinzukriegen. Und wenn alles sitzt evt. einen Temperatursensor 
ansteuern. Alles zusammen werd ich dann komplett vom Aufbau bis zur 
Fertigstellung komplett hochladen. Nochmals danke Stefan!

MfG Ronald

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Super gut und Danke für die Blumen!!!
Viel Erfolg bei deinem nächsten Projekt!

von Ronald E. (ronald_1)


Lesenswert?

Hallo Stefan,

ich bins nochmals. Nun hab ich auch mal probiert, das Display auf einem 
ATMEGA8 zu betreiben. Es scheint auch zu funktionieren. Die Buchstaben 
werden jedoch trotz richtiger Kontrastspannung nicht richtig dargestellt 
(verblasst, zum Teil verschwinden ganze Bereiche eines Buchstaben). 
Herumregeln an der Kontrastspannung hilft auch nicht wirklich.
Hättest du evt. eine Idee? Ich bitte um Hilfe.

MfG Ronald

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Ronald, die Beschreibung deutet eher auf ein Hardwareproblem als auf ein 
Softwareproblem hin. Eventuell ein Versorgungsproblem. Zu beidem kann 
ich aber nix genaueres sagen, weil Programm und Schaltplan/Bild vom 
Aufbau fehlen. Tipp: Vielleicht beteiligen sich mehr Helfer, wenn du 
dafür einen extra Thread auf machst (mit ggf. Link hierher). Infineon im 
Titel schreckt viele AVR-ianer schon ab.

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.