Hallo
habe in einem kleinen Beispiel zu einem Attiny 841 die Zeile gefunden:
1
PRR&=~(1<<PRADC);// Power on ADC
Leider konnte ich keinerlei Hinweis dazu finden. Im Datenblatt des Ati
841 konnte ich auch nichts finden. Was macht das?
(Attiny 841/ 16MHz/ C)
Aus dem Programm leite ich es so ab, das der ADC damit eingeschaltet
wird.
Konnte aber nichts dazu finden.
LG Paul
Seite 38 Kapitel 7.4.2 !?
PRR – Power Reduction Register
The Power Reduction Register provides a method to reduce power
consumption by allowing peripheral clock signals to
be disabled.
Bit 0 – PRADC: Power Reduction ADC
Writing a logic one to this bit shuts down the ADC. The ADC must be
disabled before shut down. The analog comparator
cannot be used when the ADC is shut down
Paul schrieb:> Aus dem Programm leite ich es so ab, das der ADC damit eingeschaltet> wird.
Der ADC wird abgeschaltet, wenn das Bit 1 ist.
> Konnte aber nichts dazu finden.
Wo hast du denn gesucht? Erste Anlaufstelle sollte immer das Datenblatt
des Chip sein. Da findet man es auch umgehend, wenn man nach ADC, PRR
oder PRADC sucht.
Paul schrieb:> Danke an den Klugen. Betrachte es als Klugscheisserei
Man sollte den Thread beenden, er will nichts lernen und versteht nicht,
dass alles notwendige im Datenblatt steht.
Die Grundlagen einer Sprache, ob AVR Assembler oder C sollte man schon
kennen.
Dann könnte man sich nur über der Interpretation und Nebeneffekte
unterhalten.
Karl M. schrieb:> Man sollte den Thread beenden, er will nichts lernen und versteht nicht,> dass alles notwendige im Datenblatt steht.
Ja, leider hast Du recht; Paul ist nicht nur beratungsresistent, sondern
auch unfähig - und unwillens, Datenblätter zu lesen und zu verstehen.
Schade um die Zeit
Der Kluge schrieb:> Paul schrieb:>> Danke an den Klugen. Betrachte es als Klugscheisserei
lies:
https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Zugriff_auf_Register
speziell:
Verändern von Registerinhalten
Einzelne Bits setzt und löscht man "Standard-C-konform" mittels
logischer (Bit-) Operationen.
x |= (1 << Bitnummer); // Hiermit wird ein Bit in x gesetzt
x &= ~(1 << Bitnummer); // Hiermit wird ein Bit in x geloescht
Es wird jeweils nur der Zustand des angegebenen Bits geändert, der
vorherige Zustand der anderen Bits bleibt erhalten.
Beispiel:
#include <avr/io.h>
...
#define MEINBIT 2
...
PORTA |= (1 << MEINBIT); /* setzt Bit 2 an PortA auf 1 */
PORTA &= ~(1 << MEINBIT); /* loescht Bit 2 an PortA */
Paul schrieb:> Leider konnte ich keinerlei Hinweis dazu finden. Im Datenblatt des Ati> 841 konnte ich auch nichts finden. Was macht das?
Steht doch hinten dran: Es schaltet den ADC ein.
Paul schrieb:> Das Beispiel oben setzt PRADC auf 1 und negiert es?
Richtig, es setzt das Bit im PRR auf 0. Jetzt einfach mal lesen: Power
Reduction ADC gleich 0, sprich der Energiesparmodus für den ADC soll
ausgeschaltet werden, d.h. der ADC soll eingeschaltet werden. So schwer
ist das nicht, erst recht wenn man sich ernsthaft damit beschäftigt.
M. K. schrieb:> Paul schrieb:>> Das Beispiel oben setzt PRADC auf 1 und negiert es?>> Richtig ...
Was ist daran richtig?
Das PRADC-Bit wird weder auf 1 gesetzt, noch wird es negiert.
In der Zeile
1
PRR&=~(1<<PRADC);// Power on ADC
wird PRR mit dem konstanten Wert 0b11111110 verundet. Negiert wird die
Konstante 0b00000001 und nicht das PRADC-Bit.
Der Kluge schrieb:> leider hast Du recht; Paul ist nicht nur beratungsresistent, sondern> auch unfähig - und unwillens, Datenblätter zu lesen und zu verstehen.
Er scheint in erster Linie unfähig Datenblätter zu lesen, weil sie auf
Englisch sind. Wobei die Details am Ende auch egal sind:
@Paul: wenn dich das Lesen eines englischsprachigen Datenblatts
überfordert, dann ist das kein Hobby für dich. Such dir was anderes.
Oder lern halt Englisch. So schwer ist das nicht. Das haben Zillionen
anderer Menschen geschafft. U.a. all jede, die dir hier helfen, obwohl
du ihnen eigentlich nur Lebenszeit stiehlst.
Wolfgang schrieb:> M. K. schrieb:>> Paul schrieb:>>> Das Beispiel oben setzt PRADC auf 1 und negiert es?>>>> Richtig ...>> Was ist daran richtig?> Das PRADC-Bit wird weder auf 1 gesetzt, noch wird es negiert.>> In der Zeile
1
PRR&=~(1<<PRADC);// Power on ADC
wird PRR mit dem
> konstanten Wert 0b11111110 verundet. Negiert wird die Konstante> 0b00000001 und nicht das PRADC-Bit.
Im Endeffekt wird dadurch das PRADC-Bit auf Null gesetzt, man kann hier
durchaus davon sprechen, dass das PCADC-Bit zunächst auf 1 gesetzt wird
(1 << PRADC) und dann negiert wird (~).
Deine Erklärung stimmt ja auch nicht so ganz. Wenn du schon Klugscheißen
willst, dann doch bitte richtig:
Es wird zunächst eine 1 um PRADC-Stellen weit binär nach links geschoben
und dann wird dieser Wert bitweise invertiert und mit dem Register PRR
verundet.
M. K. schrieb:> Im Endeffekt wird dadurch das PRADC-Bit auf Null gesetzt, man kann hier> durchaus davon sprechen, dass das PCADC-Bit zunächst auf 1 gesetzt wird> (1 << PRADC) und dann negiert wird (~).
Quatsch, das PRADC-Bit sitzt im PRR. Und mit dem Register wird nur die
Verundung mir der Konstanten gemacht. Das PRADC-Bit dort wird gar nicht
einzeln angefasst.
Im ersten Schritt in der Programmzeile "(1<<PRADC)" wird eine Konstante
mit dem Wert 0b00000001 generiert.
Im Datenblatt unter 7.4.2. PRR Register ist das PRR mit den
entsprechenden Bits angegeben. Im Bit 0 steht "Inital Vlue PRADC = 0".
Muss ich das Bit trotzdem auf 0 setzen?
PRADC = 1 - ADC aus
PRADC = 0 - ADC ein
LG Paul
PS: Mit englisch geht es einiger massen, bloss technisches englisch ist
eine andere Nummer
Paul schrieb:> Im Bit 0 steht "Inital Vlue PRADC = 0".> Muss ich das Bit trotzdem auf 0 setzen?
Nö, steht doch da. Wenn als Startwert nach Reset da schon eine Null
steht, braucht man da nix zu nullen.
Paul schrieb:> Im Datenblatt unter 7.4.2. PRR Register ist das PRR mit den> entsprechenden Bits angegeben. Im Bit 0 steht "Inital Vlue PRADC = 0".> Muss ich das Bit trotzdem auf 0 setzen?> PRADC = 1 - ADC aus> PRADC = 0 - ADC ein> LG Paul>> PS: Mit englisch geht es einiger massen, bloss technisches englisch ist> eine andere Nummerhttps://dict.leo.org/englisch-deutsch/Initial
>> wird einzig und alleine das PRADC-Bit zu 0 gesetzt, hier wird im> Endeffekt sehr wohl nur das PRADC-Bit einzeln angefasst.
Das kann man aus dem C-Code allein nicht ablesen. Je nachdem ob PRR als
I/O Register erreichbar ist und evtl. auch, welche Optimierungsstufe der
Compiler verwendet, kann dieses C-Fragment wahlweise zu einer atomaren
CBI Instruktion umgesetzt werden, die tatsächlich nur das eine Bit
anfaßt. Oder es wird ein read-modify-write daraus, das beim Schreiben
alle Bits anfaßt. Und ja, bei I/O Registern kann es sehr wohl einen
Unterschied machen, ob man ein Bit, das bereits auf 1 steht, nochmal mit
einer 1 beschreibt oder eben nicht.
Die Wortwahl vom "Bit anfassen" ist unglücklich und im gegebenen Kontext
auch noch vollkommen irrelevant. Es geht schlicht darum, das Bit für
"ADC Stromsparen" im "Stromsparregister" zurückzusetzen. Um das zu
verstehen, muß man einerseits das Datenblatt lesen (kann Paul nicht) und
braucht andererseits Grundkenntnisse zum Thema Bitmanipulation in C (da
habe ich bei Paul auch Zweifel)
M. K. schrieb:> wird einzig und alleine das PRADC-Bit zu 0 gesetzt, hier wird im> Endeffekt sehr wohl nur das PRADC-Bit einzeln angefasst.
Und du meinst, dass der Compiler die Konstante auswertet und anhand des
Ergebnisses statt des Codes für einen einzelnen bytebreiten
Read-Modify-Write Zugriff Code für bis zu acht Einzelbitzugriffen macht
- vergiss es.
Guck mal den generierten Assembercode an.
Axel S. schrieb:> Das kann man aus dem C-Code allein nicht ablesen.
Warum nicht? Da steht '&=' , was klar macht, das es eine
Read-Modify-Write Operation ist.
Axel S. schrieb:> Das kann man aus dem C-Code allein nicht ablesen.
Öhm doch.
Axel S. schrieb:> Es geht schlicht darum, das Bit für> "ADC Stromsparen" im "Stromsparregister" zurückzusetzen.
Genauer: Zu 0 zu setzen. Es gibt auch Bits, die sind Default auf 1 ;)
Axel S. schrieb:> Die Wortwahl vom "Bit anfassen" ist unglücklich
Unter "Anfassen" versteht offenbar jeder etwas völlig anderes.
Wolfgang schrieb:> Und du meinst, dass der Compiler die Konstante auswertet und anhand des> Ergebnisses statt des Codes für einen einzelnen bytebreiten> Read-Modify-Write Zugriff Code für bis zu acht Einzelbitzugriffen macht> - vergiss es.
Das hab ich auch nicht behauptet. Nicht zuviel in die Texte
reininterpretieren. Der Schlüssel liegt bei meinem Text nicht in
"Anfassen" sondern in der Phrase "Im Endeffekt". Kleines Gegenbeispiel
dazu: Es ist egal ob ich ins Meer springe, in einen Fluss falle oder
durch den Regen laufen: Im Endeffekt werde ich immer nass ;)
Wolfgang schrieb:> Und du meinst, dass der Compiler die Konstante auswertet und anhand des> Ergebnisses statt des Codes für einen einzelnen bytebreiten> Read-Modify-Write Zugriff Code für bis zu acht Einzelbitzugriffen macht> - vergiss es.
Ich bin ziemlich sicher, dass der Compiler solche Optimierungen bei
einzelnen Bits vornimmt. Es ist aber schon lange her, dass ich das
tatsächlich überprüft habe.
Paul schrieb:> Irgendwie habe ich das Gefühl, da es verschiedene Meinungen gibt.> Da hilft wahrscheinlich nur ausprobieren.
Nein, hier gibt es nur ein Wissen!
Das im Datenblatt.
Alle Unsicherheiten finden sich nur in deinem Kopf.
(und evtl. noch in ein paar anderen Köpfen)
Was der Kompiler daraus macht ist klar:
Lesen modifizieren schreiben.
Weil das Register eine hohe Adresse hat. (steht auch so im Datenblatt)
Läge die Adresse im IO Bereich, wäre es nur 1 ASM Statement.
Und ja, das kann der GCC erkennen und mit -Os auch soweit optimieren.
Matthias S. schrieb:> Axel S. schrieb:>> Das kann man aus dem C-Code allein nicht ablesen.>> Warum nicht? Da steht '&=' , was klar macht, das es eine> Read-Modify-Write Operation ist.
Der Compiler darf das trotzdem zu SBI/CBI compilieren. Und er macht das
auch. Immer dann, wenn nur ein einzelnes Bit zu setzen oder rückzusetzen
ist. Und wenn die Zieladresse von SBI/CBI adressiert werden kann. Und
möglicherweise muß die Optimierung noch angeschaltet sein.
Axel S. schrieb:> Der Compiler darf das trotzdem zu SBI/CBI compilieren. Und er macht das> auch. Immer dann, wenn nur ein einzelnes Bit zu setzen oder rückzusetzen> ist. Und wenn die Zieladresse von SBI/CBI adressiert werden kann. Und> möglicherweise muß die Optimierung noch angeschaltet sein.
Wie Axel S. schon andeutete, die richtige Antwort lautet wie immer:
Kommt drauf an.
Das gleichzeitige setzen oder löschen mehrerer Bits in einem Register
resultiert immer in eine "read-modify-write"-Sequenz.
Das setzen oder löschen eines einzelnen Bits resultiert, je nach dem, an
welcher Adresse das Register liegt, entweder in einer direkten Anweisung
(sbi, cbi),
oder in eine "read-modify-write"-Sequenz.
Beispielhaft seien hier ein paar C-Codefetzen mit generiertem
Assemblercode mal für einen ATtiny2313A und einmal für einen ATmega161
aufgeführt:
Zu "cbi" sei beispielhaft folgendes erwähnt (gilt auch für "sbi"):
aus AVR_Instruction_set.pdf (steinalt) S.48
Clears a specified bit in an I/O Register. This Instruction operates on
the lower 32 I/O Registers-addresses 0-31.
An welcher Adresse das "PRR"-Register liegt, steht sicherlich im
Datenblatt.
Axel S. schrieb:> Der Compiler darf das trotzdem zu SBI/CBI compilieren. Und er macht das> auch.
Nope. Nicht bei PRR:
SBI A,b 0 ≤ A ≤ 31, 0 ≤ b ≤ 7 PC ← PC + 1
PRR hat Adresse (A) 0x70.
leo