Attiny 841 und PRR

Gast #6002018
Lesenswert?

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
#6002031
Lesenswert?

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
Gast #6002032
Lesenswert?

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.
Gast #6002180
Lesenswert?

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.
Gast #6002186
Lesenswert?

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
Gast #6002196
Lesenswert?

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 */
#6002221
Lesenswert?

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.
Gast #6002239
Lesenswert?

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.
#6002310
Lesenswert?

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.
#6002351
Lesenswert?

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.
Gast #6002364
Lesenswert?

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.
Gast #6002536
Lesenswert?

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
Gast #6002546
Lesenswert?

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 Nummer

https://dict.leo.org/englisch-deutsch/Initial
#6002699
Lesenswert?

M. K. schrieb:
> Wolfgang schrieb:
>> Das PRADC-Bit dort wird gar nicht
>> einzeln angefasst.
>
> Mit
>
>
1
PRR &= ~(1 << PRADC);
>
> 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)
Gast #6002725
Lesenswert?

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.
#6002802
Lesenswert?

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 ;)
Gast #6002872
Lesenswert?

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.
Gast #6002992
Lesenswert?

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.
#6002996
Lesenswert?

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.
Persönliche Seite #6003004
Lesenswert?

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:
1
/*ATtiny2313A*/
2
  USI_DIR_REG |= USI_DATAOUT_PIN | USI_CLOCK_PIN | USI_ENABLE_PIN;
3
//  IN        R24,0x17  // Adresse 0x17 (dez. 23)
4
//  ORI       R24,0xC4
5
//  OUT       0x17,R24                            /*read modify write*/
6
  USI_DIR_REG &= ~USI_DATAIN_PIN;
7
//  CBI       0x17,5    // Adresse 0x17 (dez. 23) /*bit clear*/
8
  USI_OUT_REG |=  USI_DATAIN_PIN;
9
//  SBI       0x18,5                              /*bit set*/
10
  enable_sr595();
11
//  SBI       0x18,2                              /*bit set*/
12

13
/*ATmega161*/
14
  TIMSK &= ~(1 << TICIE1);
15
//  IN        R24,0x39  // Adresse 0x39 (dez. 57)
16
//  ANDI      R24,0xF7
17
//  OUT       0x39,R24
18
  SUART_TXD_PORT |= (1 << SUART_TXD_BIT);
19
//  SBI       0x07,0    // Adresse 0x07
20
  SUART_TXD_DDR  |= (1 << SUART_TXD_BIT);
21
//  SBI       0x06,0
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren