mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Code Optimieren


Autor: Sonke A. (soeni)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wie kann man den generell einen code auf speicherplatz optimieren? ich 
bin relativer neuling im uC Programmieren und habe mal ebend einen 
kleinen robotterarm gebaut. nix dolles, zwei servos und ein magnet. ich 
programmiere in c und sehe jezt nix, was den code übermäßig aufbläht. 
ich hab schon gelesen, dass man variablen am besten lokal definiert um 
so speicherplatz zu sparen, gibts da noch weitere einfache regeln? siend 
die vielleicht irgendwo aufgelistet zu finden?

Danke Schonmal im Voraus

Sönke

PS: Hier mein code (6504 bytes von 8000 ca. 80% im flash laut compiler):
#include <stdint.h>
#include <avr/io.h> 
#include <avr/interrupt.h>
#include <math.h>

#define __OPTIMIZE__ // Code Optimieren für richtige verzögerungszeit

#define F_CPU 8000000

#define RESET_X 230
#define RESET_Y 230

#define POINT 20


#include <util/delay.h>

// Servo Frame-Time:
#define FRAME_TIME 20 // msec



uint8_t horz, vert, i=0, mgn;



struct {
uint8_t x;
uint8_t y;
uint8_t mgn;
}point[POINT];




int play(){

uint8_t z=0, a, x, y;


x=vert;
y=horz;

  while((PINB & (1 << 4))){  // stoptaste gedrückt?

  
   if(z >= (POINT+1)){  // wenn zyklus zuende von vorne beginnen
   z=0;
   }


   if(point[z].x <= 10){ 
     z=0;
   }              // Wenn kein Punkt gesetzt von vorne  beginnen

   if(point[z].y <= 10){
     z=0;
   }
  
   a=0;


   while(a==0){
 
     if(x==point[z].x){
   a=1;
   }else{
      


    if(x > point[z].x) x--;
        if(x < point[z].x) x++;  //(annähern)
    a=0;

      OCR1A  = x*10;    // set Servo 1 to xms-position
     }

      _delay_ms(10);

     if(y==point[z].y){
     
   }else{

    if(y > point[z].y) y--;
        if(y < point[z].y) y++;
    a=0;

       OCR1B  = y*10;    // set Servo 2 to xms-position
     }
  
   }
   
   // Magnetsteuerung (an aus)
   if(point[z].mgn==0){
     //PORTD |= (1 << 2);    /* setzt Bit 1 an PortD auf 1 */  // Lampe
     PORTE &= ~(1 << 0);   /* loescht Bit 0 an PortB */
   }else{
   PORTE |= (1 << 0);    /* setzt Bit 0 an PortB auf 1 */
     //PORTD &= ~(1 << 2);   /* loescht Bit 0 an PortD */      // Lampe
   }




   x=point[z].x;
   y=point[z].y;

   z++;

   if(x==point[z].x && y==point[z].y){
   
       _delay_ms(1000);  // wenn zweimal der gleiche Punkt dann warten

   }
  }

return 0;
}






int main(void) {

//Pin Konfiguration
DDRB = 0x00; //PORT B als Eingang
DDRD = 0xFF; //PORT D als Ausgang
DDRE = 0xFF; //PORT E als Ausgang

PORTD |= (1 << 0);    /* setzt Bit 0 an PortD auf 1 */
PORTD |= (1 << 1);    /* setzt Bit 1 an PortD auf 1 */
PORTD |= (1 << 2);    /* setzt Bit 1 an PortD auf 1 */


// init timer 1:
ICR1   = FRAME_TIME * 1000;                      // PWM cycle time in usec
TCCR1A = (1<<COM1A1) | (1<<COM1B1) | (1<<WGM11); // OC1A/B clr on match, set on TOP
TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS11);    // TOP = ICR1, clk = sysclk/8 (->1us)
TCNT1  = 0;                                      // reset Timer

OCR1A  = 1000;    // set Servo 1 to 1ms-position

_delay_ms(10);

OCR1B  = 1000;    // set Servo 1 to 1ms-position
            
//_delay_ms(1000);

vert = 100;

horz = 100;

mgn=0;

loop:

while(1==1){

  if(!(PINB & (1 << 0))){  // bit 0 wird abgefragt gesezt
 

     vert--;

   if(vert <= 0x32){  // fa == 250
   vert=0x32;
   }


   OCR1A  = vert*10;    // set Servo 1 to xms-position

 
  }

  if(!(PINB & (1 << 1))){  // bit 1 wird abgefragt gesezt
  

     vert++;


   if(vert >= 0xFA){
   vert=0xFA;
   }

   OCR1A  = vert*10;    // set Servo 1 to xms-position

 
  }
  // Horizontale bewegung runter
  if(!(PINB & (1 << 2))){  // bit 2 wird abgefragt gesezt
 

     horz--;

   if(horz <= 0x32){  // fa == 250
   horz=0x32;
   }


   OCR1B  = horz*10;    // set Servo 2 to xms-position

 
  }
  // Horizontale bewegung rauf
  if(!(PINB & (1 << 3))){  // bit 3 wird abgefragt gesezt
  

     horz++;


   if(horz >= 0xFA){
   horz=0xFA;
   }

   OCR1B  = horz*10;    // set Servo 2 to xms-position

 
  }
  //Magnet an/aus
  if(!(PINB & (1 << 4))){  // bit 4 wird abgefragt gesezt
  


   if(mgn==1){
     mgn=0;
     PORTD |= (1 << 2);    /* setzt Bit 1 an PortD auf 1 */  // Lampe
     PORTE &= ~(1 << 0);   /* loescht Bit 0 an PortE */      // Magnet
   }else{
     mgn=1;
     PORTD &= ~(1 << 2);   /* loescht Bit 0 an PortD */      // Lampe
     PORTE |= (1 << 0);    /* setzt Bit 0 an PortE auf 1 */  // Magnet
   }


  _delay_ms(500);   // Zum Entprellen Warten

 
  }

// Steuerung fertig

// Speicher löschen (Interner Reset)

  if(!(PINB & (1 << 7))){  // bit 7 wird abgefragt gesezt
  

     horz=RESET_Y;
   vert=RESET_X;

   OCR1A  = vert*10;    // set Servo 1 to xms-position

     _delay_ms(10);

   OCR1B  = horz*10;    // set Servo 2 to xms-position

   

   while(i>=1){  // Löschen der Punkte
   point[i].x=0;
   point[i].y=0;
   point[i].mgn=0;
   i--;
   }
 
  }

   //Schritt speichern
  if(!(PINB & (1 << 6))){  // bit 6 wird abgefragt gesezt
  

   

   point[i].x=vert;
   point[i].y=horz;
   point[i].mgn=mgn;
   i++;
   if(i>=POINT){
   i=POINT;
   }
   PORTD &= ~(1 << 1);   /* loescht Bit 0 an PortB */

     _delay_ms(1000);

     PORTD |= (1 << 1);    /* setzt Bit 0 an PortB auf 1 */  
 
  }


   // Abfrage desd Playtasters
  if(!(PINB & (1 << 5))){  // bit 5 wird abgefragt gesezt
  

  play();

  PORTD &= ~(1 << 1);   /* loescht Bit 0 an PortB */

 

     horz=RESET_Y;
   vert=RESET_X;

   OCR1A  = vert*10;    // set Servo 1 to xms-position

     _delay_ms(10);

   OCR1B  = horz*10;    // set Servo 2 to xms-position

  PORTD |= (1 << 1);    /* setzt Bit 0 an PortB auf 1 */   
 
  goto loop;

  }

_delay_ms(50);   // Zum Entprellen Warten

}
  
return 0;
}


Autor: Ulrich (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wird mit -Os compiliert?
Ansonsten sieht der Code schonmal gar nicht so schlecht aus. Sollte aber 
normalerweise kürzer sein.

ich lasse mir immer mit diesem Befehl:
avr-nm --size-sort --print-size *elf
anzeigen welches objekt wieviel speicher braucht

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich vermute, du kompilierst den Code ohne Optimierung, und hast ein
#define __OPTIMIZE__
drinnen, um genau die Warnung deswegen auszublenden...


Also, #define raus, und echte Optimierung einschalten.

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

Bewertung
0 lesenswert
nicht lesenswert
Hast du die Compileroptimierung eingeschaltet?

~6KB für diesen Code kommen mir aus dem Bauch heraus
reichlich viel vor.

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Welchen Prozessor und welche Compilerversion nutzt du denn?

Nur so zum Vergleich mit WinAVR20071221 für einen Mega128:
Program:    4458 bytes ohne Optimierung (-O0)
Program:     960 bytes mit Optimierung auf Größe (-Os)

>#define _OPTIMIZE_ // Code Optimieren für richtige verzögerungszeit

???

Oliver

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Oliver:

>>#define _OPTIMIZE_ // Code Optimieren für richtige verzögerungszeit
>
> ???

die delay.h schreibt ne böse Warnung, wenn man versucht _delay_ms OHNE 
Optimierung zu verwenden...
mit dem #define wird man die Warnung los, aber das Problem besteht 
natürlich fort...

Autor: Sonke A. (soeni)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wie schaltet man die den ein, ich dachte man macht das durch #define 
_OPTIMIZE_ wie den sonst?

habe einen atmega 8515

softwareversionen (avr studio)

AVR Studio    4.13.528
GUI Version    4, 13, 0, 528
AVR Simulator    1, 0, 2, 0
ATmega8515    222

Operating System
Major      5
Minor      1
PlatformID    2
Build      2600
Service Pack 3

Plugins:

AvrPluginAvrAsmObject  1, 0, 0, 45
AvrPluginavrgccplugin  1, 0, 0, 7
Stk500Dll      1, 0, 1, 0

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

Bewertung
0 lesenswert
nicht lesenswert
Im AVR Studio gibt es Menü einen Menüpunkt
 "Project" / "Configuration Options"

Im Dialog, der sich daraufhin öffnet, ist ziemlich weit
unten die Einstellung für Optimierung "Optimization".
Die stellst du mal auf -Os

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
nein, _OPTIMIZE_ wird vom Compiler automatisch definiert, wenn man die 
Optimierung eingeschaltet hat...
Zum "echten" Einschalten bei den Compiler-Optionen einfach -O0 durch -O2 
oder -Os ersetzen. (bzw. Hinzufügen, wenn -O0 nicht vorkommt)

Grundsätzlich sind Funktionen und #defines, die mit einem Unterstrich 
anfangen erstmal tabu für den Programmierer, und sollten nur eingesetzt 
werden, wenn man wirklich weiß, was man tut.

"_delay_ms" startet z.B. mit einem _, um den Anwender mitzuteilen: 
"Achtung, diese Funktion verhält sich evtl. nicht wie erwartet, braucht 
besondere Rahmenbedingungen, etc => Dokumentation aufmerksam lesen"

Autor: Sonke A. (soeni)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke code ist jezt be ca. 850 bytes so ist das ok

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.