Forum: Mikrocontroller und Digitale Elektronik Attiny 841 und PRR


von Paul (Gast)


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

von Holger L. (max5v)


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

von Stefan F. (Gast)



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.

von Paul (Gast)


Lesenswert?

Sorry, habe ab Seite 128 gesucht. Die anderen habe ich gar nicht so 
wahrgenommen. Danke für eure Hilfe.
LG Paul

von Paul (Gast)


Lesenswert?

Noch eine Frage dazu.
Muss man den ADC vor der Nutzung einschalten?
Das Beispiel oben setzt PRADC auf 1 und negiert es?

von Einer K. (Gast)


Lesenswert?

Auch das steht im Datenblatt.

von Der_Kluge (Gast)


Lesenswert?

Mann

Das muss man wissen, wenn man mit AVRs arbeitet - das sind 
GRUNDKENNTNISSE!!!

von Stefan F. (Gast)


Lesenswert?

Auf Seite 38 ist der Default-Wert für das Register angegeben.

von Paul (Gast)


Lesenswert?

Danke an den Klugen. Betrachte es als Klugscheisserei

von Wolfgang (Gast)


Lesenswert?

Paul schrieb:
> Das Beispiel oben setzt PRADC auf 1 und negiert es?

Nein, es löscht das PRADC-Bit im PRR.

von Karl M. (Gast)


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.

von Der Kluge (Gast)


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

von Der Kluge (Gast)


Lesenswert?

Zu Deiner Info - lies mal:
https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial

Paul schrieb:
> Danke an den Klugen. Betrachte es als Klugscheisserei

von Der Kluge (Gast)


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 */

von M. K. (sylaina)


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.

von Wolfgang (Gast)


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.

von Paul (Gast)


Lesenswert?

Danke Wolfgang für deine Info

von Der Kluge (Gast)


Lesenswert?

Mann

Du bist wirklich unfähig - das steh doch ALLES im von mir zitierten link 
- kannste wirklich nicht lesen oder willste nich??

von Axel S. (a-za-z0-9)


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.

von M. K. (sylaina)


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.

von Wolfgang (Gast)


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.

von Paul (Gast)


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

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

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.

von M. K. (sylaina)


Lesenswert?

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.

von Theor (Gast)


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

von Axel S. (a-za-z0-9)


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)

von Wolfgang (Gast)


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.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

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.

von Paul (Gast)


Lesenswert?

Irgendwie habe ich das Gefühl, da es verschiedene Meinungen gibt. Da 
hilft wahrscheinlich nur ausprobieren.

von M. K. (sylaina)


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

von Stefan F. (Gast)


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.

von Einer K. (Gast)


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.

von Axel S. (a-za-z0-9)


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.

von Lötlackl *. (pappnase) Benutzerseite


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.

von leo (Gast)


Lesenswert?

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

von Lötlackl *. (pappnase) Benutzerseite


Lesenswert?

Axel S. schrieb:
> Und wenn die Zieladresse von SBI/CBI adressiert werden kann.

Dann isses klar. read-modify-write

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.