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 ?
>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.
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 | }
|
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.
Warum hat das keinen Zweck ? Ich habe dir den Code und die Beschaltung gezeigt warum hat es keinen Zweck ?
>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.
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.
Hi, das Display läuft ! Nur die Umlaute funktionieren noch nicht, aber eigene Zeichen erstellen funktioniert wunderbar. Danke für die Aufmerksamkeit
>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
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.
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 :-)
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
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
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?
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
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
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 ?
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.
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( 'ß' ); |
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.
>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;
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.
Im Bereich von E und F also 0xE. bis 0xF. befinden sich überwiegend grichische Zeichen PI ny etc.
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.
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.
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); |
> 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.
http://www.mikrocontroller.net/articles/AVR-Tutorial:_LCD http://www.mikrocontroller.net/articles/FAQ
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.