PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Bitfolgen in hex darstellen



Barthimaeus
04.10.2008, 01:07
Ich versuche grade zum 2. Mal in die AVR Programmierung mit C einzusteigen. Die Grundzüge und Kontrollstrukturen der Sprache sind mir vom Programmieren am Computer aus bekannt und stellen daher kein Problem dar. Es ist mir gelungen avr-gcc einzurichten und ich kann mit einer makefile das Programm auch direkt in den Controller flashen. Soweit Alles prima.

Nun zu meinem eigentlichen Problem. Am AVR sind ja alle IO Pins in Ports zu je 8 Stück zusammengefasst. Aufgrund der Beschaffenheit von C kann ich nun nicht jeden Pin einzeln ansprechen, sondern ich muss eine Zahl in das entsprechende Port(-richtungs-)byte schreiben, die den Zustand aller 8 pins am Port beinhaltet. In Binär ist das kein Problem. "00000101" würde beispielsweise Pin 0 und 2 des Ports einschalten, bzw. als Ausgang definieren. Nun ist es aber verhältnismäzig umständlich diese Bitfolgen in Binär zu schreiben, bzw. es dauert einfach relativ lang. Daher benutzen viele Leute anscheinend hex. Ich bin mir darüber im klaren, wie das hexadezimalsystem funktioniert, aber ich komme nicht dahinter, was es so einfach macht Bitfolgen in hex darzustellen. Wenn ich das machen wollte müsste ich den hexwert einer Bitfolge entweder in einer Tabelle nachschlagen, oder ihn Mühevoll umrechnen. Aber dann könnte ich ja auch gleich das dezimalsystem verwenden, oder? Kann mir bitte jemand erklären, wie ich von einer (binären) Bitfolge auf einen Hexwert komme, ohne auf eine dieser Möglichkeiten zurückzugreifen? Fände ich echt klasse von euch, denn ich komme einfach nicht dahinter.

markusj
04.10.2008, 01:44
Hi,

viele Leute nutzen nicht Hex, sondern so ein Konstrukt hier: DDRB = (1 << DDB3);
Das bedeutet: Schiebe die eins so weit nach "links", dass sie bei DDB3 "landet".
Willst du also dein "00000101" darstellen, kannst du folgendes verwenden:
X = (1 << 2)|(1<<0).
Damit wird eine eins zweimal nach links geschoben, also von 00000001 nach 000000100. Das Ergebnis wird dann mit einer eins, die nicht verschoben wird, per logischem Oder verknüpft:
000000100
000000001
------------
000000101

Oder du nimmst dennoch Hex und rechnest es eben aus. Jeweils vier Bits ergeben ein Zeichen, es wird durchgezählt von null bis 15, wobei die Zahlen zehn bis 15 durch die Buchstaben A bis F repräsentiert werden.
Und ansonsten das übliche, Bit 0 entspricht 1, Bit 1 entspricht 2, Bit 3 entspricht 4, Bit 4 entspricht 8.

mfG
Markus

PS: Eine besser Erklärung gibts sicher im RN-Wissen-Artikelbereich.

nil.at
04.10.2008, 01:58
Guten Abend,

markusj hat das ja bereits prima erklärt, zur Ergänzung ein recht hilfreicher Link und ein kleines Beispiel.
Link:
http://www.easycalculation.com/hex-converter.php
Dort kannst du einen HEX Wert eingeben und du siehst sofort welchen Binärwert er repräsentiert.

Und zum Beispiel und der Umrechnung:
Du kennst HEX ja bereits, also wirst du wissen dass man mit einer HEX Zahl 16 Zahlen, also 0 - 15 darstellen kann.
Um dieselbe Anzahl an Zahlen im Binärsystem darstellen zu können bräuchtest du 4 Bit. (2^4 = 16)
Ergo entsprichen 4 Bit 1 HEX.
In Hex wird 0 - 9 durchnummeriert mit den Zahlen 0 - 9, für 10 - 15 wird, wie markusj ebenso schon gesagt hat A - F verwendet.

Das heisst, 1111 entspricht F, 1010 entspricht A, 0111 entspricht 7.
Wenn du demnach die Zahl 00000101 (aus deinem Thread) darstellen willst , wäre das in hex 05, oder nur 5.
In C müsstest du dass dann mit 0x5 schreiben.

Hoffe geholfen zu haben.
Gruß und gn8

McJenso
04.10.2008, 10:15
Hallo,

wenn du denn doch umrechnen musst, der Windows-Taschenrechner kann in der wissenschaftlichen Ansicht prima hex in dez oder auch bin und umgekehrt rechnen. Wenn es Linux ist, gcalctool kann es auch.
Ansonsten ist es halt recht praktisch das zwei Ziffern ein Byte ergeben. Erste Ziffer für die 4 höherwertigen Bits die zweite Ziffer für die 4 niederwertigen. Für das Programm ist es letztendlich egal, welches Zahlensystem du nimmst.

Gruß

Jens

Barthimaeus
04.10.2008, 11:12
X = (1 << 2)|(1<<0)
Und wenn ich mit einem solchen Konstrukt 7 von 8 Bits in einem Byte setzten möchte wird das ganze dann ziemlich lang, oder?

Vielen dank an alle für die bisherigen, sehr aufschlussreichen erklärungen!

markusj
04.10.2008, 11:48
X = (1 << 2)|(1<<0)
Und wenn ich mit einem solchen Konstrukt 7 von 8 Bits in einem Byte setzten möchte wird das ganze dann ziemlich lang, oder?
Vielen dank an alle für die bisherigen, sehr aufschlussreichen erklärungen!
Ja, aber thats C ;)
Es gibt auch noch die inoffizielle Syntax mit 0b01101001, das ist aber nur in WinAVR eingepatcht und gehört nicht zum C-Standard.

Der Vorteil besteht darin, dass du zum Bleistift bei einer Initialisierung:

UCSR0B = (1 << RXCIE0)|(1 << RXEN0)|(1 << TXEN0);
Schnell siehst, welche Bits (und damit Funktionen) gesetzt werden.

mfG
Markus

PS: Und wenn du sieben von acht Bits setzen willst: X = ~(1<<Nicht_Gesetztes_Bit);
\:D/

Barthimaeus
04.10.2008, 19:58
#include <avr/io.h>

int main (void) {

DDRC = 0xff;
PORTC = (1<<4)|(0<<3);

while(1) {
}

return 0;
}

Also würde folgendes Programm den gesamten Port C als Ausgang definieren und PortC.5 auf 1 und PortC.4 auf null setzten? Wenn dem so ist müsste eine LED zwischen PortC.5 und PortC.4 aufleuchten?

Warum tut sie es bei mir nicht?

markusj
04.10.2008, 21:07
Öhm, du solltest beim Zugriff auf die Ports/Pins die definierten Werte zu benutzen:
PORTC = (1 << PB4);
Nullen brauchst du nicht schieben, du hast Null und definierst die gesetzten Einsen.

Es gibt für DDRx jeweils DDxN (N ist eine Zahl), für PINx gibt es PINxN, PORTx hat PxN definiert.

@LED: Möglicherweise kapott? Hast du nen Vorwiderstand dabei? Richtig herum gepolt?

mfG
Markus

Barthimaeus
04.10.2008, 22:06
Mit "PORTC = (1<<PC5);" klappt es. Aber als was ist denn PC5 definiert? Ich hätte angenommen, dass "PORTC = (1<<PC5)" "PORTC = (1<<4)" entspricht, denn wenn, man eine 1 im PORTC Byte um vier Stellen nach links verschiebt, so müsste doch das fünfte Bit gesetzt sein, oder?

markusj
04.10.2008, 22:34
Keine Ahnung, vielleicht liegts an dem verwendeten µC. Du kannst dir die Include-Files im WinAVR-Zeichnis\avr\include\avr\io*.h
Wobei * der entsprechende Typ ist, teilweise werden Familien auch zusammengefasst (iomx8.h für ATMega 48,88,168) werden.

mfG
Markus