Forum: Mikrocontroller und Digitale Elektronik ab welchem AVR lohnt sich C statt asm?


von ChristophK (Gast)


Lesenswert?

Ich frage mich, ab welchem AVR sich lohnt, in C zu programmieren 
(Speichergröße, Stack usw.)

von Martin (Gast)


Lesenswert?

Das kann man so nicht beantworten.

von ChristophK (Gast)


Lesenswert?

Kann man denn bestimmte AVRs von vorn herein ausschließen?

von Kai F. (kai-) Benutzerseite


Lesenswert?

Das hängt immer davon ab wieviel Platz du noch übrig hast...
ich würde es immer erst in C versuchen, wenns nicht passt versuchen den 
Code in C zu komprimieren und erst dann in Assembler programmieren
Die C Compiler sind allerdings schon recht gut, also wirst du es in 
Assembler auch nicht viel kleiner bekommen. Da lohnt sich vielleicht ein 
größerer µC :P

von Winfried (Gast)


Lesenswert?

Zumindest sollte der AVR internen Ram haben. Und dann kann man davon 
ausgehen, dass ein C-Programm durchaus doppelt so viel Programmspeicher 
verbraucht. Je nachdem.

von Jadeclaw D. (jadeclaw)


Lesenswert?

@ChristophK:
Auszuschließen für C, Bascom, etc. sind alle Controller ohne SRAM, da 
diesen der Speicher für Stapel und Variablen fehlt. Die 32 Register 
reichen meist auch für einfache Dinge nicht aus. Da sind z.B. AT90S1200, 
ATTiny 11, 12, 15, 28. Ab ATTiny 2313 wird es auch mit C interessant. 
Assembler empfiehlt sich ebenfalls unabhängig von der Controllergröße 
für zeitkritische Anwendungen, da dabei die Ausführungsgeschwindigkeit 
für jeden Befehl bekannt ist. Sind nur kleine Teile zeitkritisch, C und 
Assembler lassen sich mischen. ( s. WinAVR-Dokumentation )

Gruss
Jadeclaw.

von ChristophK (Gast)


Lesenswert?

@Jadeclaw:
>Ab ATTiny 2313 wird es auch mit C interessant.

OK, das wollte ich fast wissen. Da bin ich mit ATTiny2313 also gerade so 
an der Grenze.

von Troll B. (blaubeer)


Lesenswert?

ChristophK wrote:
> @Jadeclaw:
>>Ab ATTiny 2313 wird es auch mit C interessant.
>
> OK, das wollte ich fast wissen. Da bin ich mit ATTiny2313 also gerade so
> an der Grenze.

Der C-Freund meidet ASM sogut er kann. Er erklärt RAM-lose AVRs zu 
Schrott und empfiehlt überdimensionierte Controller.

Der ASM-Freund meidet C und arbeitet gern auf kleineren überschaubaren 
AVRs.

Der BASCOM-Freund meidet C, ASM, Dokumentationen und Datenblätter.

Die Wahrheit wird irgendwo dazwischen liegen und ist für Jeden etwas 
anders. Mach's also so, wie Du (Du, Deine Person) am besten zurecht 
kommst.

MfG, BlauBär

von Jens (Gast)


Lesenswert?

>Kann man denn bestimmte AVRs von vorn herein ausschließen?

Kommt darauf an, welchen Compiler du benutzt. Der gcc unterstützt nur 
AVRs mit SRAM, d. h. einen AT90S1200 kannst du nicht verwenden. Von 
Imagecraft gibt es einen Compiler, der auch für AVRs ohne SRAM geeignet 
ist. Klar ist, dass du in diesem Fall aber keine großen Sachen machen 
kannst.

von Jens (Gast)


Lesenswert?

>Die C Compiler sind allerdings schon recht gut, also wirst du es in
>Assembler auch nicht viel kleiner bekommen.

[ ] Du hast schon mal in C programmiert.
[ ] Du hast schon mal in ASM programmiert.
[ ] Du hast mal den vom C-Compiler erzeugten Code angesehen.

von D. W. (dave) Benutzerseite


Lesenswert?

>>Die C Compiler sind allerdings schon recht gut, also wirst du es in
>>Assembler auch nicht viel kleiner bekommen.

>[X] Du hast schon mal in C programmiert.
>[X] Du hast schon mal in ASM programmiert.
>[X] Du hast mal den vom C-Compiler erzeugten Code angesehen.

Ich stimm dem oberen Zitat zu...

Wenn man die Optimierung im AVR-GCC einschaltet, dann kommen da doch 
manchmal Sachen raus, die man selbst nicht bemerkt hätte. Gerade bei 
größeren Projekten mit vielen Variablen und so zeuch ist man mit einem 
Assembler-Projekt doch mal schnell überfordert beim Optimieren.

Bei manchen Sachen muss man halt wissen, dass man eine Funktion besser 
_inline_ und/oder _static_ macht...

von Peter D. (peda)


Lesenswert?

Der WINAVR benötigt internen RAM, also kann man alles ab dem ATtiny13 in 
C programmieren.

Die Attiny12, 15 sollte man eh nicht mehr für Neuentwicklungen nehmen.

Und wenns im ATtiny13 knapp wird, kann man ja auf ATtiny25/45/85 
upgraden, der Preisunterschied ist für den Bastler unerheblich.

Für größere Sachen ist die ATmega48/88/168 Serie geeignet.

Der ATtiny2313 ist heikel, für den gibts keine direkte 
Upgrademöglichkeit (außer AT89LP4052).


Peter

von Ralph (Gast)


Lesenswert?

Wer in C Müll programmiert darf sich nciht wundern wenn da ein sehr 
großer Code mit viel Rambedarf rauskommt.

Auch C Programmieren will gelernt sein , ein Buch lesen reicht da nciht.

Ist das C Program gut, dann erzeugt der Compiler einen Code der 
effizienter und schneller ist, als alles was 99 % aller Assemblerfreaks 
so von sich geben.

von bascom-looser (Gast)


Lesenswert?

C = Müll

von Troll B. (blaubeer)


Lesenswert?

Ralph wrote:
> Auch C Programmieren will gelernt sein , ein Buch lesen reicht da nciht.

Dem stimme ich voll zu.

> Ist das C Program gut, dann erzeugt der Compiler einen Code der
> effizienter und schneller ist, als alles was 99 % aller Assemblerfreaks
> so von sich geben.

Das stimmt. Ich glaube nur nicht, dass 99% aller C-Programmierer das 
können. Daher halte ich C (alleine) nicht für die Lösung aller 
AVR-Probleme.

MfG, Blaubär, der auf C verzichtet.

von Troll B. (blaubeer)


Lesenswert?

bascom-looser wrote:
> C = Müll

Troll' hier nicht 'rum, das ist mein Job. Geh' ins Bascom-Forum, die 
brauchen noch Leutz wie Dich.

MfG, BlauBär, der auch auf Bascom verzichtet.

von Benedikt K. (benedikt)


Lesenswert?

Ralph wrote:
> Ist das C Program gut, dann erzeugt der Compiler einen Code der
> effizienter und schneller ist, als alles was 99 % aller Assemblerfreaks
> so von sich geben.

Kommt drauf an.
Ich behaupt einfach mal, dass meine Inline Assembler Programme etwa 
10-500% schneller sind als der Code, den AVR-gcc erzeugt.
Das liegt ganz einfach daran, dass der Compiler z.B. nicht weiß wie groß 
eine Variable werden kann, und daher meist mit größeren Datentypen 
rechnet als eigentlich notwendig ist.
Ein Compiler rechnet so wie es mathematisch korrekt ist. Allerdings ist 
dies oftmals nicht notwendig. Nimmt man Rundungsfehler usw. in kauf, 
ergeben sich oftmals neue Optimierungsmöglichkeiten. Außerdem nutzt der 
Compiler nicht alle Befehle (wie z.B. fmul) aus.

von Ralph (Gast)


Lesenswert?

Benedikt was du schreibst macht deutlich das du NICHT weißt wie man 
seinen Compiler im Griff hat und wie man ein C Programm effektiv 
schreibt.

Der Compiler verwendet den Datentyp den der Programmierer mit seiner 
Definition bestimmt, und keinen anderen. Nichts anderes machst du bei 
Assembler, nur DA machst du es.
Ein sinnvolles CAST vor/in einer Berechnung hilft da wahre Wunder.

Wer natürlich in C alles mit FLOAT berechnet, statt Integer zu benutzen 
bekommt eine trügerische Genauigkeit zu immensen Kosten ( Ram, Rom, 
Laufzeit).

Als Beispiel:
Multipliziere mit oder dividiere durch 1000 ==> hoher Bedarf an Ram, 
Rom, Laufzeit

Nutze dazu 1024  ==> Ram, Rom, Laufzeit fast nichts
Dazu gehört eine sinnvolle Scalierung der Werte.

von Andreas K. (a-k)


Lesenswert?

> Der Compiler verwendet den Datentyp den der Programmierer mit seiner
> Definition bestimmt, und keinen anderen.

Nicht ganz. Wenn es ein Standard C Compiler ist und die beteiligten 
Datentypen kleiner als "int" sind, dann muss die Rechung formell als 
"int" durchgeführt werden. Vorschrift. Manchmal muss er das auch 
wirklich (z.B. bei i+1 < n), manchmal merkt er dass es einfacher geht 
und manchmal merkt er es auch nicht.

von Benedikt K. (benedikt)


Lesenswert?

Ralph wrote:
> Benedikt was du schreibst macht deutlich das du NICHT weißt wie man
> seinen Compiler im Griff hat und wie man ein C Programm effektiv
> schreibt.

Wenn du meinst...
Dann stell mal bitte deine optimale Lösung vor, um z.B. auf einem 
ATmega8 eine 16bit Zahl möglichst effizient und mit hinreichender 
Genauigkeit mit dem konstanten Faktor 1.234 zu multiplizieren. Das 
Ergebnis sollte wieder eine 16bit Zahl sein. Der Faktor ergibts sich 
halt so und dient dazu einen 12bit ADC Messwert anzupassen.

Das ist ein wunderbares Beispiel in dem DU beweisen kannst, dass DU den 
Compiler im Griff hast.
Ich bin schon gespannt wie du das löst. Ich benötige dazu <25 Takte...

von Hagen R. (hagen)


Lesenswert?

Ralph wrote:
> Benedikt was du schreibst macht deutlich das du NICHT weißt...

Von Benedikt habe ich schon viel Source gesehen und der ist gut aus 
meiner Sicht.

Ich denke nicht das Benedikt das so meinte wie's bei Ralf rüberkam.
Auch ich meine der Mensch, mit ausreichend Zeit, wird in ASM Code 
schreiben können der mindestens 50% kleiner und 200% schneller ist als 
der Code eines Compilers. Sollte man eine andere Annahme treffen so 
behauptet diese Person in meinen Augen das sein geliebter C Compiler 
intelligenter ist als er selber. Noch ist ein Compiler eine dumme 
Maschine die der Mensch erdacht hat. Also alles worauf ein Compiler als 
Optimierung kommt wird ein Mensch besser können. Und das ganz unabhängig 
von der Komplexität des programmes, also auch ein Program mit 1 Million 
C Source Zeilen kann ein Mensch in Assembler weitaus besser kodieren. 
ABER! die liebe Zeit. Der Compiler als Maschine kann wie jede Maschine 
seine Aufgabe viel schneller als ein Mensch erledigen. Und das ist der 
springende Punkt, der Mensch hat Compiler erschaffen damit sie ihm Zeit 
einsparen und das tun sie auch. Das heist aber eben nicht das der 
Compiler besser wäre als ein erfahrener ASM Programmierer.

Speziell in Bezug auf den GCC kann ich aus Erfahrung mit zwei meiner 
Bibliotheken sagen das man ohne großes ASM Können den erzeugten Code um 
50% Speicher reduzieren und um 200% performanter machen kann.

Die Frage ist nur ob ein um 50 Cent teuerer Prozessor mit doppeltem Takt 
und doppeltem Speicher die langwierige Arbeit in Assembler auf einem 50 
Cent preiswerteren Chip rechtfertigt.

Gruß Hagen

von DasGlaubIchNicht (Gast)


Lesenswert?

@benedikt:
Dann könntest du ja mal diesen Thread befruchten:

Beitrag "16 bit Div durch 100 bei AVR Mega32"

Ist eine Multiplikation mit 0.01

Aber bitte <25 Takte ;-)

von Ralph (Gast)


Lesenswert?

Was ist für dich eine hinreichende Genauigkeit ??

Wenn du mit 1.234 multiplizierst bekommst du eine FLOAT Operation, Elend 
viel Resourcenbedarf ohne eine FPU.

multipliziere das so : ( prinzip, je nachgenauigkeit reicht auch 512 , 
256 128,...)

1. #define FAKTOR (U16)1.234 * 1024

2. X = (U16)((U32)Wert * Faktor)/1024)        ==> Integeroperation

Wenn du weißt das in der Multiplikation Wert * Faktor der Wert IMMER 
kleiner als 65535 bleibt, dann kannst du das (U32) durch (U16 )ersetzen 
und den Compiler dazu zwingen mit einer U16 zu rechnen.

U16 = unsigned 16 Bit
U32 = unsigned 32 Bit


Ich kenne jetzt nicht die Assemblerefehle des AVR, kann dir also da 
keine Vergleichsrechnung anbieten.

Ich kenne die Compiler auf denen ich unterwegs bin, nur ein AVR ist 
nicht dabei. Also spezifiche AVR sachen hab ich keine Info's zu.

Aber von Prinzip sind die Compiler da alle identisch.

Ich arbeite mit 8051 auf Keil µVision und TMS 470 mit Compiler von TI.

Poste mal bitte den Code mit deinen <25 Takten, inklusive Kommentaren, 
würde mir das gerne mal ansehen.
Und wenn es geht lass meinen Vorschlag mal übersetzen und sag mir 
wieviel Takte der AVR Compiler draus macht.

von Peter D. (peda)


Lesenswert?

Benedikt K. wrote:

> Dann stell mal bitte deine optimale Lösung vor, um z.B. auf einem
> ATmega8 eine 16bit Zahl möglichst effizient und mit hinreichender
> Genauigkeit mit dem konstanten Faktor 1.234 zu multiplizieren. Das
> Ergebnis sollte wieder eine 16bit Zahl sein. Der Faktor ergibts sich
> halt so und dient dazu einen 12bit ADC Messwert anzupassen.
>
> Das ist ein wunderbares Beispiel in dem DU beweisen kannst, dass DU den
> Compiler im Griff hast.


Ne, das ist dann nur ein Beispiel, wie gut Du die Aufgabe umstellen 
kannst, bevor Du sie in Code umsetzt.

Mit C vs. Assembler hat das absolut nichts zu tun, es geschieht ja schon 
in Deinem Kopf, vor dem Code hinschreiben.

Wenn man die direkte Umsetzung mit 1.234 als float Zahl nimmt, dann 
dauerts auch in Assembler lange.

Zeig also einfach mal Deine Lösung in Assembler oder als Pseudosprache, 
damit man gleiche Ausgangsbedingungen hat.

Die C Umsetzung wird vielleicht einige wenige Zyklen länger sein, aber 
nie 500%.


Peter

von Joe (Gast)


Lesenswert?

Wieder mal ein schönes Beispiel wie ein Thread in C vs. ASM ausartet, 
pubertäres Gehabe.

Ein guter Programmierer, zumindestens wenn er sich mit MC's beschäftigt, 
beherscht beides und weis, wann was angebracht ist.

Die Diskussion über C dreht sich eher um Standardisierung. Es wird 
heutzutage in der Regel C verlangt, ist nunmal so. Die Fülle an 
Controllern und C Compilern trägt dem Rechnung. Der GCC mag ne Gurke 
sein, dennoch sollte man den Leuten die das Ding zum MC Compiler 
verbiegen, dankbar sein.

>> Auch C Programmieren will gelernt sein , ein Buch lesen reicht da nicht.

So ist es ! Das Gleiche gilt für Assembler.

>> Der C-Freund meidet ASM sogut er kann. Er erklärt RAM-lose AVRs zu
>> Schrott und empfiehlt überdimensionierte Controller.

>> Der ASM-Freund meidet C und arbeitet gern auf kleineren überschaubaren
>> AVRs.

Und der Profi beherscht beides und kann unterscheiden was wann Sinn 
macht.

In diesem Sinne, viel Spaß beim bla. bla.

von Jadeclaw D. (jadeclaw)


Lesenswert?

Joe wrote:
> Wieder mal ein schönes Beispiel wie ein Thread in C vs. ASM ausartet,
> pubertäres Gehabe.
Leider. :-(

> Und der Profi beherscht beides und kann unterscheiden was wann Sinn
> macht.
Amen.

Gruss
Jadeclaw.

von Benedikt K. (benedikt)


Lesenswert?

Es gibt 3 Lösungen, zwei in C, eine in Assembler:
Die C Lösung:
wert=ADC+ADC/4-ADC/64;
Ganz ohne float, 32bit usw.
Wenn man es nachrechnet, dann ergibt das in etwa (abgesehen von den 
Rundungsfehlern bei der Division) wert=ADC*1,234;
Zeit: etwa 40 Takte, Speicherplatz: 28 Bytes
Das funktioniert mit jeder noch so krummen Zahl: 1024->5,000mV ergibt 
einen Faktor von 4,8828125:
wert=4*ADC+ADC-ADC/8+ADC/128;

Die Lösung mit dem casten auf long benötigt 90 Bytes und viele Takte, da 
der Compiler das ganze als 32bit x 32bit->32bit rechnet. Und dies kann 
man meines Wissens nach durch casts nicht besser hinbekommt. Dadurch 
benötigt der Compiler etwas über 100 Takte.

Assembler Lösung:
clr null
clr var32
clr var33

mul var10,var20
mov var31,r1

mul var10,var21
add var31,r0
adc var32,r1

mul var11,var20
add var31,r0
adc var32,r1
adc var33,null

mul var11,var21
add var32,r0
adc var33,r1

mov r22, var31
mov r23, var32
mov r24, var33
clr r25

Im Prinzip eine 16bit x 16bit -> 32bit Multiplikation, bei der das 
niederwertigste Byte direkt weggelassen wird und die anderen Bytes 
nachrücken. Diese Funktion würde mit ADC und 1.234*256 als Parameter 
aufgerufen werden. Diese Lösung habe ich mir gebaut, um die 32bit 
Operationen zu vermeiden, die vor allem bei AVRs ohne Hardware 
Multiplizierer etwas über 500 Takte benötigen. Diese Routine ohne 
Multiplizierer benötigt etwa 170 Takte, das sind immerhin etwa 1/3 von 
der 32bit Version.

Bei Controllern ohne Division ist die oberste Version eindeutig die 
schnellste. Allerdings muss der Faktor zur Compilezeit schon bekannt 
sein, und der Programmierer muss sich Gedanken machen und die einzelnen 
Faktoren ausrechnen.

von Ralph (Gast)


Lesenswert?

Joe hat recht. Lassen wir die Diskussion über Vor und Nachteile von C 
oder Assembler an der Stelle sein.


Kommen wir zurück zur Anfangsfrage.

1. Sieh nach welche AVR Version vom Compiler unterstützt wird.
2. Überlege welche Sprache du verwenden willst und such den dazu 
passenden µC aus

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.