Forum: Mikrocontroller und Digitale Elektronik Wie kann ich die Binärstellen einer Variable auf Ausgangsports verlinken


von Gernot H. (schnuck)


Lesenswert?

Hallo zusammen,

wie kann ich die Binärstellen einer INT Variable direkt auf die 
Ausgangsports (Atmega8) verknüpfen?

Als Beispiel habe ich eine Integer Variable "X" die den Wert 13 
(00001101) besitzt. Dann soll die Variable "X" folgendermaßen mit den 
PORTA verknüpft werden.

1  => PORTA.2
0
1  => PORTA.0
1  => PORTA.1
0
0
0
0

Die Programmcode möglichst in C++ schreiben.

Danke schonmal im Vorraus

Schnuck

von Nico S. (Gast)


Lesenswert?

ATmega und C++? Viel Spaß.

von Gernot H. (schnuck)


Lesenswert?

Es geht auch in C.

von Chris L. (kingkernel)


Lesenswert?

PORTA = i;

von Gernot H. (schnuck)


Lesenswert?

Christian L. schrieb:
> PORTA = i;

Werden hier nicht die Ports aufsteigend der Binärstellen belegt?

von holger (Gast)


Lesenswert?

>Als Beispiel habe ich eine Integer Variable "X" die den Wert 13
>(00001101) besitzt. Dann soll die Variable "X" folgendermaßen mit den
>PORTA verknüpft werden.

Wenn die anderen Pins 0 bleiben sollen:

temp = 0;
temp = (var & 0x01) << 2;
temp |= (var & 0x04) >> 2;
temp |= (var & 0x08) >> 2;
PORTA = temp;

von Chris L. (kingkernel)


Lesenswert?

Was genau willst du machen? Welche Portpins sollen mit welcher Bitstelle 
verknüpft werden
vielleicht auch so:
1
PORTA = 0;
2
if(i & (1 << 0)) PORTA |= 1 << PA0;
3
if(i & (1 << 1)) PORTA |= 1 << PA1;
4
if(i & (1 << 2)) PORTA |= 1 << PA2;
5
if(i & (1 << 3)) PORTA |= 1 << PA3;
6
if(i & (1 << 4)) PORTA |= 1 << PA4;
7
if(i & (1 << 5)) PORTA |= 1 << PA5;
8
if(i & (1 << 6)) PORTA |= 1 << PA6;
9
if(i & (1 << 7)) PORTA |= 1 << PA7;
Da kannst du dan indem du die PA? änderst den jeweiligen Portpin 
auswählen. Simpelste Grundlagen!

[EDIT]
Wenn du das ganze mehrmals machen willst, könntest du die Bitstellen des 
Ports in ein Array packen und alles schön einer einer Schleife 
abarbeiten und entsprechend setzen.
[/EDIT]

von Gernot H. (schnuck)


Lesenswert?

Christian L. schrieb:
> Was genau willst du machen? Welche Portpins sollen mit welcher Bitstelle
> verknüpft werden


Also der PORTA.2 soll die niedrigste, PORTA.0 die dritt niedrigste, und 
der PORTA.1 die viert niedrigste Stelle der Variablen darstellen.

von eProfi (Gast)


Lesenswert?

Wenn PortA ansonsten unverändert bleiben soll:

PORTA = (PINA & 0b11111000)
      | ((x&(1<<3))>>(3-PA1))
      | ((x&(1<<2))>>(2-PA0))
      | ((x&(1<<0))<<(PA2-0));

von Gernot H. (schnuck)


Lesenswert?

Ich könnte zwar auch die einzelnen Stellen rechnerisch ermitteln und den 
einzelnen Port´s zuweisen, aber ich dacht mir, dass es noch eine 
elegantere Art gibt.

Ich schau mir mal die einzelnen Lösungen genauer an.

von holger (Gast)


Lesenswert?

>Ich könnte zwar auch die einzelnen Stellen rechnerisch ermitteln und den
>einzelnen Port´s zuweisen, aber ich dacht mir, dass es noch eine
>elegantere Art gibt.

13 in drei Bits zu packen ist schon ziemlicher
Schwachsinn. Das geht gar nicht.
Drei Bits können maximal 7 darstellen.

Sag was du wirklich machen möchtest. Dann kann
man dir auch eine SINNVOLLE Lösung bieten.

von Gernot H. (schnuck)


Lesenswert?

holger schrieb:
> 13 in drei Bits zu packen ist schon ziemlicher
> Schwachsinn. Das geht gar nicht.
> Drei Bits können maximal 7 darstellen.
>
> Sag was du wirklich machen möchtest. Dann kann
> man dir auch eine SINNVOLLE Lösung bieten.


Ich versuchs nochmal zu erklären. Wenn die Variable "X" einen gerade 
Wert besitzt, dan soll der PORTA.2 low sein (niedrigstes Bit = 0). Wenn 
der Wert ungerade ist, soll der PORTA.2 high sein (niedrigstes Bit = 1). 
Analog dazu soll der PORTA.0 und der PORTA.1 entsprechend ihrer binären 
wertigkeit angesprochen werden.

von Karl H. (kbuchegg)


Lesenswert?

Dann würde ich sagen: dumm gelaufen.

wenn man beim Hardware-Bauen ein wenig mitdenkt, kann man sich Arbeit 
ersparen. Tut man das nicht, muss man dann eben im Code ausbaden, was 
man beim Hardware-Designen verpasst hat.

Lösungsvorschlag hast du ja.

von Roland P. (pram)


Lesenswert?

Wenn du genug Speicher hast kannst das auch mit einer lookuptable machen

PORTA = lookup[x]

(bzw mit pgm-Makros direkt aus dem Flash lesen)

von eProfi (Gast)


Lesenswert?

Meine Kristallkugel sagt:
Die Steuerleitungen eines LCDs sind anders angeschlossen.
Das korrigiert man besser vorher mit den Defines.
Oder ist es was anderes?



Holger fragte schon danach:
> Sag was du wirklich machen möchtest. Dann kann
> man dir auch eine SINNVOLLE Lösung bieten.

Auch ich bitte um eine KLARTEXT-Aussage:
Wo kommt das x her?
Was ist an PORTA angeschlossen?
Warum müssen die Bits verdreht werden?
Bitte keine schwammigen Angaben.
Danke

von Gernot H. (schnuck)


Lesenswert?

eProfi schrieb:
> Auch ich bitte um eine KLARTEXT-Aussage:
> Wo kommt das x her?
> Was ist an PORTA angeschlossen?
> Warum müssen die Bits verdreht werden?



Ich lasse die Variable X in einem Timerinterrupt bis zu einen bestimten 
Wert hochzählen und setze diesen dann bei einem bestimmten Wert wieder 
auf Null zurück. Die einzelen PORTs dienen dann als eine Art 
Frequenzteiler.

Mir ist schon klar, dass ich einfach "PORTA = X;" hätte nehmen können. 
Mir ging es aber darum, eine bestimmte binäre Stelle, einem bestimmten 
Port zu zuweisen.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Gernot H. schrieb:
> Mir ging es aber darum, eine bestimmte binäre Stelle, einem bestimmten
> Port zu zuweisen.

Kann man ja auch machen, aber dann designt man die Hardware so, daß die 
Wertigkeit der Portbits denen der internen Repräsentation entspricht.

von holger (Gast)


Lesenswert?

>Kann man ja auch machen, aber dann designt man die Hardware so, daß die
>Wertigkeit der Portbits denen der internen Repräsentation entspricht.

Ach nö. Wenn man es kann geht das auch schon mal
kreuz und quer über mehrere Ports;) Das Problem ist
halt: Wenn man es KANN

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Wenn man es tatsächlich kann, dann macht man sowas nicht. Natürlich 
kann man Hardwaredesignfehler auch per Software ausbügeln, aber das ist 
nur Zudecken eines Fehlers, kein Können an sich.

Sicher, wer Fusch* zum laufen bekommt, kann sich was drauf einbilden, 
aber es bleibt primär Fusch.

*) bewusst ohne 'P'

von holger (Gast)


Lesenswert?

>Wenn man es tatsächlich kann, dann macht man sowas nicht. Natürlich
>kann man Hardwaredesignfehler auch per Software ausbügeln, aber das ist
>nur Zudecken eines Fehlers, kein Können an sich.

Bullshit. Wenn mein Hardwaredesign alle möglichen Pins
mit den entsprechenden Funktionen belegt und noch ein paar Pins
verteilt auf mehrere Ports für ein einfaches LCD zur Verfügung
stehen, warum sollte ich das da nicht anschliessen? Es geht doch!

von Jobst M. (jobstens-de)


Lesenswert?

holger schrieb:
> Bullshit. Wenn mein Hardwaredesign alle möglichen Pins
> mit den entsprechenden Funktionen belegt und noch ein paar Pins
> verteilt auf mehrere Ports für ein einfaches LCD zur Verfügung
> stehen, warum sollte ich das da nicht anschliessen? Es geht doch!

Sehe ich allerdings genau so.

In asm sieht das in meinen LCD-routinen daher so aus:
1
LCD_4Bit_MSB_setzen:
2
    ; Einzelne Portbits setzen. Dieser Umstand ist wg. variabler Portzuweisung nötig
3
    disp_d7_aus
4
    disp_d6_aus
5
    disp_d5_aus
6
    disp_d4_aus
7
8
    SBRC  temp, 7
9
    disp_d7_an
10
    SBRC  temp, 6
11
    disp_d6_an
12
    SBRC  temp, 5
13
    disp_d5_an
14
    SBRC  temp, 4
15
    disp_d4_an
16
    RET


Gruß

Jobst

von Ralli (Gast)


Lesenswert?

Ja und?

Das ergibt in in C eine langweilige switch - case -
Strickleiter, die in C++ auch nicht schöner wird.

ELEGANT???

Ist beim nachträglichen anfrickeln nun mal nicht
schöner zu machen.

von holger (Gast)


Lesenswert?

>> Bullshit. Wenn mein Hardwaredesign alle möglichen Pins
>> mit den entsprechenden Funktionen belegt und noch ein paar Pins
>> verteilt auf mehrere Ports für ein einfaches LCD zur Verfügung
>> stehen, warum sollte ich das da nicht anschliessen? Es geht doch!
>
>Sehe ich allerdings genau so.

Grins. Und wenn die LCD Routinen hier im Tutorial
von je her eine freie Pinbelegung erlaubt hätten,
dann wären ca. 19812300 Fragen zu Problemen damit gar
nicht nötig gewesen. Der Könner nimmt was er hat
und macht was damit;)

von Gernot H. (schnuck)


Lesenswert?

Danke nochmal für die schnellen Antworten...

von Gernot H. (schnuck)


Lesenswert?

eProfi schrieb:
> Wenn PortA ansonsten unverändert bleiben soll:
>
> PORTA = (PINA & 0b11111000)
>       | ((x&(1<<3))>>(3-PA1))
>       | ((x&(1<<2))>>(2-PA0))
>       | ((x&(1<<0))<<(PA2-0));


Also hier könnte ich noch mal ein wenig Hilfe gebrauchen. Bei der 
Bitmanipulatin "| ((x&(1<<3))>>(3-PA1))". Wenn ich das richtig 
interpretiere, dann wird hier ein 1 in das Bit 2 gesetzt.


Was bedeutet dann der Befehl ">>(3-PA1))"?

von eProfi (Gast)


Lesenswert?

Das ist nur ausführlich hingeschrieben, um es leichter zu verstehen, und 
wird zur Compilezeit berechnet.

Kurzgefasst:
PORTA = (PINA & 0xf8) | ((x&8)>>2) | ((x&4)>>2) | ((x&1)<<2);
Du setzt die Bits PA2-PA0 auf Null.
Du maskierst Bit3 von X und schiebst es um 2 nach rechts ins PA1.
Du maskierst Bit2 von X und schiebst es um 2 nach rechts ins PA0.
Du maskierst Bit0 von X und schiebst es um 2 nach links  ins PA2.


Schade, dass x>>y für negative y undefiniert ist.
Wäre höchst erfreulich, wenn für ein negatives y ein entsprechender 
shift left erfolgen würde, dann hätte man universeller schreiben können:


#define XBA 0  //X Bit A
#define XBB 2
#define XBC 3
PORTA = (PINA & 0b11111000)
      | ((x&(1<<XBC))>>(XBC-PA1))
      | ((x&(1<<XBB))>>(XBB-PA0))
      | ((x&(1<<XBA))>>(XBA-PA2)); //Ergebnis in C leider undefiniert


Der Vorteil dieser Schreibweise ist, dass das Port auf einen Sitz 
geschrieben wird, nicht Bit für Bit wie bei 21.01.2011 21:51.

Jobstens Asm hätte ich beinahe auch gepostet, eleganter geht es nicht.
Außer man löscht das Bit wirklich nur, wenn nötig, um Spikes zu 
vermeiden:

    SBRC  temp, 7
    disp_d7_an
    SBRS  temp, 7
    disp_d7_aus

    SBRC  temp, 6
    disp_d6_an
    SBRS  temp, 6
    disp_d6_aus

    SBRC  temp, 5
    disp_d5_an
    SBRS  temp, 5
    disp_d5_aus

    SBRC  temp, 4
    disp_d4_an
    SBRS  temp, 4
    disp_d4_aus

Dieses Asm lässt sich auch in ein C-Programm integrieren mit
asm(" ... ");

------------------------------------------------------------------------ 
-----

>eProfi schrieb:
>> Auch ich bitte um eine KLARTEXT-Aussage:
>> Wo kommt das x her?
>> Was ist an PORTA angeschlossen?
>> Warum müssen die Bits verdreht werden?

> Ich lasse die Variable X in einem Timerinterrupt bis zu einen
> bestimten Wert hochzählen und setze diesen dann bei einem
> bestimmten Wert wieder auf Null zurück. Die einzelen PORTs
> dienen dann als eine Art Frequenzteiler.

Ist für mich immer noch kein Klartext (... einem bestimmten Wert..., 
...eine Art...).

von Simon K. (simon) Benutzerseite


Lesenswert?

eProfi schrieb:
> Kurzgefasst:
> PORTA = (PINA & 0xf8) | ((x&8)>>2) | ((x&4)>>2) | ((x&1)<<2);

Das ist aber schon Murks. Natürlich muss "PINA" durch "PORTA" ersetzt 
werden. Das PIN Register liest nur das Eingangsregister aus. Wenn also 
bestimmte Bits als Eingang definiert wurden und von extern auf High 
gezogen werden, schaltet man als Nebeneffekt dieser (falschen) Anweisung 
denjenigen Pullup an.
Das kann so nicht die Intention gewesen sein ;-)

Ihr macht da aber auch einen Riesen-Thread raus. Gerade wenn man im 
Hobbybereich auf Lochraster oder einseitigen Platinen arbeitet und man 
ein schönes Platinenlayout mit möglichst wenigen Brücken hinkriegen 
möchte, dann geht es schon fast nicht anders als mal ein paar Portpins 
(z.B. Taster oder LEDs) am Prozessor zu verteilen. Ist ja auch kein Akt 
und kostet im Wesentlichen auch nur 0,00001% (geschätzt) der 
Rechenleistung ;-)

Am schnellsten dürfte die Methode mit den If-Anweisungen sein.
Also einfach das Bit Testen und den entsprechenden Ausgang setzen oder 
zurücksetzen.

von Alex E. (tecnologic) Benutzerseite


Lesenswert?

Hi,

Warum macht ihr euch das Bit gewackel so kompliziert?
1
struct bits_st {
2
3
uint8_t b1:1;
4
uint8_t b2:1;
5
uint8_t b3:1;
6
uint8_t b4:1;
7
uint8_t b5:1;
8
uint8_t b6:1;
9
uint8_t b7:1;
10
uint8_t b8:1;
11
}__atribute__((__packed__);
12
13
typedef union port_t{
14
struct bits_st bit;
15
uint8_t byte;
16
}
17
18
19
//Verwendung alla
20
21
port_t* PortA;
22
port_t* PinA;
23
24
PortA = (port_t*)&PORTA;
25
PinA = (port_t*)&PINA;
26
27
// und jetzt geht
28
PortA->byte = 0xff;
29
30
//oder eben
31
32
PortA->bit.b1 = 1;
33
34
if(PinA->bit.b2 == 0) {
35
//Do something silly
36
}

so hat er seine C++ Syntax fast.

MfG

Tec

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.