Forum: Compiler & IDEs Ports Splitten


von Sebastian (Gast)


Lesenswert?

Hallo,

Ich mache gerade meine ersten Schritte mit WinAVR und C. Ich habe
bereits einzelne Ports erfolgreich angesprochen, nun zu meiner Frage
Problem:

Ich möchte gerne bei einem Atmage8 ein "virtuelles Port" durch C
erstellen.
Genau genommen so:
PB.4 = Bit1
PB.5 = Bit2
PC.0 = Bit3
PC.1 = Bit4
PC.2 = Bit5
PC.3 = BIT6
PC.4 = Bit7
PC.5 = Bit8

Es soll dann die Möglichkeit bestehen das virtuelle Port mit einem Byte
zu füttern, und dieses Byte soll dann richtig an den einzelnen Pins von
Portb und Portc rauskommen.

Ich war bereits fleißig und hab gegoogelt und auch ihr im Forum
folgenden Beitrag gefunden:

http://www.mikrocontroller.net/forum/read-2-219856.html#new

darin steht folgende Lösung:
#define MYPORT ((PINB & 0x01)<<8 | (PINB & 0x04)<<7 | ....)

uint8_t bla;
bla = MYPORT;

Leider, da ich c anfänger bin versteh ich das leider nicht ganz:

(PINB & 0x01)<<8

Was bedeutet diese Zeile den genau?

(PINB & 0x01) bedeutet dies, dass Pinb.0 angesprochen werden soll?

...<<8 bedeutet dies, dass bit8 von myport zugeordnet wird?

Demnach sollte das bei mir dann so gehen?:

#define MYPORT ((PORTC & 0x20)<<8 | (PINC & 0x10)<<7 |
(PINC & 0x08)<<6 | (PINC & 0x04)<<5 | (PINC & 0x02)<<4 |
(PINC & 0x01)<<3 | (PINB & 0x20)<<2 | (PINB & 0x10)<<1 | )

Stimmt das?Danke schon mal!

von Sebastian (Gast)


Lesenswert?

Sollen natürlich Ausgänge sein!

Also dann so:

#define MYPORT ((PORTC & 0x20)<<8 | (PORTC & 0x10)<<7 |
(PORTC & 0x08)<<6 | (PORTC & 0x04)<<5 | (PORTC & 0x02)<<4 |
(PORTC & 0x01)<<3 | (PORTB & 0x20)<<2 | (PORTB & 0x10)<<1 | )

uint8_t test;
MYPORT = test;

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

1
#define MYPORT(x) \
2
  do { \
3
    PORTC = (PORTC & 0xc0) | ((x) & 0xfc) >> 2); \
4
    PORTB = (PORTB & 0xcf) | ((x) & 3) << 4); \
5
  } while(0)
6
...
7
MYPORT(test);

Verstehen musst du es bitte selbst.  Lies dir im C-Buch oder -Artikel
deiner Wahl das Kapitel über Bitoperatoren durch.  Die Bedeutung des
do ... while(0)-Konstrukts ist hier im Forum schon paarmal durchgekaut
worden.  Nur kurz dazu: überleg dir, wie sich der Makro verhält, wenn
du
1
if (some_condition)
2
  MYPORT(test);
3
else
4
  do_something_else();

schreibst.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

p.s.: Sonderlich effektiv wird das Ganze nicht sein.

von Sebastian (Gast)


Lesenswert?

mh... danke!
aber da versteh ich jetzt leider nich viel...
also geht mein vorschlag nicht, oder?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> also geht mein vorschlag nicht, oder?

Ja, er geht nicht.

von Sebastian (Gast)


Lesenswert?

ich komm da nicht so zurecht, bitte helft mir! Hier mal nochmal eine
Idee von mir:

#include <io.h>
#include <inttypes.h>

void setport (unsigned char x)



main()
{
DDRC = 0xff;
DDRB = 0xff;


setport(0x0f)

};

void setport(unsigned char x)
{


(PORTC & 0x20)<<Myport.b8;
(PORTC & 0x10)<<Myport.b7;
(PORTC & 0x08)<<Myport.b6;
(PORTC & 0x04)<<Myport.b5;
(PORTC & 0x02)<<Myport.b4;
(PORTC & 0x01)<<Myport.b3;
(PORTB & 0x20)<<Myport.b2;
(PORTB & 0x10)<<Myport.b1;
};

typedef struct {
  unsigned char b1:1;
  unsigned char b2:1;
  unsigned char b3:1;
  unsigned char b4:1;
  unsigned char b5:1;
  unsigned char b6:1;
  unsigned char b7:1;
  unsigned char b8:1;
} Myport;

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Nein, das geht alles so nicht, glaub's doch.

Du kannst meinen Macro gern nehmen, auch als ,blackbox', aber
bevor du weiter mit trial&error irgendwelchen unsinnigen (sorry)
Code zusammennagelst, bitte, bitte, lies' dir die Geschichte mit
den Bitmanipulationsoperatoren in einem ordentlichen C-Buch durch.

von Karl H. (kbuchegg)


Lesenswert?

Jörg hat Recht.
Dir fehlen zuviele Grundlagen. Lies ein C-Buch.

> (PINB & 0x01) bedeutet dies, dass Pinb.0 angesprochen werden soll?

Nein. Es bedeutet, dass der Wert von PINB geholt wird und
mit einer Maske von (hex) 01 ein einzelnes Bit isoliert wird
(alle anderen Bits werden definiert auf 0 gesetzt).

> ...<<8 bedeutet dies, dass bit8 von myport zugeordnet wird?

Nein: << ist in C der Links-Schiebe-Operator
Der vorher erhaltene Wert wird um 8 bits nach links geschoben.

von Peter (Gast)


Lesenswert?

Du kannst auch schon sehr viel lehrreiches im hiesigen AVR-GCC Tutorial
finden:

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial

von Bernhard Ahorn (Gast)


Lesenswert?

Hallo Sebastian,

ich hatte ein ähnliches Problem.
Beschäftige mich nach über 20 Jahren zum ersten mal wieder mit uC´s.
Teilweise war das LCD mit 3 Segmenten so an einen Atmega16
angeschlossen, dass ein Segment auf 3 Ports verteilt war.
Den Tipp habe ich von einem Kollegen bekommen.

Du kannst das ganze lösen indem du mit Shift und logischen Operatoren
arbeitest. z.B.
PORTB = (LCD.d2&0x1c)|((LCD.d3<<4)&0xc0)|((LCD.d1>>3)&0x03)|(1>>PB5);

LCD.dx ist die Variable die die Segmentausgabe enthält.
Wie du siehst war das PORTB auf 3 Segmente verteilt PB5 steuerte den
Dezimal Punkt des Displays.
z.B. PB2-PB4 bildeten die bits 2-4 von LCD.d2 mit
(LCD.d2&0x1c) maskierst du die restlichen Bits
PB6 und PB7 bildeten die Bits 2 und 3 von LCD.d3 mit
((LCD.d3<<4)&0xc0 shiftest du die Stellen auf die richtige Position für
dein PORTB und maskiert Sie wieder durch die Oder Verknüpfung werden Sie
in dein PORTB stellenrichtig integriert. usw.
Damit kannst du jede Verdrahtung realisieren.

Gruß
Bernhard

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.