Forum: Compiler & IDEs LCD Ansteuerung


von Johannes L. (megatron)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe schon einmal den Versuch unternommen hier im Forum Hilfe zu 
bekommen leider muss ich nochmal einen Versuch wagen.

Es geht um eine LCD Display (HD44780 4x20 Zeichen) Ansteuerung mit einem 
Atmega 128

Ich habe die Routinen hier aus dem Forum als Basis verwendet.

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung

Folgende Änderungen habe ich vorgenommen:

Quarz angepasst 16 Mhz.
Ports definiert

PORTD 0-3 = Datenbits PIN 4-7
PORTD 6   = RS
PORTD 4   = En
PORTD 5   = RW


Ich habe mehrfach die Verbindunegn kontrolliert !

Fuse Bit M103C auch verändert !

Einzige Erkenntnis:

Wenn ich PORTD PD6 welcher an RS angeschlossen ist ändere auf PD7 
welcher eigentlich Vo also Kontrast darstellt dann sehe ich kurz in der 
ersten und dritten Zeile schwarze Balken die kurz danach verschwinden 
???

Ich habe für PD7 nichts festegelegt ?

Ich kann den Vorgang aber nicht verstehen ?

von Noname (Gast)


Lesenswert?

>Ich kann den Vorgang aber nicht verstehen ?

Doch, doch. Es ist durchaus möglich den Vorgang zu verstehen.

>Wenn ich PORTD PD6 welcher an RS angeschlossen ist ändere auf PD7
>welcher eigentlich Vo also Kontrast darstellt dann sehe ich kurz in der
>ersten und dritten Zeile schwarze Balken die kurz danach verschwinden
>???

Hm. Dann ändere das doch einfach nicht. Warum tust Du das?

Und was genau hast Du getan? In der Software das define für RS von PD6 
auf PD7 geändert oder in der Schaltung PD6 von dem Anschluss RS des LCD 
an den Anschluss VO des LCD gelegt?

Ich vermute ersteres, denn das würde dazu passen, das der Kontrast 
kurzzeitig extrem hoch ist. Aber nocheinmal. Wozu tust Du das? Die 
Software will eben an PD6 den RS Anschluss des LCD.

Sei so gut, poste Deine Schaltung und den Quellcode. Letztes in 
ungepackter Form, denn zumindest ich habe keine Lust das erst 
runterzuladen und zu entpacken.

von Johannes L. (megatron)


Lesenswert?

Vielen Dank erstmal für dein Interesse an meinem Problem.

Die Schaltung ist leicht zu beschreiben:

_LCD Display Eingänge_:

Pin   Bezeichnung  Funktion
1  Vss          GND
2  Vdd/Vcc          5V
3  Vee          Kontrastspannung (0V bis 5V)
4  RS          Register Select (Befehle/Daten)
5  RW          Read/Write
6  E          Enable
7  DB0          Datenbits 0−7
8  DB1
9  DB2
10  DB3
11  DB4
12  DB5
13  DB6
14  DB7
15  A          LED-Beleuchtung, Anode
16  K          LED-Beleuchtung, Kathode


nun meine Anschlussbelegung am Atmega 128


_µC_:              _LCD Display_:

Versorgung VCC     auf 2 und 15
Masse      GND     auf 1 und 16
Datenbits  PD0-3   11-14
En         PD4     Enable
R/W        PD5     Read/Write
RS         PD6     Register Select
V0         PD7     Kontrast

lcd-routine.h:
1
// Ansteuerung eines HD44780 kompatiblen LCD im 4-Bit-Interfacemodus
2
// http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung
3
//
4
 
5
#ifndef LCD_ROUTINES_H
6
#define LCD_ROUTINES_H
7
 
8
////////////////////////////////////////////////////////////////////////////////
9
// Hier die verwendete Taktfrequenz in Hz eintragen, wichtig!
10
 
11
#ifndef F_CPU
12
#define F_CPU 16000000
13
#endif
14
 
15
////////////////////////////////////////////////////////////////////////////////
16
// Pinbelegung für das LCD, an verwendete Pins anpassen
17
// Alle LCD Pins müssen an einem Port angeschlossen sein und die 4
18
// Datenleitungen müssen auf aufeinanderfolgenden Pins liegen
19
 
20
//  LCD DB4-DB7 <-->  PORTD Bit PD0-PD3
21
#define LCD_PORT      PORTD
22
#define LCD_DDR       DDRD
23
#define LCD_DB        PD0
24
25
 
26
//  LCD RS      <-->  PORTD Bit PD6     (RS: 1=Data, 0=Command)
27
#define LCD_EN        PD4
28
#define LCD_RW      PD5
29
#define LCD_RS        PD6
30
31
//  LCD EN      <-->  PORTD Bit PD4     (EN: 1-Impuls für Daten)
32
33
34
35
#define LCD_V0      PD7
36
37
38
39
40
41
42
43
44
 
45
////////////////////////////////////////////////////////////////////////////////
46
// LCD Ausführungszeiten (MS=Millisekunden, US=Mikrosekunden)
47
 
48
#define LCD_BOOTUP_MS           15 //15
49
#define LCD_ENABLE_US           20//20
50
#define LCD_WRITEDATA_US        46//46
51
#define LCD_COMMAND_US          42//42
52
 
53
#define LCD_SOFT_RESET_MS1      5//5
54
#define LCD_SOFT_RESET_MS2      1//1
55
#define LCD_SOFT_RESET_MS3      1//1
56
#define LCD_SET_4BITMODE_MS     5//5
57
 
58
#define LCD_CLEAR_DISPLAY_MS    2//2
59
#define LCD_CURSOR_HOME_MS      2//2
60
 
61
////////////////////////////////////////////////////////////////////////////////
62
// Zeilendefinitionen des verwendeten LCD
63
// Die Einträge hier sollten für ein LCD mit einer Zeilenlänge von 16 Zeichen passen
64
// Bei anderen Zeilenlängen müssen diese Einträge angepasst werden
65
 
66
#define LCD_DDADR_LINE1         0x00
67
#define LCD_DDADR_LINE2         0x40
68
#define LCD_DDADR_LINE3         0x14
69
#define LCD_DDADR_LINE4         0x54
70
 
71
////////////////////////////////////////////////////////////////////////////////
72
// Initialisierung: muss ganz am Anfang des Programms aufgerufen werden.
73
void lcd_init( void );
74
 
75
////////////////////////////////////////////////////////////////////////////////
76
// LCD löschen
77
void lcd_clear( void );
78
 
79
////////////////////////////////////////////////////////////////////////////////
80
// Cursor in die 1. Zeile, 0-te Spalte
81
void lcd_home( void );
82
 
83
////////////////////////////////////////////////////////////////////////////////
84
// Cursor an eine beliebige Position 
85
void lcd_setcursor( uint8_t spalte, uint8_t zeile );
86
 
87
////////////////////////////////////////////////////////////////////////////////
88
// Ausgabe eines einzelnen Zeichens an der aktuellen Cursorposition 
89
void lcd_data( uint8_t data );
90
 
91
////////////////////////////////////////////////////////////////////////////////
92
// Ausgabe eines Strings an der aktuellen Cursorposition 
93
void lcd_string( const char *data );
94
 
95
////////////////////////////////////////////////////////////////////////////////
96
// Definition eines benutzerdefinierten Sonderzeichens.
97
// data muss auf ein Array[5] mit den Spaltencodes des zu definierenden Zeichens
98
// zeigen
99
void lcd_generatechar( uint8_t code, const uint8_t *data );
100
 
101
////////////////////////////////////////////////////////////////////////////////
102
// Ausgabe eines Kommandos an das LCD.
103
void lcd_command( uint8_t data );
104
 
105
 
106
////////////////////////////////////////////////////////////////////////////////
107
// LCD Befehle und Argumente.
108
// Zur Verwendung in lcd_command
109
 
110
// Clear Display -------------- 0b00000001
111
#define LCD_CLEAR_DISPLAY       0x01
112
 
113
// Cursor Home ---------------- 0b0000001x
114
#define LCD_CURSOR_HOME         0x02
115
 
116
// Set Entry Mode ------------- 0b000001xx
117
#define LCD_SET_ENTRY           0x04
118
 
119
#define LCD_ENTRY_DECREASE      0x00
120
#define LCD_ENTRY_INCREASE      0x02
121
#define LCD_ENTRY_NOSHIFT       0x00
122
#define LCD_ENTRY_SHIFT         0x01
123
 
124
// Set Display ---------------- 0b00001xxx
125
#define LCD_SET_DISPLAY         0x08
126
 
127
#define LCD_DISPLAY_OFF         0x00
128
#define LCD_DISPLAY_ON          0x04
129
#define LCD_CURSOR_OFF          0x00
130
#define LCD_CURSOR_ON           0x02
131
#define LCD_BLINKING_OFF        0x00
132
#define LCD_BLINKING_ON         0x01
133
 
134
// Set Shift ------------------ 0b0001xxxx
135
#define LCD_SET_SHIFT           0x10
136
 
137
#define LCD_CURSOR_MOVE         0x00
138
#define LCD_DISPLAY_SHIFT       0x08
139
#define LCD_SHIFT_LEFT          0x00
140
#define LCD_SHIFT_RIGHT         0x04
141
 
142
// Set Function --------------- 0b001xxxxx
143
#define LCD_SET_FUNCTION        0x20
144
 
145
#define LCD_FUNCTION_4BIT       0x00
146
#define LCD_FUNCTION_8BIT       0x10
147
#define LCD_FUNCTION_1LINE      0x00
148
#define LCD_FUNCTION_2LINE      0x08
149
#define LCD_FUNCTION_5X7        0x00
150
#define LCD_FUNCTION_5X10       0x04
151
 
152
#define LCD_SOFT_RESET          0x30
153
 
154
// Set CG RAM Address --------- 0b01xxxxxx  (Character Generator RAM)
155
#define LCD_SET_CGADR           0x40
156
 
157
#define LCD_GC_CHAR0            0
158
#define LCD_GC_CHAR1            1
159
#define LCD_GC_CHAR2            2
160
#define LCD_GC_CHAR3            3
161
#define LCD_GC_CHAR4            4
162
#define LCD_GC_CHAR5            5
163
#define LCD_GC_CHAR6            6
164
#define LCD_GC_CHAR7            7
165
 
166
// Set DD RAM Address --------- 0b1xxxxxxx  (Display Data RAM)
167
#define LCD_SET_DDADR           0x80
168
 
169
#endif


Hauptprogramm:

main.c
1
//#############################################################################
2
//
3
// Programmierung ATmega A128
4
//
5
//Autor: J.L
6
//Datum:8.1.2012
7
//Version:0.1
8
//
9
//Beschreibung der Funktion: Display Ansteuerung
10
//
11
//Parameter:   typ
12
//
13
//Rückgabe:    XXXXXXXXX0-ok 
14
//Rückgabe:    XXXXXXXXX1-nicht ok
15
//Rückgabe:    XXXXXXXX1X-Fehler1
16
//Rückgabe:    XXXXXXX1XX-Fehler2
17
//Rückgabe:    XXXXXX1XXX-Fehler3
18
//
19
//
20
//############################################################################
21
22
23
24
25
#include <avr/io.h>   
26
#include <lcd-routines.h>
27
#include <util/delay.h>
28
29
30
///////////////////////////////////////////////////////
31
32
33
void clock_init(void);
34
35
36
int main (void) {            
37
 
38
////////////////  Initialisierungen ///////////////////////////////////////
39
  
40
41
//////////////////////// Port Definitionen ///////////////////////////////
42
  
43
 
44
 
45
 
46
  
47
48
  // Read /  Write seten 
49
  //LCD_PORT &= ~(1<<LCD_RW); // Enable auf 0 setzen
50
  //LCD_PORT &= ~(1<<LCD_V0); // V0 auf 0 setzen  
51
52
  LCD_PORT |= (1<<LCD_RW); 
53
  LCD_PORT |= (1<<LCD_V0); 
54
55
56
  // Initialisierung des LCD
57
  // Nach der Initialisierung müssen auf dem LCD vorhandene schwarze Balken
58
  // verschwunden sein
59
60
  lcd_init();
61
 
62
  
63
   
64
        
65
  // Text in einzelnen Zeichen ausgeben
66
  lcd_data( 'T' );
67
  lcd_data( 'e' );
68
  lcd_data( 's' );
69
  lcd_data( 't' );
70
 
71
  // Die Ausgabemarke in die 2te Zeile setzen
72
  lcd_setcursor( 0, 2 );
73
 
74
  // erneut Text ausgeben, aber diesmal komfortabler als String
75
  lcd_string("Hello World!");  
76
77
///////////////////////////////////////////////////////
78
79
80
while(1) {   
81
   
82
  }                 
83
 
84
      return 0; 
85
86
                
87
}

von Noname (Gast)


Lesenswert?

Naja. Hat wohl keinen Zweck.
Trotzdem viel Erfolg noch.

von Klaus W. (mfgkw)


Lesenswert?

Johannes L, schrieb:
> Versorgung VCC     auf 2 und 15

Du bist sicher, daß du auf Pin 15 des LCD 5V legen willst?
Steht das so im Datenblatt?

> Datenbits  PD0-3   11-14

Alleine dafür gibt es 16 Möglichkeiten.

von Klaus W. (mfgkw)


Lesenswert?

Noname schrieb:
> Naja. Hat wohl keinen Zweck.

Ja, sowas kommt leider gelegentlich vor.

von Johannes L. (megatron)


Lesenswert?

Warum hat das keinen Zweck ?
Ich habe dir den Code und die Beschaltung gezeigt warum hat es keinen 
Zweck ?

von Noname (Gast)


Lesenswert?

>Warum hat das keinen Zweck ?

Hm. Liest sich vielleicht ein wenig beleidigend, ist aber nicht so 
gemeint. Wie sag ichs meinem Kinde? :-)

Am Wochenende gibt es hier viele sehr unerfahrene Leute, von denen eine 
nicht unbeträchtliche Anzahl versucht Code lediglich zu kopieren ohne 
wirklich zu verstehen, was sie tun.

Da Du 1. auf meine Bitte um den Schaltplan eben nicht mit einem 
Schaltplan, sondern mit einer Beschreibung des selben geantwortet hast, 
2. dem von Dir geposteten Code wesentliche Teile fehlen (ich rede nicht 
von dem ZIP-File, sondern von Deinem zweiten Post hier) und 3. auch eine 
Erklärung, warum Du nun den Port-Pin wechselst, überhaupt 4. eine 
Beschreibung Deines Problems fehlt, muss ich annehmen, das eine 
sinnvolle Diskussion nicht möglich ist.

Das 5. ein Verweis auf den Typ des LCD fehlt (es gibt sicher hunderte 
HD44780 kompatible LCD), nicht zuletzt wegen der Frage wieviel Spannung 
eigentlich die LED-Beleuchtung haben will und ob die Spannung nicht wg. 
der Flussspannung einer "roh" angeschlossenen LED zusammenbricht, das 6. 
der Code nicht im Anhang gepostet wurde, tut ein übriges.

Der Terminus "LCD Display" ist dann noch das i-Tüpfelchen.

Na, vielleicht ergänzt Du ja die fehlenden Infos noch. Und, aus 
gegebenen Anlass, poste doch bitte ein Foto von Deinem Aufbau.

Also, wiegesagt, nichts für ungut und viel Erfolg.

von holger (Gast)


Lesenswert?

V0         PD7     Kontrast

Nimm ein Poti für den Kontrast, so wie es alle machen.

von Other-Noname (Gast)


Lesenswert?

Noname schrieb:
> Der Terminus "LCD Display" ist dann noch das i-Tüpfelchen.

Was ist daran auszusetzen?
Es gibt einen Haufen Bücher, die sich mit Liquid Crystal Devices 
auseinandersetzen - frag Tante Google.
Das Display des TO wird wohl aus einer größeren Anzahl solcher 
Flüssigkristallelementen aufgebaut sein.

von Johannes L. (megatron)


Angehängte Dateien:

Lesenswert?

Hi,

das Display läuft !

Nur die Umlaute funktionieren noch nicht, aber eigene Zeichen erstellen 
funktioniert wunderbar.

Danke für die Aufmerksamkeit

von holger (Gast)


Lesenswert?

>Nur die Umlaute funktionieren noch nicht

#if DEFAULT_TABLE
 // Standard conversion table used by most displays
 switch(ps)
  {
   case 'ä' : ps = 0xE1; break;
   case 'ö' : ps = 0xEF; break;
   case 'ü' : ps = 0xF5; break;
   case 'ß' : ps = 0xE2; break;
   case '°' : ps = 0xDF; break;
   case 'µ' : ps = 0xE4; break;
  }
#endif

von Johannes L. (megatron)


Lesenswert?

Hallo Holger,

vielen Dank für deine Hilfe.

Ich habe leider noch wenig Erfahrung bis gar keine :-)
Ich habe versucht die Definition einzubinden in die lcd-routine.h leider 
bisher noch ohne Erfolg.

Das LCD Beispiel 2 hier im Forum beschreibt eine Möglichkeit Zahlen mit 
Hilfe von itoa(Int to ASCI II) in einen character umzuwandeln und per 
string auszugeben. Leider muss ich feststellen die Umsetzung 
funktioniert nur bedingt. Eine case Unterscheidung ist auch hier 
notwendig glaube ich.

von Karl H. (kbuchegg)


Lesenswert?

Johannes L, schrieb:
> Hallo Holger,
>
> vielen Dank für deine Hilfe.
>
> Ich habe leider noch wenig Erfahrung bis gar keine :-)
> Ich habe versucht die Definition einzubinden in die lcd-routine.h leider
> bisher noch ohne Erfolg.

WO genau hast du das eingebunden?

holgers Code muss in die Einzelzeichenausgabe lcd_data. Da aber lcd_data 
dadurch aber für binäre Ausgaben unbrauchbar wird, wird am besten eine 
neue Funktion eingeführt

void lcd_char( char c )
{
  switch(c)
  {
   case 'ä' : c = 0xE1; break;
   case 'ö' : c = 0xEF; break;
   case 'ü' : c = 0xF5; break;
   case 'ß' : c = 0xE2; break;
   case '°' : c = 0xDF; break;
   case 'µ' : c = 0xE4; break;
  }

  lcd_data( c );
}

und der Aufruf von lcd_data in lcd_string auf diese neue Funktion 
umgeändert.

Dann hat man eine Einzelzeichen Ausgabe und eine String Ausgabe, die mit 
Umlauten umgehen können und für direkte Ausgabe steht lcd_data immer 
noch zur Verfügung.

> Das LCD Beispiel 2 hier im Forum beschreibt eine Möglichkeit Zahlen mit
> Hilfe von itoa(Int to ASCI II) in einen character umzuwandeln und per
> string auszugeben. Leider muss ich feststellen die Umsetzung
> funktioniert nur bedingt.

Was heißt 'bedingt'?
wenn da was nicht funktioniert, dann hast du das zu verantworten :-)

von Johannes L. (megatron)


Lesenswert?

Vollkommen richtig, meine Verantwortung :-)

Ich werde die Tage den Versuch starten mit den Umlauten und mich etwas 
mehr mit der Ausgabe von Zahlen beschäftigen.

Vielen Dank für die sehr hilfreichen Ratschläge.
Ich melde mich ... zurück wenn es Neuigkeiten gibt

Ciao

von Johannes L (Gast)


Lesenswert?

Guten Morgen,

habe eben versucht den Code einzubinden in lcd-routines.c
1
void lcd_char( char c )
2
{
3
  switch(c)
4
  {
5
   case 'ä' : c = 0xE1; break;
6
   case 'ö' : c = 0xEF; break;
7
   case 'ü' : c = 0xF5; break;
8
   case 'ß' : c = 0xE2; break;
9
   case '°' : c = 0xDF; break;
10
   case 'µ' : c = 0xE4; break;
11
  }
12
}

zusätzlich habe ich entdeckt das in der routines.h folgende Einbindung 
existiert.
1
#if DEFAULT_TABLE
2
 // Standard conversion table used by most displays
3
 switch(ps)
4
  {
5
   case 'ä' : ps = 0xE1; break;
6
   case 'ö' : ps = 0xEF; break;
7
   case 'ü' : ps = 0xF5; break;
8
   case 'ß' : ps = 0xE2; break;
9
   case '°' : ps = 0xDF; break;
10
   case 'µ' : ps = 0xE4; break;
11
  }
12
#endif

ich erhalte immer japanische Zeichen wenn ich versuche:
1
lcd_data('ä');

oder
1
lcd_string("äöüß");

auszugeben.

Ich vermute ich habe noch keine Verbindung zu der Case Unterscheidung 
hergestellt.

Bitte um Hilfe

von Karl H. (kbuchegg)


Lesenswert?

Johannes L schrieb:
> Guten Morgen,
>
> habe eben versucht den Code einzubinden in lcd-routines.c
>
> void lcd_char( char c )
> {

Du hast also eine Funktion lcd_char

(Apropos: in lcd-char muss mit dem geänderten Zeichen natürlich schon 
auch noch lcd_data aufgerufen werden. Irgendwann muss ja schliesslich 
das Byte auch mal ausgegeben werden.)


> zusätzlich habe ich entdeckt das in der routines.h folgende Einbindung
> existiert.
>
> #if DEFAULT_TABLE
>  // Standard conversion table used by most displays
>  switch(ps)
>   {
>    case 'ä' : ps = 0xE1; break;
>    case 'ö' : ps = 0xEF; break;
>    case 'ü' : ps = 0xF5; break;
>    case 'ß' : ps = 0xE2; break;
>    case '°' : ps = 0xDF; break;
>    case 'µ' : ps = 0xE4; break;
>   }
> #endif

wo genau existiert dieses und ist das Makro DEFAULT_TABLE auch 
entsprechend definiert?

> ich erhalte immer japanische Zeichen wenn ich versuche:
> lcd_data('ä');

Soso. Du kriegst also japanische Zeichen, wenn du eine ganz andere 
Funktion aufrufst. Wundert mich jetzt nicht wirklich.


> lcd_string("äöüß");

welche Ausgabefunktion wird von lcd_string benutzt. lcd_data oder 
lcd_char?

> Bitte um Hilfe

zeig deine kompletten Code-Änderungen. Oder geh einfach mal auf dem 
Papier(Monitor) den Programmfluss durch. Kommst der Programmfluss 
überhaupt an der Ersetzung vorbei?

von Johannes L (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe jetzt den Ablauf verstanden.

1. LCD-Data für Ausgabe eines Characters
2. LCD-String für Ausgabe einer Kette von Charactern
3. LCD-Char Umlaute ändern und in LCD-Data verwenden.

Wie rufe ich nach der Case Unterscheidung lcd-data auf ?

Ich habe versucht in der Funktion LCD String lcd_char zu verwenden aber 
ohne Erfolg.

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

Code für LCD-Data und LCD-Char
1
////////////////////////////////////////////////////////////////////////////////
2
// Sendet ein Datenbyte an das LCD
3
void lcd_data( uint8_t data )
4
{
5
    LCD_PORT |= (1<<LCD_RS);    // RS auf 1 setzen
6
 
7
    lcd_out( data );            // zuerst die oberen, 
8
    lcd_out( data<<4 );         // dann die unteren 4 Bit senden
9
 
10
    _delay_us( LCD_WRITEDATA_US );
11
}
12
 
13
////////////////////////////////////////////////////////////////////////////////
14
///Funktion für Umlaute
15
void lcd_char( char c )
16
{
17
  switch(c)
18
  {
19
   case 'ä' : c = 0xE1; break;
20
   case 'ö' : c = 0xEF; break;
21
   case 'ü' : c = 0xF5; break;
22
   case 'ß' : c = 0xE2; break;
23
   case '°' : c = 0xDF; break;
24
   case 'µ' : c = 0xE4; break;
25
  }
26
}
27
////////////////////////////////////////////////////////////////////////////////


Frage Makro Default Table

Das makro befindet sich am Ende der lcd-routines.h

Im Anhang befinden sich die routines.c und h Dateien

von Karl H. (kbuchegg)


Lesenswert?

Johannes L schrieb:

> 1. LCD-Data für Ausgabe eines Characters

Nein.
lcd_data für die Ausgabe eines Bytes ohne Ansehen des Bytes selber (also 
dessen Wert). Drum heisst das auch DATA.

> 2. LCD-String für Ausgabe einer Kette von Charactern
> 3. LCD-Char Umlaute ändern und in LCD-Data verwenden.

No.
lcd_char gibt ein Zeichen aus. Dazu sieht es sich das Zeichen an, macht 
eventuell Ersetzungen und benutzt dann lcd_data (welchem das exakte Byte 
wurscht ist) um dann dieses eventuell ersetzte Zeichen auszugeben. Da 
sich lcd_data nicht mehr um den Wert kümmert ist da auch ok. Die Aufgabe 
von lcd_char besteht darin, mögliche Ersetzungen vorzunehmen und dann 
auszugeben. Daher auch lcd_char, weil CHAR impliziert, dass es sich hier 
um anzeigbare Zeichen handelt, während DATA einfach nur aussagt: 1 Byte, 
egal was dieses Byte ist, zb Zeilen oder Spaltennummer oder 
Konfigurationsdaten oder was auch immer.

DATA ist also der ganz allgemeine Begriff, während CHAR einem Byte schon 
eine gewisse Bedeutung zuweist (das es sich hierbei um ein anzeigbares 
Zeichen handelt)


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

soweit ok.
Bei einem String handelt es sich um Zeichen. Also ist auch ein Aufruf 
der Funktion, die Zeichen ausgibt angebracht. Genau das ist lcd_char

> void lcd_char( char c )
> {
>   switch(c)
>   {
>    case 'ä' : c = 0xE1; break;
>    case 'ö' : c = 0xEF; break;
>    case 'ü' : c = 0xF5; break;
>    case 'ß' : c = 0xE2; break;
>    case '°' : c = 0xDF; break;
>    case 'µ' : c = 0xE4; break;
>   }
> }

und wo wird das möglicherweise ersetzte Zeichen ausgegeben?


Die Funktionen bilden hierarchische Levels!

Level 2:   lcd_string     weiß, dass es sich um einen String, also
                          eine Abfolge von anzeigbaren Zeichen handelt
                          Benutzt lcd_char um alle Zeichen nacheinander
                          auszugeben

Level 1:   lcd_char       weiß, dass es sich um anzeigbare Zeichen
                          handelt. Macht möglicherweise Ersetzungen
                          um für bestimmte Zeichen Ersatzcodes zu finden
                          die vom LCD für genau das gewünschte Zeichen
                          benutzt werden. lcd_char ersetzt den Code
                          für ein Zeichen eventuell durch einen anderen
                          Code und benutzt dann lcd_data für die
                          eigentliche Ausgabe.

Level 0:   lcd_data       gibt ein Byte aus. Und zwar so wie es ist

von Johannes L (Gast)


Lesenswert?

Vielen Dank,

ich habe die DATA Verarbeitung völlig falsch verstanden !
Also ist in der Data Ausgabe keine explizite Information des Characters 
enthalten es ist nur eine Ausgabe von einem Byte.

Ich habe lcd_char für die Zeichenkontrolle aber keine Verbindung zum 
senden der Zeichen , daher muss ich lcd_data einbinden, wenn ich alles 
vertanden habe.

Bloß wie ?

wenn ich folgendes versuche:

// Schreibt einen String auf das LCD

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


kommen nur schwarze Balken, warum ist mir aach klar. Es gibt Verbindung 
zu char und data doch wie leite ich die Verbindung nach der 
Zeichenkontrolle ein ?

von Karl H. (kbuchegg)


Lesenswert?

Johannes L schrieb:

> Ich habe lcd_char für die Zeichenkontrolle aber keine Verbindung zum
> senden der Zeichen , daher muss ich lcd_data einbinden, wenn ich alles
> vertanden habe.
>
> Bloß wie ?

Indem du die Funktion aufrufst?

void lcd_char( char c )
{
   mach was mit c, ersetzte es eventuell durch andere Codes

  lcd_data( c );
}


> kommen nur schwarze Balken,
dann hast du dir noch was anderes zerstört. Da dein lcd_char im zuletzt 
geposteten Code lcd_data überhaupt nicht aufruft, kann auch lcd_string 
keine Ausgabe erzeugen. Ergo sind die Balken noch von der fehlerhaften 
Initialisierung und du hast dir (unabsichtlich) was anderes zerstört. 
Geh nochmal zurück zum letzten funktionierenden Code und rüste von dort 
nochmal neu auf. Das geht schneller als da jetzt lang und breit die 
Stelle zu suchen, die du unabsichtlich verändert hast.

von Johannes L (Gast)


Lesenswert?

Ich habe nun folgende Funktion
1
///Funktion für Umlaute
2
void lcd_char( char c )
3
{
4
  switch(c)
5
  {
6
   case 'ä' : c = 0xF1; break;
7
   case 'ö' : c = 0xEF; break;
8
   case 'ü' : c = 0xF5; break;
9
   case 'ß' : c = 0xE2; break;
10
   case '°' : c = 0xDF; break;
11
   case 'µ' : c = 0xE4; break;
12
  }
13
14
lcd_data( c );

wenn ich in der main.c folgendes versuche erhalte ich ganz 
unterschiedliche Ergebnisse d.h. das ersetzen funktioniert nur die 
Zeichen sind die falschen ?
1
  lcd_char('ä');
2
  lcd_char('ö');
3
  lcd_char('ü');
4
  lcd_char('ß');
5
6
  lcd_data( 'ä' );
7
  lcd_data( 'ö' );
8
  lcd_data( 'ü' );
9
  lcd_data( 'ß' );

von Karl H. (kbuchegg)


Lesenswert?

Johannes L schrieb:

> wenn ich in der main.c folgendes versuche erhalte ich ganz
> unterschiedliche Ergebnisse

Sag mal.
Denkst du eigentlich selber auch noch mit oder wartest du darauf, dass 
dir hier irgendwer alles ereldigt (was im Prinzip ohnehin schon 
geschehen ist)

>   lcd_char('ä');
>   lcd_data( 'ä' );

logisch kriegst du da unterschiedliche Ausgaben aufs LCD!

lcd_char ersetzt das 'ä' (was immer das auch für einen ASCII Code hat) 
durch ein Zeichen, welches am LCD auch ein ä hinmalen sollte (siehe LCD 
COde-Tabelle), lcd_data tut das nicht.

von holger (Gast)


Lesenswert?

>wenn ich in der main.c folgendes versuche erhalte ich ganz
>unterschiedliche Ergebnisse d.h. das ersetzen funktioniert nur die
>Zeichen sind die falschen ?

Was für ein Display hast du?

Für EADIP kannst du mal folgende Tabelle versuchen:

   case 'ä' : ps=0x7B; break; //Umlenkung auf neuen Zeichen Code
   case 'ö' : ps=0x7C; break;
   case 'ü' : ps=0x7E; break;
   case 'ß' : ps=0xBE; break;
   case 'Ä' : ps=0x5B; break;
   case 'Ö' : ps=0x5C; break;
   case 'Ü' : ps=0x5E; break;

von Johannes L (Gast)


Lesenswert?

Ja ich denke mit :-)

Mir ist ja vollkommen klar das ich zwei verschiedene Ausgaben erhalte. 
Nur erhalte ich kein äöü sondern andere Zeichen.


Folgender Versuch von mir:

switch(c)
  {
   case 'ä' : c = 0xE1; break;
   case 'ö' : c = 0xEF; break;
   case 'ü' : c = 0xF5; break;
   case 'ß' : c = 0xE2; break;
   case '°' : c = 0xDF; break;
   case 'µ' : c = 0xE4; break;
  }

Ergebnis

mit lcd_char('ä');

erhalte ich ein kleines ypsilon..... wenn ich die Tabelle von Holger 
verwende erhalte ich

Tabelle von Holger:


 case 'ä' : ps=0x7B; break; //Umlenkung auf neuen Zeichen Code
   case 'ö' : ps=0x7C; break;
   case 'ü' : ps=0x7E; break;
   case 'ß' : ps=0xBE; break;
   case 'Ä' : ps=0x5B; break;
   case 'Ö' : ps=0x5C; break;
   case 'Ü' : ps=0x5E; break;

erhalte ich für 'ä' eine geschweifte Klammer für 'ö' einen senkrechten 
Strich und für 'ü' eine kleine Welle sowie für 'ß' ein Wurzelzeichen.

Laut Anleitung habe ich ein Display mit 192 fest einprogrammierten ASCII 
Zeichen.

von Johannes L (Gast)


Lesenswert?

'ps' habe ich natürlich geändert in 'c'

von Johannes L (Gast)


Lesenswert?

E0 = ß soviel weiß ich nun sicher !

von Johannes L (Gast)


Lesenswert?

Im Bereich von E und F also 0xE. bis 0xF. befinden sich überwiegend 
grichische Zeichen PI ny etc.

von Johannes L (Gast)


Angehängte Dateien:

Lesenswert?

Probieren geht über studieren !

Ich habe folgende Zeichenverknüpfungen herausgefunden.

Ich hoffe jemand kennt die dazugehörige Zeichen-Tabelle. Es müsste eine 
Tabelle für grichisch, italentisch und spanisch.

Code für Zeichunterscheidung
1
 switch(c)
2
  {
3
   case 'ä' : c=0x84; break; //Umlenkung auf neuen Zeichen Code
4
   case 'ö' : c=0x94; break;
5
   case 'ü' : c=0x81; break;
6
   case 'ß' : c=0xE0; break;
7
   case 'Ä' : c=0x8E; break;
8
   case 'Ö' : c=0x99; break;
9
   case 'Ü' : c=0x9A; break;
10
  
11
  }

Ergebnis habe ich als Bild angefügt.

von Karl H. (kbuchegg)


Lesenswert?

Johannes L schrieb:
> Probieren geht über studieren !

Na siehst du.

> Ich hoffe jemand kennt die dazugehörige Zeichen-Tabelle. Es müsste eine
> Tabelle für grichisch, italentisch und spanisch.

Schreib dir ein Programm, welche alle Bytes von 0 bis 255 ans LCD sendet 
und sieh dir am LCD an, welchen darstellbaren Zeichen jeder Code 
zugeordnet ist.

Ein STandard-LCD hat für alle Zeichen größer 128 normalerweise immer die 
gleichen japanisch/logischen/Blockgrafik/Umlaut/AKzent Zeichen. Das muss 
aber nicht so sein, dass kann jeder Hersteller dann machen wie er will.
Deines ist offenbar nicht Standard. Und anstelle von rumraten, macht man 
sich halt einfach ein Programm, welches direkt am LCD alle Zeichen 
ausgibt.
Dann sieht man am fraglichen Objekt selber, welcher Code welchem Zeichen 
entspricht.

von Johannes L (Gast)


Angehängte Dateien:

Lesenswert?

Vielen Dank für deine Hilfe ohne dich wäre ich immer noch beim 
verzweifeln an lcd_data :-)

Ich habe die Tabelle gefunden !

Es gibt eine Standard Tabelle wie du sagst, jedoch muss ich für mein LC 
Display eine andere verwenden. Ich habe grade mal die Tabelle 
ausgedruckt und ein Bild gemacht

Siehe Anhang

Als nächstes möchte ich mich mit der Ausgabe von Zahlen widmen :-)

Ich will eine Zähler der bis Zahl x läuft ohne das ein Zahlenfehler 
auftritt.
Bei einer einfachen Übergabe von Zahlen welche in einem Buffer stehen 
passiert immer ein Fehler mit den Stellen....


BSP:
1
lcd_data( variable );
2
 
3
    itoa( variable, Buffer, 10 ); 
4
5
   lcd_setcursor( 0, 4 );
6
 
7
    lcd_string(Buffer);

von Karl H. (kbuchegg)


Lesenswert?

> lcd_data( variable );

wieso lcd_data?

Du musst unterscheiden zwischen Codes und dem was du anzeigen willst. 
Schau auf deine Tabelle. Wenn du das Zeichen

    *
    **
    ***
    ****
    ***
    **
    *
also den 'Pfeil nach links' ausgeben willst, dann must du den Code 0x10 
ausgeben.
Also
   lcd_data( 0x10 );

Ob du die 0x10 direkt angibst oder über eine Variable

uint8_t pfeil = 0x10;
lcd_data( pfeil );

ist wurscht. Die Funktion lcd_data bekommt den Wert 0x10 (also dezimal 
16) überträgt diesen Code an das LCD und das LCD erzeugt das zu diesem 
Code gehörende Zeichen.

Willst du aber haben, dass am LCD tatsächlich der Text "16" steht, dann 
musst du dir erst mal aus dem Zahlenwert einen String machen. AUs 157 
muss erst mal der Text "157" werden, der dann mittels lcd_string 
ausgegeben werden kann. Und genau das macht itoa.

von NullAhnung (Gast)


Lesenswert?


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.