mikrocontroller.net

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


Autor: Brocken Sei (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier
http://www.mikrocontroller.net/articles/FAQ#Aktivi...
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

Autor: Markus J. (markusj)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.

Autor: Brocken Sei (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke Markus für die Antwort.
Ich habe das jetzt mal gleich ausprobiert und sehe immer noch 
Fragezeichen.
Mein Code:
#include <stdio.h>
#include <stdlib.h>
#include <avr/io.h>
#include <string.h>
#include "Dekl-FKT.h"
#include "lcd-routines.h"
#include <util/delay.h>

int main()
{
  char Schleife = 0;
  double Sensor0, Sensor1, Sensor2, Sensor3, Sensor4;
  const double ADC_V = 0.01960784;
  char Buf[100];

  //ADC-Init:
  ADCSRA = 0b10000111;
  ADMUX = 0b01100000;

  //LCD init:
  lcd_init();
  lcd_clear();

  //Ein-/Ausgabe

  //Hauptschleife:
  do
  {
    /*Sensor0 = GetADC_8bit(0) * ADC_V;
    Sensor1 = GetADC_8bit(1) * ADC_V;
    Sensor2 = GetADC_8bit(2) * ADC_V;
    Sensor3 = GetADC_8bit(3) * ADC_V;
    Sensor4 = GetADC_8bit(4) * ADC_V;*/

    Sensor0 = 1.1;
    Sensor1 = 3.2;
    Sensor2 = 2.3;
    Sensor3 = 2.4;
    Sensor4 = 7.5;

    sprintf(Buf, "%f", Sensor0);
        lcd_setcursor(0, 1);
        lcd_string(Buf);

    sprintf(Buf, "%f", Sensor1);
        lcd_setcursor(4, 1);
        lcd_string(Buf);

    sprintf(Buf, "%f", Sensor2);
        lcd_setcursor(8, 1);
        lcd_string(Buf);

    sprintf(Buf, "%f", Sensor3);
        lcd_setcursor(12, 1);
        lcd_string(Buf);

    sprintf(Buf, "%f", Sensor4);
        lcd_setcursor(16, 1);
        lcd_string(Buf);

    _delay_ms(250);
  }
  while(Schleife == 0);//zurück
  return 0;
}

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#Aktivi...
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:
//Unterprogramme------------------------------------------------------
//ADC-UP
uint8_t GetADC_8bit(uint8_t Chanel)
{
  uint8_t result;
  ADMUX = (ADMUX & ~(0x1F)) | (Chanel & 0x1F); //set chanel
  ADCSRA |= (1<<ADSC); //start ADC
  while (ADCSRA & (1<<ADSC)); //warte bis ADC fertig
  result = ADCH;
  return result;
}

// Erzeugt einen Enable-Puls
static void lcd_enable( void )
{
    LCD_PORT |= (1<<LCD_EN);     // Enable auf 1 setzen
    _delay_us( LCD_ENABLE_US );  // kurze Pause
    LCD_PORT &= ~(1<<LCD_EN);    // Enable auf 0 setzen
}

// Sendet eine 4-bit Ausgabeoperation an das LCD
static void lcd_out( uint8_t data )
{
    data &= 0xF0;                       // obere 4 Bit maskieren

    LCD_PORT &= ~(0xF0>>(4-LCD_DB));    // Maske löschen
    LCD_PORT |= (data>>(4-LCD_DB));     // Bits setzen
    lcd_enable();
}

// Initialisierung: muss ganz am Anfang des Programms aufgerufen werden.
void lcd_init( void )
{
    // verwendete Pins auf Ausgang schalten
    uint8_t pins = (0x0F << LCD_DB) |           // 4 Datenleitungen
                   (1<<LCD_RS) |                // R/S Leitung
                   (1<<LCD_EN);                 // Enable Leitung
    LCD_DDR |= pins;

    // initial alle Ausgänge auf Null
    LCD_PORT &= ~pins;

    // warten auf die Bereitschaft des LCD
    _delay_ms( LCD_BOOTUP_MS );

    // Soft-Reset muss 3mal hintereinander gesendet werden zur Initialisierung
    lcd_out( LCD_SOFT_RESET );
    _delay_ms( LCD_SOFT_RESET_MS1 );

    lcd_enable();
    _delay_ms( LCD_SOFT_RESET_MS2 );

    lcd_enable();
    _delay_ms( LCD_SOFT_RESET_MS3 );

    // 4-bit Modus aktivieren
    lcd_out( LCD_SET_FUNCTION |
             LCD_FUNCTION_4BIT );
    _delay_ms( LCD_SET_4BITMODE_MS );

    // 4-bit Modus / 2 Zeilen / 5x7
    lcd_command( LCD_SET_FUNCTION |
                 LCD_FUNCTION_4BIT |
                 LCD_FUNCTION_2LINE |
                 LCD_FUNCTION_5X7 );

    // Display ein / Cursor aus / Blinken aus
    lcd_command( LCD_SET_DISPLAY |
                 LCD_DISPLAY_ON |
                 LCD_CURSOR_OFF |
                 LCD_BLINKING_OFF);

    // Cursor inkrement / kein Scrollen
    lcd_command( LCD_SET_ENTRY |
                 LCD_ENTRY_INCREASE |
                 LCD_ENTRY_NOSHIFT );

    lcd_clear();
}

// Sendet ein Datenbyte an das LCD
void lcd_data( uint8_t data )
{
    LCD_PORT |= (1<<LCD_RS);    // RS auf 1 setzen

    lcd_out( data );            // zuerst die oberen,
    lcd_out( data<<4 );         // dann die unteren 4 Bit senden

    _delay_us( LCD_WRITEDATA_US );
}

// Sendet einen Befehl an das LCD
void lcd_command( uint8_t data )
{
    LCD_PORT &= ~(1<<LCD_RS);    // RS auf 0 setzen

    lcd_out( data );             // zuerst die oberen,
    lcd_out( data<<4 );           // dann die unteren 4 Bit senden

    _delay_us( LCD_COMMAND_US );
}

// Sendet den Befehl zur Löschung des Displays
void lcd_clear( void )
{
    lcd_command( LCD_CLEAR_DISPLAY );
    _delay_ms( LCD_CLEAR_DISPLAY_MS );
}

// Sendet den Befehl: Cursor Home
void lcd_home( void )
{
    lcd_command( LCD_CURSOR_HOME );
    _delay_ms( LCD_CURSOR_HOME_MS );
}

// Setzt den Cursor in Spalte x (0..15) Zeile y (1..4)

void lcd_setcursor( uint8_t x, uint8_t y )
{
    uint8_t data;

    switch (y)
    {
        case 1:    // 1. Zeile
            data = LCD_SET_DDADR + LCD_DDADR_LINE1 + x;
            break;

        case 2:    // 2. Zeile
            data = LCD_SET_DDADR + LCD_DDADR_LINE2 + x;
            break;

        case 3:    // 3. Zeile
            data = LCD_SET_DDADR + LCD_DDADR_LINE3 + x;
            break;

        case 4:    // 4. Zeile
            data = LCD_SET_DDADR + LCD_DDADR_LINE4 + x;
            break;

        default:
            return;                                   // für den Fall einer falschen Zeile
    }

    lcd_command( data );
}

// Schreibt einen String auf das LCD

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

// Schreibt ein Zeichen in den Character Generator RAM

void lcd_generatechar( uint8_t code, const uint8_t *data )
{
    // Startposition des Zeichens einstellen
    lcd_command( LCD_SET_CGADR | (code<<3) );

    // Bitmuster übertragen
    for ( uint8_t i=0; i<8; i++ )
    {
        lcd_data( data[i] );
    }
}


und in den Headerdatein steht folgendes:
uint8_t GetADC_8bit(uint8_t Chanel);

// Ansteuerung eines HD44780 kompatiblen LCD im 4-Bit-Interfacemodus
// http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung
//
 
#ifndef LCD_ROUTINES_H
#define LCD_ROUTINES_H
 
////////////////////////////////////////////////////////////////////////////////
// Hier die verwendete Taktfrequenz in Hz eintragen, wichtig!
 
#ifndef F_CPU
#define F_CPU 8000000
#endif
 
////////////////////////////////////////////////////////////////////////////////
// Pinbelegung für das LCD, an verwendete Pins anpassen
// Alle LCD Pins müssen an einem Port angeschlossen sein und die 4
// Datenleitungen müssen auf aufeinanderfolgenden Pins liegen
 
//  LCD DB4-DB7 <-->  PORTD Bit PD0-PD3
#define LCD_PORT      PORTC
#define LCD_DDR       DDRC
#define LCD_DB        PC2
 
//  LCD RS      <-->  PORTD Bit PD4     (RS: 0=Data, 1=Command)
#define LCD_RS        PC6
 
//  LCD EN      <-->  PORTD Bit PD5     (EN: 1-Impuls für Daten)
#define LCD_EN        PC7
 
////////////////////////////////////////////////////////////////////////////////
// LCD Ausführungszeiten (MS=Millisekunden, US=Mikrosekunden)
 
#define LCD_BOOTUP_MS           15
#define LCD_ENABLE_US           1
#define LCD_WRITEDATA_US        46
#define LCD_COMMAND_US          42
 
#define LCD_SOFT_RESET_MS1      5
#define LCD_SOFT_RESET_MS2      1
#define LCD_SOFT_RESET_MS3      1
#define LCD_SET_4BITMODE_MS     5
 
#define LCD_CLEAR_DISPLAY_MS    2
#define LCD_CURSOR_HOME_MS      2
 
////////////////////////////////////////////////////////////////////////////////
// Zeilendefinitionen des verwendeten LCD
// Die Einträge hier sollten für ein LCD mit einer Zeilenlänge von 16 Zeichen passen
// Bei anderen Zeilenlängen müssen diese Einträge angepasst werden
 
#define LCD_DDADR_LINE1         0x00
#define LCD_DDADR_LINE2         0x40
#define LCD_DDADR_LINE3         0x10
#define LCD_DDADR_LINE4         0x50
 
////////////////////////////////////////////////////////////////////////////////
// Initialisierung: muss ganz am Anfang des Programms aufgerufen werden.
void lcd_init( void );
 
////////////////////////////////////////////////////////////////////////////////
// LCD löschen
void lcd_clear( void );
 
////////////////////////////////////////////////////////////////////////////////
// Cursor in die 1. Zeile, 0-te Spalte
void lcd_home( void );
 
////////////////////////////////////////////////////////////////////////////////
// Cursor an eine beliebige Position 
void lcd_setcursor( uint8_t spalte, uint8_t zeile );
 
////////////////////////////////////////////////////////////////////////////////
// Ausgabe eines einzelnen Zeichens an der aktuellen Cursorposition 
void lcd_data( uint8_t data );
 
////////////////////////////////////////////////////////////////////////////////
// Ausgabe eines Strings an der aktuellen Cursorposition 
void lcd_string( const char *data );
 
////////////////////////////////////////////////////////////////////////////////
// Definition eines benutzerdefinierten Sonderzeichens.
// data muss auf ein Array[5] mit den Spaltencodes des zu definierenden Zeichens
// zeigen
void lcd_generatechar( uint8_t code, const uint8_t *data );
 
////////////////////////////////////////////////////////////////////////////////
// Ausgabe eines Kommandos an das LCD.
void lcd_command( uint8_t data );
 
 
////////////////////////////////////////////////////////////////////////////////
// LCD Befehle und Argumente.
// Zur Verwendung in lcd_command
 
// Clear Display -------------- 0b00000001
#define LCD_CLEAR_DISPLAY       0x01
 
// Cursor Home ---------------- 0b0000001x
#define LCD_CURSOR_HOME         0x02
 
// Set Entry Mode ------------- 0b000001xx
#define LCD_SET_ENTRY           0x04
 
#define LCD_ENTRY_DECREASE      0x00
#define LCD_ENTRY_INCREASE      0x02
#define LCD_ENTRY_NOSHIFT       0x00
#define LCD_ENTRY_SHIFT         0x01
 
// Set Display ---------------- 0b00001xxx
#define LCD_SET_DISPLAY         0x08
 
#define LCD_DISPLAY_OFF         0x00
#define LCD_DISPLAY_ON          0x04
#define LCD_CURSOR_OFF          0x00
#define LCD_CURSOR_ON           0x02
#define LCD_BLINKING_OFF        0x00
#define LCD_BLINKING_ON         0x01
 
// Set Shift ------------------ 0b0001xxxx
#define LCD_SET_SHIFT           0x10
 
#define LCD_CURSOR_MOVE         0x00
#define LCD_DISPLAY_SHIFT       0x08
#define LCD_SHIFT_LEFT          0x00
#define LCD_SHIFT_RIGHT         0x01
 
// Set Function --------------- 0b001xxxxx
#define LCD_SET_FUNCTION        0x20
 
#define LCD_FUNCTION_4BIT       0x00
#define LCD_FUNCTION_8BIT       0x10
#define LCD_FUNCTION_1LINE      0x00
#define LCD_FUNCTION_2LINE      0x08
#define LCD_FUNCTION_5X7        0x00
#define LCD_FUNCTION_5X10       0x04
 
#define LCD_SOFT_RESET          0x30
 
// Set CG RAM Address --------- 0b01xxxxxx  (Character Generator RAM)
#define LCD_SET_CGADR           0x40
 
#define LCD_GC_CHAR0            0
#define LCD_GC_CHAR1            1
#define LCD_GC_CHAR2            2
#define LCD_GC_CHAR3            3
#define LCD_GC_CHAR4            4
#define LCD_GC_CHAR5            5
#define LCD_GC_CHAR6            6
#define LCD_GC_CHAR7            7
 
// Set DD RAM Address --------- 0b1xxxxxxx  (Display Data RAM)
#define LCD_SET_DDADR           0x80
 
#endif 


Gruß Bro

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Andi ... (xaos)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
hier mal nen paar screens aus na ppt von letztem jahr..

Autor: Brocken Sei (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Brocken Sei (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: Tobi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank Karl-Heinz, besser kann man es nicht beschreiben.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.