Forum: Compiler & IDEs Aktivieren der Floating Point Version von sprintf in Eclipse


von Brocken Sei (Gast)


Lesenswert?

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

von Markus J. (markusj)


Angehängte Dateien:

Lesenswert?

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.

von Brocken Sei (Gast)


Lesenswert?

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

von Stefan E. (sternst)


Lesenswert?

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?

von TestX .. (xaos)



Lesenswert?

hier mal nen paar screens aus na ppt von letztem jahr..

von Brocken Sei (Gast)


Angehängte Dateien:

Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Brocken Sei (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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)

von Tobi (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.