Bitte um optimierung von C Code

GreenArrow

Neues Mitglied
26. Aug. 2008
23
0
0
Sprachen
Hey Leute, ich habe ein Wahnsinnig gutes Tutorial über C gefunden und mich da gestern mal eingearbeitet. Hier mal der Link http://www.peacesoftware.de/ckurs1.html
Jetzt wollte ich ein Programm schreiben. Und zwar eine Art Mini POV aus 5 LED´s. Quasi sowas hier:
http://projects.dimension-x.net/pictures/pov/pov_hello_sm.jpg
Leider muss das ganze aus Platzgründen auf nen Attiny13 passen. Der code steht soweit,ich kann ihn aber nicht testen weil er zu groß ist für den Tiny. Und das liegt nur an der "Zeichen" Funktion. Hier mal der Code
Code:
#include <avr/io.h>
#include <util/delay.h>   

       
uint8_t verzoegerung = 3;
uint8_t verzoegerung2 = 6;
uint8_t a[14]={1,1,1,1,1,1,0,1,0,1,1,1,1,1,1};



int main (void) {             

DDRB = (1 <<DDB0)| (1<<DDB1)| (1<<DDB2) | (1<<DDB3) | (1<<DDB4);  //PB0-PB4 als Ausgang

zeichen(a);

return 0;                

}


void zeichen(uint8_t eingabe_array[15])
{
  uint8_t x,y;
  
  // erste Reihe
  for (y=0; y<5; y++)
  {
    
        x==eingabe_array[y];

	switch(y)
	{
	case 0:PORTB |= (x << PB0);break;
	case 1:PORTB |= (x << PB1);break;
	case 2:PORTB |= (x << PB2);break;
	case 3:PORTB |= (x << PB3);break;
	case 4:PORTB |= (x << PB4);break;
	}
	
  }
  _delay_ms(verzoegerung);


  // zweite Reihe
  for (y=5; y<10; y++)
  {
    x==eingabe_array[y];

	switch(y)
	{
	case 5:PORTB |= (x << PB0);break;
	case 6:PORTB |= (x << PB1);break;
	case 7:PORTB |= (x << PB2);break;
	case 8:PORTB |= (x << PB3);break;
	case 9:PORTB |= (x << PB4);break;
	}
	
  }
  _delay_ms(verzoegerung);
  

// dritte Reihe
  for (y=10; y<15; y++)
  {
    x==eingabe_array[y];
	
	switch(y)
	{
	case 10:PORTB |= (x << PB0);break;
	case 11:PORTB |= (x << PB1);break;
	case 12:PORTB |= (x << PB2);break;
	case 13:PORTB |= (x << PB3);break;
	case 14:PORTB |= (x << PB4);break;
	}
  }
  _delay_ms(verzoegerung);
  
  // nach jedem Buchstaben kurz warten
  
  _delay_ms(verzoegerung2);
}


Nach dem Compilieren bekomm ich

Program: 4228 bytes (412.9% Full)
(.text + .data + .bootloader)

Data: 280 bytes (437.5% Full)
(.data + .bss + .noinit)

angezeigt. Das heißt mein code ist leider vier mal zu groß. Es liegt wahrscheinlich an den Case anweisungen. Aber wenn ich die durch IF ersetzte ist er genauso groß.
Hat da jemand ne Idee?
Vielen Dank schonmal, GreenArrow
 
Hallo Grünpfeil

Stell dir einen Übergewichtigen Computertrottel vor, welcher, um deine Frage zu beantworten, in seinem dunklen Kämmerchen sitzend gerade seine Fingerdehnübungen über seiner Tastatur ausführt, gerade so als ob er auf seiner Debian(Linux)-Maschiene mit seinen üblichen 400 Anschlägen in der Minute zu einem Komplexen Programm ansetzen würde.
Nebenbei hört er sich übrigens noch den neuesten Podcast des CCC an, erläutert einem Kollegen über Teamspeak noch die Vorteile von Linux Windows gegenüber, zieht sich über den Strohalm ein paar RedBull rein, schiebt mit dem Ellenbogen die Reste des leeren Pizzakartons in den Mülleimer, lädt sich über seinen T3 Anschluss coole Videos von Pinguinen welche Fenster zertrümmern runter, testet die Übermacht von Wine gegenüber einer virtuell laufenden Windows-Maschiene aus und Compiliert gerade seinen frisch runtergeladenen Kernel v2.6.30.2.
Auf sowas fliegen die Frauen doch. Oder?:D

Wie das Leben so spielt bin ich leider nicht übergewichtig, kann Linux nicht ausstehen, verwende nur 9 Finger bei etwa 100 Anschlägen die Minute, sitze in einem gut ausgeleuchteten Zimmer und hab keine Ahnung von dem was ich da oben überhaupt geschrieben habe.
Aber keine Sorge ich kann dir helfen:

x==eingabe_array[y];
Das doppelte "=" (==) ist ein Vergleich und keine Zuweisung(=), wenn du das so einsam im programm stehen lässt wird es wegoptimiert. Ich habe übrigens das Gefühl dass dir der Compiler die for-Schleife aufklappt und deshalb der Code so aufgebläht wird.(probier mal eine andere Optimierung, bzw. keine Optimieung)

Nebenbeibemerkt würde ich anstatt den vorhandenen Code zu optimieren einen anderen Ansatz wählen. Du speicherst beispielsweise einzelne Bits in ganze Bytes rein und fügst dann diese in Bytes gespeicherten Bits zu halben Bytes zusammen.
 
@Nomis3000 bzw. Simon, erstmal danke für deine amüsant eingeleitete Antwort.
Mist, das mit dem == hätte ich selbst sehen müssen. Aber ich kannte früher nur Pascal, da wurden zuweisungen schön mit := gemacht. An die Umstellung muss ich mich noch gewöhnen,da passiert sowas schonmal.

Das mit der Optimierung hab ich schonmal gelesen, wo kann ich das denn einstellen? Ich schreibe den Code im AVRStudio 4.

Das mit dem Bits in ganzen Bytes speichern, hab ich auch schonmal gehört,aber da ich ja noch Anfänger in C bin, wollte ich es nicht gleich übertreiben. Außerdem versteh ich nicht wieso ich die dann zu halben Bytes zusammenfügen soll? Naja, bin ja noch klein :D
 
Hallo Grünpfeil

Das mit der Optimierung hab ich schonmal gelesen, wo kann ich das denn einstellen? Ich schreibe den Code im AVRStudio 4.
Unter Projects->Configuration Options, da kann man eine Optimization auswählen. -O0 wäre zum Beispiel keine Optimisierung. Dann dürfte er deine Schleifen nicht mehr aufklappen.
Das mit dem Bits in ganzen Bytes speichern, hab ich auch schonmal gehört,aber da ich ja noch Anfänger in C bin, wollte ich es nicht gleich übertreiben. Außerdem versteh ich nicht wieso ich die dann zu halben Bytes zusammenfügen soll? Naja, bin ja noch klein :D
Mit dem "Bits in Bytes speichern" meinte ich:
uint8_t a[14]={1,1,1,1,1,1,0,1,0,1,1,1,1,1,1};
Und mit dem "in Bytes gespeicherte Bits zu einem halben Byte zusammenfügen" meinte ich:
for (y=0; y<5; y++)
{

x=eingabe_array[y];

switch(y)
{
case 0:pORTB |= (x << PB0);break;
case 1:pORTB |= (x << PB1);break;
case 2:pORTB |= (x << PB2);break;
case 3:pORTB |= (x << PB3);break;
case 4:pORTB |= (x << PB4);break;
}
}
Es ist eben etwas kompliziert und nicht sehr ressourcenschonend
geschrieben. (von der Funktionalität ganz zu schweigen)
Hier mal meine Version von deinem Programm:


CodeBox C
#include <avr/io.h>
#include <util/delay.h>


uint8_t verzoegerung = 3;
uint8_t verzoegerung2 = 6;
//uint8_t a[14]={1,1,1,1,1,1,0,1,0,1,1,1,1,1,1};
uint8_t a[]={ 0b00011111,
0b00010101,
0b00011111};


void zeichen(uint8_t eingabe_array[3]);
int main (void) {

DDRB = (1 <<DDB0)| (1<<DDB1)| (1<<DDB2) | (1<<DDB3) | (1<<DDB4); //PB0-PB4 als Ausgang

zeichen(a);

return 0;

}


void zeichen(uint8_t eingabe_array[3])
{


// erste Reihe
PORTB=eingabe_array[0];

_delay_ms(verzoegerung);


// zweite Reihe
PORTB=eingabe_array[1];

_delay_ms(verzoegerung);


// dritte Reihe
PORTB=eingabe_array[2];

_delay_ms(verzoegerung);

// nach jedem Buchstaben kurz warten

_delay_ms(verzoegerung2);
}


Die braucht zwar weniger aber immer noch viel zu viel Speicher. (noch)Keine Ahnung warum.
Edit: Gehört der Tiny13 nicht zu den Tinys, die keine GCC Unterstützung haben?
 
Hey Simon,
finde deine Verison von dem Programm echt spitze. Wär da glaub ich selbst nicht so schnell drauf gekommen.
Und es ist immer noch zu groß? (Kann es grad selber nicht testen,weil ich auf der Arbeit bin). Bei dem bißchen Code sollte das doch eigentlich locker drauf passen.

Also ich hab gestern drei Zeilen Code in GCC geschrieben,die halt zum testen nur mal ne LED anmachen. Das ließ sich tadelos compilieren und hochladen. Daher sollte der Tiny13 doch eigentlich damit klar kommen,oder?
:confused: :confused: :confused:
 
Guten Abend GreenArrow

finde deine Verison von dem Programm echt spitze.
Naja, Spitze ist das noch nicht.

....Bei dem bißchen Code sollte das doch eigentlich locker drauf passen.

Also ich hab gestern drei Zeilen Code in GCC geschrieben,die halt zum testen nur mal ne LED anmachen. Das ließ sich tadelos compilieren und hochladen. Daher sollte der Tiny13 doch eigentlich damit klar kommen,oder?
:confused: :confused: :confused:
Es sind die _delay_ms Funktionen, die den Code so aufblähen. Damit es besser läuft solltest du anfangen dir selber ein paar Timerfunktionen zu schreiben.
 
Na Toll,bin extra von Assembler zu GCC gewechselt, weil mich das fehlende Delay und das ständige Schleifen basteln in Assembler nervte. Jetzt muss ich in C anscheinend auch wieder basteln. Naja,wär auch langweilig gewesen,wenns direkt geklappt hätte :)
Trotzdem vielen Dank für die Infos und die Denkanstöße. Hast mir auf jeden Fall wahnsinnig geholfen!
Schönen Abend noch, Der Grünpfeil :)


Seltsam,hab grade bemerkt,das der Code durch die Delay Funktion nur so riesig wird, wenn man Variablen einsetzt. Wenn ich anstatt der Variablen, Delay direkt mit einer festen Zahl aufrufe, bleibt der Code klein. Strange!
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)