Forum: Mikrocontroller und Digitale Elektronik ATmega328P; Bit setzen/löschen eines Integers klappt nicht.


von Ratloser (Gast)


Lesenswert?

Hallo zusammen

Ich bin grad echt am verzweifeln ob des seltsamen verhaltens meines 
Programmcodes.

Geplante Funktion:
Ich möchte immer wenn ein Timerinterrupt passiert einen Pinstatus 
abfragen und den Wert (1/0) Bitweise in einen Integer schreiben. Dazu 
benutze ich eine Funktion. (Das Programm ist etwas grösser als nur den 
Code, aber es macht die Fehlersuche einfacher).

Code:
1
volatile uint8_t puffer=0;
2
volatile uint8_t bit=10;
3
4
ISR (TIMER0_COMPA_vect)
5
{
6
  //mache einige kleine sachen
7
  
8
  //und nun die etwas längere extern...
9
  funktion_abrufen();
10
}
11
12
void funktion_abrufen()
13
{
14
  //Pinstatus abfragen
15
  if (PINB & (1<<0)) puffer |= (1<<bit);    //und Bitweise den Integer verändern
16
  else puffer &= ~(1<<bit);
17
  bit--;
18
}

Problem:
Der Wer des Integers wird nur geändert wenn ich diesen kurz vorher auf 0 
stelle... Hier nochmals Code:
1
void funktion_abrufen()
2
{
3
  //NUR WENN DER PUFFER = 0 IST WIRD DAS BIT GESETZT
4
  puffer=0;
5
  
6
  //Pinstatus abfragen
7
  if (PINB & (1<<0)) puffer |= (1<<bit);    //und Bitweise den Integer verändern
8
  else puffer &= ~(1<<bit);
9
  bit--;
10
}

Wenn ich "puffer" in der Interruptroutine zurücksetze (=0), dann geht 
auch nix... ich seh einfach mein Problem nicht, bin nun schon sehr lange 
am suchen aber finde es einfach nicht.

Vielen Dank für eure Mithilfe und schöne Weihnachten :D

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


Lesenswert?

Ratloser schrieb:
> volatile uint8_t puffer=0;
Das ist gar kein Integer, sondern nur ein Byte. So ein Byte hat 8 
Bitpositionen (0 - 7).
Wenn du jetzt
> puffer |= (1<<bit);
machen willst schiebst du 10 mal ein Bit nach links. Da müsste dir jetzt 
was auffallen :-P

von Ratloser (Gast)


Lesenswert?

Matthias S. schrieb:
> Ratloser schrieb:
>> volatile uint8_t puffer=0;
> Das ist gar kein Integer, sondern nur ein Byte. So ein Byte hat 8
> Bitpositionen (0 - 7).
> Wenn du jetzt
>> puffer |= (1<<bit);
> machen willst schiebst du 10 mal ein Bit nach links. Da müsste dir jetzt
> was auffallen :-P

Oh, hoppla... stimmt. Im richtigen Programm ist das nicht das Problem.
Dort habe ich einen uint32_t und eine höchtste Bitzahl von 26, sollte 
also gehen.

Habe diesen Code zur vereinfachung geschrieben, aber ich kann den 
Originalen Code sonst mitsenden, wenn gewünscht.

Danke dir schonmal

von g457 (Gast)


Lesenswert?

> Im richtigen Programm ist das nicht das Problem. Dort habe ich einen
> uint32_t und eine höchtste Bitzahl von 26, sollte also gehen.

..und schiebst Du auch den passenden Datentyp?

> [..] ich kann den Originalen Code sonst mitsenden, wenn gewünscht.

Natürlich.

von Ratloser (Gast)


Angehängte Dateien:

Lesenswert?

g457 schrieb:
>> Im richtigen Programm ist das nicht das Problem. Dort habe ich
> einen
>> uint32_t und eine höchtste Bitzahl von 26, sollte also gehen.
>
> ..und schiebst Du auch den passenden Datentyp?
Hmm... da bin ich jetzt verwirrt... also, ich schiebe eine 1, d.h. es 
ist ja auch Binär ne 1.

So, Datei ist angefügt, sollte nen RC5 Empfänger sein. (Ja, ich weiss 
das es da bessere und vorgefertigte Codes gibt (Peter Danegger), aber 
ich möchte selbst so etwas entwickeln, es geht um die Herausforderung)

von g457 (Gast)


Lesenswert?

> Hmm... da bin ich jetzt verwirrt... also, ich schiebe eine 1, d.h. es
> ist ja auch Binär ne 1.

Jaaber eine "1" ist nur 16 Bits lang, und wenn Du die um 26 stellen nach 
links schubst, dann bleibt davon nicht mehr viel übrig.

von Ratloser (Gast)


Lesenswert?

g457 schrieb:
>> Hmm... da bin ich jetzt verwirrt... also, ich schiebe eine 1,
> d.h. es
>> ist ja auch Binär ne 1.
>
> Jaaber eine "1" ist nur 16 Bits lang, und wenn Du die um 26 stellen nach
> links schubst, dann bleibt davon nicht mehr viel übrig.

Ja stimmt, Atmel Studio wandelt wandelt aber alle Zahlen direkt in 
Binärzahlen um, d.H. es ist Binär eine 1, welche ja nur ein Bit 
benötigt.

Ich habe jetzt wieder und wieder versucht und ich glaube dem Problem auf 
der Spur zu sein... ich habe in der main Schleife eine Abfrage die so 
aussieht
1
if (puffer==1<<0) PORTC |= 1;
2
else PORTC &= ~1;

Ich glaube das Problem liegt darin das ich mit == teste. Wenn da noch 
weitere Zeichen stehen im puffer als die, die ich prüfe, dann ergibt das 
logisch 1 und nichts geht.

von Ratloser (Gast)


Lesenswert?

So nochmals um alle Aufzuklären, ich habe den Fehler jetzt.

Mein Programm funktioniert soweit, das Problem lag in meiner Abfrage.

Das Programm erzeugt einen Code: z.B. "0101010101"
Die Abfrage überprüft: if ("0101010101" == "01") //machwas

ich hätte nicht == nehmen sollen in der Abfrage, dadurch wird der 
returnwert immer 0, ausser wenn ich den Integer zurücksetzt und dann 
einen Wert schreibe:

if ("00000001" == "01") //machwas


Vielen Dank an alle die mir zu solch später Stunde noch geholfen haben, 
ihr habt mich indirekt auf die Lösung gebracht dadurch das ich meinen 
Code nochmals aus anderer Sicht hinterfragt habe. Sollte jemand den Code 
für den RC5 Empfänger benötigen kann er sich gerne melden. (Eine 
halbfertige Version ist oben zu finden)

Grüsse und nochmals vielen Dank - Ratloser (naja, jetzt nicht mehr so 
sehr)

von (prx) A. K. (prx)


Lesenswert?

Ratloser schrieb:
>> Jaaber eine "1" ist nur 16 Bits lang, und wenn Du die um 26 stellen nach
>> links schubst, dann bleibt davon nicht mehr viel übrig.
>
> Ja stimmt, Atmel Studio wandelt wandelt aber alle Zahlen direkt in
> Binärzahlen um, d.H. es ist Binär eine 1, welche ja nur ein Bit
> benötigt.

Das ändert nichts am Problem, dass "int" nur 16 dieser Bits hat.

von Logic Operator (Gast)


Lesenswert?

Wie kommst du auf 16 bit für das integer?
Das int8 hat 8 bit und ist singend.
Das uint32 ist 32 bit lang und unsingned.

von (prx) A. K. (prx)


Lesenswert?

Logic Operator schrieb:
> Wie kommst du auf 16 bit für das integer?

Weil der C Quelltext
  1
per Sprachdefinition eine Zahl vom Typ "int" darstellt, und damit bei 
AVR 16 Bits hat. Das Ergebnis der Operation
  1 << bit
ist deshalb ebenso per Definition vom Typ "int". Unabhängig vom Kontext, 
in dem dieser Ausdruck steht!

: Bearbeitet durch User
von Logic Operator (Gast)


Lesenswert?

Okay, wieder was gelernt. Danke, diese Notation bei den avr war neu für 
mich.

von (prx) A. K. (prx)


Lesenswert?

Logic Operator schrieb:
> Danke, diese Notation bei den avr war neu für
> mich.

Mit AVR hat das nur insofern zu tun, als "int" da 16 Bits breit ist. 
Weniger ist in C nicht zulässig. Der Rest ergibt sich aus der 
Sprachdefinition von C.

Logic Operator schrieb:
> Das int8 hat 8 bit und ist singend.

Das wiederum wusste ich noch nicht. Sopran oder Alt? ;-)

: Bearbeitet durch User
von Ratloser (Gast)


Lesenswert?

A. K. schrieb:
> Logic Operator schrieb:
>> Wie kommst du auf 16 bit für das integer?
>
> Weil der C Quelltext
>   1
> per Sprachdefinition eine Zahl vom Typ "int" darstellt, und damit bei
> AVR 16 Bits hat. Das Ergebnis der Operation
>   1 << bit
> ist deshalb ebenso per Definition vom Typ "int". Unabhängig vom Kontext,
> in dem dieser Ausdruck steht!

Das war mir auch neu (nicht das ich es nicht glaube). Prima, noch was 
dazugelernt und mein Code funktioniert jetzt auch perfekt.

von #define BIT0 0x01 (Gast)


Lesenswert?

Sorry, aber diese 1<<irgendetwas ist die größte Schei... wie man hier 
wieder schön sieht.
Schreib ordentliche Bitmasken oder Hex-Werte, so wie es die ganze Welt 
macht. Nur das kleine Atmel-Dorf nutzt den schlecht lesbaren Schei...

von Karl M. (Gast)


Lesenswert?

Sorry,

so ein wirrer Gedanke kommt nur bei unerfahrenden Programmieranfängern 
erfahrungsmäßig vor.

Auch ist es keine Erscheinung von Atmel, sondern das Mittel zur 
Umsetzung von Bitnummern (Bitbezeichnungen) zu Bitmasken.

Die Nutzung von Bitbezeichnungen erhöht ungemein die Lesbarkeit, da sich 
ein Mensch über die Sprache austauscht. Das Merken und Reden über/ von 
Zahlen fällt vielen dabei viel schwerer.

Denken Sie darüber mal nach.

#define BIT0 0x01 schrieb:
> Sorry, aber diese 1<<irgendetwas ist die größte Schei... wie man hier
> wieder schön sieht.
> Schreib ordentliche Bitmasken oder Hex-Werte, so wie es die ganze Welt
> macht. Nur das kleine Atmel-Dorf nutzt den schlecht lesbaren Schei...

von #define BIT0 0x01 (Gast)


Lesenswert?

Karl M. schrieb:
> Auch ist es keine Erscheinung von Atmel

Und wer bitte schön nutzt noch dieses Verwirrspiel?

Karl M. schrieb:
> Die Nutzung von Bitbezeichnungen erhöht ungemein die Lesbarkeit
1
    // ala ATMEL
2
#define BIT3    3
3
4
... foo = 1<<BIT3;
5
6
   // und besser
7
#define BIT3    0x04;
8
9
... foo = BIT3;

Karl M. schrieb:
> Denken Sie darüber mal nach.

Das mach einmal, Herr Anfänger.

von Joachim B. (jar)


Lesenswert?

A. K. schrieb:
> Weil der C Quelltext
>   1
> per Sprachdefinition eine Zahl vom Typ "int" darstellt

will man mehr muss man 1L schreiben damit der als LONG interpretiert 
wird

von STK500-Besitzer (Gast)


Lesenswert?

#define BIT0 0x01 schrieb:
> Sorry, aber diese 1<<irgendetwas ist die größte Schei... wie man hier
> wieder schön sieht.
> Schreib ordentliche Bitmasken oder Hex-Werte, so wie es die ganze Welt
> macht. Nur das kleine Atmel-Dorf nutzt den schlecht lesbaren Schei...

Blödsinn.
Wenn man Bits in einer Integer-Variablem (also einer ganzen Zahl) per 
Schleife setzen will, geht das nur mit Verschiebungen.
Oder einer Switch-Case-Abfrage oder einer If-Orgie.

von define BIT0 0x01 (Gast)


Lesenswert?

STK500-Besitzer schrieb:
> per
> Schleife setzen will, geht das nur mit Verschiebungen

??? Es geht nicht um Schiebe-Operatoren, sondern die schwachsinnige 
Deklarations-Variante von Atmel. Also shift mit Konstanten aus dem 
Header.

#define BIT0 0x01 schrieb:
> // ala ATMEL
> #define BIT3    3
>
> ... foo = 1<<BIT3;

Bist du noch im Weichnachstschlaf? ;)

von Karl M. (Gast)


Lesenswert?

Guten Morgen STK500-Besitzer,

als Ergänzung, kann man noch ein Isomorphismus zwischen den Bit-Nummern 
und den Bit-Masken, über eine Tabelle (Array), nutzen.
1
uint8_t toBitmask[] = {1,2,4,8,16,32,64,128};
2
3
uint8_t bitmask;
4
bitmask = toBitmask[0];

von Carl D. (jcw2)


Lesenswert?

Karl M. schrieb:
> Guten Morgen STK500-Besitzer,
>
> als Ergänzung, kann man noch ein Isomorphismus zwischen den Bit-Nummern
> und den Bit-Masken, über eine Tabelle (Array), nutzen.
>
1
const uint8_t toBitmask[] = {1,2,4,8,16,32,64,128};
2
> 
3
> uint8_t bitmask;
4
> bitmask = toBitmask[0];

Noch ein const vor toBitmask, das hilft dem Compiler.
Lustig wird es auch, aus einer 8Bit-Maske die Bitnummer rauszufinden.

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

#define BIT0 0x01 schrieb:
> Sorry, aber diese 1<<irgendetwas ist die größte Schei... wie man hier
> wieder schön sieht.

Es gibt Fälle, in denen man die Bitnummer benötigt. Nicht bei AVR C, 
aber dafür bei AVR Assembler und bei diversen ARMen.

von Einer K. (Gast)


Lesenswert?

define BIT0 0x01 schrieb:
> Bist du noch im Weichnachstschlaf? ;)

Du!

Wenn du einen einzelnen Ausgang adressieren möchtest, dann geht das nur 
über das IO Register und eine Pin Nummer.
Genau diese beiden Daten brauchst du dafür!


Andere Systeme, als AVR, machen das genau so.
Nur, dass die Register da anders heißen, evt. viel breiter sind, und der 
Zugriffscode in HALs verborgen wird.

von define BIT0 0x01 (Gast)


Lesenswert?

Karl M. schrieb:
> uint8_t toBitmask[] = {1,2,4,8,16,32,64,128};

Aber bitte nur mit const davor und hoher Optimierungsstufe. Wir wollen 
ja keine Variablen.

von define BIT0 0x01 (Gast)


Lesenswert?

A. K. schrieb:
> AVR Assembler und bei diversen ARMen

von A T M E L. Bitte zeige mir einen Header eines anderen großen 
Herstellers, der das auch so macht.

@all:
Die Welt ist größer als das Atmel-Dorf.

von define BIT0 0x01 (Gast)


Lesenswert?

Arduino F. schrieb:
> Andere Systeme, als AVR, machen das genau so.

Beispiel, bitte zeige ein Beispiel.

Alle anderen geben im Header die Wertigkeit an, die du direkt nutzen 
kannst.
Die Welt ist größer als Atnmel!

von (prx) A. K. (prx)


Lesenswert?

define BIT0 0x01 schrieb:
>> AVR Assembler und bei diversen ARMen
>
> von A T M E L. Bitte zeige mir einen Header eines anderen großen
> Herstellers, der das auch so macht.

Andersrum: Die Bitnummer benötigt man in ein paar AVR Assemblerbefehlen. 
Die Includes werden bei Atmel aus der gleichen Quelle für C und für Asm 
erzeugt. Folglich enthalten die Includes sinnvollerweise die Bitnummer 
an Stelle einer Maske. Denn aus der Bitnummer die Maske zu erzeugen ist 
trivial.

Viele ARM Cortex M, egal ob von Atmel oder sonstwem, sind per Bitbanding 
in der Lage, Einzelbits zu adressieren. Dazu benötigt man die Bitnummer. 
Liegt die in den Includes nicht vor, hat man ein Problem. Denn aus der 
Maske die Bitnummer abzuleiten ist nicht trivial.

Insofern macht Atmel es IMHO richtig.

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

> Insofern macht Atmel es IMHO richtig.

Sehe ich auch so. Die Header Dateien von STM sind voller magischer 
Zahlen.

von define BIT0 0x01 (Gast)


Lesenswert?

A. K. schrieb:
> Die Includes werden bei Atmel aus der gleichen Quelle für C und für Asm
> erzeugt. Folglich enthalten die Includes sinnvollerweise die Bitnummer
> an Stelle einer Maske.

Danke, du schreibst ja selbst, dass es aus der Not geboren ist.

Und wenn man so eine Zusammenstellung einer Bitmaske mit 3 oder mehr 
Bits vor sich hat, erkennt man sofort diese Krücke.

von (prx) A. K. (prx)


Lesenswert?

define BIT0 0x01 schrieb:
> Danke, du schreibst ja selbst, dass es aus der Not geboren ist.

Yep. Programmierung ist aus der Not geboren, weil die Maschinen noch 
nicht in der Lage sind, es zu aller Zufriedenheit selber zu machen. Bis 
das so weit ist, muss sich der Mensch eben selbst bemühen. ;-)

Insofern müsstest du eigentlich die Hardware-Designer verprügeln. Weil 
sie die für dich unerträgliche Frechheit besassen, Bits zu nummerieren, 
statt sie ausschliesslich als Maske zu codieren.

: Bearbeitet durch User
von define BIT0 0x01 (Gast)


Lesenswert?

A. K. schrieb:
> Insofern müsstest du eigentlich die Hardware-Designer verprügeln. Weil
> sie die für dich unerträgliche Frechheit besassen, Bits zu nummerieren,
> statt sie ausschliesslich als Maske zu codieren.

Nö, Atmel müsste für seine Faulheit gekopfft werden. Und du kannst das 
natürlich schreiben, wie du möchtest.

Heute ist man um lesbaren Code bemüht. Und da ist Atmels Krücke 
kontraproduktiv.
Und um das zu umschiffen, hat man das Makro _BV bemüht.

Wie gesagt, die ganze Welt macht es scheinbar falsch, ausser Atmel. ;)

von Stefan F. (Gast)


Lesenswert?

Es ist doch völlig egal, welche Syntax der eine oder der andere schöner 
findet. Mit Makros kann man es sich ggf. so umbauen, wie man es gerne 
haben möchte. Zur Not steht es sogar jedem frei, die ganze Datei gegen 
eine schönere auszutauschen.

Man bedenke auch, wie alt diese Sachen sind. Damals war das vielleicht 
"state of the art".

Wichtiger ist doch, dass es funktioniert.

Abgesehen davon ist Software von  Hardware Herstellern fast immer 
suboptimal. Die haben ihre Expertise eben woanders.

von (prx) A. K. (prx)


Lesenswert?

Stefan U. schrieb:
> Mit Makros kann man es sich ggf. so umbauen, wie man es gerne
> haben möchte.

Wie sieht dein umgedrehter _BV Makro aus, also der aus einer Maske eine 
Bitnummer macht? Vorzugsweise Standard-C bis 64 Bits. Gehen tuts, aber 
schön geht anders.

: Bearbeitet durch User
von define BIT0 0x01 (Gast)


Lesenswert?

Stefan U. schrieb:
> Man bedenke auch, wie alt diese Sachen sind. Damals war das vielleicht
> "state of the art".

Nö, das gibt es erst seit den AVRs, C on µC aber schon länger.

Stefan U. schrieb:
> Wichtiger ist doch, dass es funktioniert.

Das ist nicht der Ansatz moderner Programmierung. Oder wie stehst du zu 
MISRA und Co.? Code darf übersichtlich und lesbar sein. Er darf Qualität 
besitzen. Dazu tragen Atmels Schiebespielchen nicht bei.

von (prx) A. K. (prx)


Lesenswert?

define BIT0 0x01 schrieb:
> Dazu tragen Atmels Schiebespielchen nicht bei.

Schönheit liegt im Auge des Betrachters.

von Einer K. (Gast)


Lesenswert?

Ich finde wenn dem "Autor: define BIT0 0x01 (Gast)" das Atmel Prinzip 
nicht gefällt, dann soll er sich bei dem Verein beschweren.

Hier kann er/sie/es solange mit den Füßen auf der Erde rum stampfen, wie 
es will. Atmel/Microchip wird das nicht kümmern.
Es wird die Situation nicht ändern.

Meine Oma sagte schon:
> Gott gebe mir Gelassenheit, hinzunehmen, was nicht
> zu ändern ist. Mut zu ändern, was ich ändern kann.
> Und Weisheit, zwischen beidem zu unterscheiden.

Und auch, wie Noäl Coward schon schrieb:
> Die Kritik an anderen hat noch keinem die eigene Leistung erspart.

Also nicht meckern...
Sondern: Zeige uns, wie es besser geht!

von Stefan F. (Gast)


Lesenswert?

> Zeige uns, wie es besser geht!

Das hat er doch schon. jetzt fehlt nur noch die praktische Umsetzung für 
sämtliche AVR's. Das kann man dann als Fork bei GitHub veröffentlichen 
und dann staunen, wie viele Leute diesen Fork verwenden (oder auch 
nicht).

von (prx) A. K. (prx)


Lesenswert?

Arduino F. schrieb:
> Es wird die Situation nicht ändern.

Nein? Vielleicht doch.

Dazu braucht er ein kleines Programm, das den Quelltext der Includes 
abgrast und für alle Makros mit eindeutiger Bitnummer ein zweites Makro 
hinzu fügt, das die Maske enthält. Mit _m hinten am Namen.

Und das geht dann ggf. auch umgekehrt, für Fans der Bitnummer ohne 
passende Includes gibts dann für alle Masken, die sich in Bitnummern 
übersetzen lassen, eine Version mit Bitnummer und _b.

: Bearbeitet durch User
von define BIT0 0x01 (Gast)


Lesenswert?

Arduino F. schrieb:
> Zeige uns, wie es besser geht!

Habe ich doch schon.

A. K. schrieb:
> Wie sieht dein umgedrehter _BV Makro aus, also der aus einer Maske eine
> Bitnummer macht?

Zeig mal dein Atmel-konformes Beispiel.

A. K. schrieb:
> Nein? Vielleicht doch.

Atmels Header werde ich nicht mehr ändern. Aber ich lasse mir den Mist 
nicht schön reden. Das einzige Pro-Argument war bisher die 
Bequemlichkeit, keine vernüftigen C-Header schreiben zu wollen, von A. 
K.

von (prx) A. K. (prx)


Lesenswert?

define BIT0 0x01 schrieb:
> Zeig mal dein Atmel-konformes Beispiel.

Was stört dich am Klassiker
  #define _BV(n) (1<<(n))

> Atmels Header werde ich nicht mehr ändern.

#include <my/avr/ioxxx.h>
Dieses vom Include-Scanner automatisch erzeugte File:
  #include <avr/ioxxx.h>
  #define MEINBIT_m (1<<MEINBIT))
  ...
Oder so ähnlich.

: Bearbeitet durch User
von define BIT0 0x01 (Gast)


Lesenswert?

A. K. schrieb:
> Was stört dich am Klassiker

Den habe ich doch selber schon ins Spiel gebracht. ;)
Und der macht eine Bit-Maske, wie in allen nicht-Atmel Headern bereits 
deklariert. Wenn du _BV() gut findest, sind wir einer Meinung und 
verbannen diese Schiebespielchen aus unseren Quelltexten.

von define BIT0 0x01 (Gast)


Lesenswert?

define BIT0 0x01 schrieb:
> A. K. schrieb:
>> Wie sieht dein umgedrehter _BV Makro aus, also der aus einer Maske eine
>> Bitnummer macht?

Wo bleibt das Beispiel?

von (prx) A. K. (prx)


Lesenswert?

define BIT0 0x01 schrieb:
> Wo bleibt das Beispiel?

Ja, das frage ich mich auch. ;-)

Wobei ich zwei habe. Das nicht portable als dem ARM Bitbanding Artikel 
rücke ich freiwillig raus:
#define BBitOfMask(mask) (31 - __builtin_clz(mask))

von define BIT0 0x01 (Gast)


Lesenswert?

A. K. schrieb:
> Ja, das frage ich mich auch. ;-)

A. K. schrieb:
> Wie sieht dein umgedrehter _BV Makro aus, also der aus einer Maske eine
> Bitnummer macht? Vorzugsweise Standard-C bis 64 Bits. Gehen tuts, aber
> schön geht anders.

Zeige bitte das Beispiel mit den Atmel-Deklarationen, damit der Vorteil 
der Schiebespielchen ersichtlich wird. Bisher gab es nur heisse Luft.

Ich finde es schlechter, weil der Quelltext unnötig überladen wird:

... if (registerFoo & ((1 << BIT6) | (1 << BIT5) | (1 << BIT4) | (1 << 
BIT3)) ...


besser lesbar (wie bei allen anderen Herstellern)

... if (registerFoo & (BIT6 | BIT5 | BIT4 | BIT3) ...

Du kannst ja die überflüssigen Zeichen zählen. ;)

von (prx) A. K. (prx)


Lesenswert?

define BIT0 0x01 schrieb:
> Zeige bitte das Beispiel mit den Atmel-Deklarationen, damit der Vorteil
> der Schiebespielchen ersichtlich wird. Bisher gab es nur heisse Luft.

https://www.mikrocontroller.net/articles/ARM_Bitbanding
Ohne das bereits aufgeführte für GCC spezifische BBitOfMask.

: Bearbeitet durch User
von Carl D. (jcw2)


Lesenswert?

A. K. schrieb:
> define BIT0 0x01 schrieb:
>> Wo bleibt das Beispiel?
>
> Ja, das frage ich mich auch. ;-)
>
> Wobei ich zwei habe. Das nicht portable als dem ARM Bitbanding Artikel
> rücke ich freiwillig raus:
> #define BBitOfMask(mask) (31 - __builtin_clz(mask))

Nachteil einer Maske statt der Bitnummer bleibt aber, daß man auch 
mehrere Bits setzen kann. Welches soll es dann sein? Das 
Erste/Letzte/Mittlere?

Bitnummer->Maske ist eine Funktion, umgekehrt nicht!

Aber zum Glück wird man nicht gezwungen Atmel Produkte zu benutzen.

von define BIT0 0x01 (Gast)


Lesenswert?

A. K. schrieb:

Wie bitte geht daraus ein Vorteil für die Atmel-konforme 
Headerverkrüppelung hervor?

In deinem Makro oben steht eine 31. Kannst ja einmal erklären, wie sich 
deine 64Bit Anfrage oder auch 8Bit und 16Bit dort wieder finden.

Alles sehr dünn hier mit den Argumenten für den Atmel-Quatsch. Bleibt 
einzig Atmels Bequemlichkeit; und das ist, zwar nicht technisch, 
nachvollziehbar.

von define BIT0 0x01 (Gast)


Lesenswert?

Carl D. schrieb:
> Nachteil einer Maske statt der Bitnummer bleibt aber, daß man auch
> mehrere Bits setzen kann. Welches soll es dann sein? Das
> Erste/Letzte/Mittlere?

??? Die Maske kann (und bei einzelnen Bits "besteht") nur aus einem 
gesetzten Bit bestehen.

Carl D. schrieb:
> Bitnummer->Maske ist eine Funktion, umgekehrt nicht!

Maske1Bit->MaskeVieleBits auch!!!

;(((

von HildeK (Gast)


Lesenswert?

A. K. schrieb:
> Was stört dich am Klassiker
>   #define _BV(n) (1<<(n))

... oder an der Variante von P. Dannegger mit der sbit.h?
1
#include "sbit.h"
2
3
#define LED0      PORT_B0
4
#define LED1       PORT_B1
5
#define INPUT     PIN_B2
6
7
#define EIN 0      
8
#define AUS 1   
9
.
10
.
11
// im Code dann z.B.: 
12
13
if(LED1 == EIN) LED0 = EIN;
14
.
15
.
16
LED0 ^= 1;  // Toggle
17
.
18
.
19
if (INPUT == LOW) LED0 = AUS;

Eine mir sehr sympathische Variante der Bitmanipulation :-)

(sbit.h ist im Forum schon mehrfach gepostet worden).

von (prx) A. K. (prx)


Lesenswert?

define BIT0 0x01 schrieb:
> In deinem Makro oben steht eine 31. Kannst ja einmal erklären, wie sich
> deine 64Bit Anfrage oder auch 8Bit und 16Bit dort wieder finden.

Wozu? Ich hatte explizit darauf hingewiesen, dass diese Variante nicht 
portabel ist.

Dieses Makro wird aber nur benötigt, um leider als Maske definierte Bits 
in eine benötigte Bitnummer umzurechnen. Liegen die Bits bereits als 
Bitnummer vor, wird dieses Makro überhaupt nicht benötigt. Wenn man die 
Includes also im Stil von Atmel definiert, braucht man das 
problematische Makro nicht.

von define BIT0 0x01 (Gast)


Lesenswert?

HildeK schrieb:
> #include "sbit.h"

... und eine weitere Variante, sich dem Schiebespiel zu entziehen.

Danke für die Unterstützung.

von (prx) A. K. (prx)


Lesenswert?

Carl D. schrieb:
>> #define BBitOfMask(mask) (31 - __builtin_clz(mask))
>
> Nachteil einer Maske statt der Bitnummer bleibt aber, daß man auch
> mehrere Bits setzen kann.

Alte C Regel: Schrott rein, Schrott raus. Wer BBitOfMask mit mehreren 
Bits füttert, kriegt in dieser Version das oberste davon. Und ganz ohne 
gesetzte Bits gibts -1 oder 0xFFFFFFFF.

Dieses Makro war auch nur eine Notlösung, weil ST in den Headers keine 
Bits angibt, sondern Masken.

: Bearbeitet durch User
von define BIT0 0x01 (Gast)


Lesenswert?

A. K. schrieb:
Wo bleibt dein Beispiel?

A. K. schrieb:
> Wie sieht dein umgedrehter _BV Makro aus, also der aus einer Maske eine
> Bitnummer macht? Vorzugsweise Standard-C bis 64 Bits.

Zeig doch endlich mal Code, wo das schön leserlich eingesetzt wird. 
Bisher gibts nur rosa Elefanten von dir.

von HildeK (Gast)


Lesenswert?

define BIT0 0x01 schrieb:
> ... und eine weitere Variante, sich dem Schiebespiel zu entziehen.

Für die Bedienung der IOs wird das Ergebnis sehr leserlich.
Für die Registersettings ist für mich auch das 'Schiebespiel' ok. Man 
sieht ja durch die Bitnamen noch deutlich, was gemeint ist.

von (prx) A. K. (prx)


Lesenswert?

define BIT0 0x01 schrieb:
> Zeig doch endlich mal Code, wo das schön leserlich eingesetzt wird.
> Bisher gibts nur rosa Elefanten von dir.

Was missfällt dir an rosa Elefanten? ;-)

Dass du diese Shifts ekelerregend findest, sie mir aber nicht so viel 
ausmachen, wurde bereits ausgiebig geklärt. Wobei ich die Shifts 
durchaus reduziert einsetze, typischerweise in Form verschiedener Wege 
von Abstraktion. Der Unterschied: Es macht mir nichts aus, 
beispielsweise ins Config-File für die genutzten Port-Bits sowas 
reinzuschreiben:
1
#define VRAM_RAS    (1<<PD3)
2
#define VRAM_CAS    (1<<PD2)
3
#define VRAM_DTOE   (1<<PD7)
4
#define VRAM_WBWE   (1<<PD4)

Oder in einem anderen Fall bitorientierter so:
Beitrag "Re: attiny USI Slave Implementierung"

von define BIT0 0x01 (Gast)


Lesenswert?

A. K. schrieb:
> #define VRAM_RAS

... was ja wieder nix anderes als die, von dir gescholtene, Bit-Maske 
darstellt. Und schon sind wir uns einig: Bit-Maske ist besser lesbar 
(egal wie sie erstellt wurde).

A. K. schrieb:
> Es macht mir nichts aus,
> beispielsweise ins Config-File für die genutzten Port-Bits sowas
> reinzuschreiben

... was sonst die Hersteller, ausser Atmel, per Header bereits mit 
liefern.

Man, war das ein langer Weg.

von Carl D. (jcw2)


Lesenswert?

A. K. schrieb:
> Carl D. schrieb:
>>> #define BBitOfMask(mask) (31 - __builtin_clz(mask))
>>
>> Nachteil einer Maske statt der Bitnummer bleibt aber, daß man auch
>> mehrere Bits setzen kann.
>
> Alte C Regel: Schrott rein, Schrott raus. Wer BBitOfMask mit mehreren
> Bits füttert, kriegt in dieser Version das oberste davon. Und ganz ohne
> gesetzte Bits gibts -1 oder 0xFFFFFFFF.
>
> Dieses Makro war auch nur eine Notlösung, weil ST in den Headers keine
> Bits angibt, sondern Masken.

Mein Hauptargument: eine Bitnummer kann jederzeit eindeutig zu einer 
Maske gemacht werden, ist also quasi die höherwertige Information. Eine 
Mask dagegen kann ganz leicht uneindeutig bzgl. "welches Bit ist das" 
gemacht werden.
Also Bitnummer, frei nach Scott Meyers: Easy to use, imposible TO 
missuse.

Aber auch egal, jeder wie er will, damit auch: der andere darf auch 
anders.

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

define BIT0 0x01 schrieb:
> ... was ja wieder nix anderes als die, von dir gescholtene, Bit-Maske
> darstellt. Und schon sind wir uns einig: Bit-Maske ist besser lesbar
> (egal wie sie erstellt wurde).

Missverständnis? Ich mag es nicht, wenn ich in Headern nur die Maske 
zur Verfügung habe. Von mir aus dürfen sie gerne beide Varianten 
reinschreiben. Da die Leutchen aber meist nur eine Variante definieren, 
ziehe ich dort die Bitnummer vor. Ich kann es dann selber nutzen wie 
es grad besser passt und den Grund hat Carl soeben genannt.

Ansonsten solltest du versuchen, weniger selektiv zu lesen. Das andere 
Beispiel ist nämlich etwas anders, wie erwähnt.

: Bearbeitet durch User
von define BIT0 0x01 (Gast)


Lesenswert?

Carl D. schrieb:
> eine Bitnummer kann jederzeit eindeutig zu einer
> Maske gemacht werden, ist also quasi die höherwertige Information. Eine
> Mask dagegen kann ganz leicht uneindeutig bzgl. "welches Bit ist das"
> gemacht werden.

Puh, was geht denn jetzt ab? ;(

In beiden Varianten gibt es einen eindeutigen Zahlencode. Die eine
1, 2, 3, ...
und die andere
0x01, 0x02, 0x04, ...

Sorry, aber es wird albern.



A. K. schrieb:
> Ich mag es nicht, wenn ich in Headern nur die Maske
> zur Verfügung habe.

Also nutzt du nur Atmel und kennst nix anderes? Das erklärt deine 
Verbohrtheit.

Und natürlich soll jeder nutzen, was ihm gefällt. Aber bitte nicht in 
Entwicklungsteams mit Qualitätsstandards. ;)

von Carl D. (jcw2)


Lesenswert?

define BIT0 0x01 schrieb:
> Carl D. schrieb:
>> eine Bitnummer kann jederzeit eindeutig zu einer
>> Maske gemacht werden, ist also quasi die höherwertige Information. Eine
>> Mask dagegen kann ganz leicht uneindeutig bzgl. "welches Bit ist das"
>> gemacht werden.
>
> Puh, was geht denn jetzt ab? ;(
>
> In beiden Varianten gibt es einen eindeutigen Zahlencode. Die eine
> 1, 2, 3, ...
> und die andere
> 0x01, 0x02, 0x04, ...
>
> Sorry, aber es wird albern.
>

Das ist nicht albern,
wenn einer den Unterschied zwischen 0..7 und 0..255 nicht versteht.

von define BIT0 0x01 (Gast)


Lesenswert?

Carl D. schrieb:
> 0..255

Oh man, du weisst gar nicht worüber hier die ganze Zeit geschrieben 
wurde? ;(((

Beitrag #5256717 wurde vom Autor gelöscht.
von Carl D. (jcw2)


Lesenswert?

define BIT0 0x01 schrieb:
> Carl D. schrieb:
>> 0..255
>
> Oh man, du weisst gar nicht worüber hier die ganze Zeit geschrieben
> wurde? ;(((

Ein Geisterfahrer? Hunderte!

von define BIT0 0x01 (Gast)


Lesenswert?

A. K. schrieb im Beitrag #5256717:
> Plonk

Wenn keine Argumente vorhanden, ist das auch eine Art. ;)

von Thomas E. (thomase)


Lesenswert?

define BIT0 0x01 schrieb:
> Also nutzt du nur Atmel und kennst nix anderes? Das erklärt deine
> Verbohrtheit.

define BIT0 0x01 schrieb:
> Wenn keine Argumente vorhanden, ist das auch eine Art.

Du sagst es.

von define BIT0 0x01 (Gast)


Lesenswert?

Carl D. schrieb:
> Geisterfahrer

Im Ursprung hatte der TO genau das Problem der Schiebespielchen. Mit 
entsprechenden Bitmasken (nur eine '1' pro Maske, wie üblich) wäre das 
nicht passiert.

Und wie wir im Verlauf schön sehen können, landen auch die ganzen Umwege 
wieder bei der Bitmaske (mit nur eine '1' pro Maske, wie üblich). Und 
alle finden es gut. ;)

von define BIT0 0x01 (Gast)


Lesenswert?

Thomas E. schrieb:
> Du sagst es.

Und ich konnte ihn sogar "aufbohren". ;)
A. K. schrieb:
> #define VRAM_RAS

von (prx) A. K. (prx)


Lesenswert?

define BIT0 0x01 schrieb:
> Und ich konnte ihn sogar "aufbohren". ;)

Nicht nachhaltig. ;-)
1
// set USI control register, TWI mode, auto-extend mode for SCL when overflow interupt enabled
2
#define setUSICR(start,ovf)    USICR = (start)<<USISIE | (ovf)<<USIOIE \
3
       | 1<<USIWM1|(ovf)<<USIWM0 | 1<<USICS1|0<<USICS0|0<<USICLK | 0<<USITC
4
#define enableStart_disableOverflow()  setUSICR(1,0)
5
#define enableStart_enableOverflow()   setUSICR(1,1)
6
7
// set USI status register, clear overflow flag, optionally clear other flags, set counter
8
#define setUSISR(start,stop,bits)  USISR = (start)<<USISIF | 1<<USIOIF \
9
       | (stop)<<USIPF | 0<<USIDC | (16-2*(bits))<<USICNT0
10
#define clearStartStop_setCounter(n)    setUSISR(1,1,n)
11
#define setTransmit(n)                  setOutput(), setUSISR(0,0,n)
12
#define setReceive(n)                   setInput(), setUSISR(0,0,n)
Aus dem anderen Code-Beispiel, das du zu ignorieren vorzogst.

: Bearbeitet durch User
von define BIT0 0x01 (Gast)


Lesenswert?

A. K. schrieb:
> #define enableStart_disableOverflow()  setUSICR(1,0)

sehr aussagekräftig, super
setUSICR(1,0)
man erkennt sofort, welches Bit gesetzt wird. ;(
Oder was passiert bei setUSICR(7,0)? ;(

Üblicherweise (mit richtigem Header) schreibt man  USICR = USISIE
was man natürlich auch noch abstrahieren kann
#define enableStart_disableOverflow  (USICR = USISIE)

Ist wohl für jeden leicht zu erkennen, was lesbarer ist. ;)

Beitrag #5256887 wurde vom Autor gelöscht.
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.