Hey Forum
Ich hab am nächstes Schuljahr Programmierung in c auf den Stundenplan an
ucs und wollte mich schonmal etwas ein arbeiten. Und muss jetzt mal eine
ganz doofe Frage stelle. Wie ändere ich Bits in einem Register ohne
andere zu ändern also aus ein bit von 1 auf 0 oder von 0 auf 1 aber die
andern sollen unverändert bleiben.
Hab mir den Beitrag mal durch Gelesen und hab mal 2 Verständnis fragen
Wenn ich ein Port habe nennen wir ihn mal A mit den Wert 0b0000
Jetzt schreibe ich
A|= (1<<1) | (1<<4);
Ist das, dass selbe wie
A|= (1<<1);
A|= (1<<4);
Dann hat A den Wert 0b1001?
Wenn ich jetzt
A&= (1<<1) & (1<<4);
Setzte ist A=0b0000 ?
Wie bereits gesagt: Beschäftige Dich mit binären Zahlen.
A ist nur zufällig gleich 0
(1<<1) & (1<<4);
ist 0
A &= 0 ist Null.
Du hattest aber den Sonderwunsch: "Wie ändere ich Bits in einem Register
ohne andere zu ändern"
Das stimmt aber nicht.
Ist A vorher 1101, so ist A &= 0 ebenfalls 0.
Anfänger schrieb:> Ist das, dass selbe wie>> A|= (1<<1);> A|= (1<<4);
Ja
Anfänger schrieb:> Dann hat A den Wert 0b1001?
Nein
(1<<1) | (1<<4)
=> 10010
du wolltest
(1<<0) | (1<<3)
Die bits sind nicht 1 und 4 sondern 0 und 3
Anfänger schrieb:> Wenn ich jetzt>> A&= (1<<1) & (1<<4);>> Setzte ist A=0b0000 ?
Nein
Du must noch negieren
also
!((1<<1) & (1<<4))
MfG
Vorsicht bissiger Hund:
(1<<1) & (1<<4) ist Null
0000.0010 0000.0010
& |
0001.0000 0001.0000
= =
0000.0000 0001.0010
0000.0000 0001.0010
! !
1111.1111 1110.1101
0001.0010 0001.0010
& &
1111.1111 1110.1101
= =
0001.0010 0000.0000
oder so
TO hier kannst Du auch "sehen" warum etwas binäre Zahlen nicht schaden
können.
A guats Nächtlie
Anfänger schrieb:> A|= (1<<1);> A|= (1<<4);>> Dann hat A den Wert 0b1001?
Nein.
weil 1<<1 den Wert 2 ergibt ( b0010)
weil 1<<4 den Wert 16 ergibt (b10000)
im 8-Bit Zahlenraum schiebt man sinnvollerweise 0 bis 7 mal.
icke schrieb:> !((1<<1) & (1<<4))Sebastian S. schrieb:> 0000.0000 0001.0010> ! !> 1111.1111 1110.1101
Auweia. Bitte nicht die logische mit der bitweisen Negation verwecheln.
Richtig wäre hier '~' statt '!'.
Und entweder
~((1<<1) | (1<<4))
oder
~(1<<1) & ~(1<<4)
avr schrieb:> Auweia. Bitte nicht die logische mit der bitweisen Negation verwecheln.> Richtig wäre hier '~' statt '!'.
Autsch! Sorry und danke!
Meine Muttersprache ist Pascal.
Da Schreibt man einfach Not
und der Compiler ist schlau genug zu erkennen ob binär oder logisch.
Bei C habe ich immer wieder Probleme.
MfG
wieder ein sehr schönes beispiel für die C hater Seite :-)
Die ich übrigens super finde, auch wenn man C lernen will!! da man
versucht die Beispiele zu verstehen auch wenn manche Flach sind, so sind
die für Anfänger supe, da man sieht ob man darauf reingefallen wäre..
Zeigt aber auch wieder die Vorteile von Pascal...!
Anfänger schrieb:> Wie ändere ich Bits in einem Register
Wieder nur für AVR gültige Antworten hier. Auf einem ARM mit
Bit-adressierbaren Registern oder einem 8051 geht das auch in C direkt
(und atomar) so:
#define LED P0_0
LED ^= 1;
bzw.
sbit LED = P0^0;
LED ^= 1;
Ok mit der 0 war ein Flüchtigkeitsfehler. Natürlich meinte ich 1<<0 und
1<<3.
Zu der atomaren Sache mal ne frage. Wenn ich im Register A die Bits 0-7
mit den Buchstaben a-h versehe mit #define
Muss ich beim zuweisen der Bits dann immer das Register mit angeben,
oder weiß der Compiler automatisch das es sich bei b immer um das 1. bit
aus Register A handelt?
Dann könnte man doch, wenn man zur ausgangsfrage zurückkehrt einfach
schreiben
b=1 und A hat den Wert 0b00000010 = dez 2
Und dann bei b=0 hat A den Wert 0
also probier gerade mit den bit Operationen etwas rum jetzt steh ich
gerade vor einem Problem und find nicht die richtige Operation.
ich hab in A= entwerder 0b001 oder 0b011 stehen
jetzt will ich sicher gehen das dort egal welcher zustand von den beiden
gegeben ist in A= 0b011 steht aber ich find nicht die richtige
Operation.
Anfänger schrieb:> Zu der atomaren Sache mal ne frage. Wenn ich im Register A die Bits 0-7> mit den Buchstaben a-h versehe mit #define>> Muss ich beim zuweisen der Bits dann immer das Register mit angeben,> oder weiß der Compiler automatisch das es sich bei b immer um das 1. bit> aus Register A handelt?
Nein, sowas geht (in C) nur, wenn die Hardware es kann und der Compiler
entsprechende Erweiterungen hat.
8051 z.B. hat P0 als einen 8-Bit-Port und P0_0..P0_7 als mit speziellen
Befehlen direkt addressierbare Bits, die HW-seitig die Bits des P0 sind.
Typische 8051-C-Compiler kennen den Datentyp __bit und erlauben mit "at
0x80" die Adresse einer Variable festzulegen. Damit kann man dann deine
Vorstellung verwirklichen.
ARM hat dafür "Bitbanding", aber das ist für die Zeit nach den
Grundlagen ;-)
Allgemein ist ein Port eine 8..32-Bit-Variable und die einzelnen Bits
müssen durch AND und OR manipuliert werden.
HW-Ports sind übrigens (fast immer) "volatile" deklariert, was bedeutet,
der Compiler muß jederzeit mit einer Änderung rechnen, die er nicht
selbst verursacht hat. Wenn man dann 2 Statements benutzt um 2 Bits zu
manipulieren,
1
// ASM in handübersetzt AVR-like
2
PORT|=(1<<2);// in r24,PORT; ori r24,0x04; out PORT,r24
3
PORT|=(1<<4);// in r24,PORT; ori r24,0x10; out PORT,r24
dann werden da garantiert 2 (Schreib)Zugriffe auf den Port draus.
Bei nur einen Statement
1
PORT|=((1<<2)|(1<<4));// in r24,PORT; ori r24,0x14; out PORT,r24
passieren dagegen beide Änderungen aus Port-Sicht gleichzeitig.
Carl D. schrieb:> HW-Ports sind übrigens (fast immer) "volatile" deklariert, was bedeutet,> der Compiler muß jederzeit mit einer Änderung rechnen, die er nicht> selbst verursacht hat.
Seit wann verursachen Compiler RT-Änderungen ? ;-)
Anfänger schrieb:> ich hab in A= entwerder 0b001 oder 0b011 stehen>> jetzt will ich sicher gehen das dort egal welcher zustand von den beiden> gegeben ist in A= 0b011 steht aber ich find nicht die richtige> Operation.
einfach zuweisen, da muss man ja gar nicht rechnen
a = 0b011;
Anfänger schrieb:> A|= (1<<1) | (1<<4);>> Ist das, dass selbe wie>> A|= (1<<1);> A|= (1<<4);
Nein, das ist nicht immer dasselbe. Typischerweise wird sowas nämlich
gebraucht, wenn A ein Register ist. Das wird dann als volatile
deklariert. Variante 1 setzt beide Bits auf einmal, bei Variante 2 sind
es zwei Schreibzugriffe, zwischen denen auch noch ein Interrupt
passieren kann.
Ist A hingegen nicht das eigentliche Register, sondern eine normale,
lokale Variable (Schattenregister), also nicht volatile, dann wid der
Compiler den Code aus Variante 2 zu dem aus Variante 1 zusammenfassen.
Daß die Bitzählung bei 0 losgeht und nicht bei 1, wurde ja schon
erwähnt.
Carl D. schrieb:> ARM hat dafür "Bitbanding", aber das ist für die Zeit nach den Grundlagen
Bitbanding ist nicht vollständig atomar, da ja intern doch wieder ein
READ-MODIFY-WRITE ausgeführt wird. Aktuelle ARM haben tatsächlich wie
ein 8051 Bit-adressierbare Peripherie-Register d.h. z.B. jedes Pin eines
Ports wird in ein Byte im Speicher gemappt. Im C Include sieht das dann
z.B. für LPC810 so aus:
#define PIN0BASE 0xA0000000
__IO_REG8(P0_0, PIN0BASE , __READ_WRITE);
__IO_REG8(P0_1, PIN0BASE + 1, __READ_WRITE);
...
Somit geht dann in C:
#define LED P0_1
LED = 1;
Und daraus wird dann in ASM:
STRB TRUE, [PIN0BASE, #1]
Zudem haben aktuelle ARM auch noch eine AND-NOT-Logik zum atomaren
Toggeln, das ist aber eher was für Inline ASM:
MOVS R0, #10B
STR R0, [NOT0]
icke schrieb:> Da Schreibt man einfach Not> und der Compiler ist schlau genug zu erkennen ob binär oder logisch.> Bei C habe ich immer wieder Probleme.Tanja schrieb:> wieder ein sehr schönes beispiel für die C hater Seite :-)> Die ich übrigens super finde, auch wenn man C lernen will!! da man> versucht die Beispiele zu verstehen auch wenn manche Flach sind, so sind> die für Anfänger supe, da man sieht ob man darauf reingefallen wäre..> Zeigt aber auch wieder die Vorteile von Pascal...!
Anfänger schrieb:> Wie ändere ich Bits in einem Register ohne> andere zu ändern also aus ein bit von 1 auf 0 oder von 0 auf 1 aber die> andern sollen unverändert bleiben.
Bei log. Verknüpfungen gilt:
Mit UND schaltet man bits aus.
Mit ODER schaltet man bits ein.
MIT Exklusiv-ODER invertiert man bits.
Felix H. schrieb:> Bei log. Verknüpfungen gilt:
Nein, du meinst bitweise Verknüpfungen.
Bei logischen geht es um boolsche Logik. Bei bitweisen um Bits.
Für mich besonders elegant zur Bitmanipulation erschien mir die Variante
mit sbit.h - ich glaube, sie war von Peter Dannegger und ist sicher mit
der Suchfunktion zu finden.
Dann sieht der entsprechende Teil im Programm z.B. so aus:
1
#include"sbit.h"
2
3
#define EIN 1
4
#define AUS 0
5
#define HIGH 1
6
#define LOW 0
7
8
#define OUTPUT 1
9
#define INPUT 0
10
11
#define KEY PORT_C6
12
#define KEY_DIR DDR_C6
13
#define KEY_IN PIN_C6
14
15
#define FET PORT_B2
16
#define FET_DIR DDR_B2
17
18
intmain()
19
{
20
KEY=HIGH;// Pullup on
21
KEY_DIR=INPUT;
22
FET_DIR=OUTPUT;
23
FET=AUS;
24
25
if(KEY_IN==HIGH)
26
{
27
FET=EIN;
28
}
29
else
30
{
31
FET=AUS;
32
}
33
.
34
.
35
.
36
}
Das soll nur ein anschauliches Beispiel sein - hier ohne
Tastaturentprellung und Endlosschleife ...
Man hat am Kopf eben etwas mehr 'defines', erhält dafür aber auch einen
deutlich besser lesbaren Code.
Ich hoffe, ich trete ihm nicht zu nahe, wenn ich die 'sbit.h' hier mit
anhänge.
icke schrieb:> Meine Muttersprache ist Pascal.> Da Schreibt man einfach Not> und der Compiler ist schlau genug zu erkennen ob binär oder logisch.
Dürfte daran liegen, daß Boolean in Pascal immer schon ein ganz eigener
Datentyp war und somit And, Not usw. angewandt auf Datentyp Bool, immer
eine logische Operation sein muß. Hingegen dieselben Operationen,
angewandt auf Integer, werden dann wohl binäre Operationen sein.
In C gab es bis C99 keinen Datentyp Boolean. Man konnte sich das mit
Makros nachahmen, aber das ergab dann wieder eigene Fallstricke. Es gilt
in C, daß jede ganzzahlige Variable logisch TRUE ist, die ungleich 0
ist. 0 ist dann FALSE.
P.S.: Ich hab auch anno dunnemals mit Pascal angefangen und bin dann
nach C-Land ausgewandert. Dort habe ich mich so gut eingelebt, daß ich
Pascal verlernt habe.
Felix H. schrieb:> avr schrieb:>> Nein, du meinst bitweise Verknüpfungen.>> Falsch.
Noch schlimmer. Es bleibt aber dabei, dass logische Verknüpfungen zur
boolschen Algebra gehören und damit nichts mit Bits zu tun haben.