eigenen port aus einzelnen "Portpins" zusammensetzen

#7050611
Lesenswert?

Hallo mal wieder.

Habe folgendes Problem:

Bin gerade etwas am rumbasteln mit 7 segment Anzeigen im 
Multiplexverfahren.
Es scheint ja gängig zu sein, für das ansteuern der jeweiligen Anzeige 
die Zahlen/Symbole durch ein entsprechendes array zu codieren also in 
z.B:

const char 7SEG[] = {hexwert für 0, hexwert für 1, hexwert für 2, usw.};

um dies dann über einen 8 bit breiten PORT ausgeben zu können:

PORTX = 7SEG[1];

nächstes digit();

PORTX = 7SEG[2];

soweit so primitiv.
Was mache ich jetzt aber, wenn ich z.B aus Platzgründen die Pins von 
mehreren PORTs
zusammenfassen muss sagen wir z.B PD0-PD5 für Segmente a-e und PC0-PC2 
für Segmente f und DP, um auf meine 8 bits zu kommen. Wie könnte ich mir 
in C einen "virtuellen" PORT erstellen, welcher meinen 8 bit wert wie 
ich es mir wünsche auf die Portpins verteilt?
#7050617
Lesenswert?

Du kannst dir ein Struct bauen, indem du die Pointer auf den jeweiligen 
Port speicherst, aber wirklich viel bringen tut das nicht, sobald du 
mehr als einen Port benutzt musst du auch entsprechend viele 
Schreibzugriffe auf die einzelnen Portes machen.

Verschiedene Ports haben immer den Nachteil das man das Digit nicht in 
einem schreiben kann und je nachdem wieviele benutzt werden dauert es 
natürlich länger.

eine Alternative wäre ein externer IO Expander bzw. ein 7-Segment 
Treiber.
Gast #7050630
Lesenswert?

Da gibt es viele Möglichkeiten, jeweils mit Vor- und Nachteilen 
behaftet.

Z.B.: man kann das Array so lassen, wie es ist und mit ein oder zwei 
Schleifen jeden Port-Pin einzeln setzen/löschen
- mit einer Schleife und in der Schleife ein if-Statement zum 
entscheiden, ob der eine oder der andere Port gerade bearbeitet wird
- mit zwei Schleifen, eine für den einen Port, die andere für den 
anderen Port, das spart das if

oder man bleibt bei dem Array, so wie es ist, und manipuliert die 
Ports/Array-Daten durch Maskieren und entsprechendes verschieben der 
Bits.
PORTX = PORTX & 0b11000000 | 7SEG[1] & 0b00111111   // im Beispiel aus 
der Frage wäre das für PD
PORTX = PORTX & 0b11111100 | 7SEG[1] >> 6   // im Beispiel aus der Frage 
wäre das für PC
der erste &-Teil löscht erst die Pins, die verändert werden sollen und 
behält die 2 MSB bei, der zweite &-Teil sorgt dafür, dass die Daten in 
7SEG nicht die 2 MSB "überschreiben"

oder man hat eine sehr zeitkritische Anwendung aber noch etwas Speicher 
frei, dann kann man die Daten natürlich auch schon entsprechend 
vorbereitet in 2 Arrays bereitstellen und spart sich das 2te & bzw. das 
verschieben der MSB.
Gast #7050674
Lesenswert?

Mach einfach ein SEG-Array für jeden Port.  Kein gumgeshifte und 
kompakt.
Z.B.:
1
  #define SEG_PA_BITS 0xc3  // PA0/1/6/7
2
  #define SEG_PC_BITS 0x87  // PC0/1/2/7
3
  const uint8_t SEG_PA[] = { ... };
4
  const uint8_t SEG_PC[] = { ... };
5
  ...
6
  PORTA = (PORTA & ~SEG_PA_BITS) | SEG_PA[x];
7
  PORTC = (PORTC & ~SEG_PC_BITS) | SEG_PC[x];
Gast #7051332
Lesenswert?

Markus P. schrieb:
> const char 7SEG[] = {hexwert für 0, hexwert für 1, hexwert für 2, usw.};

Ist das C++ oder Arduino oder was?

vgl. K&R "The C Programming Language":

2.1 Variable Names
Although we didn't say so in Chapter 1, there are some restrictions on 
the names of variables and symbolic constants. Names are made up of 
letters and digits; the first character must be a letter. The 
underscore `` _ '' counts as a letter; it is sometimes useful for 
improving the readability of long variable names.
(Firma: S-C-I DATA GbR) #7051347
Lesenswert?

Frage dazu, (rein Interessenshalber) habe ja mit Arduino nix am Hut.
Aber der Prozessor unterstützt doch auch Befehle die mehrere Adressen 
mit einem Rutsch von a nach B schiebt?

Dann kann man doch das Display als Shadowbereich im Ram ablegen und mit 
1 Befehl das ganze in die Ports schieben, so das garantiert kein 
"Gezappel" im Display ist?

Für Direkt CRT an µC verwende ich das Prinzip auch, das beim Bildaufbau 
kein Geflicker auf dem CRT/LCD zu sehen ist, und spart nebenbei noch 
erheblich Code.

Wen ich Segmentdisplays habe nehme ich e die µC mit integriertem LCD 
Kontroller, das macht es erheblich einfacher..

alles etwas OT,(Sorry) aber selbst der Z80 kannte schon den LDIR 
befehl?
Gast #7051356
Lesenswert?

Patrick L. schrieb:

> Frage dazu, (rein Interessenshalber) habe ja mit Arduino nix am Hut.

Das merkt man, nichtmal eine grobe Übersicht ist vorhanden...

> Aber der Prozessor unterstützt doch auch Befehle die mehrere Adressen
> mit einem Rutsch von a nach B schiebt?

Nun, ich bin auch nicht gerade Arduino-Fan, aber so viel weiß ich dann 
doch:
Das hängt vom Prozessor ab. "Arduino" gibt's schon seit undenklichen 
Zeiten für (ziemlich verschiedene) Prozessoren, in jüngerer Zeit ist 
deren Zahl sogar förmlich explodiert.
Gast #7051374
Lesenswert?

Patrick L. schrieb:

> @TO hat der den Du verwendest, nicht ein µC Drauf der die Befehle
> unterstützt?

Das alleine würde ja noch nicht reichen. Es müssten zusätzlich auch die 
PORT-Register an linear aufsteigenden Adressen liegen oder sich 
zumindest irgendwie so hinmappen lassen. Und das ist (zumindest bei den 
"Arduino-Prozessoren", die ich kenne) bei keinem der Fall.

Und selbst wenn es irgendeinen Exoten gibt, bei dem das möglich wäre, 
wäre es ziemlicher Unsinn, dieses exotische Feature zu verwenden. Eben 
weil es dann bei allen anderen nicht funktioniert.

Sollte logisch sein, oder?
Gast #7051427
Lesenswert?

Markus P. schrieb:
>
> Bin gerade etwas am rumbasteln mit 7 segment Anzeigen im
> Multiplexverfahren.
>
> Was mache ich jetzt aber, wenn ich z.B aus Platzgründen die Pins von
> mehreren PORTs zusammenfassen muss sagen wir z.B PD0-PD5 für Segmente a-e
> und PC0-PC2 für Segmente f und DP, um auf meine 8 bits zu kommen.

Keinen Zweifel, das geht sicher - irgendwie. Z.B. könnte man im 
7Segment-Code für a-e (resp. PD0-PD5) die unteren 6 bits reservieren und 
bei der Ausgabe PD6-PD7 trickreich rein- und rausmaskieren. Oder du 
könntest dir aus Langeweile ein Loch ins Knie bohren und Backpulver 
einfüllen ...

Ich würde mir aber diesen Stress nicht machen, sondern die Ports 
sinnvoll zuordnen. Aber mach mal wie Du denkst, ist schließlich dein 
Projekt...
Gast #7051696
Lesenswert?

Markus M. schrieb:
> Oder du
> könntest dir aus Langeweile ein Loch ins Knie bohren und Backpulver
> einfüllen ...

Ein wirklich weiterführender Ratschlag. Gelle?

Also, daß man sich die Ports nicht so heraussuchen kann, wie es einem 
grad genehm ist, das ist recht üblich. Oftmals sind die Ports nur bei 
der größten Gehäuseform (BGA) komplett herausgeführt oder irgendwelche 
Pins mittendrin sind bereits anderweitig belegt.

So konzentriert sich das Problem darauf, eine bestimmte Datenmenge auf 
verschiedene Ports und Pins zu verteilen. Das muß nicht ein Byte sein, 
es kann auch mal irgend eine andere Datenbreite haben.

Schlußendlich wird man in den meisten Fällen darauf kommen, daß eine 
stupide Einzelverteilung (hi oder lo) nach dem Übersetzen zum 
effektivsten Maschinencode führt. Ohne Schleifenkonstrukte und ohne 
Arrays. Sowas führt hier nur zu zusätzlichem Verwaltungsaufwand.

W.S.
#7051823
Lesenswert?

W.S. schrieb:
> Schlußendlich wird man in den meisten Fällen darauf kommen, daß eine
> stupide Einzelverteilung (hi oder lo) nach dem Übersetzen zum
> effektivsten Maschinencode führt. Ohne Schleifenkonstrukte und ohne
> Arrays. Sowas führt hier nur zu zusätzlichem Verwaltungsaufwand.

Wenn die Pin-Verteilung zur Compile-Zeit bekannt ist, kann dieses 
GCC-Builtin hilfreich sein:

-->  __builtin_avr_insert_bits

https://gcc.gnu.org/onlinedocs/gcc/AVR-Built-in-Functions.html

https://godbolt.org/z/sh4bM64Ke

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren