Hi,
im Quellcode von einigen AVR Projekten, die Gebrauch vom ADC machen, ist
mir aufgefallen, dass das ADC im ersten Schritt "eingestellt" wird, und
erst im zweiten die ersten Konvertierung beginnt.
Das sieht dann in etwa so aus:
1
ADCSRA=_BV(ADEN)|_BV(ADIE)|_BV(ADPS2)|_BV(ADPS0);
2
ADCSRA|=_BV(ADSC);
Inwiefern ist es denn möglich/sinnvoll bzw. nicht sinnvoll das zusammen
zu fassen, sodass es ein paar Byte weniger Programmcode werden. Ich
finde im Datenblatt jedenfalls nichts was dagegen spricht.
Aussehen würde das dann in etwa so:
ADC schrieb:> Hi,>> im Quellcode von einigen AVR Projekten, die Gebrauch vom ADC machen, ist> mir aufgefallen, dass das ADC im ersten Schritt "eingestellt" wird, und> erst im zweiten die ersten Konvertierung beginnt.>> Das sieht dann in etwa so aus:>>
>> Inwiefern ist es denn möglich/sinnvoll bzw. nicht sinnvoll das zusammen> zu fassen, sodass es ein paar Byte weniger Programmcode werden.
Das ganze wird dann sinnvoll, wenn du bedenkst, dass diese
Konfigurierung im Regelfall ja nur ein einziges Mal bei Programmstart
gemacht wird und danach ja nur noch mittels ADSC jeweils die nächste
Messung gestartet wird.
Allerdings zeigt sich auch immer wieder, dass dieses einfache Konzept
1
intmain()
2
{
3
KonfigurierungundHardwareinitialisieren
4
zbdenADCeinschaltenunddieADCVorteilereinstellen
5
6
sei();
7
8
while(1){
9
10
Programmlogik,zbeineADCWandlungstarten
11
12
}
13
}
des öfteren schon mal auf Verständnisprobleme bei so manchem
Programmierer stösst.
> Ich> finde im Datenblatt jedenfalls nichts was dagegen spricht.>> Aussehen würde das dann in etwa so:>>
Karl Heinz Buchegger schrieb:> Allerdings zeigt sich auch immer wieder, dass dieses einfache Konzept
Das habe ich schon verstanden. Bei mir geht es einzig und allein um die
Initialisierung. Dort vollführe ich genau eine Wandlung und halte diese
vor, sodass ggf. andere Module bereits darauf zugreifen können.
In einem Timer wird dann regelmäßig eine neue Messung durchgeführt und
verarbeitet.
Karl Heinz Buchegger schrieb:> Ich würds trotzdem nicht tun.
Wieso nicht? Damit spart man sich 10 Byte und einen echten Grund,
welcher dagegen spricht, hast du nicht genannt :(.
Dennoch vielen Dank schon einmal ...
ADC schrieb:> Wieso nicht? Damit spart man sich 10 Byte
wie kommst du auf 10?
Das eine Bit im ADCSRA zu setzen dauert genau 1 Assembler-Befehl und
damit 2 Byte Flash. Bei deeeen Flash-Größen ziemlich uninteressant.
> und einen echten Grund, welcher dagegen spricht, hast du nicht genannt
Ich bin eben ein Verfechter der alten Schule: zuerst konfigurieren und
dann erst einschalten. Keine Experimente oder Race-Conditions. Hat sich
für mich bewährt.
Karl Heinz Buchegger schrieb:> wie kommst du auf 10?
Durch Ausprobieren ;).
Karl Heinz Buchegger schrieb:> Das eine Bit im ADCSRA zu setzen dauert genau 1 Assembler-Befehl und> damit 2 Byte Flash. Bei deeeen Flash-Größen ziemlich uninteressant.
Dann sag das meinem avr-gcc. Im "zusammengefassten" Teil generiert er
mir Folgendes für das Setzen des Bits:
1
lds r24, 0x007A
2
ori r24, 0x40
3
sts 0x007A, r24
Laut Instruktionssatz sind das 10 Byte (4 + 2 + 4). So genau kenne ich
den Instruktionssatz auch wieder nicht, aber "sbi" geht nur bei I/O
Registern (Adressen 0 - 31). Und sobald ich den Inhalt des ADCSRA in ein
Register kopieren muss, welches ich bearbeiten kann, komme ich um die 8
Byte für das "lds" und "sts" nicht herum.
Ich würde fast davon ausgehen, dass der Compiler bei solchen einfachen
Registeroperationen sein Bestes gibt und kann mir kaum vorstellen, dass
es da noch Optimierungspotential gibt. Oder hast du hier eine Idee?
Karl Heinz Buchegger schrieb:> Ich bin eben ein Verfechter der alten Schule: zuerst konfigurieren und> dann erst einschalten. Keine Experimente oder Race-Conditions. Hat sich> für mich bewährt.
Naja, das ist für mich zunächst einmal ziemlich subjektiv. Wenn es
anders herum auch geht, und das Datenblatt einen nicht davon abhält,
dann sehe ich nämlich keinen Grund das nicht so zu machen.
Vielen Dank!
Übrigens bezieht sich das o.g. Assembler Listing auf den Fall der nicht
zusammengefassten Version. Konkret sind die o.g. Befehle für das Setzen
des ADSC Bits im ADCSRA Register zuständig.
ADC schrieb:> Dann sag das meinem avr-gcc. Im "zusammengefassten" Teil generiert er> mir Folgendes für das Setzen des Bits:>>
1
> lds r24, 0x007A
2
> ori r24, 0x40
3
> sts 0x007A, r24
4
>
>> Laut Instruktionssatz sind das 10 Byte (4 + 2 + 4). So genau kenne ich> den Instruktionssatz auch wieder nicht, aber "sbi" geht nur bei I/O> Registern (Adressen 0 - 31). Und sobald ich den Inhalt des ADCSRA in ein> Register kopieren muss, welches ich bearbeiten kann, komme ich um die 8> Byte für das "lds" und "sts" nicht herum.
OK. erwischt.
Ich hab nicht bei allen Prozessoren nachgesehen, wo im Speicher das
ADCSRA Register liegt und ob es mit einem sbi erreichbar ist. Bei einem
Mega8 geht ein sbi.
Karl Heinz Buchegger schrieb:> Ich hab nicht bei allen Prozessoren nachgesehen, wo im Speicher das> ADCSRA Register liegt und ob es mit einem sbi erreichbar ist.
Gut, ich habe auch nicht erwähnt auf welchen Prozessor ich mich hier
beziehe (ATmega168), wobei ich mir kaum vorstellen kann, dass es einen
Controller in der AVR Familie gibt bei welchem das ADCSRA im I/O Bereich
liegt. Wobei ich das jetzt auch nicht kontrolliert habe ;).
ADC schrieb:> Karl Heinz Buchegger schrieb:>> Ich hab nicht bei allen Prozessoren nachgesehen, wo im Speicher das>> ADCSRA Register liegt und ob es mit einem sbi erreichbar ist.>> Gut, ich habe auch nicht erwähnt auf welchen Prozessor ich mich hier> beziehe (ATmega168), wobei ich mir kaum vorstellen kann, dass es einen> Controller in der AVR Familie gibt bei welchem das ADCSRA im I/O Bereich> liegt. Wobei ich das jetzt auch nicht kontrolliert habe ;)., der alte
Doch.
Der alte M8 hat es dort liegen, die kleineren Tinys, der Mega16 hat es
per SBI erreichbar.
Also einigen wir uns: Bandbreite 2 bis 10 Bytes.
Sind bei zb 8K Flash immer noch keine Welten.
ADC schrieb:> Gut, ich habe auch nicht erwähnt auf welchen Prozessor ich mich hier> beziehe (ATmega168), wobei ich mir kaum vorstellen kann, dass es einen> Controller in der AVR Familie gibt bei welchem das ADCSRA im I/O Bereich> liegt. Wobei ich das jetzt auch nicht kontrolliert habe ;).
Ich habs mir gerade beim M168 angesehen.
Das ist ja cool.
Die Hälfte der Adressen im I/O Register Bereich ist 'reserved', dafür
drängelt sich alles in dem Bereich, der mittels Bit-Befehle nicht mehr
erreichbar ist.
OK, Ich bin sicher dass Atmel dafür einen extrem guten Grund hat (den
ausser dem Entwicklungsingenieur keiner kennt), aber so ganz einsichtig
ist das für mich nicht.
Spess53 schrieb:> Macht bei mir>> LDS 2 bytes> ori 2 bytes> STS 2 bytes>> oder 3 Befehle
Dann solltest du dir den Instruktionssatz nochmal genau ansehen ;). LDS
und STS gibt es jeweils in zwei Versionen (2 und 4 Byte breit). Die 2
Byte breite Version kann aber nur Bereiche zwischen 0x40..0xbf
adressieren. Das bringt mir in meinem Fall aber nichts.
Wie gesagt: Ich wäre sehr erstaunt, wenn ein Compiler bei einfachen
Registeroperationen nicht "optimal" arbeitet. Das ist ja verhältnismäßig
einfach umzusetzen.
Um zur eigentlichen Frage zurück zu kommen: Gibt es noch andere
Meinungen? Bzw. Meinungen von anderen Leuten ;). Einfach nur aus
Interesse ...
10 Byte hin oder her - das soll jetzt nicht der entscheidende Faktor
sein. Mir geht es eher allgemein ums Prinzip bzw. ob einen Probleme
erwarten.
Hi
>Dann solltest du dir den Instruktionssatz nochmal genau ansehen ;). LDS>und STS gibt es jeweils in zwei Versionen (2 und 4 Byte breit).
Hast Recht. Da war ich beim 'falschen' lds gelandet.
Ansonsten halte ich das Ganze eher für eine akademische Frage. Bei
Autotrigger braucht man, außer im Freerunning-Mode, überhaupt kein ADSC.
MfG Spess
Guten Morgen,
ein wichtiger Grund den ADC nur einmalig zu aktivieren ist, dass der
erste Messwert verworfen werden muss und auch etwas mehr Zeit für die
Wandlung benötigt.
Somit müsste man bei einem Aus - Einschalten, mehr Zeit für die Erste
Wandlung einplanen, das Ergebnis ADCW lesen und verwerfen und danach
eine weitere Messung starten.
Erst jetzt wären die ADC Messwert 'glaubwürdig'.
Steht aber auch alles im Datenblatt.
Hi
>Somit müsste man bei einem Aus - Einschalten, mehr Zeit für die Erste>Wandlung einplanen, das Ergebnis ADCW lesen und verwerfen und danach>eine weitere Messung starten.>Erst jetzt wären die ADC Messwert 'glaubwürdig'.
Hast du das schon mal getestet?
Ich kann nämlich keine nennenswerten Abweichungen feststellen (AVR
Dragon, ADC ATMega644P mit interner Refrenz 2,56V).
>Steht aber auch alles im Datenblatt.
Persönlich liest sich das für mich wie die 'Möglichen Nebenwirkungen'
auf einem Beipackzettel.
MfG Spess
Ein weiterer Grund wäre, dass ich mit dem Mux einen anderen Eingang
auswählen möchte!? Dann ist es schon ganz praktisch, den Zeitpunkt der
Wandlung "im Griff" zu haben.
Grüße,
Jörg
Joerg S: schrieb:> Ein weiterer Grund wäre, dass ich mit dem Mux einen anderen Eingang> auswählen möchte!? Dann ist es schon ganz praktisch, den Zeitpunkt der> Wandlung "im Griff" zu haben.
Dann musst du auf jeden Fall die settling time berücksichtigen, die der
MUX und der S/H braucht (abhängig vom Innenwiderstand der zu messenden
Quelle) bis man überhaupt mit der Wandlung starten darf oder eben Mist
misst.
Also immer besser der Karl Heinz Ansatz:
Im Zweifel jede Race condition vermeiden.
Kontrolliert eines nach dem anderen tun.
Sonst handelt man sich Probleme ein, die nicht reproduzierbar und fast
nicht zu finden sind.
Für mich sind die eingebauten Wandler nichts als bessere Schätzeisen und
sonst nichts.
In den meisten Anwendungen geht es aber gar nicht um absolute
Genauigkeiten, sondern um eine Kombination aus Was und Wann, um sich
dann mit der Änderung herumzuschlagen.
Unter diesen Bedingungen könnte ich mit einem Messwert, der "irgendwann"
angefallen ist, sowieso nichts anfangen. So schön die Antwort vom
A/D-Wandler: "Ja ich habe was für dich", auch im Programmablauf ist.
Karl Heinz Buchegger schrieb:> Die Hälfte der Adressen im I/O Register Bereich ist 'reserved', dafür> drängelt sich alles in dem Bereich, der mittels Bit-Befehle nicht mehr> erreichbar ist.
Ja, leider. Trotzdem verwende ich den ATMega48 recht gern, er hat doch
ein paar nützliche Features mehr als der ATMega8. Und wenn es nur die
ganz brauchbaren PWMs des 8-Bit-Timers sind.
Karl Heinz Buchegger schrieb:> OK, Ich bin sicher dass Atmel dafür einen extrem guten Grund hat (den> ausser dem Entwicklungsingenieur keiner kennt), aber so ganz einsichtig> ist das für mich nicht.
Vermutlich will Atmel "Ordnung schaffen", also bei allen ATMegas
einheitliche Adressen für denselben Zweck benutzen. Das bringt aber
nichts, denn dann könnten sie aber auch gleich einen Einheits-AVR
schaffen, den sie in unterschiedliche Gehäuse packen und ggf. bei
kleineren Gehäusen I/O-Ports weglassen.
ADC schrieb:> Gibt es noch andere> Meinungen? Bzw. Meinungen von anderen Leuten ;). Einfach nur aus> Interesse ...
Ja. Gibt es.
Wenn ich einzelne Bits in I/O-Registern schalten muss, die nicht mit
SBI/CBI erreichbar sind, dann verwende ich auch gern mal vordefinierte
Konstanten, die ich dann nur ausgeben brauch (LDI/Out oder LDI/STS). Das
erspart dann das Read/Mofify/Write-Geraffel.
Und gerade beim ADC gibt es auch andere Strategien als "Starten, warten,
auslesen".
...
amateur schrieb:> Für mich sind die eingebauten Wandler nichts als bessere Schätzeisen und> sonst nichts.
Das dachte ich auch mal. Inzwischen sehe ich das anders. Das kommt aber
natürlich auch auf die Ansprüche an. Andererseits erfordert ein
"besserer" externer ADC auch ein entsprechend besser designtes Board,
ansonsten misst der auch nur Mist.
...
Es kann ja sein dass ich mich irre, aber soweit ich mich erinnern kann
benötigen ADC doch eine gewisse start-time. Das bedeutet er muss diese
Zeit vor der ersten conversion warten.
müsste doch im Datenblatt stehen aber selbst habe ich es nicht
überprüft.