-         

Ergebnis 1 bis 5 von 5

Thema: Programmgrösse AVR_GCC

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    13.04.2008
    Beiträge
    34

    Programmgrösse AVR_GCC

    Anzeige

    Hallo an Alle!

    Ich spiele mit dem Gedanken, dass ich von Bascom auf GCC umsteige. Ich habe mein erstes Programm geschrieben, funktioniert bestens, nur wird für diese Winzprogramm 4200Byte im Controller benötigt!
    Code:
    //*************************************************************************
    //Title:    AnalogDigitalConverter
    //Author:    
    //File:     Analogwert_01.c 
    //Software: AVR-Studio 4.15
    //Hardware: AVR with built-in UART, tested on ATMEGA8 at 8 Mhz 
    //
    //DESCRIPTION:
    //          Beispielprogramm für den Gebrauch der  "uart.h"
    //
    //************************************************************************* 
    #include <stdlib.h>
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <util/delay.h>
    
    #include "uart.h"               // einbinden uart.h 
    #define XTAL 8000000UL          // festlegen der CPU - Frequenz in Mhz 
    #define UART_BAUD_RATE 9600     // 9600 baud für RS232 
    
    //----------------------------------------------------------------------- 
    // Deklaration der Konstanten / Variablen  
    //----------------------------------------------------------------------- 
    
    
    //----------------------------------------------------------- 
    //AnalogSpannung messen
    //----------------------------------------------------------- 
    //ADCMUX:   00 1 0 , 0000
    //          Bit 7:6 – REFS1:0: Reference Selection Bits 
    //          Bit 5   – ADLAR: ADC Left Adjust Result
    //          Bit 3:0 – MUX3:0: Analog Channel Selection Bits
    //
    //ADCSRA:   1110,0010
    //          Bit 7 – ADEN: ADC Enable
    //          Bit 6 – ADSC: ADC Start Conversion
    //          Bit 5 – ADFR: ADC Free Running Select
    //          Bit 4 – ADIF: ADC Interrupt Flag
    //          Bit 3 – ADIE: ADC Interrupt Enable
    //          Bits 2:0 – ADPS2:0: ADC Prescaler Select Bits 
    //--------------------------------------------------------------  
    void init(void)
    {
    
        //---------------------------------------------------
    //Pins bzw. Ports als Ein-/Ausgänge konfigurieren //---------------------------------------------------
        DDRB |= 0x00;	//00000000 -> Eingänge - nicht verwendet
        DDRC |= 0x00;	//00000000 -> alle Analogports als Eingänge
        DDRD |= 0x00;	//00000000 -> Eingänge - nicht verwendet
    
        ADMUX |= (0<<REFS1) | (1<<REFS0);                       // interne Referenzspannung nutzen!!
        ADCSRA = (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);          // Frequenzvorteiler 
    
        uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,XTAL) );     // Initialisieren der UART-Library durch Übergabe der baudrate und XTAL  
        sei();                                                  // interrupt freigeben 
    
    } 
     
    //----------------------------------------------------------- 
    //AnalogSpannung messen
    //----------------------------------------------------------- 
    //ADCMUX:   00 1 0 , 0000
    //          Bit 7:6 – REFS1:0: Reference Selection Bits 
    //          Bit 5   – ADLAR: ADC Left Adjust Result
    //          Bit 3:0 – MUX3:0: Analog Channel Selection Bits
    //
    //ADCSRA:   1110,0010
    //          Bit 7 – ADEN: ADC Enable
    //          Bit 6 – ADSC: ADC Start Conversion
    //          Bit 5 – ADFR: ADC Free Running Select
    //          Bit 4 – ADIF: ADC Interrupt Flag
    //          Bit 3 – ADIE: ADC Interrupt Enable
    //          Bits 2:0 – ADPS2:0: ADC Prescaler Select Bits 
    //--------------------------------------------------------------  
    uint16_t ReadChannel(uint8_t mux)
    {
        uint8_t byZeiger;                   //Zeiger Schleife
        uint16_t result;                    //Messwert
        //----------------------------
    
        ADMUX = (ADMUX&0xF0)|mux;           // Kanal festlegen
        ADCSRA = (1<<ADEN) | (1<<ADSC);     // Aktivieren des ADC und erste ADC-Wandlung auslesen
        while ( ADCSRA & (1<<ADSC) ) {;}    // auf Abschluss der Konvertierung warten     
        result = ADCW;                      // ADCW muss einmal gelesen werden,
        result = 0;                         //Zwischenpeicher leeren
    
    
        //ADC 4mal einlesen uns Mittelwert bilden
        for( byZeiger=0; byZeiger<4; byZeiger++ )
        {
            ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
            while ( ADCSRA & (1<<ADSC)) {;} // auf Abschluss der Konvertierung warten
            result += ADCW;                 // Wandlungsergebnisse aufaddieren
        }
    
        ADCSRA &= ~(1<<ADEN);               // ADC deaktivieren (2)
        result /= 4;                        // Summe durch vier teilen = arithm. Mittelwert
        return result;
    }
    
    
    //----------------------------------------------------------------------- 
    // Hauptprogramm
    //----------------------------------------------------------------------- 
    int main(void)
    {
    const float rDigitADC   = 0.0048828125;	//Referenzwert zur Multiplikation mit den Werten der Analogports (5/1024)
    char buffer[7];             //Array für Aussgabe Daten über UART
    uint16_t wAnalog;            //Variable für jeweils an einem Analogport gemessenen Wert 
     
        init(); //Initialisierung 
        //----------------------------------------------------------------------- 
        // Hauptschleife 
        //----------------------------------------------------------------------- 
        while (1)        
    	{
     
            // 1 Sekunde warten 
            _delay_ms(1000); 
             
            wAnalog = ReadChannel(1);       //ADC_0 einlesen
    
     
            utoa( wAnalog, buffer, 10);     // konvertieren interger nach String (decimal format)         
            uart_puts(buffer);              // übertrage string an UART library
            uart_puts("  - Digit \n");
    
        	dtostrf(wAnalog * rDigitADC, 11, 8, buffer);    //Spannung umrechnen	
            uart_puts(buffer);  
            uart_puts(" Volt\r\n\n");
        }
    }
    Selbst wenn ich alles für die Ausgabe über UART weg lasse, werden noch immer >3800Byte benötigt. Das vergleichbare Programm mit Bascom kommt fast mit dem halben Speicherplatz aus.
    Code:
    Build started 11.2.2009 at 21:56:22
    avr-gcc  -mmcu=atmega8 -Wall -gdwarf-2 -std=gnu99 -DF_CPU=8000000UL -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums  -Os  -MD -MP -MT Analogwert_01.o -MF dep/Analogwert_01.o.d  -c  ../Analogwert_01.c
    avr-gcc -mmcu=atmega8 -Wl,-Map=Analogwert_01.map Analogwert_01.o uart.o     -o Analogwert_01.elf
    avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature  Analogwert_01.elf Analogwert_01.hex
    avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O ihex Analogwert_01.elf Analogwert_01.eep || exit 0
    avr-objdump -h -S Analogwert_01.elf > Analogwert_01.lss
    
    AVR Memory Usage
    ----------------
    Device: atmega8
    
    Program:    4192 bytes (51.2% Full)
    (.text + .data + .bootloader)
    
    Data:        333 bytes (32.5% Full)
    (.data + .bss + .noinit)
    
    Build succeeded with 0 Warnings...
    Die Optimierung habe ich bereits auf -Os gestellt.
    Gibt es da noch möglichkeiten zur Speicheroptimierung?

    Danke

  2. #2
    Erfahrener Benutzer Robotik Einstein Avatar von Felix G
    Registriert seit
    29.06.2004
    Ort
    49°32'N 8°40'E
    Alter
    34
    Beiträge
    1.780
    Ich würde mal sagen der enorme Platzbedarf kommt von dtostrf...

    gerade bei solchen Funktionen sollte man schon genau überlegen ob man sie wirklich braucht, oder ob es nicht auch platzsparende Alternativen gibt (prinf und scanf z.B. gehören auch in die Kategorie der Speicherfresser)
    So viele Treppen und so wenig Zeit!

  3. #3
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    Die Größe resultiert aus dem Benutzen von Gleitkommaarithmetik ohne Verwendung der entsprechenden Library (-lm).
    MfG
    Stefan

  4. #4
    Benutzer Stammmitglied
    Registriert seit
    13.04.2008
    Beiträge
    34
    Ich danke euch beiden!!

    Bereits das einbinden der libm.a spart >1500Byte und das weglassen der dtostrf spart > 3000Byte.

    Jetzt ist wieder Licht in Sicht!


    Danke

    Vbxler

  5. #5
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    Zitat Zitat von Vbxler
    das weglassen der dtostrf spart > 3000Byte.
    Ja, aber nicht das Weglassen der Funktion an sich spart diese große Menge, sondern der dadurch entstehende Verzicht auf Gleitkommaarithmetik im allgemeinen.
    MfG
    Stefan

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •