Forum: Mikrocontroller und Digitale Elektronik Code Optimieren


von Sonke A. (soeni)


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):
1
#include <stdint.h>
2
#include <avr/io.h> 
3
#include <avr/interrupt.h>
4
#include <math.h>
5
6
#define __OPTIMIZE__ // Code Optimieren für richtige verzögerungszeit
7
8
#define F_CPU 8000000
9
10
#define RESET_X 230
11
#define RESET_Y 230
12
13
#define POINT 20
14
15
16
#include <util/delay.h>
17
18
// Servo Frame-Time:
19
#define FRAME_TIME 20 // msec
20
21
22
23
uint8_t horz, vert, i=0, mgn;
24
25
26
27
struct {
28
uint8_t x;
29
uint8_t y;
30
uint8_t mgn;
31
}point[POINT];
32
33
34
35
36
int play(){
37
38
uint8_t z=0, a, x, y;
39
40
41
x=vert;
42
y=horz;
43
44
  while((PINB & (1 << 4))){  // stoptaste gedrückt?
45
46
  
47
   if(z >= (POINT+1)){  // wenn zyklus zuende von vorne beginnen
48
   z=0;
49
   }
50
51
52
   if(point[z].x <= 10){ 
53
     z=0;
54
   }              // Wenn kein Punkt gesetzt von vorne  beginnen
55
56
   if(point[z].y <= 10){
57
     z=0;
58
   }
59
  
60
   a=0;
61
62
63
   while(a==0){
64
 
65
     if(x==point[z].x){
66
   a=1;
67
   }else{
68
      
69
70
71
    if(x > point[z].x) x--;
72
        if(x < point[z].x) x++;  //(annähern)
73
    a=0;
74
75
      OCR1A  = x*10;    // set Servo 1 to xms-position
76
     }
77
78
      _delay_ms(10);
79
80
     if(y==point[z].y){
81
     
82
   }else{
83
84
    if(y > point[z].y) y--;
85
        if(y < point[z].y) y++;
86
    a=0;
87
88
       OCR1B  = y*10;    // set Servo 2 to xms-position
89
     }
90
  
91
   }
92
   
93
   // Magnetsteuerung (an aus)
94
   if(point[z].mgn==0){
95
     //PORTD |= (1 << 2);    /* setzt Bit 1 an PortD auf 1 */  // Lampe
96
     PORTE &= ~(1 << 0);   /* loescht Bit 0 an PortB */
97
   }else{
98
   PORTE |= (1 << 0);    /* setzt Bit 0 an PortB auf 1 */
99
     //PORTD &= ~(1 << 2);   /* loescht Bit 0 an PortD */      // Lampe
100
   }
101
102
103
104
105
   x=point[z].x;
106
   y=point[z].y;
107
108
   z++;
109
110
   if(x==point[z].x && y==point[z].y){
111
   
112
       _delay_ms(1000);  // wenn zweimal der gleiche Punkt dann warten
113
114
   }
115
  }
116
117
return 0;
118
}
119
120
121
122
123
124
125
int main(void) {
126
127
//Pin Konfiguration
128
DDRB = 0x00; //PORT B als Eingang
129
DDRD = 0xFF; //PORT D als Ausgang
130
DDRE = 0xFF; //PORT E als Ausgang
131
132
PORTD |= (1 << 0);    /* setzt Bit 0 an PortD auf 1 */
133
PORTD |= (1 << 1);    /* setzt Bit 1 an PortD auf 1 */
134
PORTD |= (1 << 2);    /* setzt Bit 1 an PortD auf 1 */
135
136
137
// init timer 1:
138
ICR1   = FRAME_TIME * 1000;                      // PWM cycle time in usec
139
TCCR1A = (1<<COM1A1) | (1<<COM1B1) | (1<<WGM11); // OC1A/B clr on match, set on TOP
140
TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS11);    // TOP = ICR1, clk = sysclk/8 (->1us)
141
TCNT1  = 0;                                      // reset Timer
142
143
OCR1A  = 1000;    // set Servo 1 to 1ms-position
144
145
_delay_ms(10);
146
147
OCR1B  = 1000;    // set Servo 1 to 1ms-position
148
            
149
//_delay_ms(1000);
150
151
vert = 100;
152
153
horz = 100;
154
155
mgn=0;
156
157
loop:
158
159
while(1==1){
160
161
  if(!(PINB & (1 << 0))){  // bit 0 wird abgefragt gesezt
162
 
163
164
     vert--;
165
166
   if(vert <= 0x32){  // fa == 250
167
   vert=0x32;
168
   }
169
170
171
   OCR1A  = vert*10;    // set Servo 1 to xms-position
172
173
 
174
  }
175
176
  if(!(PINB & (1 << 1))){  // bit 1 wird abgefragt gesezt
177
  
178
179
     vert++;
180
181
182
   if(vert >= 0xFA){
183
   vert=0xFA;
184
   }
185
186
   OCR1A  = vert*10;    // set Servo 1 to xms-position
187
188
 
189
  }
190
  // Horizontale bewegung runter
191
  if(!(PINB & (1 << 2))){  // bit 2 wird abgefragt gesezt
192
 
193
194
     horz--;
195
196
   if(horz <= 0x32){  // fa == 250
197
   horz=0x32;
198
   }
199
200
201
   OCR1B  = horz*10;    // set Servo 2 to xms-position
202
203
 
204
  }
205
  // Horizontale bewegung rauf
206
  if(!(PINB & (1 << 3))){  // bit 3 wird abgefragt gesezt
207
  
208
209
     horz++;
210
211
212
   if(horz >= 0xFA){
213
   horz=0xFA;
214
   }
215
216
   OCR1B  = horz*10;    // set Servo 2 to xms-position
217
218
 
219
  }
220
  //Magnet an/aus
221
  if(!(PINB & (1 << 4))){  // bit 4 wird abgefragt gesezt
222
  
223
224
225
   if(mgn==1){
226
     mgn=0;
227
     PORTD |= (1 << 2);    /* setzt Bit 1 an PortD auf 1 */  // Lampe
228
     PORTE &= ~(1 << 0);   /* loescht Bit 0 an PortE */      // Magnet
229
   }else{
230
     mgn=1;
231
     PORTD &= ~(1 << 2);   /* loescht Bit 0 an PortD */      // Lampe
232
     PORTE |= (1 << 0);    /* setzt Bit 0 an PortE auf 1 */  // Magnet
233
   }
234
235
236
  _delay_ms(500);   // Zum Entprellen Warten
237
238
 
239
  }
240
241
// Steuerung fertig
242
243
// Speicher löschen (Interner Reset)
244
245
  if(!(PINB & (1 << 7))){  // bit 7 wird abgefragt gesezt
246
  
247
248
     horz=RESET_Y;
249
   vert=RESET_X;
250
251
   OCR1A  = vert*10;    // set Servo 1 to xms-position
252
253
     _delay_ms(10);
254
255
   OCR1B  = horz*10;    // set Servo 2 to xms-position
256
257
   
258
259
   while(i>=1){  // Löschen der Punkte
260
   point[i].x=0;
261
   point[i].y=0;
262
   point[i].mgn=0;
263
   i--;
264
   }
265
 
266
  }
267
268
   //Schritt speichern
269
  if(!(PINB & (1 << 6))){  // bit 6 wird abgefragt gesezt
270
  
271
272
   
273
274
   point[i].x=vert;
275
   point[i].y=horz;
276
   point[i].mgn=mgn;
277
   i++;
278
   if(i>=POINT){
279
   i=POINT;
280
   }
281
   PORTD &= ~(1 << 1);   /* loescht Bit 0 an PortB */
282
283
     _delay_ms(1000);
284
285
     PORTD |= (1 << 1);    /* setzt Bit 0 an PortB auf 1 */  
286
 
287
  }
288
289
290
   // Abfrage desd Playtasters
291
  if(!(PINB & (1 << 5))){  // bit 5 wird abgefragt gesezt
292
  
293
294
  play();
295
296
  PORTD &= ~(1 << 1);   /* loescht Bit 0 an PortB */
297
298
 
299
300
     horz=RESET_Y;
301
   vert=RESET_X;
302
303
   OCR1A  = vert*10;    // set Servo 1 to xms-position
304
305
     _delay_ms(10);
306
307
   OCR1B  = horz*10;    // set Servo 2 to xms-position
308
309
  PORTD |= (1 << 1);    /* setzt Bit 0 an PortB auf 1 */   
310
 
311
  goto loop;
312
313
  }
314
315
_delay_ms(50);   // Zum Entprellen Warten
316
317
}
318
  
319
return 0;
320
}

von Ulrich (Gast)


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

von Εrnst B. (ernst)


Lesenswert?

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


Also, #define raus, und echte Optimierung einschalten.

von Karl H. (kbuchegg)


Lesenswert?

Hast du die Compileroptimierung eingeschaltet?

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

von Oliver (Gast)


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

von Εrnst B. (ernst)


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...

von Sonke A. (soeni)


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

von Karl H. (kbuchegg)


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

von Εrnst B. (ernst)


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"

von Sonke A. (soeni)


Lesenswert?

danke code ist jezt be ca. 850 bytes so ist das ok

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.