Forum: Mikrocontroller und Digitale Elektronik Verständnisfrage


von xMcx (Gast)


Lesenswert?

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^^

von Lutz (Gast)


Lesenswert?

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

von Zero V. (Firma: Angestellter/Freelancer) (gnd)


Lesenswert?

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.

von xMcx (Gast)


Lesenswert?

ja das schon aber warum weiß er, dass er dort ein ein 8 Bit Register 
verwendet?
Wenn man also irgendwo z.B (1<<3) schreibt macht er daraus
                            0000 1000  ?

von Zero V. (Firma: Angestellter/Freelancer) (gnd)


Lesenswert?

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!

von xMcx (Gast)


Lesenswert?

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^^

von DirkB (Gast)


Lesenswert?

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.

von xMcx (Gast)


Lesenswert?

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
                   ?????

von Achim M. (minifloat)


Lesenswert?

xMcx schrieb:
> i=|255;

Wenn du "i |= 255;" oder "i |= 0xFF;" schreibst, ist es tatsächlich so 
wie du sagst.

mfg mf

von KlausK (Gast)


Lesenswert?

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
int asdf = 160;  // --> 0b10100000
2
asdf |= (1<<2);  // drittes Bit von rechts setzen --> 0b10100100
3
asdf &= ~(1<<2); // drittes Bit von rechts löschen --> 0b10100000

HTH,
Klaus

von xMCx (Gast)


Lesenswert?

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?

von Karl H. (kbuchegg)


Lesenswert?

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

von xMCx (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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)

von xMCx (Gast)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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

von Hannes L. (hannes)


Lesenswert?

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.

...

von Hannes L. (hannes)


Lesenswert?

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.

...

von Karl H. (kbuchegg)


Lesenswert?

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.

von Hannes L. (hannes)


Lesenswert?

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.

...

von xMCx (Gast)


Lesenswert?

hab ich das nun falsch formuliert? Tut mir echt leid, dass deine Nerven 
so belastet werden

von xMCx (Gast)


Lesenswert?

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

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.