Forum: Compiler & IDEs Umstieg ATmega32 auf AT90CAN128 WinAVR


von Rick M. (rick00)


Lesenswert?

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

von Falk B. (falk)


Lesenswert?

@ 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

von Rick M. (rick00)


Lesenswert?

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

von Falk B. (falk)


Lesenswert?

@ 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

von Rick M. (rick00)


Lesenswert?

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

von Falk B. (falk)


Lesenswert?

@ 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

von Rick M. (rick00)


Lesenswert?

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

von Falk B. (falk)


Lesenswert?

@ 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

von Rick M. (rick00)


Lesenswert?

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

von Peter D. (peda)


Lesenswert?

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

von Rick M. (rick00)


Lesenswert?

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

von Falk B. (falk)


Lesenswert?

@ 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

von Oliver (Gast)


Lesenswert?

>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.

von Rick M. (rick00)


Lesenswert?

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

von Falk B. (falk)


Lesenswert?

@ 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

von Rick M. (rick00)


Angehängte Dateien:

Lesenswert?

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

von holger (Gast)


Lesenswert?

>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);
         }
}

von Falk B. (falk)


Lesenswert?

@  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

von Falk B. (falk)


Lesenswert?

@  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

von holger (Gast)


Lesenswert?

@ 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.

von Rick M. (rick00)


Lesenswert?

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

von Falk B. (falk)


Lesenswert?

@ 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?

von Rick M. (rick00)


Lesenswert?

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

von Simon K. (simon) Benutzerseite


Lesenswert?

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.

von Rick M. (rick00)


Lesenswert?

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

von Falk B. (falk)


Lesenswert?

@ 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

von Rick M. (rick00)


Lesenswert?

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
Noch kein Account? Hier anmelden.