Hi! Ich habe mir vor ca 3 Monaten mein erstes uC-Board (RN-Control mit ATmega32) gekauft, um in die Welt der Mikrocontroller einzusteigen. Ich bastle gerade an einer Heizungssteuerung und habe das Problem, daß mir der Mega32 einfach in vielerlei Hinsicht zu klein wird. Als Anfänger kann ich nicht abschätzen, wie groß der Code später einmal wird und weiß daher auch nicht ob der 32er genug Programmspeicher für mich bietet. Auch was die Pins angeht, müsste ich mit vielen IC´s erweitern, damit ich alles unter einen Hut bringen könnte.(Portexpander, PWM, CAN..) Ein größerer Controller wäre hier die Lösung. Und da ist mir der AT90CAN128 ins Auge gestochen, welcher genau in mein Anforderungsprofil passt. Da ich Anfänger bin und bis jetzt nur mit einem ATmega32 gearbeitet habe, weiß ich aber nicht, was da so an Problemen auf mich zukommt, wenn ich den AT90CAN128 nehmen würde. Von folgenden Fehlern/Eigenheiten hab ich bisher gelesen: 1.) Silicon Bug (Stack Fehler): Wenn ich das richtig verstanden habe, ist dieser Hardwarefehler nur relevant, wenn man einen externen Arbeitsspeicher an der Controller anschließt. 2.) Timer2 Bug: Wenn ins Compare Register geschreiben wird, wenn der Timer gerade "überläuft" geht der Interrupt verlohren. (betrifft aber auch mega32,44,88,168) 3.) ISP wird anders angeschlossen 4.) Man muss auf das M103C-Fuse (Atmega103 Compatibility Mode) achten und ausschalten. 5.) Diese Anmerkung kann ich bisher nicht richtig deuten(AVR-Checkliste): Außerdem funktionieren einige IO-Pins an PORTC, PORTF und PORTG anders. Was bedeutet anders? Um ehrlich zu sein hab ich jetzt doch "Angst" den Schritt zu wagen und den AT90CAN128 zu nehmen, weil ich einfach nicht weiß, was da auf mich zukommt. Läuft ein C-Code, der unter WinAVR für einen ATmega32 entwickelt wurde, auch auf einen AT90CAN128 einwandfrei, oder gibt es da haufenweise Überraschungen.(Anpassung auf richtige Portpins vorrausgesetzt)? Hat einer von euch diesbezüglich Erfahrungen und kann mir einen Rat geben? Lieber beim 32er bleiben und mit etlichen weiteren IC´s erweitern oder doch einen größeren Controller nehmen? Vielen Dank im voraus. Grüsse Rick
@ Erik M. (rick00) >Ich bastle gerade an einer Heizungssteuerung und habe das Problem, daß >mir der Mega32 einfach in vielerlei Hinsicht zu klein wird. Muss ja ne verdammt grosse Heizung sein, dss 32 kB damit verbraucht werden. >Als Anfänger kann ich nicht abschätzen, wie groß der Code später einmal >wird und weiß daher auch nicht ob der 32er genug Programmspeicher für >mich bietet. Auch was die Pins angeht, müsste ich mit vielen IC´s Für ne Heizungsteuerung reicht das dreimal. >erweitern, damit ich alles unter einen Hut bringen könnte.(Portexpander, >PWM, CAN..) Ja und? der 32er ist schon ziemlich gross und AFAIK für dich vollkommen ausreichend. Hast du die Optimierung im WINAVR eingeschaltet? >Läuft ein C-Code, der unter WinAVR für einen ATmega32 entwickelt wurde, >auch auf einen AT90CAN128 einwandfrei, oder gibt es da haufenweise >Überraschungen.(Anpassung auf richtige Portpins vorrausgesetzt)? Zu 99%. >Lieber beim 32er bleiben und mit etlichen weiteren IC´s erweitern oder >doch einen größeren Controller nehmen? Was reicht dir denn beim 32er nicht? MFG Falk
Falk Brunner wrote: > Muss ja ne verdammt grosse Heizung sein, dss 32 kB damit verbraucht > werden. Wie schon erwähnt kann in der Zukunft noch einiges dazukommen, wie z.B: mind. 3x Ansteuerung von Mischermotoren Boiler Solarpaneele für den Boiler CAN-Bus für 3 Raumthermostate Gastherme ..... Auslegung für den Anfang: 3 Heizkreise, Puffer, Holzkessel >>Als Anfänger kann ich nicht abschätzen, wie groß der Code später einmal >>wird und weiß daher auch nicht ob der 32er genug Programmspeicher für >>mich bietet. Auch was die Pins angeht, müsste ich mit vielen IC´s > > Für ne Heizungsteuerung reicht das dreimal. > >>erweitern, damit ich alles unter einen Hut bringen könnte.(Portexpander, >>PWM, CAN..) > > Ja und? der 32er ist schon ziemlich gross und AFAIK für dich vollkommen > ausreichend. Hast du die Optimierung im WINAVR eingeschaltet? Ich brauch jetzt schon 20% des Programmspeichers nur für die Temparaturmessung und Displayausgabe, da ist ja noch nichtmal ne Steuerung programmiert und auch noch keine I2C Routinen..... Optimierung ist ein ud auf-0s > >>Läuft ein C-Code, der unter WinAVR für einen ATmega32 entwickelt wurde, >>auch auf einen AT90CAN128 einwandfrei, oder gibt es da haufenweise >>Überraschungen.(Anpassung auf richtige Portpins vorrausgesetzt)? > > Zu 99%. > >>Lieber beim 32er bleiben und mit etlichen weiteren IC´s erweitern oder >>doch einen größeren Controller nehmen? > > Was reicht dir denn beim 32er nicht? Wenn ich Display, Tempsensoren und 3 Taster anschließe ist der Controller voll. (SPI-Schnittstelle für spätere CAN-Erweiterung freigehalten) Ich brauch da schon nen Portexpander per I2C um überhaupt die 8 Relais für die Umwälzpumpen ansteuern zu können. Für spätere PWM-Signale brauch ich dann auch jeweils 1nen IC für I2C Bus. Grüsse Rick
@ Erik M. (rick00) >Wie schon erwähnt kann in der Zukunft noch einiges dazukommen, wie z.B: >mind. 3x Ansteuerung von Mischermotoren >Boiler >Solarpaneele für den Boiler >CAN-Bus für 3 Raumthermostate >Gastherme >..... Auch nicht sooo viel. >Auslegung für den Anfang: 3 Heizkreise, Puffer, Holzkessel Als Anfänger. Hmmm. >Ich brauch jetzt schon 20% des Programmspeichers nur für die >Temparaturmessung und Displayausgabe, da ist ja noch nichtmal ne 6kB für so wenig? Was machst du da? Wieviel tausend TExte willst du denn ausgeben. >Steuerung programmiert und auch noch keine I2C Routinen..... >Optimierung ist ein ud auf-0s OK. Hollentlich keine variablen Parameter in der _delay_ms(). etc. >Wenn ich Display, Tempsensoren und 3 Taster anschließe ist der >Controller >voll. ???? Häää LCD -> 7 IO Temperatursensoren analog - max. 8 IOs 3 Taster 3 IOS Macht bei mir 18 IOs. Der 32er hat AFAIK 32 IOs. >(SPI-Schnittstelle für spätere CAN-Erweiterung freigehalten) >Ich brauch da schon nen Portexpander per I2C um überhaupt die 8 Relais >für die Umwälzpumpen ansteuern zu können. Und? Ist doch optimal. Die schalten so langsam, da reicht I2C locker. >Für spätere PWM-Signale brauch ich dann auch jeweils 1nen IC für I2C >Bus. Der AVR kann auch PWM, der 32er AFAIK 3mal. Vor allem gibt es AFAIK den AT90CAN128 nicht im bastlerfreundlichen DIP Gehäuse. MFG Falk
Hi! PORTA für Tasten und Temp.Messung = 8Pin PORTC + PD7 für Display und I2C = 9Pin (7+2) PD4+PD5 für 16bit-PWM = 2Pin RS232 = 2Pin SPI für CAN = 4Pin 3*Digitale Eingänge für vorhandene 2Punkt Raumthermostate = 3Pin 2* Ext INT für I2C+? = 2Pin Zähleingang für eventuell Durchflussmengenmessung= 1Pin Piezo = 1 Pin --------------------------------------------------------------------- Summe: 32 Pins Der Mega32 hat auch nur 1nen 16bit Timer mit 2ch PWM. AT90CAN128 hat 2x 16Bit Timer mit 3ch PWM. Timer hat man sowieso immer zu wenig. Ein 16bit Timer ist schnell verbraucht, z.B für die Delays für den DS18B20 (1sec). PWM-Signal kann ich dann keins mehr erzeugen, jedenfalls nicht 16bittig. Warum mein Milchmädchencode so groß ist, weiß ich nicht. Ich hab bloß 2 Libraries von Peter Fleury (LCD+UART) + ein bißchen eigenen Code für DS18B20 Temp. Messung. Das is alles und AVRStudio meldet 20% used? ....keine variablen Parameter bei den Delay Routinen nur fixe Werte. Ich weiß, daß es den AT90CAN128 nicht im Dip Gehäuse gibt, sonder nur im TQFP. Da brauch ich nen Adapter. Gruß Rick
@ Erik M. (rick00) >Summe: 32 Pins OK. >Der Mega32 hat auch nur 1nen 16bit Timer mit 2ch PWM. Er hat noch zwei 8 Bit Timer, die auch PWM können. 16 Bit PWM braucht man eher selten. >Timer hat man sowieso immer zu wenig. Ein 16bit Timer ist schnell >verbraucht, z.B für die Delays für den DS18B20 (1sec). ;-) Weil so ne popelige Heizungssteuerung auch soooo viele Timer braucht. >PWM-Signal kann ich dann keins mehr erzeugen, jedenfalls nicht 16bittig. Willst du deine Temperatur aum Milligrad vorgeben? >Warum mein Milchmädchencode so groß ist, weiß ich nicht. Ich hab bloß 2 >Libraries von Peter Fleury (LCD+UART) + ein bißchen eigenen Code für >DS18B20 Temp. Messung. Das is alles und AVRStudio meldet 20% used? >....keine variablen Parameter bei den Delay Routinen nur fixe Werte. >Ich weiß, daß es den AT90CAN128 nicht im Dip Gehäuse gibt, sonder nur im >TQFP. Da brauch ich nen Adapter. Na dann nimm ihn und gut. Ich sag ja nicht dass man das nicht darf. MFG Falk
Falk Brunner wrote: > Na dann nimm ihn und gut. Ich sag ja nicht dass man das nicht darf. > > MFG > Falk Ich will hier nicht an ihrgendwas festhalten. Der mega32 wär mir auch lieber, weil ich da ein fertiges Testboard hab und es ihn im DIP gibt. Kann es sein, daß das AVRStudio keinen kompakten Code erzeugen kann? Im AVR-GCC Tutorial steh da was drinnen. Gruß Rick
@ Erik M. (rick00) >Ich will hier nicht an ihrgendwas festhalten. Der mega32 wär mir auch >lieber, weil ich da ein fertiges Testboard hab und es ihn im DIP gibt. Dann nimm den und nutze ihn solange, bis der FLASH voll ist. Wenn dein Programm halbwegs gescheit programmiert ist, kann man es dann leicht auf einem anderen AVR mit mehr FLASH laufen lassen. >Kann es sein, daß das AVRStudio keinen kompakten Code erzeugen kann? Nöö, WINAVR ist schon ganz gut. >Im AVR-GCC Tutorial steh da was drinnen. ??? Wo. MFG Falk
Falk Brunner wrote: > @ Erik M. (rick00) > >>Ich will hier nicht an ihrgendwas festhalten. Der mega32 wär mir auch >>lieber, weil ich da ein fertiges Testboard hab und es ihn im DIP gibt. > > Dann nimm den und nutze ihn solange, bis der FLASH voll ist. Wenn dein > Programm halbwegs gescheit programmiert ist, kann man es dann leicht auf > einem anderen AVR mit mehr FLASH laufen lassen. > >>Kann es sein, daß das AVRStudio keinen kompakten Code erzeugen kann? > > Nöö, WINAVR ist schon ganz gut. > >>Im AVR-GCC Tutorial steh da was drinnen. > > ??? > Wo. > Beim Wechsel vom makefile-Ansatz nach WinAVR-Vorlage zu AVRStudio ist darauf zu achten, dass AVRStudio (Stand: AVRStudio Version 4.13) bei einem neuen Projekt die Optimierungsoption (vgl. Abschnitt Exkurs: Makefiles, typisch: -Os) nicht einstellt und die mathematische Bibliothek der avr-libc (libm.a, Linker-Option -lm) nicht einbindet. Beides ist Standard bei Verwendung von makefiles nach WinAVR-Vorlage und sollte daher auch im Konfigurationsdialog des avr-gcc-Plugins von AVRStudio "manuell" eingestellt werden, um auch mit AVRStudio kompakten Code zu erzeugen. Da blick ich nicht so ganz durch. Ich hab im AVRStudio unter Project/ Configuration Options/ General/ Optimization -0s eingestellt. Gruß Rick
Erik M. wrote: > Timer hat man sowieso immer zu wenig. Ein 16bit Timer ist schnell > verbraucht, z.B für die Delays für den DS18B20 (1sec). > PWM-Signal kann ich dann keins mehr erzeugen, jedenfalls nicht 16bittig. Nö. Timer verbrauchen sich nicht. Für alle Delays, Uhrzeit, Kalender, Multiplexen, Entprellen usw. ist genau ein einziger Timer nötig. Muß in der Regel auch nicht 16 Bit sein. Du kannst noch vom Mega32 auf den Mega644 upgraden (pinkompatibel). Peter
Hi! O.K. ich nehm den gut gemeinten Rat an und bleib erstmal beim Mega32 bzw. 644. Kann ich bei den Einstellungen im AVR Studio etwas falsch machen, sodaß der Code zu groß wird? Grusse Rick
@ Erik M. (rick00) >Kann ich bei den Einstellungen im AVR Studio etwas falsch machen, sodaß >der Code zu groß wird? Nicht so ohne weiteres. Mit -Os ist im wesentlichen alles OK. Der Rest hängt davon ab, ob du solche Monster wie printf(), scanf() und Fliesskommaberechnungen nutzt. MFG Falk
>Kann ich bei den Einstellungen im AVR Studio etwas falsch machen, sodaß >der Code zu groß wird? Natürlich. In den *.c-Files kann man jede Menge Platz verbraten :-) Ansonsten brauchen die "ersten" Funktionen immer den meisten Platz. mathelib, LCD-Bibliothek, Tastenentprellung, Menuverwaltung, usw, brauchen halt Platz. Aber wenn die einmal drin sind, geht es mit der Codegrösse nur noch langsam voran. Mit reinen Rechenfunktionen für die Heizung bekommst du den 32'er nicht voll. Was viel Platz braucht, ist die Benutzeroberfläche. Wenn da ein Grafikdisplay zum Einsatz kommt, mit vielen schönen Symbolen, dann könnte es knapp werden. Aber wie schon gesagt, ein 644 ist pinkompatibel. Ausserdem wird es garantiert neben ca. 1039248 Softwareversionen auch mindesten 2 Hardwarerevisionen geben. Da kannst du später immer noch auf einen anderen Prozessor umstellen. Oliver P.S. Wenn du gerne bastelst, ist das ein tolles Projekt. Wenn du eine funktionsfähige Heizungsteuerung brauchst, kauf dir eine UVR1611.
Falk Brunner wrote: > @ Erik M. (rick00) >>Auslegung für den Anfang: 3 Heizkreise, Puffer, Holzkessel > > Als Anfänger. Hmmm. Naja schaun ma mal was ich bis nächsten Winter so zusammenkrieg ;-) Falk Brunner wrote: >Nicht so ohne weiteres. Mit -Os ist im wesentlichen alles OK. Der Rest >hängt davon ab, ob du solche Monster wie printf(), scanf() und >Fliesskommaberechnungen nutzt. Zum Glück steht im AVR-GCC-Tutorial bzw. im Artikel Festkommaarithmetik genau das drinnen, weshalb ich einen Bogen um diese Fkt.en gemacht habe. Kann es sein, daß die Verwendung von _delay_us(), welche ich oft verwendet habe, viel Platz brauchen? Oliver wrote: >Ausserdem wird es garantiert neben ca. 1039248 Softwareversionen auch >mindesten 2 Hardwarerevisionen geben. Da kannst du später immer noch auf >einen anderen Prozessor umstellen. Das glaub ich auch :-) >P.S. Wenn du gerne bastelst, ist das ein tolles Projekt. Wenn du eine >funktionsfähige Heizungsteuerung brauchst, kauf dir eine UVR1611. Danke für den Tipp, als Rettungsanker, falls meine Steuerung nix wird sicherlich toll, aber auch nicht ganz billig. Danke für eure Ratschläge und Hilfe! Grüsse Rick
@ Erik M. (rick00) >Kann es sein, daß die Verwendung von _delay_us(), welche ich oft >verwendet habe, viel Platz brauchen? Naja, was ist bei dir "oft"? Die Funktion ist ein Assemblermacro und braucht glaub ich 4..5 Worte, sprich 8..10 Bytes. Nicht so tragisch. ABER! Du darfst sie keinesfalls mit variablen Parametern nutzen! Siehe http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Warteschleifen_.28delay.h.29 MFG Falk
Hi! Mit oft versteh ich, daß ich die Delay-Funktionen auch mehrmals mittels for-Schleife aufrufe, um größere Delay-Werte zu erhalten. Siehe Anhang. Grüsse Rick
>inline void delay_us(uint8_t delay, uint8_t m) >{ > uint8_t i; > > for(i=1;i<=m;i++) //Wartezeit multiplizieren > _delay_us(delay); >} Das funktioniert nicht. _delay_us() nimmt keine Variablen. Es müssen konstante Werte sein. Der Compiler muss beim compilieren wissen wie gross delay ist. Das dürfte besser sein: inline void delay_us(uint16_t delay) { while(delay--) //Wartezeit multiplizieren { _delay_us(1); } }
@ Erik M. (rick00)
Wie holger schon sagte, deine Funktion delay_us ist Unsinn. Und vor
allem sind solche kleinen Verzögerungen nicht wirklich in der Form
realisierbar. Braucht man auch nicht wirklich. _delay_us() nutzt man nur
mit konstanten Parametern. Einzig _delay_ms() kann man wie im Link oben
gezeigt aufbohren (Millisekunden, nicht MIKROsekunden).
Nimm mal diese komische Funktion raus und staune über die Codegrösse.
@ holger (Gast)
>Das dürfte besser sein:
Nee, das ist Augenwischerei. Vor allem bei relativ niedrigen
Taktfrequenzen stimmen die Zeiten hinten und vorne nicht. Bei 4 MHz ist
eine Mikrosekunde gerade mal 4 Takte lang. Das reicht gerade mal zum
runterzählen der 16 Bit Variable.
MFG
Falk
@ Erik M. (rick00) Noch ein paar Anmerkungen. - Deine Delays sind konstant >delay_us(48,11); Waum nicht gleich 48*11= 528us warten? Vorsicht, mit _delay_us() geht das nicht unbedingt. Besser _delay_ms() nutzen, beide Funktionen arbeiten auch mit Kommazahlen. _delay_ms(0.528); Das gleiche für >delay_us(33,2); Hier aber mit der _delay_us() Funktion. _delay_us(66); - Dein Switch kann wesentlich vereinfacht werden, spart Code und ist übersichtlicher.
1 | void temp_channel(uint8_t ch) |
2 | {
|
3 | if (ch & 0x01) |
4 | ADR_0 |= (1<<ADR_0_PIN); |
5 | else
|
6 | ADR_0 &= ~(1<<ADR_0_PIN); |
7 | |
8 | if (ch & 0x02) |
9 | ADR_1 |= (1<<ADR_1_PIN); |
10 | else
|
11 | ADR_1 &= ~(1<<ADR_1_PIN); |
12 | |
13 | if (ch & 0x04) |
14 | ADR_2 |= (1<<ADR_2_PIN); |
15 | else
|
16 | ADR_2 &= ~(1<<ADR_2_PIN); |
17 | |
18 | _delay_us(2); //2us Umschaltzeit (minimum 1usec) |
19 | }
|
MFG Falk
@ Falk
>Nee, das ist Augenwischerei.
Weiss ich doch.
_delay_us(1);
Macht ein Delay von MINDESTENS einer us.
Wenn man 2us möchte ist eine Schleife sicher nicht
von Vorteil. Da ist _delay_us(2) besser.
Das Problem ist das man ganz schnell mal dumme Sachen macht:
_delay_us(1000)
Und das ist problematisch. 1000 ist zu groß. Siehe Doku zu _delay_us().
Man kann die Auflösung in Schleifen je nach Bedarf etwas verbessern
ohne in die Falle zu treten:
while(delay-=10) //Wartezeit multiplizieren
{
_delay_us(10);
}
Einigermassen genaues Timing ist mit _delay_us() und _delay_ms()
nur möglich wenn man weiss was man tut. Und dann
noch die kleinen Problemchen das man die Optimierung
im makefile auf jeden Fall aktivieren muss.
Falk Brunner wrote: > @ Erik M. (rick00) > > Noch ein paar Anmerkungen. > - Deine Delays sind konstant eben > >>delay_us(48,11); > > Waum nicht gleich 48*11= 528us warten? Vorsicht, mit _delay_us() geht > das nicht unbedingt. Besser _delay_ms() nutzen, beide Funktionen > arbeiten auch mit Kommazahlen. > > _delay_ms(0.528); > Ich habe schon im libc Manual nachgeschaut, ob _delay_ms() auch mit Kommazahlen arbeitet, hab allerdings nichts gefunden. bei 528usec ist diese Lösung sicherlich besser...aber > Das gleiche für > >>delay_us(33,2); > > Hier aber mit der _delay_us() Funktion. > > _delay_us(66); > bei 66usec gibts ein Problem, denn ich verwende einen 16Mhz Quarz und da ist bei 48usec schluß, weshalb ich 33x2usec verwendet habe. Da muß ich wohl _delay_ms(0.066) verwenden. > - Dein Switch kann wesentlich vereinfacht werden, spart Code und ist > übersichtlicher. > Wie fallen einem solche Sachen ein? Ich habe noch nicht alle Fälle durchprobiert, aber scheint zu funktionieren. Selber wär mir das nie eingefallen, für mich eine sehr "eigenartige" Art zu denken. ..C-denkweise....macht mir ziemlich Schwierigkeiten! Übersichtlicher? für mich nicht wirklich. Danke für die Verbesserung, ich werds natürlich einbauen, wenns funktioniert, was es warscheinlich tut. > >
1 | > void temp_channel(uint8_t ch) |
2 | > { |
3 | > if (ch & 0x01) |
4 | > ADR_0 |= (1<<ADR_0_PIN); |
5 | > else |
6 | > ADR_0 &= ~(1<<ADR_0_PIN); |
7 | >
|
8 | > if (ch & 0x02) |
9 | > ADR_1 |= (1<<ADR_1_PIN); |
10 | > else |
11 | > ADR_1 &= ~(1<<ADR_1_PIN); |
12 | >
|
13 | > if (ch & 0x04) |
14 | > ADR_2 |= (1<<ADR_2_PIN); |
15 | > else |
16 | > ADR_2 &= ~(1<<ADR_2_PIN); |
17 | >
|
18 | > _delay_us(2); //2us Umschaltzeit (minimum 1usec) |
19 | > } |
20 | >
|
>
Grüsse Rick
@ Erik M. (rick00) >> _delay_ms(0.528); >> >Ich habe schon im libc Manual nachgeschaut, ob _delay_ms() auch mit >Kommazahlen arbeitet, hab allerdings nichts gefunden. ??? Der Parameter der Funktion (die eigentlich nur eine Macro ist) ist ein double! "Two wrapper functions allow the specification of microsecond, and millisecond delays directly, using the application-supplied macro F_CPU as the CPU clock frequency (in Hertz). These functions operate on double typed arguments, however when optimization is turned on, the entire floating-point calculation will be done at compile-time." >> _delay_us(66); >> >bei 66usec gibts ein Problem, denn ich verwende einen 16Mhz Quarz und da >ist bei 48usec schluß, weshalb ich 33x2usec verwendet habe. >Da muß ich wohl _delay_ms(0.066) verwenden. Oder 2 mal _delay_us(33); Der Unterschied zwischen _delay_ms() und delay_us() ist nur der, dass erstere mit einem 16 Bit Zähler arbeitet und 4 Takte pro Schleifendurchlauf braucht, während es bei der zweiten ein 8 Bit Zähler ist und nur 3 Takte pro Durchlauf braucht. Damit kann man die zeit feiner einstellen. Ist hier aber bei 16 MHz und 66us egal. >> - Dein Switch kann wesentlich vereinfacht werden, spart Code und ist >> übersichtlicher. >Wie fallen einem solche Sachen ein? Mein Matheprof propagierte immer "Die Methode des scharfen Blicks". Das Delay ist über drin, kann also rausgezogen werden, ist wie in der Mathematik das Ausklammern von Faktoren. Der Rest macht nix anderes, als deine drei Bits auf verschiedene Ports und verschiedene Bits zu kopieren. Thats it. >Selber wär mir das nie eingefallen, für mich eine sehr "eigenartige" Art >zu denken. ..C-denkweise....macht mir ziemlich Schwierigkeiten! Nein, nicht wirklich. Wenn man mal länger drüber nachdenkt, ist eher die "normale" Denkweise im Alltag eigenartig, weil wild gewachsen und selten logisch hinterfragt. >Übersichtlicher? für mich nicht wirklich. Nicht? Meine Lösung passt problemlos auf eine Bildschirmseite, deine nicht. Und zuviele Leerzeilen stören auch nur. Man solls auch nicht übertreiben. MFG Falk P.S. Wie hat sich die Codegrösse gändert, als du die variable _delay_us() rausgenommen hast?
Falk Brunner wrote: > @ Erik M. (rick00) > >>> _delay_ms(0.528); >>> >>Ich habe schon im libc Manual nachgeschaut, ob _delay_ms() auch mit >>Kommazahlen arbeitet, hab allerdings nichts gefunden. > > ??? > Der Parameter der Funktion (die eigentlich nur eine Macro ist) ist ein > double! > > "Two wrapper functions allow the specification of microsecond, and > millisecond delays > directly, using the application-supplied macro F_CPU as the CPU clock > frequency (in > Hertz). These functions operate on double typed arguments, however when > optimization > is turned on, the entire floating-point calculation will be done at > compile-time." > O.k da hab ich falsch geschaltet? Hab geade nochmal im C-Buch nachgelesen. Double ist das genauere Float. Hab ich mit dem DWORD verwechselt. >>> _delay_us(66); >>> >>bei 66usec gibts ein Problem, denn ich verwende einen 16Mhz Quarz und da >>ist bei 48usec schluß, weshalb ich 33x2usec verwendet habe. > >>Da muß ich wohl _delay_ms(0.066) verwenden. > > Oder 2 mal _delay_us(33); > > Der Unterschied zwischen _delay_ms() und delay_us() ist nur der, dass > erstere mit einem 16 Bit Zähler arbeitet und 4 Takte pro > Schleifendurchlauf braucht, während es bei der zweiten ein 8 Bit Zähler > ist und nur 3 Takte pro Durchlauf braucht. Damit kann man die zeit > feiner einstellen. Ist hier aber bei 16 MHz und 66us egal. > >>> - Dein Switch kann wesentlich vereinfacht werden, spart Code und ist >>> übersichtlicher. > >>Wie fallen einem solche Sachen ein? > > Mein Matheprof propagierte immer "Die Methode des scharfen Blicks". > > Das Delay ist über drin, kann also rausgezogen werden, ist wie in der > Mathematik das Ausklammern von Faktoren. Der Rest macht nix anderes, als > deine drei Bits auf verschiedene Ports und verschiedene Bits zu > kopieren. Thats it. > Äh ja die Methode des scharfen Blicks. Das hat mir immer schon irgendwie Probleme bereitet. So richtig bei den Differentialgleichungen....oh Graus welch Erinnerungen da hochkommen. Entweder siehst Du es oder Du steckst furchtbar in der Patsche, wie ich immer bei den Schularbeiten in Mathe :-( >>Selber wär mir das nie eingefallen, für mich eine sehr "eigenartige" Art >>zu denken. ..C-denkweise....macht mir ziemlich Schwierigkeiten! > > Nein, nicht wirklich. Wenn man mal länger drüber nachdenkt, ist eher die > "normale" Denkweise im Alltag eigenartig, weil wild gewachsen und selten > logisch hinterfragt. > >>Übersichtlicher? für mich nicht wirklich. > > Nicht? Meine Lösung passt problemlos auf eine Bildschirmseite, deine > nicht. Und zuviele Leerzeilen stören auch nur. Man solls auch nicht > übertreiben. > > MFG > Falk > > P.S. Wie hat sich die Codegrösse gändert, als du die variable > _delay_us() rausgenommen hast? Deine Optimierung bezüglich der Fkt. temp_channel: Einsparung etwa 50 Byte. Einsparung innsgesamt: Programm usage vorher fast 20% jetzt nur 8,3%! Das is nicht schlecht, da komm ich ja doch noch vielleicht mit dem mega32 aus. Toll! ThanX Grüsse Rick
Jep. Ursache ist nämlich, dass doch die float-library inkludiert wurde (Da du double-Berechnungen zur Laufzeit ausgeführt hast) PS: double ist bei der avr-libc nicht "besser" als float. Beides ist 32 bit PPS: 32kb reichen schon für verdammt (ja, verdammt!) viele Sachen aus. Bedenke auch, dass sich die Codegröße nicht linear verändert. Wenn der Compiler viele verschiedene Divisions-, Multiplikations- oder ganz andere Funktionen hinzufügt, da dein Programm diese erfordert, steigt die Größe natürlich stark an. Rufst du aber diese Funktion öfters auf, wird sie trotzdem nur einmal im Flash hinterlegt, sodass der Codeverbrauch zu diesem Zeitpunkt sich nicht mehr so stark ändert.
Simon K. wrote: > Jep. > > Ursache ist nämlich, dass doch die float-library inkludiert wurde (Da du > double-Berechnungen zur Laufzeit ausgeführt hast) > Meine for-Schleife wurde so also zur double Multiplikation? > PS: double ist bei der avr-libc nicht "besser" als float. Beides ist 32 > bit > > PPS: 32kb reichen schon für verdammt (ja, verdammt!) viele Sachen aus. Der Änfänger hofft mal ;-) Leider konnte ich meinen RAM verbrauch nicht senken, welcher immer noch bei 19,8% liegt. > > Bedenke auch, dass sich die Codegröße nicht linear verändert. Wenn der > Compiler viele verschiedene Divisions-, Multiplikations- oder ganz > andere Funktionen hinzufügt, da dein Programm diese erfordert, steigt > die Größe natürlich stark an. > > Rufst du aber diese Funktion öfters auf, wird sie trotzdem nur einmal im > Flash hinterlegt, sodass der Codeverbrauch zu diesem Zeitpunkt sich > nicht mehr so stark ändert. leuchtet ein. Gruß Rick
@ Erik M. (rick00) >Meine for-Schleife wurde so also zur double Multiplikation? Nein, der Aufruf _delay_us(delay); dDelay ist variabel, dass muss zur Laufzeit berechnet werden. Damit ist die Funktion aber wertlos. Siehe Doku. >Leider konnte ich meinen RAM verbrauch nicht senken, welcher immer noch >bei 19,8% liegt. Bleiben immer noch 81,2%! Sei doch mal positiv! MFG Falk
Falk Brunner wrote: > @ Erik M. (rick00) > >>Meine for-Schleife wurde so also zur double Multiplikation? > > Nein, der Aufruf > > _delay_us(delay); > dDelay ist variabel, dass muss zur Laufzeit berechnet werden. Damit ist > die Funktion aber wertlos. Siehe Doku. O.k. habs kapiert. > >>Leider konnte ich meinen RAM verbrauch nicht senken, welcher immer noch >>bei 19,8% liegt. > > Bleiben immer noch 81,2%! Sei doch mal positiv! Hast recht :-) Gruß Rick
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.