Timer Programmierung Grundlagenfrage

Hallo!

Ich möchte gern die Timer-Programmierung verstehen udlnd lese mich gerade in die einzelnen Bits usw. ein.

Was ich nicht verstehe: Warum arbeiten die Beispiele meistens mit Schiebe- und And-Befehlen, wenn ein but gesetzt werden soll?
Ich könnte das Byte doch genausogut binär darstellen und über eine Addition zuweisen.

Irgendwie habe ich an der Stelle noch einen Denkfehler.

Hat einer eine schöne Quelle, wo das beschrieben wird? Wahescheinlich eher C-Grundlagen als was anderes...

Viele Grüße und vielen Dank!

P.S. Schieben usw. sagt mir eigentlich was, da ich vor etlichen Jahren auch mal Assembler programmiert habe, aber warum macht man das hier?

Frank

Ich könnte das Byte doch genausogut binär darstellen

Das ist doch kaum lesbar. Durch das Schieben werden die Bit-Masken erzeugt. Der Bit-Name ist einfach deren Nummer (von 0 bis 7). Dann schiebt man eine 1 entsprechend nach links um die Maske zu bekommen:
1 << 5 = 0010 0000

Durch ein Oder damit setzt man ein Bit. Gelöscht wird es durch UND mit der invertierten Maske (weil irgendwas UND 0 immer 0 ist)

Dafür kannst du auch das _BV() (bit value) Makro verwenden. z.B.:

TCCR1A = _BV(CS11) | _BV(CS10);

Du siehst den Namen des Registers und des Bits das gesetzt wird. Das ist alles was man wissen muss.

Es gibt auch in der Arduino IDE zusätzliche Makros wie bit() für die Maske und bitSet()/sbi() und bitClear()/cbi() für das Setzen und Löschen eines Bits. Könnte also auch so sein:

bitSet(TCCR1A, CS11);

Bei sowas weiß man ohne Kommentare nicht was gemacht wird:

TCCR1A = 0b1001001;

Und selbst mit Kommentaren ist es schlecht lesbar und wartbar

VIELEN DANK!

Dann hatte ich zumindest technisch keinen Denkfehler.

Lesbarkeit ist tatsächlich deutlich besser. Das verstehe ich jetzt durch deine Beschreibung.

Wie gesagt, vielen Dank für die ausführliche Erklärung!

Frank

Und:

Im Endeffekt landet im Programm genau die Zahl, Die Du zuvor berechnet und 'als Byte' eingegeben hast.
Das zusammen schieben der Bits macht der Kompiler schon beim Kompilieren.
Der muß dafür zwar ein paar Dinge mehr machen, aber bei heutigen Rechner ist diese Zeit wohl kaum der Rede wert.
Wesentlich bessere Lesbarkeit bei identischem Endergebnis.

MfG

Mein Denkfehler waren hauptsächlich die vorgefertigten Konstanten.
Als serenifly geschrieben hat, dass die ja die Position des bits angeben, ist der Knoten geplatzt.

Und zur Geschwindigkeit: Selbst wenn es der Microcontroller selbst machen muss, sind ein Schiebe- und AND-Befehl seit "Urzeiten" die schnellsten Befehle, die so ein Ding hat.

Habt vielen Dank!

Frank

sind ein Schiebe- und AND-Befehl seit "Urzeiten" die schnellsten Befehle, die so ein Ding hat.

AND, ja...
Schieben nicht.
z.B. die AVR haben keinen Barrel-Shifter.

Quellcode:

#include <Streaming.h>

volatile byte s = 6; // um schieben zur Laufzeit zu erzwingen

byte myshift()
{
  return 1 << s; // schieben zur Laufzeit
}

void setup() 
{
  Serial.begin(9600);
  Serial << "Start: "<< __FILE__ << endl;
  Serial << myshift() << endl;
}

void loop() 
{

}

Erzeugter ASM Code:

byte myshift()
{
  return 1 << s;
 540:	20 91 00 01 	lds	r18, 0x0100	; 0x800100 <__data_start>
 544:	81 e0       	ldi	r24, 0x01	; 1
 546:	90 e0       	ldi	r25, 0x00	; 0
 548:	01 c0       	rjmp	.+2      	; 0x54c <main+0x124>
 54a:	88 0f       	add	r24, r24
 54c:	2a 95       	dec	r18
 54e:	ea f7       	brpl	.-6      	; 0x54a <main+0x122>

In kurzform erklärt:
Anstatt Assembler Shift Statements, wird eine Addition in einer Schleife gemacht!
Jeder shift wird zu einer Addition mit sich selber, was einer Multiplikation mit 2 entspricht.
Der Shift im Beispiel kostet 6 Additionen, und eben so viele Sprünge und Schleifenzählerabhandlungen

Hi

Wahrscheinlich wird der Kompiler diesen Weg wählen, weil Er kürzer ist - aber bitweise schieben kann Der schon.
LSL/LSR/ROL/ROR/ASR
Zugegeben - die Dinger sind nur für Byte

MfG
PS
ATmega48A, ATmega48PA, ATmega88A, ATmega88PA, ATmega168A, ATmega1688PA, ATmega328, ATmega328P datasheet
Seite 626 (vor 662)

aber bitweise schieben kann Der schon.

Dennoch bleibt erhalten:
Bitshift um 1 benötigt eine Zeit
Bitshift um 6 benötigt sechs mal die eine Zeit
Und die Schleife muss auch noch sein, wenn der Schiebewert nicht konstant ist.

Übrigens:
ADD Rd,Rd und LSL haben sogar den gleichen Opcode/Maschinencode.
Das eine ist also nur ein Alias für das andere.

Die Aussage, dass schieben zur Laufzeit, zu den billigsten Dingen gehört, ist damit irgendwie nicht so recht haltbar.
Finde ich.

Hi

ORI und SBR müssten ebenfalls identisch sein (OR i, SetBitsRegister)

MfG