hi, wenn ich z.B eine abfrage eines pins vornehmen möchte funktioniert
das ja z.B über
if (!(PINB&(1<<PB3)))
soweit ich das verstanden hab ist das so:
PINB= angenommener Zustand: 1111 1111
dies wird mit 0000 1000
mit einem UND verknüpft :
wenn die beiden zusammen an der stelle (PB3) nicht wahr sind würde ja
die if abfrage durchlaufen.
warum wird bei dem satz (1<<PB3) anscheinend immer ein leere 8 bit
kombination vorrausgesetzt (0000 0000)
kann man dies beeinflussen? z.b 0000 0000 0000 0000?
hoffentlich ist das einigermaßen verständlich^^
Beim Bitshift (1<<PB3) wird eine "1" um 3 Stellen nach links geshiftet.
Die Definition in C ist , daß beim Shiften immer mit Nullen aufgefüllt
wird.
Wenn die Prozessorachitektur 8 bit ist, wird daraus 0000 1000. Bei 16
Bit wird daraus 0000 0000 0000 1000.
Man kann dies auch z.B. durch sogenanntes casten erreichen, z.B. mit
(uint16_t) (1<<PB3).
xMcx schrieb:> z.b 0000 0000 0000 0000?
Wozu das denn?
Dein PINB Register ist nur 8Bit lang, so macht es keinen Sinn diesen mit
z.B. 0100 0000 0000 0000 zu vergleichen.
Mit 1<<3 sagst du ja das im 1. Byte eine 1 geshiftet wird und nicht
darüber hinaus (1 Byte kleinster Datentyp).
Würde jetzt mit 16Bit verglichen werden werden Reststellen mit 0
gefüllt!
sry, hab das oben von Lutz nicht gelesen.
Danke, das ist die Antwort.
Also ist das praktisch bei einer 8- Bit Architektur vorgegeben außer man
schreibt es selber vor wie du geschrieben hast.
Danke^^
Die Berechnungen werden als int durchgeführt.
PINB wird zum int erweitert und das (1<<PB3) ist sowieso ein int.
Sinnvoller wäre es daher die 1 zu casten. Die ist ein int.
Wenn du ((long)1<<4) schreibst klappt das auch wenn sizeof(long) !=
sizeof(int) ist.
noch eine Frage
Annahme:
uint16_t i=0;
i=(255<<8);
i=|255;
weiß grad nicht ob man die 255 so da rein schreiben kann aber mir geht
es um das Verständnis.
Passiert hier das: i= 0000 0000 0000 0000
i=(255<<8); i= 1111 1111 0000 0000
i=|255; i= 1111 1111 1111 1111
?????
Hi,
xMcx schrieb:> hi, wenn ich z.B eine abfrage eines pins vornehmen möchte funktioniert> das ja z.B über>> if (!(PINB&(1<<PB3)))>> soweit ich das verstanden hab ist das so:> PINB= angenommener Zustand: 1111 1111> dies wird mit 0000 1000> mit einem UND verknüpft :
if() wertet aus, ob das Ergebnis == 0 (0b00000000) ist, also False --
die if()-Bedingung ist dann nicht erfüllt. Wenn irgendein Bit im
Ergebnis gesetzt ist, dann ist das Ergebnis != 0, also True: die
if()-Bedingung ist erfüllt, und Dein Programm springt in den if()-Block.
Anders gesagt: 0 ist äquivalent zu False, alles andere ist True -- das
ist der ganze Trick.
1
. 1111 1111
2
& 0000 1000
3
------------
4
= 0000 1000 == 8 == True
5
6
. 1111 0111
7
& 0000 1000
8
------------
9
= 0000 0000 == 0 == False
Das geht auch mit mehreren Bits -- sobald nur eines der gewünschten Bits
gesetzt ist, wird der Ausdruck True:
1
. 1111 1101
2
& 0000 1010
3
------------
4
= 0000 1000 == 8 == True
5
6
. 1111 1111
7
& 0000 1010
8
------------
9
= 0000 1010 == 10 == True
10
11
. 1111 0111
12
& 0000 1010
13
------------
14
= 0000 0010 == 2 == True
15
16
. 1111 0101
17
& 0000 1010
18
------------
19
= 0000 0000 == 0 == False
> warum wird bei dem satz (1<<PB3) anscheinend immer ein leere 8 bit> kombination vorrausgesetzt (0000 0000)
Naja, ich versuch's mal so zu erklären: Du shiftest eine Eins in Nichts.
Das Nichts ist per Definition 0. Oder 0b0000000 ... you get the idea.
> kann man dies beeinflussen?
Ja, indem Du eine Variable mit dem gewünschten Wert vorbelegst, und dann
wendest Du Deine Bitoperation auf die Variable an.
1
intasdf=160;// --> 0b10100000
2
asdf|=(1<<2);// drittes Bit von rechts setzen --> 0b10100100
3
asdf&=~(1<<2);// drittes Bit von rechts löschen --> 0b10100000
Vielen Dank auch hierfür =).
Mich plagt noch ein kleines Problem (hoffentlich das letzte) und zwar:
Im Datenblatt des atmega 168 steht zum USART:
19.10.1 UDRn – USART I/O Data Register n,
dieses besteht soweit ich sehe aus 2* 8 Bit-Register
Wenn ich nun im Programm schreibe:
UDR = x;
Dann muss er ja x in das Write Register schreiben.
Wäre diese Operation gleich wie das hier
TXB = x; ?
ersetzt der Compiler automatisch beim Schreibzugriff das UDR durch TXB
und beim Lesezugriff durch RXB?
oder was passiert da?
xMCx schrieb:> 19.10.1 UDRn – USART I/O Data Register n,>> dieses besteht soweit ich sehe aus 2* 8 Bit-Register
Ja.
Aber nur deshalb, weil dein Mega auch 2 unabhängige UART hat.
das n in der Beschreibung ist so zu verstehen, dass es anzeigt, welche
UART gemeint ist.
UDR0 .... die UART, die Datenblatt überall als die UART 0
bezeichnet wird, und deren Pins laut ANschlussschema
des Prozessors auch entsprechend zugeordnet sind.
UDR1 .... die UART, die im Datenblatt überall als die UART 1
bezeichnet wird, und deren Pins laut ANschlussschema
des Prozessors auch entsprechend zugeordnet sind.
man hätte da auch eine "rote" und eine "gelbe", oder eine "runde" und
eine "eckige" UART einfügen können. Aber einfach Durchnummerieren ist
nun mal das einfachst und es gibt keine Misverständnisse.
> Wäre diese Operation gleich wie das hier>> TXB = x; ?
Es gibt kein Register namens TXB. Zumindest keines, das du ansprechen
könntest. Beim Schreiben auf UDR landet das Byte im AUsgangsregister von
der UART, beim Lesen von UDR kommt das Byte aus dem Eingangsregister der
UART
Wenn ich z.B schreibe UDR=x; woher weiß der dann das er das untere
Register nehmen muss und beim Lesen x=UDR; das obere Register?
Weiß nicht wie ich das schreiben soll, zweifel grad selber ;)
xMCx schrieb:> Wenn ich z.B schreibe UDR=x; woher weiß der dann das er das untere> Register
NOch mal.
Es gibt kein 'unteres' UDR Register.
Wenn du mit der UART0 arbeitest, dann gibt es ein UDR0 Register.
Wenn du mit der UART1 arbeitest, dann gibt es ein UDR1 Register.
(d.h. beide existieren natürlich dauernd. Aber für dich ist immer nur
dasjenige interessant, dass zu der UART gehört, mit der du arbeitest)
ja das schon aber das ist ja 16 Bit groß z.B das UDR0.
8- Bit zum Lesen, 8- Bit zum Schreiben oder?
ich dachte das es da irgendeine Operation gibt wie beim ADC Register.
Dort kann man glaub auch das Register direkt ansprechen obwohl es aus 2*
8 Bit Register besteht.
x=ADC;
Dort muss doch der Compiler oder sonst was auch festlegen wie der Wert
von dem ADC in x kommt.
die 16 Bit werden ja nicht auf einmal geschickt.
xMCx schrieb:> ja das schon aber das ist ja 16 Bit groß z.B das UDR0.
NEIN
> 8- Bit zum Lesen, 8- Bit zum Schreiben oder?
NEIN
UDR ist 8 Bit groß. Wie Atmel das intern macht, dass beim Schreiben das
µC intern in einem anderen Siliziumareal landet als das von dem du die
Daten bekommst, wenn du auf UDR lesend zugreifst .... das ist etwas, was
dich nicht zu interessieren braucht.
Du beschreibst UDR und schickst damit 8 Bit auf die Reise.
8-Bit Daten kommen rein, und du kriegst sie, indem du auf UDR lesend
zugreifst.
Atmel hat das im Datenblatt möglicherweise etwas verwirrend dargestellt.
VOn den im Datenblatt zusammengefassten Prozessoren, Mega48, Mega88 und
Mega168 verfügt keiner über 2 UARTS. n ist bei dir immer 0
Karl Heinz Buchegger schrieb:> Es gibt kein 'unteres' UDR Register.
Er meint wohl was Anderes.
UDRx ist ein gemeinsamer Name für 2 physikalisch getrennte Register.
Beim Schreiben wird automatisch immer das Senderegister gewählt,
beim Lesen wird automatisch immer das Empfangsregister gewählt.
Es ist so wie mit dem "Briefkasten". Will man etwas versenden, so meint
man die gelbe Kiste bei der Post, will man etwas bekommen, meint man den
eigenen Briefkasten am Haus. Beides nennt man aber "Briefkasten", weil
die Unterscheidung automatisch aus dem Kontext erfolgt.
...
xMCx schrieb:> ich dachte das es da irgendeine Operation gibt wie beim ADC Register.> Dort kann man glaub auch das Register direkt ansprechen obwohl es aus 2*> 8 Bit Register besteht.
Das ist was völlig Anderes. ADC und 16-Bit-Timer haben 16-Bit-Register.
Um auf diese atomar zugreifen zu können, wird ein Hilfsregister als
Zwischenspeicher verwendet. Deshalb muss beim Lesen und Schreiben die
richtige Reihenfolge von H-Byte und L-Byte eingehalten werden.
...
Hannes Lux schrieb:> Es ist so wie mit dem "Briefkasten". Will man etwas versenden, so meint> man die gelbe Kiste bei der Post, will man etwas bekommen, meint man den> eigenen Briefkasten am Haus. Beides nennt man aber "Briefkasten", weil> die Unterscheidung automatisch aus dem Kontext erfolgt.
Gutes Beispiel. Muss ich mir merken.
Wenn im Programm steht:
"Schmeiss den Brief in den Briefkasten"
dann ist der bei der Post gemeint.
Steht im Programm
"Hol den Brief aus dem Briefkasten"
dann ist der im Flur gemeint, in den der Briefträger die Post reinlegt.
im ersten Fall wäre das dann
UDR = 'x'; // Das Bitmuster für x wird versandt
der zweite Fall ist
uint8_t i;
i = UDR; // Da empfangene Bitmuster wird geholt
rein nur durch die Verwendung bestimmst du, welches der beiden im
Datenblatt im Kapitel UDR angegebene 'Register' TXB oder RXB benutzt
wird.
Karl Heinz Buchegger schrieb:> Atmel hat das im Datenblatt möglicherweise etwas verwirrend dargestellt.> VOn den im Datenblatt zusammengefassten Prozessoren, Mega48, Mega88 und> Mega168 verfügt keiner über 2 UARTS. n ist bei dir immer 0
Die Autoren von Atmel stellen auf Textbausteine (wiederverwertbaren
Text, so wie C-Programmierer wiederverwertbaren Code bevorzugen) um.
Somit gilt ein UART-Kapitel (oder Timer, oder...) für alle künftigen
AVRs, egal wie viele UARTs (oder andere Peri-Einheiten) dort
implementiert sind.
...
>>UDRx ist ein gemeinsamer Name für 2 physikalisch getrennte Register.>>Beim Schreiben wird automatisch immer das Senderegister gewählt,>>beim Lesen wird automatisch immer das Empfangsregister gewählt.
Das hat mir gefehlt.
Ich hab mich gefragt wie er das Senderegister anwählt.
Wo ist das definiert, dass er beim Senden UDR0=x;
das Richtige Register nimmt, glaub das TXB wars.
Das läuft aber dann intern ab?
Vielen vielen Dank an alle