- Akku Tests und Balkonkraftwerk Speicher         
Seite 1 von 3 123 LetzteLetzte
Ergebnis 1 bis 10 von 22

Thema: Hilfe! Programm zu groß trotz aktivierter Optimierung!

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    12.06.2007
    Beiträge
    42

    Hilfe! Programm zu groß trotz aktivierter Optimierung!

    Anzeige

    Praxistest und DIY Projekte
    Hallo!

    Ich möchte in meinem Progamm zu Testzwecken die Funktion sprintf() verwenden. Jedoch habe ich auf dem tiny2313 nur 2K Programmspeicher zur Verfügung, und nach Einbau von sprintf() wird diese Grenze gesprengt und der Compiler verweigert den Dienst.

    Ich poste einfach mal meinen ganzen Code. Vielleicht hat ja irgend jemand noch eine Idee, wie ich das Programm kleiner bekomme, ohne Funktionalität einbüßen zu müssen. Mir fällt da leider nichts mehr ein.

    Ich bin sicher, dass man für die Konvertierung von int nach char[] auch andere Wege als sprintf() gehen könnte, aber es geht mir eher um die Optimierung des restlichen Codes. Schließlich ist das Programm ohne sprintf() schon bei ca. 1800 Bytes. Das ist zuviel und müsste doch irgendwie verkleinert werden können.

    Die Compiler-Option zur Optimierung ist natürlich eingestellt ("-0s", habe alle ausprobiert).

    Falls sich jemand wirklich die Qual antut, den kompletten Code nach Möglichkeiten zu durchforsten, dann VIELEN, VIELEN DANK!

    Code:
    #ifndef F_CPU
    	#define F_CPU 4000000
    #endif
    #ifndef UART_BAUD_RATE
    	#define UART_BAUD_RATE 9600
    #endif
    //
    #include <avr/io.h>
    #include <avr/eeprom.h>
    #include <stdio.h>
    #include <util/delay.h>
    /*
    #include <avr/interrupt.h>
    #include <stdint.h>
    #include <stdbool.h>
    */
    //
    //PROTOTYPEN
             void myWait(unsigned int iX);
     unsigned int myPot2(unsigned int iExp);
             void USART_init(unsigned int baud);
             void USART_transmit(unsigned char cData);
             void USART_transmit_str(char *cStr);
             void long_delay_ms( unsigned long ms );
    
    
    /***************/
    int main(void) {
    /***************/
      unsigned short int i = 0;
    /*
    	unsigned short int iBin = 0;
            unsigned int iWait = 12000;
            unsigned int iIncr = 100;
            unsigned int iWaitMax = 8000;
            unsigned int iWaitMin = 2000;
                    bool bWaitGoesDown = true;
                    bool bDirIsLeft = true;
            unsigned int iEEPROM_index = 0;
    */
                    char *cUSART_inp = NULL;
      unsigned short int iUSART_inp = 0;
      unsigned long iTest=0;
      unsigned char cZahl[3] = {0};
    	//
    	DDRB = 0xff;	//Port B Pins als Ausgänge definieren
    	PORTB = 0xff;
    	//DDRD = 0x00;	//Port D Pins als Eingänge definieren. Wohl nicht notwendig, da die Bits standardmäßig sowieso 0 sind
    	//
    	USART_init(UART_BAUD_RATE);
    	//
    	for(;;) {
    		//
        if( iTest++ % 500 == 0 ) {
          USART_transmit('.');
        }
        //
    		if( UCSRA & (1<<RXC) ) {	//Zeichen werden empfangen und im char-array gespeichert
          cUSART_inp = (char *)realloc( cUSART_inp , (++iUSART_inp) * sizeof(char) );
          cUSART_inp[iUSART_inp-1] = UDR;
    		}
        //
        if( !(PIND & (1<<PIND2)) && iUSART_inp>0) {    //SW0 gedrückt
          for(i=0;i<iUSART_inp;i++) {
            eeprom_write_byte(i,cUSART_inp[i]);  //char-array (cUSART_inp) in EEPROM speichern
          }
          //
          free(cUSART_inp);   //char-array löschen, aber nicht den Index iUSART_inp, da dieser
          cUSART_inp = NULL;  //beim Zurücklesen gebraucht wird.
          //
          USART_transmit_str(" SAVED ");
          long_delay_ms(200);  //wartet 1 Sek, nicht 200 MSek... warum auch immer...
        }
        //
        if( !(PIND & (1<<PIND3)) && iUSART_inp>0) {    //SW1 gedrückt
          cUSART_inp = (char *)realloc( cUSART_inp , (iUSART_inp) * sizeof(char) );
          //
          sprintf(cZahl,"%i",iUSART_inp);
          USART_transmit_str("iUSART_inp: " + *cZahl);
          //
          for(i=0;i<iUSART_inp;i++) {
            cUSART_inp[i] = eeprom_read_byte(i);  //Inhalt des EEPROMs rurück in das char-array schreiben
          }
          //
          USART_transmit_str(cUSART_inp);
          //
          free(cUSART_inp);   //string wurde auf Terminal ausgegeben, daher char-array
          cUSART_inp = NULL;  //und Index zurücksetzen
          iUSART_inp = 0;
        }
    		//
        //
        // Hier folgen ein Lauflicht und diverse Möglichkeiten, dieses zu beeinflussen.
        // Zum Testen von USART- und EEPROM-Funktionen ist dieser Teil auskommentiert.
        //
    /*
    		// SW0:
    		while( !(PIND & (1 << PIND2)) ) {
    			;// Lauflicht anhalten, wenn SW0 gedrückt ist
    		}
    		//
    		// SW1:
    		if( !(PIND & (1 << PIND3)) ) {	//Laufrichtung ändern, wenn SW1 gedrückt wird
    			if( bDirIsLeft ) {
    				bDirIsLeft = false;
    				iBin = 8;
    			}else {
    				bDirIsLeft = true;
    				iBin = 0;
    			}
    			myWait(1000);
    		}
    		//
    		// SW2:
    		while( !(PIND & (1 << PIND4)) ) {	//perfektes Disco-Licht auf SW2 !
    			PORTB = 0x00;
    			myWait(2500);
    			PORTB = 0xff;
    			myWait(2500);
    		}
    		//
    		// SW3:	
    		if( !(PIND & (1 << PIND5)) ) {		//auf SW3 soll per USART ans Terminal gesendet werden
    			//
          USART_transmit('U');
    			USART_transmit('S');
    			USART_transmit('A');
    			USART_transmit('R');
    			USART_transmit('T');
    			USART_transmit(' ');
    			USART_transmit('T');
    			USART_transmit('E');
    			USART_transmit('S');
    			USART_transmit('T');
    		}
    		//
    		if( bDirIsLeft ) {		//hier wird die LED verschoben, abhängig von der Laufrichtung
    			PORTB = 0xff - myPot2(iBin++);
    			if( iBin==8 ) {
    				iBin=0;
    			}
    		}else {
    			PORTB = 0xff - myPot2(--iBin);
    			if( iBin==0 ) {
    				iBin=8;
    			}
    		}
    		//
    		myWait(iWait);
    		//
    		if( bWaitGoesDown ) {
    			if( iWait < iWaitMin+500 ) {
    				iIncr = 20;
    			}
    			if( iWait > iWaitMin ) {
    				iWait	-= iIncr;
    			}else {
    				bWaitGoesDown=false;
    			}
    		}else {
    			if( iWait > iWaitMin ) {
    				iIncr = 100;
    			}
    			if( iWait < iWaitMax ) {
    				iWait += iIncr;
    			}else {
    				bWaitGoesDown=true;
    			}
    		}
    */
    	}
    	//
    	return 0;
    }
    
    /***************/
    unsigned int myPot2(unsigned int iExp) {  //potenziert die Basis 2 mit dem Exponenten iExp
    /***************/
    	unsigned short int i,iErg;
    	iErg = 1;
    	for(i=0;i<iExp;i++) {
    		iErg = iErg * 2;
    	}
    	return iErg;
    
    }
    
    /***************/
    void long_delay_ms( volatile unsigned long ms ) {
    /***************/
      while( ms-- )
        _delay_ms( 1 );
    }
    
    /***************/
    void USART_init(unsigned int baud) {    //nochmal genau ansehen und schöner formulieren!
    /***************/
    /*
    UBRRH = (unsigned char)(baud>>8);		//Baudrate setzen
    UBRRL = (unsigned char)baud;				//
    //
    UCSRB = (1<<RXEN)|(1<<TXEN);		//Receiver und Transmitter aktivieren
    //
    UCSRC = (1<<USBS)|(3<<UCSZ0);	//8 Datenbits, 2 Stopbits (?)
    */
    UCSRA=0x00;
    //UCSRB=0x08;
    UCSRC=0x86;
    UBRRH=0x00;
    UBRRL=0x17;
    //
    UCSRB = (1<<RXEN)|(1<<TXEN);		//Receiver und Transmitter aktivieren
    }
    
    /***************/
    void USART_transmit(unsigned char cData) {
    /***************/
    	while( !(UCSRA & (1<<UDRE)) ) {
    		;//warten, bis der transmit buffer leer ist, so dass wieder übertragen werden kann
    	}
    	UDR = cData;
    }
    
    /***************/
    void USART_transmit_str(char *cStr) {
    /***************/
      while(*cStr) {
        USART_transmit(*cStr++);
      }
    }

  2. #2
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    10.07.2004
    Ort
    Nürnberg
    Alter
    42
    Beiträge
    186
    Hi,
    probiers mal mit itoa anstatt sprintf!
    Musst halt mal nach itoa googlen da steht wie dus anwendest!
    Ich bin keine Signatur ich mach hier nur sauber

  3. #3
    Benutzer Stammmitglied
    Registriert seit
    12.06.2007
    Beiträge
    42
    Ja, mit itoa() bin ich so gerade im grünen Bereich (2032 von 2048 Bytes belegt).

    Interessanter wäre für mich, wie ich grundsätzlich meinen Code optimieren kann. Ein kleines Programm, dass lediglich eine Eingabe in einem Array und im EEPROM speichert und per Tastendruck wieder ausgibt, sollte doch mit deutlich weniger als 2K zu realisieren sein, oder?

    Das dynamische Array habe ich übrigens enigebaut, da das direkte Schreiben (Zeichen für Zeichen, direkt nach der Eingabe) ins EEPROM nicht wirklich funktioniert hat (es wurden Zeichen ausgelassen...). Nur, damit nicht jemand vorschlägt, eben dieses wegzulassen.

  4. #4
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    10.07.2004
    Ort
    Nürnberg
    Alter
    42
    Beiträge
    186
    Hi,
    Speicheroptimiert Programmieren ist net so einfach, aber wo sich immer was sparen lässt ist bei variablendeklarationen!
    Beispiel: Brauch ich wirklich float für ne Variable die nach True und false abfragt?
    Wenn du am PC Programmierst kann dir des Wurst sein da ist speicherplatz kein Problem!!
    Aber hier musst du etwas aufpassen!
    Viel Erfolg noch
    Ich bin keine Signatur ich mach hier nur sauber

  5. #5
    Benutzer Stammmitglied
    Registriert seit
    12.06.2007
    Beiträge
    42
    Vielen Dank für den Tipp! Ich bin zwar der Meinung, bei den Variablen darauf geachtet zu haben, aber ich lasse mich gerne belehren und werde mich mal eingehend mit dem Thema beschäftigen.

    Gibt's vielleicht einen guten Link zu der Thematik?

    Gruß Matze

  6. #6
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    10.07.2004
    Ort
    Nürnberg
    Alter
    42
    Beiträge
    186
    Hi
    ,
    unter,https://www.roboternetz.de/wissen/in...ial#Datentypen stehen bei Datentypen die Variablen mit Speichergröße und zulässigem Wertebereich!
    Sieht auf den Ersten Blick klein aus wenn man bei ner Variable ein oder 2 Byte spart, aber die spart man pro Aufruf und das summiert sich dann schon!
    Ich bin keine Signatur ich mach hier nur sauber

  7. #7
    Benutzer Stammmitglied
    Registriert seit
    12.06.2007
    Beiträge
    42
    Ok, werd ich mir direkt mal ansehen, vielleicht sind ja noch ein paar Bytes drin.

    VIELEN DANK@zumqwadrad !!

  8. #8
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    15.11.2006
    Beiträge
    463
    Hallo,

    vielleicht kannst du noch etwas einsparen, indem man auf die dynamische Speicherverwaltung mit realloc und free verzichtet und statt dessen ein Array mit statischer Grösse verwendet. Da du im gesamten Programm sowieso nur ein Array brauchst, kannst du dafür einfach den gesamten freien Speicher verwenden.

    Gruss
    Jakob

  9. #9
    Benutzer Stammmitglied
    Registriert seit
    12.06.2007
    Beiträge
    42
    Du hast natürlich Recht. Ich habe gedacht, dass ich nicht weiß, wieviele Zeichen der User eingibt, also muss es ein dynamisches Array sein. Bei einem Maximum von 128 Zeichen (EEPROM beim 2313 ist nicht größer) kann ich auch ein passendes statisches Array verwenden. Danke für den tipp, Jakob, ich werd's gleich mal umbauen!

    Gruß Matze

  10. #10
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    21.10.2005
    Ort
    Erde
    Alter
    57
    Beiträge
    1.195
    iTest brauch nicht long sein. unsinged int reicht (muss ja nur bis 501 zählen können)

    realloc ersetzen wurde ja schon gesagt

    Deklariere die Variablen im kleinstmöglichen scope. Dann kann der Compiler besser optimieren.

Seite 1 von 3 123 LetzteLetzte

Berechtigungen

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

12V Akku bauen