Hier http://www.mikrocontroller.net/articles/FAQ#Aktivieren_der_Floating_Point_Version_von_sprintf_beim_WinAVR_mit_AVR-Studio ist es zwar beschrieben aber nur für AVR Studio. Weiß irgend jemand wo man diese wunzig kleine Eigenschaft in der riesen großen IDE Eclipse findet? Gruß Bro
Warst du schonmal auf der Projektkonfigurationsseite auf der du die ganzen Compilereinstellungen machst? Dort gibt es einen Punkt Linker, dem kannst du einfach zusätzliche Bibliotheken verpassen. Der Weg zu den Einstellungen ist im beigefügten Screenshot zu sehen, wichtig ist, dass du beim Hinzufügen der Libraries das "lib" sowie die Erweiterung im Namen weglässt. Aus "libm.a" wird also ein einfaches "m" mfG Markus Anmerkung: Ja, das ist ein Screenshot und nein, es ist kein PNG - Weil letzteres um Faktor drei größer wäre ohne erkennbaren Nutzen.
Danke Markus für die Antwort. Ich habe das jetzt mal gleich ausprobiert und sehe immer noch Fragezeichen. Mein Code:
1 | #include <stdio.h> |
2 | #include <stdlib.h> |
3 | #include <avr/io.h> |
4 | #include <string.h> |
5 | #include "Dekl-FKT.h" |
6 | #include "lcd-routines.h" |
7 | #include <util/delay.h> |
8 | |
9 | int main() |
10 | {
|
11 | char Schleife = 0; |
12 | double Sensor0, Sensor1, Sensor2, Sensor3, Sensor4; |
13 | const double ADC_V = 0.01960784; |
14 | char Buf[100]; |
15 | |
16 | //ADC-Init:
|
17 | ADCSRA = 0b10000111; |
18 | ADMUX = 0b01100000; |
19 | |
20 | //LCD init:
|
21 | lcd_init(); |
22 | lcd_clear(); |
23 | |
24 | //Ein-/Ausgabe
|
25 | |
26 | //Hauptschleife:
|
27 | do
|
28 | {
|
29 | /*Sensor0 = GetADC_8bit(0) * ADC_V;
|
30 | Sensor1 = GetADC_8bit(1) * ADC_V;
|
31 | Sensor2 = GetADC_8bit(2) * ADC_V;
|
32 | Sensor3 = GetADC_8bit(3) * ADC_V;
|
33 | Sensor4 = GetADC_8bit(4) * ADC_V;*/
|
34 | |
35 | Sensor0 = 1.1; |
36 | Sensor1 = 3.2; |
37 | Sensor2 = 2.3; |
38 | Sensor3 = 2.4; |
39 | Sensor4 = 7.5; |
40 | |
41 | sprintf(Buf, "%f", Sensor0); |
42 | lcd_setcursor(0, 1); |
43 | lcd_string(Buf); |
44 | |
45 | sprintf(Buf, "%f", Sensor1); |
46 | lcd_setcursor(4, 1); |
47 | lcd_string(Buf); |
48 | |
49 | sprintf(Buf, "%f", Sensor2); |
50 | lcd_setcursor(8, 1); |
51 | lcd_string(Buf); |
52 | |
53 | sprintf(Buf, "%f", Sensor3); |
54 | lcd_setcursor(12, 1); |
55 | lcd_string(Buf); |
56 | |
57 | sprintf(Buf, "%f", Sensor4); |
58 | lcd_setcursor(16, 1); |
59 | lcd_string(Buf); |
60 | |
61 | _delay_ms(250); |
62 | }
|
63 | while(Schleife == 0);//zurück |
64 | return 0; |
65 | }
|
Ich habe folgendes ausprobiert: Wenn ich in dieser Zeile: sprintf(Buf, "%f", Sensor0); im mittleren Parameter vor dem Prozent einen Buchstaben oder eine Zahl hingebe dann sehe ich es am Display, aber lasse ich nur die Zahl erscheinen mit %f, so sehe ich am Display 5 Fragezeichen. Die Fragezeichen deuten darauf hin (laut anderen Forenbeiträgen), dass die Lib nicht eingebunden wurde. Dann habe ich noch laut dieser Seite http://www.mikrocontroller.net/articles/FAQ#Aktivieren_der_Floating_Point_Version_von_sprintf_beim_WinAVR_mit_AVR-Studio die libprintf_flt.a eingebunden auch ohne lib und .a und es waren immer nich die Fragezeichen. Ich habe auch schon die Kommas in Beistriche und nicht Punkte angegeben und die Fragezeichen sind noch da. Was für einen Grund könnte denn das haben? Ach ja im Projekt sind noch folgende Unterprogramme:
1 | //Unterprogramme------------------------------------------------------
|
2 | //ADC-UP
|
3 | uint8_t GetADC_8bit(uint8_t Chanel) |
4 | {
|
5 | uint8_t result; |
6 | ADMUX = (ADMUX & ~(0x1F)) | (Chanel & 0x1F); //set chanel |
7 | ADCSRA |= (1<<ADSC); //start ADC |
8 | while (ADCSRA & (1<<ADSC)); //warte bis ADC fertig |
9 | result = ADCH; |
10 | return result; |
11 | }
|
12 | |
13 | // Erzeugt einen Enable-Puls
|
14 | static void lcd_enable( void ) |
15 | {
|
16 | LCD_PORT |= (1<<LCD_EN); // Enable auf 1 setzen |
17 | _delay_us( LCD_ENABLE_US ); // kurze Pause |
18 | LCD_PORT &= ~(1<<LCD_EN); // Enable auf 0 setzen |
19 | }
|
20 | |
21 | // Sendet eine 4-bit Ausgabeoperation an das LCD
|
22 | static void lcd_out( uint8_t data ) |
23 | {
|
24 | data &= 0xF0; // obere 4 Bit maskieren |
25 | |
26 | LCD_PORT &= ~(0xF0>>(4-LCD_DB)); // Maske löschen |
27 | LCD_PORT |= (data>>(4-LCD_DB)); // Bits setzen |
28 | lcd_enable(); |
29 | }
|
30 | |
31 | // Initialisierung: muss ganz am Anfang des Programms aufgerufen werden.
|
32 | void lcd_init( void ) |
33 | {
|
34 | // verwendete Pins auf Ausgang schalten
|
35 | uint8_t pins = (0x0F << LCD_DB) | // 4 Datenleitungen |
36 | (1<<LCD_RS) | // R/S Leitung |
37 | (1<<LCD_EN); // Enable Leitung |
38 | LCD_DDR |= pins; |
39 | |
40 | // initial alle Ausgänge auf Null
|
41 | LCD_PORT &= ~pins; |
42 | |
43 | // warten auf die Bereitschaft des LCD
|
44 | _delay_ms( LCD_BOOTUP_MS ); |
45 | |
46 | // Soft-Reset muss 3mal hintereinander gesendet werden zur Initialisierung
|
47 | lcd_out( LCD_SOFT_RESET ); |
48 | _delay_ms( LCD_SOFT_RESET_MS1 ); |
49 | |
50 | lcd_enable(); |
51 | _delay_ms( LCD_SOFT_RESET_MS2 ); |
52 | |
53 | lcd_enable(); |
54 | _delay_ms( LCD_SOFT_RESET_MS3 ); |
55 | |
56 | // 4-bit Modus aktivieren
|
57 | lcd_out( LCD_SET_FUNCTION | |
58 | LCD_FUNCTION_4BIT ); |
59 | _delay_ms( LCD_SET_4BITMODE_MS ); |
60 | |
61 | // 4-bit Modus / 2 Zeilen / 5x7
|
62 | lcd_command( LCD_SET_FUNCTION | |
63 | LCD_FUNCTION_4BIT | |
64 | LCD_FUNCTION_2LINE | |
65 | LCD_FUNCTION_5X7 ); |
66 | |
67 | // Display ein / Cursor aus / Blinken aus
|
68 | lcd_command( LCD_SET_DISPLAY | |
69 | LCD_DISPLAY_ON | |
70 | LCD_CURSOR_OFF | |
71 | LCD_BLINKING_OFF); |
72 | |
73 | // Cursor inkrement / kein Scrollen
|
74 | lcd_command( LCD_SET_ENTRY | |
75 | LCD_ENTRY_INCREASE | |
76 | LCD_ENTRY_NOSHIFT ); |
77 | |
78 | lcd_clear(); |
79 | }
|
80 | |
81 | // Sendet ein Datenbyte an das LCD
|
82 | void lcd_data( uint8_t data ) |
83 | {
|
84 | LCD_PORT |= (1<<LCD_RS); // RS auf 1 setzen |
85 | |
86 | lcd_out( data ); // zuerst die oberen, |
87 | lcd_out( data<<4 ); // dann die unteren 4 Bit senden |
88 | |
89 | _delay_us( LCD_WRITEDATA_US ); |
90 | }
|
91 | |
92 | // Sendet einen Befehl an das LCD
|
93 | void lcd_command( uint8_t data ) |
94 | {
|
95 | LCD_PORT &= ~(1<<LCD_RS); // RS auf 0 setzen |
96 | |
97 | lcd_out( data ); // zuerst die oberen, |
98 | lcd_out( data<<4 ); // dann die unteren 4 Bit senden |
99 | |
100 | _delay_us( LCD_COMMAND_US ); |
101 | }
|
102 | |
103 | // Sendet den Befehl zur Löschung des Displays
|
104 | void lcd_clear( void ) |
105 | {
|
106 | lcd_command( LCD_CLEAR_DISPLAY ); |
107 | _delay_ms( LCD_CLEAR_DISPLAY_MS ); |
108 | }
|
109 | |
110 | // Sendet den Befehl: Cursor Home
|
111 | void lcd_home( void ) |
112 | {
|
113 | lcd_command( LCD_CURSOR_HOME ); |
114 | _delay_ms( LCD_CURSOR_HOME_MS ); |
115 | }
|
116 | |
117 | // Setzt den Cursor in Spalte x (0..15) Zeile y (1..4)
|
118 | |
119 | void lcd_setcursor( uint8_t x, uint8_t y ) |
120 | {
|
121 | uint8_t data; |
122 | |
123 | switch (y) |
124 | {
|
125 | case 1: // 1. Zeile |
126 | data = LCD_SET_DDADR + LCD_DDADR_LINE1 + x; |
127 | break; |
128 | |
129 | case 2: // 2. Zeile |
130 | data = LCD_SET_DDADR + LCD_DDADR_LINE2 + x; |
131 | break; |
132 | |
133 | case 3: // 3. Zeile |
134 | data = LCD_SET_DDADR + LCD_DDADR_LINE3 + x; |
135 | break; |
136 | |
137 | case 4: // 4. Zeile |
138 | data = LCD_SET_DDADR + LCD_DDADR_LINE4 + x; |
139 | break; |
140 | |
141 | default:
|
142 | return; // für den Fall einer falschen Zeile |
143 | }
|
144 | |
145 | lcd_command( data ); |
146 | }
|
147 | |
148 | // Schreibt einen String auf das LCD
|
149 | |
150 | void lcd_string( const char *data ) |
151 | {
|
152 | while( *data != '\0' ) |
153 | lcd_data( *data++ ); |
154 | }
|
155 | |
156 | // Schreibt ein Zeichen in den Character Generator RAM
|
157 | |
158 | void lcd_generatechar( uint8_t code, const uint8_t *data ) |
159 | {
|
160 | // Startposition des Zeichens einstellen
|
161 | lcd_command( LCD_SET_CGADR | (code<<3) ); |
162 | |
163 | // Bitmuster übertragen
|
164 | for ( uint8_t i=0; i<8; i++ ) |
165 | {
|
166 | lcd_data( data[i] ); |
167 | }
|
168 | }
|
und in den Headerdatein steht folgendes:
1 | uint8_t GetADC_8bit(uint8_t Chanel); |
2 | |
3 | // Ansteuerung eines HD44780 kompatiblen LCD im 4-Bit-Interfacemodus
|
4 | // http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung
|
5 | //
|
6 | |
7 | #ifndef LCD_ROUTINES_H
|
8 | #define LCD_ROUTINES_H
|
9 | |
10 | ////////////////////////////////////////////////////////////////////////////////
|
11 | // Hier die verwendete Taktfrequenz in Hz eintragen, wichtig!
|
12 | |
13 | #ifndef F_CPU
|
14 | #define F_CPU 8000000
|
15 | #endif
|
16 | |
17 | ////////////////////////////////////////////////////////////////////////////////
|
18 | // Pinbelegung für das LCD, an verwendete Pins anpassen
|
19 | // Alle LCD Pins müssen an einem Port angeschlossen sein und die 4
|
20 | // Datenleitungen müssen auf aufeinanderfolgenden Pins liegen
|
21 | |
22 | // LCD DB4-DB7 <--> PORTD Bit PD0-PD3
|
23 | #define LCD_PORT PORTC
|
24 | #define LCD_DDR DDRC
|
25 | #define LCD_DB PC2
|
26 | |
27 | // LCD RS <--> PORTD Bit PD4 (RS: 0=Data, 1=Command)
|
28 | #define LCD_RS PC6
|
29 | |
30 | // LCD EN <--> PORTD Bit PD5 (EN: 1-Impuls für Daten)
|
31 | #define LCD_EN PC7
|
32 | |
33 | ////////////////////////////////////////////////////////////////////////////////
|
34 | // LCD Ausführungszeiten (MS=Millisekunden, US=Mikrosekunden)
|
35 | |
36 | #define LCD_BOOTUP_MS 15
|
37 | #define LCD_ENABLE_US 1
|
38 | #define LCD_WRITEDATA_US 46
|
39 | #define LCD_COMMAND_US 42
|
40 | |
41 | #define LCD_SOFT_RESET_MS1 5
|
42 | #define LCD_SOFT_RESET_MS2 1
|
43 | #define LCD_SOFT_RESET_MS3 1
|
44 | #define LCD_SET_4BITMODE_MS 5
|
45 | |
46 | #define LCD_CLEAR_DISPLAY_MS 2
|
47 | #define LCD_CURSOR_HOME_MS 2
|
48 | |
49 | ////////////////////////////////////////////////////////////////////////////////
|
50 | // Zeilendefinitionen des verwendeten LCD
|
51 | // Die Einträge hier sollten für ein LCD mit einer Zeilenlänge von 16 Zeichen passen
|
52 | // Bei anderen Zeilenlängen müssen diese Einträge angepasst werden
|
53 | |
54 | #define LCD_DDADR_LINE1 0x00
|
55 | #define LCD_DDADR_LINE2 0x40
|
56 | #define LCD_DDADR_LINE3 0x10
|
57 | #define LCD_DDADR_LINE4 0x50
|
58 | |
59 | ////////////////////////////////////////////////////////////////////////////////
|
60 | // Initialisierung: muss ganz am Anfang des Programms aufgerufen werden.
|
61 | void lcd_init( void ); |
62 | |
63 | ////////////////////////////////////////////////////////////////////////////////
|
64 | // LCD löschen
|
65 | void lcd_clear( void ); |
66 | |
67 | ////////////////////////////////////////////////////////////////////////////////
|
68 | // Cursor in die 1. Zeile, 0-te Spalte
|
69 | void lcd_home( void ); |
70 | |
71 | ////////////////////////////////////////////////////////////////////////////////
|
72 | // Cursor an eine beliebige Position
|
73 | void lcd_setcursor( uint8_t spalte, uint8_t zeile ); |
74 | |
75 | ////////////////////////////////////////////////////////////////////////////////
|
76 | // Ausgabe eines einzelnen Zeichens an der aktuellen Cursorposition
|
77 | void lcd_data( uint8_t data ); |
78 | |
79 | ////////////////////////////////////////////////////////////////////////////////
|
80 | // Ausgabe eines Strings an der aktuellen Cursorposition
|
81 | void lcd_string( const char *data ); |
82 | |
83 | ////////////////////////////////////////////////////////////////////////////////
|
84 | // Definition eines benutzerdefinierten Sonderzeichens.
|
85 | // data muss auf ein Array[5] mit den Spaltencodes des zu definierenden Zeichens
|
86 | // zeigen
|
87 | void lcd_generatechar( uint8_t code, const uint8_t *data ); |
88 | |
89 | ////////////////////////////////////////////////////////////////////////////////
|
90 | // Ausgabe eines Kommandos an das LCD.
|
91 | void lcd_command( uint8_t data ); |
92 | |
93 | |
94 | ////////////////////////////////////////////////////////////////////////////////
|
95 | // LCD Befehle und Argumente.
|
96 | // Zur Verwendung in lcd_command
|
97 | |
98 | // Clear Display -------------- 0b00000001
|
99 | #define LCD_CLEAR_DISPLAY 0x01
|
100 | |
101 | // Cursor Home ---------------- 0b0000001x
|
102 | #define LCD_CURSOR_HOME 0x02
|
103 | |
104 | // Set Entry Mode ------------- 0b000001xx
|
105 | #define LCD_SET_ENTRY 0x04
|
106 | |
107 | #define LCD_ENTRY_DECREASE 0x00
|
108 | #define LCD_ENTRY_INCREASE 0x02
|
109 | #define LCD_ENTRY_NOSHIFT 0x00
|
110 | #define LCD_ENTRY_SHIFT 0x01
|
111 | |
112 | // Set Display ---------------- 0b00001xxx
|
113 | #define LCD_SET_DISPLAY 0x08
|
114 | |
115 | #define LCD_DISPLAY_OFF 0x00
|
116 | #define LCD_DISPLAY_ON 0x04
|
117 | #define LCD_CURSOR_OFF 0x00
|
118 | #define LCD_CURSOR_ON 0x02
|
119 | #define LCD_BLINKING_OFF 0x00
|
120 | #define LCD_BLINKING_ON 0x01
|
121 | |
122 | // Set Shift ------------------ 0b0001xxxx
|
123 | #define LCD_SET_SHIFT 0x10
|
124 | |
125 | #define LCD_CURSOR_MOVE 0x00
|
126 | #define LCD_DISPLAY_SHIFT 0x08
|
127 | #define LCD_SHIFT_LEFT 0x00
|
128 | #define LCD_SHIFT_RIGHT 0x01
|
129 | |
130 | // Set Function --------------- 0b001xxxxx
|
131 | #define LCD_SET_FUNCTION 0x20
|
132 | |
133 | #define LCD_FUNCTION_4BIT 0x00
|
134 | #define LCD_FUNCTION_8BIT 0x10
|
135 | #define LCD_FUNCTION_1LINE 0x00
|
136 | #define LCD_FUNCTION_2LINE 0x08
|
137 | #define LCD_FUNCTION_5X7 0x00
|
138 | #define LCD_FUNCTION_5X10 0x04
|
139 | |
140 | #define LCD_SOFT_RESET 0x30
|
141 | |
142 | // Set CG RAM Address --------- 0b01xxxxxx (Character Generator RAM)
|
143 | #define LCD_SET_CGADR 0x40
|
144 | |
145 | #define LCD_GC_CHAR0 0
|
146 | #define LCD_GC_CHAR1 1
|
147 | #define LCD_GC_CHAR2 2
|
148 | #define LCD_GC_CHAR3 3
|
149 | #define LCD_GC_CHAR4 4
|
150 | #define LCD_GC_CHAR5 5
|
151 | #define LCD_GC_CHAR6 6
|
152 | #define LCD_GC_CHAR7 7
|
153 | |
154 | // Set DD RAM Address --------- 0b1xxxxxxx (Display Data RAM)
|
155 | #define LCD_SET_DDADR 0x80
|
156 | |
157 | #endif
|
Gruß Bro
Brocken Sei schrieb: > Dann habe ich noch laut dieser Seite > http://www.mikrocontroller.net/articles/FAQ#Aktivi... > die libprintf_flt.a eingebunden auch ohne lib und .a und es waren immer > nich die Fragezeichen. Die Lib dazu linken alleine reicht nicht. Was ist mit der zusätzlich nötigen Linker-Option? Hast du die auch hinzugefügt? Wie sieht die Linker-Kommandozeile denn aktuell konkret aus?
hier mal nen paar screens aus na ppt von letztem jahr..
Stefan Ernst schrieb: > Wie sieht die > Linker-Kommandozeile denn aktuell konkret aus? Jetzt sieht sie dank Andi D wie im Bild aus. Das einzige was er nicht angenommen hat ist das -u,vfscanf, das war mir aber nicht so wichtig. Der einzige Nachteil ist es nimmt sehr sehr viel Speicher. 30% sind schon wegen dem verpulvert, aber was soll man machen. Danke jedenfalls, jetzt funktioniert es. Gruß Bro
Brocken Sei schrieb: > Der einzige Nachteil ist es nimmt sehr sehr viel Speicher. 30% sind > schon wegen dem verpulvert, aber was soll man machen. Kein Floating Point verwenden. Ganz einfach.
Karl heinz Buchegger schrieb: > Kein Floating Point verwenden. > Ganz einfach. Oder einen Atmega 644 statt Atmega16. Leider treffen deine Hilfen gegenüber mir nicht immer ins Schwarze. Hättest du nicht einmal einen Tipp geben können ob es überhaupt eine andere Möglichkeit gibt? Ich vermute natürlich ja, aber diese funktioniert auch! Gruß Bro
Brocken Sei schrieb: > Karl heinz Buchegger schrieb: >> Kein Floating Point verwenden. >> Ganz einfach. > > Oder einen Atmega 644 statt Atmega16. > Leider treffen deine Hilfen gegenüber mir nicht immer ins Schwarze. Doch. Der Tipp auf Floating Point zu verzichten ist ein sehr guter. Viele glauben das nicht. Klingt komisch ist aber so. Wenn ich Euros addieren muss, kann ich rechnen 2 Euro 30 + 3 Euro 80 Das ganze in Floating Point 2.30 +3.80 -------- 6.10 Ich kann aber auch rechnen: 230 Cent +380 Cent ---------- 610 Cent und damit das ganze in int rechnen. Alles was ich tun muss, ist bei der Ausgabe vor die Zehnerstelle der Cent wieder ein Komma einschmuggeln (und natürlich Euro anstelle von Cent hinschreiben) und schon steht an der Ausgabe wieder 6.10 Euro, obwohl ich nirgends Floating Point Arithmetik benutzt habe. Und wenn ich noch mehr Genauigkeit brauche, dann rechne ich programmintern eben nicht in Cent sondern in Zehntelcent. Genauso kann man mit Spannungen intern alles in Millivolt rechnen und vor der Ausgabe an die Tausenderstelle ein Komma einschmuggeln und schon steht auf der Anzeige wieder Volt (obwohl programmintern nirgends mit Volt gerechnet wird)
Vielen Dank Karl-Heinz, besser kann man es nicht beschreiben.
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.