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?
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.
Meines Wissens geht das nicht direkt. Aber du kannst dir natürlich eine Funktion schreiben, die das aufdröselt und das übergebene Byte an PD0-PD5 und PC0-PC2 schreibt.
Ja, einfach eine Funktion, die nur genau für diese Kombination die Bits aufdröselt. Jede elegante und wiederverwendbare Lösung bringt mehr Verwirrung als Nutzen.
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.
oder man nimmt einen TM1637 -> 2 Pins , 6 Segmente oder einen max7219 -> 3 Pins , 8 Segmente
Na ich glaube das mit dem Maskieren ist in meinem Fall wohl das Angenehmste. Habe mir auch sowas in der Art überlegt nur habe ich was das Thema Bitmanipulation angeht noch viel zu lernen ;) Großes Danke an euch!
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]; |
Holger Z. schrieb: > oder man nimmt einen TM1637 -> 2 Pins , 6 Segmente Wie kommst Du jetzt da drauf, der kann genauso 8 Segmente für jede der 6 Stellen.
Kevin M. schrieb: > 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. Bei einer Multiplexperiode von z.B. 10ms ist es natürlich gaaanz schlimm, wenn Segmengruppen mit einem Zeitversatz von vielleicht 1µs angesteuert werden ;-)
- Segmente seriel ausgeben (Schiberegister) - I2C 7-Segment Treiber verwenden - BCD zu 7-Segment Dekoder verwenden
Ohh wenn ich das hier so Lese, weiss ich gerade wieder Warum ich die MSP430 MPUX V2 und Assembler so liebe, 1 Befehl, beschreibt oder List mir grad alle oder die Gewünschte anzahl Ports :-D Leider in "C" von IAR noch nicht Implementiert Der Compiler macht da immer noch eine Spagetti-Rutiene :-(
:
Bearbeitet durch User
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.
Markus M. schrieb: >> const char 7SEG[] = {hexwert für 0, hexwert für 1, hexwert für 2, usw.}; > > Ist das C++ oder Arduino oder was? Das ist Pseudocode, kein vollständiger, korrekter C Code.
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?
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.
c-hater schrieb: > nichtmal eine grobe Übersicht ist vorhanden... Richtig erkannt :-) Trotzdem Danke für die Antwort, auch wenn die Frage dabei noch offen bleibt. Etwas Spezifisziert: @TO hat der den Du verwendest, nicht ein µC Drauf der die Befehle unterstützt?
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?
Patrick L. schrieb: > Der Compiler macht da immer noch eine Spagetti-Rutiene :-( Schreib lieber "Befehlsfolge". Vielleicht stehen da die Chancen besser, dass du das unfallfrei hinbekommst. ;-)
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...
Patrick schrieb: > Ohh wenn ich das hier so Lese, weiss ich gerade wieder Warum ich die > MSP430 MPUX V2 und Assembler so liebe, > > 1 Befehl, beschreibt oder List mir grad alle oder die Gewünschte anzahl > Ports :-D Erzähl mal mehr - kann nichts darüber finden (nur über die MPU, und die kann sowas nicht).
> Das ist Pseudocode, kein vollständiger, korrekter C Code.
DIES!
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.
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
:
Bearbeitet durch User
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.