Hallo Forum Möchte Folgendes am LCD ausgeben: AZ180.6 EL39.5 Dieser String befindet sich in einer Variable, z.B.: i = AZ180.6 EL39.5 Verwende den Code vom LCD Tutorial. http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung Hier das Hauptprogramm: // // Anpassungen im makefile: // ATMega8 => MCU=atmega8 im makefile einstellen // lcd-routines.c in SRC = ... Zeile anhängen // #include <avr/io.h> #include "lcd-routines.h" int main(void) { lcd_init(); lcd_data('T'); lcd_data('e'); lcd_data('s'); lcd_data('t'); set_cursor(0,2); lcd_string("Hello World!"); while(1) { } return 0; lcd_string("i"); funktioniert nicht. Ala nächstes habe ich die itoa()-Funktion versucht. http://www.mikrocontroller.net/articles/FAQ Dazu kopierte ich diesen Code char Buffer[20]; int i = 25; itoa( i, Buffer, 10 ); lcd_string( Buffer ); statt lcd_string("Hello World!"); in das Hauptorogramm. Funktionierte auch. Wenn ich aber in der Variable i statt 25 meinen String AZ180.6 EL39.5 einfüge funktioniert diese Funktion nicht mehr. Kann mir bitte wer die itoa-Funktion itoa( i, Buffer, 10 ); erklären? Danke für Eure Hilfe.
du musst wenn dann lcd_string(i); ausgeben mit "i" gibst du das ASCII zeichen i aus und mit lcd_string(i); die variable i Gruß
du musst wenn dann lcd_string(i); ausgeben, mit "i" gibst du das ASCII zeichen i aus und mit lcd_string(i); die variable i Gruß
Martin schrieb: > Kann mir bitte wer die itoa-Funktion itoa( i, Buffer, 10 ); > erklären? Schon mal die Doku dazu gelesen und immer noch nicht verstanden? Oder noch nicht gelesen?
Martin schrieb: > Wenn ich aber in der Variable i statt 25 meinen String AZ180.6 EL39.5 > einfüge funktioniert diese Funktion nicht mehr. Wenn i nach wie vor eine int ist, kannst du gar keinen String dort eingefügt haben. Wie äußert sich "funktioniert diese Funktion nicht mehr"?
1) Habs hinbekommen mit char i[]= "AZ180.6 EL39.5"; und lcd_string(i); Das LCD bibt dann AZ180.6 EL39.5 aus. 2) Kann mir bitte wer itoa erklären? Hab den Text auf mikrocontroller.net gelesen, aber nicht wirklich verstenden. char Buffer[20]; int i = 25; itoa( i, Buffer, 10 ); lcd_string( Buffer ); Könnte ich diese Funktion auch als andere Variante für mein Anliegen verwenden? 3) Wie kann man den wiederholenden Wortlaut bei den Postings in der Farbe grün anzeigen? Danke für Eure Hilfe
Martin schrieb: > 3) Wie kann man den wiederholenden Wortlaut bei den Postings in der > Farbe grün anzeigen? Wenn man einen ganzen Beitrag zitieren will, klickt man rechts darunter auf "Antwort mit Zitat" und schreibt dann seinen eigenen Senf dazu. Will man nur einen Teil zitieren, dann halt den Teil markieren und auf "Markierten Text zitieren" klicken.
Martin schrieb: > 2) Kann mir bitte wer itoa erklären? > Hab den Text auf mikrocontroller.net gelesen, aber nicht wirklich > verstenden. Mal hier probieren? http://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html#g4f6b3dd51c1f8519d5b8fce1dbf7a665
> Könnte ich [itoa] auch als andere Variante für mein Anliegen > verwenden? Klar. Viele Wege führen nach ROM
1 | #include <avr/io.h> |
2 | #include <string.h> // wegen strlen() |
3 | #include <stdlib.h> // wegen itoa() |
4 | #include "lcd-routines.h" |
5 | |
6 | void varausgabe(char *varname, int varwert) |
7 | {
|
8 | char Buffer[7]; // ggf. 1 Vorzeichen + 5 Ziffern + Nullbyte |
9 | int i; |
10 | int j; |
11 | |
12 | lcd_string( varname ); |
13 | //
|
14 | // Die int Zahl in varwert in die Ziffern einer Dezimalzahl
|
15 | // (Basis 10) umwandeln und die Ziffern in Buffer speichern
|
16 | // Buffer muss genügend Platz bereitstellen (s.o.)!
|
17 | //
|
18 | itoa( varwert, Buffer, 10 ); |
19 | j = strlen( Buffer ); // Anzahl Ziffern zählen |
20 | for (i = 0; i < j-2; i++) // Ziffern ausser der letzten ausgeben |
21 | lcd_data( Buffer[i] ); |
22 | lcd_data( '.' ); // Dezimaltrennzeichen ausgeben |
23 | lcd_data( Buffer[j-1] ); // Letzte Ziffer ausgeben |
24 | }
|
25 | |
26 | int main(void) |
27 | {
|
28 | int az = 1806; // Ganzzahl * 10 um Gleitkommarechnung |
29 | int el = 395; // zu vermeiden. Spart Programmplatz... |
30 | |
31 | lcd_init(); |
32 | set_cursor(0,2); |
33 | varausgabe("AZ", az); |
34 | varausgabe(" EL", el); |
35 | |
36 | while(1) |
37 | {
|
38 | }
|
39 | |
40 | return 0; |
41 | }
|
Bug!
> for (i = 0; i < j-2; i++) // Ziffern ausser der letzten ausgeben
soll heissen (wegen < und nicht <=):
for (i = 0; i < j-1; i++) // Ziffern ausser der letzten ausgeben
Möchte weiters von dem Terminal-Programm (hterm) Zeichen am LCD ausgeben. Als Kontrolle gebe ich die Zeichen an 8 LEDs aus (ASCI - Code). Somit weiß ich, dass der µC die Zeichen empfängt. Die LEDs zeigen das Zeichen richtig an. Beim LCD erscheint in der zweiten Zeile nichts. Erste Zeile zeigt Test richtig an. Als nächsten Schritt möchte ich nicht nur Zeichen sondern Strings vom UART am LCD ausgeben. //oberhalb dieses Codes sind die LCD-Funktionen und includes!!! volatile unsigned char a; volatile unsigned char az; volatile unsigned char Empfang1 = 0, Empfang2 = 0; volatile unsigned char x; //volatile unsigned char i[]= "AZ180.6 EL39.5"; //UART-Interruptroutine ISR(USART_RXC_vect){ //für LEDs a = UDR; Empfang1 = 1; //für LCD az = UDR; Empfang2 = 1; } int main(void){ //global Interrupt Enable SREG |= (1<<7); //sei(); //Schnittstelle parametrisieren UBRRH = 0; // Baudrate auf 9600 UBRRL = 51; //Empfang, Senden, Empfangsinterrupt UCSRB = (1<<RXEN) | (1<<TXEN) | (1<<RXCIE); //Defaultwerte zementieren, 8N1 UCSRC |= (1<<URSEL) | (3<<UCSZ0); DDRC = 0xFF; //PORTC = 0xff; // wenn auskommentiert leuchen die LEDs nicht am Beginn lcd_init(); lcd_data('T'); lcd_data('e'); lcd_data('s'); lcd_data('t'); set_cursor(0,2); while(1){ if(Empfang1){ PORTC = ~a; Empfang1 = 0; } if(Empfang2){ lcd_string(az); Empfang2 = 0; } } } Bitte um Hilfe. Danke im voraus.
> Die LEDs zeigen das Zeichen richtig an. Beim LCD erscheint in der > zweiten Zeile nichts. Erste Zeile zeigt Test richtig an. Da passt vielleicht dein LCD-Typ nicht zu dem Beispielcode aus dem Tutorial. Insbesondere das Positionieren in set_cursor ist abhängig vom LCD-Typ; siehe Datenblatt zu deinem LCD. Bitte mehr Infos zum LCD und vollständige Quelltexte, sonst wird es schwierig zu helfen. Außerdem wäre es nett, Quelltext hier vernünftig formatiert zu zeigen, sonst macht es keinen Spaß zu lesen. (siehe Infos zu Formatierung 3 cm über dem Betreff beim Schreiben). Grüße nach Österreich und guten Rutsch!
> Da passt vielleicht dein LCD-Typ nicht zu dem Beispielcode aus dem > Tutorial. Der Tutorial-Code funktioniert einwandfrei. Verwende das LCD-Display AC-202A. > Bitte mehr Infos zum LCD und vollständige Quelltexte, sonst wird > es schwierig zu helfen. Manche Forumnutzer beschweren sich über kopierte Codes aus dem Tutorial. Deshalb nur der wichtige Teil des C-Codes, aber wenn gewünscht hier der ganze Code. Die Header-Datei ist nicht dabei. Wenn gewünscht bitte melden.
1 | #include <avr/io.h> |
2 | #define F_CPU 8000000UL
|
3 | #include <util/delay.h> |
4 | #include <stdlib.h> |
5 | #include <avr/interrupt.h> |
6 | #include "lcd-routines.h" |
7 | |
8 | |
9 | |
10 | // sendet ein Datenbyte an das LCD
|
11 | |
12 | void lcd_data(unsigned char temp1) |
13 | {
|
14 | unsigned char temp2 = temp1; |
15 | |
16 | LCD_PORT |= (1<<LCD_RS); // RS auf 1 setzen |
17 | |
18 | temp1 = temp1 >> 4; |
19 | temp1 = temp1 & 0x0F; |
20 | LCD_PORT &= 0xF0; |
21 | LCD_PORT |= temp1; // setzen |
22 | lcd_enable(); |
23 | |
24 | temp2 = temp2 & 0x0F; |
25 | LCD_PORT &= 0xF0; |
26 | LCD_PORT |= temp2; // setzen |
27 | lcd_enable(); |
28 | |
29 | _delay_us(42); |
30 | }
|
31 | |
32 | // sendet einen Befehl an das LCD
|
33 | |
34 | void lcd_command(unsigned char temp1) |
35 | {
|
36 | unsigned char temp2 = temp1; |
37 | |
38 | LCD_PORT &= ~(1<<LCD_RS); // RS auf 0 setzen |
39 | |
40 | temp1 = temp1 >> 4; // oberes Nibble holen |
41 | temp1 = temp1 & 0x0F; // maskieren |
42 | LCD_PORT &= 0xF0; |
43 | LCD_PORT |= temp1; // setzen |
44 | lcd_enable(); |
45 | |
46 | temp2 = temp2 & 0x0F; // unteres Nibble holen und maskieren |
47 | LCD_PORT &= 0xF0; |
48 | LCD_PORT |= temp2; // setzen |
49 | lcd_enable(); |
50 | |
51 | _delay_us(42); |
52 | }
|
53 | |
54 | // erzeugt den Enable-Puls
|
55 | void lcd_enable(void) |
56 | {
|
57 | // Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers einfügen
|
58 | // http://www.mikrocontroller.net/topic/81974#685882
|
59 | LCD_PORT |= (1<<LCD_EN); |
60 | _delay_us(1); // kurze Pause |
61 | // Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers verlängern
|
62 | // http://www.mikrocontroller.net/topic/80900
|
63 | LCD_PORT &= ~(1<<LCD_EN); |
64 | }
|
65 | |
66 | // Initialisierung:
|
67 | // Muss ganz am Anfang des Programms aufgerufen werden.
|
68 | |
69 | void lcd_init(void) |
70 | {
|
71 | LCD_DDR = LCD_DDR | 0x0F | (1<<LCD_RS) | (1<<LCD_EN); // Port auf Ausgang schalten |
72 | |
73 | // muss 3mal hintereinander gesendet werden zur Initialisierung
|
74 | |
75 | _delay_ms(15); |
76 | LCD_PORT &= 0xF0; |
77 | LCD_PORT |= 0x03; |
78 | LCD_PORT &= ~(1<<LCD_RS); // RS auf 0 |
79 | lcd_enable(); |
80 | |
81 | _delay_ms(5); |
82 | lcd_enable(); |
83 | |
84 | _delay_ms(1); |
85 | lcd_enable(); |
86 | _delay_ms(1); |
87 | |
88 | // 4 Bit Modus aktivieren
|
89 | LCD_PORT &= 0xF0; |
90 | LCD_PORT |= 0x02; |
91 | lcd_enable(); |
92 | _delay_ms(1); |
93 | |
94 | // 4Bit / 2 Zeilen / 5x7
|
95 | lcd_command(0x28); |
96 | |
97 | // Display ein / Cursor aus / kein Blinken
|
98 | lcd_command(0x0C); |
99 | |
100 | // inkrement / kein Scrollen
|
101 | lcd_command(0x06); |
102 | |
103 | lcd_clear(); |
104 | }
|
105 | |
106 | // Sendet den Befehl zur Löschung des Displays
|
107 | |
108 | void lcd_clear(void) |
109 | {
|
110 | lcd_command(CLEAR_DISPLAY); |
111 | _delay_ms(5); |
112 | }
|
113 | |
114 | // Sendet den Befehl: Cursor Home
|
115 | |
116 | void lcd_home(void) |
117 | {
|
118 | lcd_command(CURSOR_HOME); |
119 | _delay_ms(5); |
120 | }
|
121 | |
122 | // setzt den Cursor in Zeile y (1..4) Spalte x (0..15)
|
123 | |
124 | void set_cursor(uint8_t x, uint8_t y) |
125 | {
|
126 | uint8_t tmp; |
127 | |
128 | switch (y) { |
129 | case 1: tmp=0x80+0x00+x; break; // 1. Zeile |
130 | case 2: tmp=0x80+0x40+x; break; // 2. Zeile |
131 | case 3: tmp=0x80+0x10+x; break; // 3. Zeile |
132 | case 4: tmp=0x80+0x50+x; break; // 4. Zeile |
133 | default: return; // für den Fall einer falschen Zeile |
134 | }
|
135 | lcd_command(tmp); |
136 | }
|
137 | |
138 | // Schreibt einen String auf das LCD
|
139 | |
140 | void lcd_string(char *data) |
141 | {
|
142 | while(*data) { |
143 | lcd_data(*data); |
144 | data++; |
145 | }
|
146 | }
|
147 | |
148 | //*****************************************************
|
149 | |
150 | |
151 | |
152 | |
153 | |
154 | volatile unsigned char a; |
155 | volatile unsigned char az; |
156 | volatile unsigned char Empfang1 = 0, Empfang2 = 0; |
157 | volatile unsigned char x; |
158 | //volatile unsigned char i[]= "AZ180.6 EL39.5";
|
159 | |
160 | |
161 | |
162 | |
163 | |
164 | |
165 | //UART-Interruptroutine
|
166 | |
167 | ISR(USART_RXC_vect){ |
168 | |
169 | //für LEDs
|
170 | a = UDR; |
171 | Empfang1 = 1; |
172 | |
173 | //für LCD
|
174 | az = UDR; |
175 | Empfang2 = 1; |
176 | |
177 | }
|
178 | |
179 | |
180 | |
181 | |
182 | |
183 | int main(void){ |
184 | |
185 | //global Interrupt Enable
|
186 | SREG |= (1<<7); //sei(); |
187 | //Schnittstelle parametrisieren
|
188 | UBRRH = 0; // Baudrate auf 9600 |
189 | UBRRL = 51; |
190 | //Empfang, Senden, Empfangsinterrupt
|
191 | UCSRB = (1<<RXEN) | (1<<TXEN) | (1<<RXCIE); |
192 | //Defaultwerte zementieren, 8N1
|
193 | UCSRC |= (1<<URSEL) | (3<<UCSZ0); |
194 | |
195 | DDRC = 0xFF; |
196 | //PORTC = 0xff; // wenn auskommentiert leuchen die LEDs nicht am Beginn
|
197 | |
198 | |
199 | |
200 | lcd_init(); |
201 | |
202 | lcd_data('T'); |
203 | lcd_data('e'); |
204 | lcd_data('s'); |
205 | lcd_data('t'); |
206 | |
207 | set_cursor(0,2); |
208 | |
209 | |
210 | |
211 | while(1){ |
212 | |
213 | if(Empfang1){ |
214 | PORTC = ~a; |
215 | Empfang1 = 0; |
216 | }
|
217 | |
218 | if(Empfang2){ |
219 | lcd_string(az); |
220 | Empfang2 = 0; |
221 | }
|
222 | |
223 | |
224 | }
|
225 | }
|
Danke über die Infos zur Formatierung.
Der von mir vermutete Fehler beim Positionieren ist keiner; in Seite 13 deiner PDF steht unten die Zuordnung ...+0x40... der zweiten Zeile zum DD-RAM des LCD, das passt zu der set_cursor(). Aber ein Fehler ist, daß az ein Zeichen ist, du das aber mit lcd_string() auszugeben versuchst. Du musst dich entscheiden: ein Zeichen mit lcd_char(), oder einen nullterminierten String mit lcd_string().
> Aber ein Fehler ist, daß az ein Zeichen ist, du das aber mit > lcd_string() auszugeben versuchst. > Du musst dich entscheiden: ein Zeichen mit lcd_char(), oder > einen nullterminierten String mit lcd_string(). Binn ein bisschen verwirrt. Ich möchte ein Zeichen übertragen, dass dann im UDR-Register liegt und dies am Lcd anzeigen. Mit az = UDR; lcd_string(az); funktioniert es nicht. Wie würdest du ein Zeichen, welches um URR liegt am Lcd ausgeben?
1. würde ich mir mal ein C-Buch nehmen und den Unterschied zwischen einem Zeichen und einem String (in C üblicherweise nullterminiert) herausfinden 2. gibt es in deinen LCD-Routinen eine Funktion lcd_data(), die du ja schon richtigerweise für die einzelnen Zeichen der ersten Zeile verwendest. Genau die kann nach dem set_cursor() ebenso jeweils ein Zeichen in der zweiten Zeile ausgeben, also lcd_data(az) anstatt lcd_string(az). 3. ist nicht garantiert, daß das Zeichen überhaupt darstellbar ist. Deshalb würde ich erst testen, ob es in einem vernünftigen Bereich liegt, und notfalls etwas anderes ausgeben, z.B. ein Fragezeichen. Im einfachsten Fall kann man dafür isprint() verwenden (dafür #include <ctype.h> mit aufnehmen):
1 | #include <ctype.h> |
2 | ...
|
3 | lcd_data( isprint(az) ? az : '?' ); |
4. Sind die Fehlerbeschreibungen noch optimierbar; zum Beispiel "Mit ... funktioniert es nicht" lässt etwas Spielraum offen, wie sich der Fehler äußert, ähem.
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.