mikrocontroller.net

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


Autor: Gernot H. (schnuck)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Nico S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ATmega und C++? Viel Spaß.

Autor: Gernot H. (schnuck)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es geht auch in C.

Autor: Chris L. (kingkernel)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PORTA = i;

Autor: Gernot H. (schnuck)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Christian L. schrieb:
> PORTA = i;

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

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;

Autor: Chris L. (kingkernel)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was genau willst du machen? Welche Portpins sollen mit welcher Bitstelle 
verknüpft werden
vielleicht auch so:
PORTA = 0;
if(i & (1 << 0)) PORTA |= 1 << PA0;
if(i & (1 << 1)) PORTA |= 1 << PA1;
if(i & (1 << 2)) PORTA |= 1 << PA2;
if(i & (1 << 3)) PORTA |= 1 << PA3;
if(i & (1 << 4)) PORTA |= 1 << PA4;
if(i & (1 << 5)) PORTA |= 1 << PA5;
if(i & (1 << 6)) PORTA |= 1 << PA6;
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]

Autor: Gernot H. (schnuck)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: eProfi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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));

Autor: Gernot H. (schnuck)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Gernot H. (schnuck)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Roland Praml (pram)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: eProfi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Gernot H. (schnuck)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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'

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Jobst M. (jobstens-de)
Datum:

Bewertung
0 lesenswert
nicht 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:
LCD_4Bit_MSB_setzen:
    ; Einzelne Portbits setzen. Dieser Umstand ist wg. variabler Portzuweisung nötig
    disp_d7_aus
    disp_d6_aus
    disp_d5_aus
    disp_d4_aus

    SBRC  temp, 7
    disp_d7_an
    SBRC  temp, 6
    disp_d6_an
    SBRC  temp, 5
    disp_d5_an
    SBRC  temp, 4
    disp_d4_an
    RET


Gruß

Jobst

Autor: Ralli (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;)

Autor: Gernot H. (schnuck)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke nochmal für die schnellen Antworten...

Autor: Gernot H. (schnuck)
Datum:

Bewertung
0 lesenswert
nicht 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))"?

Autor: eProfi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...).

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Tec Nologic (tecnologic) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

Warum macht ihr euch das Bit gewackel so kompliziert?
struct bits_st {

uint8_t b1:1;
uint8_t b2:1;
uint8_t b3:1;
uint8_t b4:1;
uint8_t b5:1;
uint8_t b6:1;
uint8_t b7:1;
uint8_t b8:1;
}__atribute__((__packed__);

typedef union port_t{
struct bits_st bit;
uint8_t byte;
}


//Verwendung alla

port_t* PortA;
port_t* PinA;

PortA = (port_t*)&PORTA;
PinA = (port_t*)&PINA;

// und jetzt geht
PortA->byte = 0xff;

//oder eben

PortA->bit.b1 = 1;

if(PinA->bit.b2 == 0) {
//Do something silly
}


so hat er seine C++ Syntax fast.

MfG

Tec

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.