Code Optimieren

#867796
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
}
Gast #867800
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
Gast #867807
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
#867808
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...
#867814
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
#867819
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"

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren