Forum: Mikrocontroller und Digitale Elektronik char bit-weise ausgeben


von tobias hofer (Gast)


Lesenswert?

hallo

mir stellt sich folgendes problem:

ich benutze einen ds89c420 "8051" und einen c-compiler.
nun habe ich eine variable

unsigned char command=0xCC;

und möchte die variable bit-weise auf dem port pin P2_B2
ausgeben.
ich möchte das ganze jedoch in c-programmieren und nicht in asm.

kann mir jemand vieleicht ein kurzes bsp geben wie ich das programieren 
kann?

besten dank
tobias

von Sascha Weitkunat (Gast)


Lesenswert?

unsigned char Mask = 0x01;

do
{
  P2_B2 = (unsigned char)Value & Mask?0:1;
} while (Mask <<= 1);

von Oliver (Gast)


Lesenswert?

Hallo Sascha,
war wohl ein bischen spät(früh?) heute morgen.

unsigned char Mask = 0x01;

do
{
  P2_B2 = (unsigned char)Value & Mask?1:0; // !
} while (Mask <<= 1);

Hochachtung.Ich muß sagen: Superlösung!

Grüße
Oliver

von tobias hofer (Gast)


Lesenswert?

danke

kannst du mir vieleicht noch kurz erklären wie das
funktioniert?

gruss tobias

von Dieter Brüggemann (Gast)


Lesenswert?

Hallo tobias

Die Lösung von Sascha ist schon der Hammer. Aber als Anfänger braucht 
man erstmal 2 Stunden, um den Code nachzuvollziehen. Also grundsätzlich 
muß man immer ein Bit abfragen, ob es gesetzt ist oder nicht. Dann kann 
man entsprechen reagieren.

Hier ein Beispiel, was vielleicht besser zu verstehen ist:
#define sda_high  sbi(i2c_DataOut,sda)
#define sda_low    cbi(i2c_DataOut,sda)


 for (j=0;j<=7;j++)  //Schleife zum ausgeben der 8 Bits
  {
  if(daten & 0x80)      // MSB von data = 1
    {  sda_high;  //dann eine 1 schreiben
    }
    else                 //ansonsten eine 0 schreiben
    {    sda_low;  //dann eine 0 schreiben
    }
    daten<<=1;    // Daten eine Stelle nach links schieben,
um nächste Bit einzustellen.
    }

if(daten & 0x80) maskiert die Variable daten mit &B1000 0000 , womit nur 
das MSB zum tragen kommt. Also gibt die Routinen erst das MSB aus.


MFG
Dieter

von tobias hofer (Gast)


Lesenswert?

sehr elegant, danke

werde das mal versuchen zu implementieren.

gruss tobias

von tobias hofer (Gast)


Lesenswert?

das mit dem ausmaskieren und dem links shiften verstehe ich jetzt.
mit der define anweisung habe ich jedoch noch meine mühe.


könnte ich das auch so programieren:

for(j=0;j<=7;j++)
{
  if(daten&0x80) P2_B2=1;
  else  P2_B2=0;
  daten<<=1;
}

gruss tobias

von Dieter Brüggemann (Gast)


Lesenswert?

Hallo

Das mit den Define hat den Vorteil, daß man ganz am Anfang im Programm 
die Port festlegen kann. Wenn man jetzt beim nächsten Programm mal 
andere Port braucht, braucht man sie nur einmal oben im Porgramm zu 
ändern. Bei deiner Lösung mußt du nachher das ganze Programm 
durchsuchen, und die Ports ändern.

#define i2c_DataOut      PORTD
#define i2c_DataDir      DDRD
#define ic2_DataIn       PIND
#define sda       7    //ow Pin hier einfach den gewünschten Pin 
einstellen
#define scl       6    //ow Pin hier einfach den gewünschten Pin 
einstellen

#define sda_high  sbi(i2c_DataOut,sda)    //Zum bessern lesen des Codes
#define sda_low    cbi(i2c_DataOut,sda)
#define scl_high  sbi(i2c_DataOut,scl)
#define scl_low    cbi(i2c_DataOut,scl)

Wenn du im Programm jetzt schreibst sda_high wird nachher folgendes 
eingesetzt  sbi(PORTD,7)

Oder bei sbi(i2c_DataDir,sda);  // SDA auf Ausgang

sbi(DDRD,7)

Hoffe das hat etwas geholfen

MFG Dieter

von Sascha Weitkunat (Gast)


Lesenswert?

Hallo nochmal und Danke an Oliver für die Verbesserung, es war wohl 
wirklich etwas spät ;)

unsigned char Mask = 0x01, Value = 0xCC;

do
{
  P2_B2 = (unsigned char)Value & Mask?1:0;
} while (Mask <<= 1);

Also hier die vermisste Erklärung:
Value wird dem LSB voran ausgegeben, das gesetzte Bit in der Maske 
verschiebt sich mit jedem Durchlauf um eine Stelle nach links 
(0b00000001, 0b00000010, 0b00000100, 0b00001000, 0b00010000, 0b00100000, 
0b01000000, 0b10000000, [0b00000000]), das macht "Mask <<= 1". Nach dem 
letzten Durchlauf, 0b10000000, wird das das Bit einfach raus geschoben 
und somit ist Mask = 0 und die While-Schleife wird verlassen. Will man 
das MSB als erstes ausgeben initialisiert man Value einach auf 0x80 und 
shiftet nach rechts.

In der Schleife wird dein Wert (Value) mit der Maske UND-Verknüpft, ist 
die jeweiligen Bitstelle gesetzt so wird P2_B2 auf 1 gesetzt, 
andernfalls auf 0. Dazu hab ich den ?-Operator benutzt, 
<Bedingung>?<True-Statement>:<False-Statement>, der Cast nach "unsigned 
char" sorgt dafür dass es auch brav 8 Bit bleiben, man müsste evtl. mal 
ausprobieren ob dies überhaupt nötig ist.

von tobias hofer (Gast)


Lesenswert?

hallo

vielen dank für deine ausfürliche beschreibung.

gruss tobias

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.