Ein Haup-Batzen dürfte die Verwendung von float sein.
Nimm zB folgendes Progrämmchen:
Und übersetz es wie gewohnt mit "avr-gcc -mmcu=atmega8 -Os -o float.elf float.c"Code:float a, b, c, d; void foo () { a = b*d - a/c; } int main() { while (1); }
Dann schauen wir auf die Größe mit "avr-size float.elf"
Der ATmega8 ist also schon zu 1/3 voll. Wo die draufgehen sieht man mit "avr-nm -S --size-sort float.elf"Code:text data bss dec hex filename 2730 8 16 2754 ac2 float.elf
In die zweiten Spalte stehen die Größen der Objekte (Bytes in hex). Das __*-Zeug kommt von der float-Software die dazugelinkt werden muss, weil AVR keine float/double Hardware-Unterstützung hat.Code:00800074 00000004 B a 00800068 00000004 B b 0080006c 00000004 B c 00800070 00000004 B d 00800060 00000008 D __thenan_sf 000000f8 0000000a T main 00000346 00000056 T __addsf3 0000039c 0000005e T __subsf3 0000005c 0000009c T foo 00000948 000000f4 T __unpack_f 00000626 00000156 T __divsf3 0000077c 000001cc T __pack_f 000003fa 0000022c T __mulsf3 00000102 00000244 t _fpadd_parts
Wenn du die Größen deiner Funktionen so auflistet, erkennt man wo am meisten Platz verbraucht wird und wo eine Optimierung am meisten bringt.
Die Optimierungsstufe von avr-gcc sollte -Os sein. -O0 oder -O3 sind keinesfalls ratsam.
Ansonsten hilft, mehrfach verwendete Sachen in eigene Funktionen zu packen. Damit kann der Code wiederverwendet werden und muss nicht jedesmal mit leicht anderen Parametern erzeugt werden.
Code://----------------------------------------------------------------------------------------------------------------- // Titel : LCD 4x16 zeigt die Uhrzeit an für Testschaltung MYAVR //----------------------------------------------------------------------------------------------------------------- // Prozessor : ATmega8 // Takt : 3686400 Hz // Sprache : C // Datum : 10.04.2008 // Version : 1.0 // Autor : //----------------------------------------------------------------------------------------------------------------- #include <avr/io.h> #ifndef F_CPU #define F_CPU 3686400UL // Quarz mit 3.6864 Mhz #endif #include <util/delay.h> // definiert _delay_ms() Warteschleife #include "i2cmaster.h" #include <stdlib.h> #include <string.h> #define DS13 0xd0 // device address of Realtime Clock DS1307, see datasheet char i; ///////////////////////////////////////////////////////////////////////////// // Uhr ///////////////////////////////////////////////////////////////////////////// // Schreibt 'num' gefolgt von 'c' an position line:pos (zeile:spalte) void lcd_write_num (unsigned char line, unsigned char pos, unsigned char num, char c) { unsigned char digit; static char buf[4]; buf[2] = c; buf[3] = 0; new_line (line, pos); // legt die Zeile, und dann die Spalte fest digit = num >> 4; buf[0] = digit + '0'; digit = num & 0xf; buf[1] = digit + '0'; } static const char * day_of_week[] = { "Mo", "Di", "Mi", "Do", "Fr", "Sa", "So" }; void Uhr2() { i2c_init(); // initialize I2C library unsigned char sek, min, std, day, date, month, year; // Typ char gibt Sekunde,Minute,Stunde,Wochentag,Tag den,Monat,Jahr. unsigned char i; for (i=1; i<30; i=i+1) { _delay_ms(250); //----------------------------------------------------------------------------------------------------------------- // Daten Auslesen des Realtime Clock DS 1307 //----------------------------------------------------------------------------------------------------------------- i2c_start_wait(DS13+I2C_WRITE); // setzt die Adresse vom DS13 und den schreiben mode i2c_write(0x00); // schreibe Address = 0 liegt Wert Zeitdaten i2c_rep_start(DS13+I2C_READ); // setzt die Adresse vom DS13 und den lese mode sek = i2c_readAck(); // lese den Inhalt von Adresse 0 Sekunden min = i2c_readAck(); // lese den Inhalt von Adresse 1 Minuten std = i2c_readAck(); // lese den Inhalt von Adresse 2 Stunden day = i2c_readAck(); // lese den Inhalt von Adresse 3 WochenTag date = i2c_readAck(); // lese den Inhalt von Adresse 4 Tag den month = i2c_readAck(); // lese den Inhalt von Adresse 5 Monate year = i2c_readNak(); // lese den Inhalt von Adresse 6 Jahre i2c_stop(); // Ende des einlesens //----------------------------------------------------------------------------------------------------------------- // LCD Hintergundbeleuchtung einschalten. // Ausgabe der Stunden auf das LCD Display. lcd_write_num (2, 5, std, ':'); //----------------------------------------------------------------------------------------------------------------- // Ausgabe der Minuten auf das LCD Display. lcd_write_num (2, 8, min, ':'); //----------------------------------------------------------------------------------------------------------------- // Ausgabe der Sekunden auf das LCD Display. lcd_write_num (2, 11, sek, 0); //----------------------------------------------------------------------------------------------------------------- // Ausgabe der Wochentage auf das LCD Display. if (day >= 1 && day <= 7) { new_line(1,2); // legt die Zeile, und dann die Spalte fest lcd_write (day_of_week[day-1]); } //----------------------------------------------------------------------------------------------------------------- // Ausgabe der Tages auf das LCD Display. lcd_write_num (1, 7, date, '.'); //----------------------------------------------------------------------------------------------------------------- // Ausgabe die Monate auf das LCD Display. lcd_write_num (1, 10, month, '.'); //----------------------------------------------------------------------------------------------------------------- // Ausgabe der Jahre auf das LCD Display. lcd_write_num (1, 13, year, 0); } } //-----------------------------------------------------------------------------------------------------------------Das ist nicht nur übersichtlicher, sondern auch etwas kleiner (256 Bytes anstatt 830, und itoa ist noch net mitgerechnet).Code:deep-thought> avr-nm -S --size-sort uhr.o 00000001 00000001 C i 00000000 00000004 b buf.0 00000015 0000000e d day_of_week 0000033e 0000002e T lcd_write_num 0000036c 000000c0 T Uhr2 00000000 0000033e T Uhr







Zitieren


Lesezeichen