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
ATmega und C++? Viel Spaß.
>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;
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]
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.
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));
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.
>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.
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.
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.
Wenn du genug Speicher hast kannst das auch mit einer lookuptable machen PORTA = lookup[x] (bzw mit pgm-Makros direkt aus dem Flash lesen)
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
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.
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.
>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
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'
>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!
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
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.
>> 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;)
Danke nochmal für die schnellen Antworten...
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))"?
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...).
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.