Nun ich habe das mal ihrgendwo so gesehen und mach es somit NACH.
Mir ist klar sbr setzt ein Bit im register.
Mir ist klar PD5 ist das 6te Bit an Port D
Mir ist aber nicht so klar was das 1<< macht bzw. 0<<
Kann mir das bitte mal einer genau erklären da ich auch gerne verstehen
möchte was ich mach und nicht einfach nur immer und immer wieder
übernehmen möchte.
Was steckt dahinter?
kopfkratzer schrieb:> Dann lies Dir den Artikel dazu durch:> http://www.mikrocontroller.net/articles/Bitmanipulation
Super danke Dir ich glaube eben ist der Groschen gefallen.
Wobei ich nun es doch nicht dazu benutzen kann was ich mir erwünscht
hatte.
Ich wollte gerne 8 Bit in einem Register zusammensetzen.
PD5 Bit 8
PD4 Bit 7
PC5 Bit 6
PC4 Bit 5
PC3 Bit 4
PC2 Bit 3
PC1 Bit 2
PC0 Bit 1
So dachte ich es ginge auch sbr r16,(1<<PD5) + (1<<PD4) + (1<<PC5)
u.s.w.
Moin,
PD5 und ähnliche sidn ja nur definierte Symbole, dahinter steht in
diesem Fall sicherlich eine Zahl.
"<<" ist der Shift Operator; k.A. ob das per Macro gehandhabt wird.
(1<<PD5) wird erstmal in (1<<5) übersetzt. Das heißt, den Wert "1" um 5
Schritte nach links zu schieben. Genau an die Stelle, die im Register
gesetzt werden soll.
Das wird im Beispiel für zwei Bit gemacht und die Werte hinterher
addiert. Klappt hier, da beide Werte nur genau aus einem Bit bestehen.
(32 und 16)
--
SJ
Holger P. schrieb:> Ich wollte gerne 8 Bit in einem Register zusammensetzen.>> PD5 Bit 8> PD4 Bit 7> PC5 Bit 6> PC4 Bit 5> PC3 Bit 4> PC2 Bit 3> PC1 Bit 2> PC0 Bit 1>> So dachte ich es ginge auch sbr r16,(1<<PD5) + (1<<PD4) + (1<<PC5)> u.s.w.
Ja was willst Du nun, feststellen welche Bits in den genannten Ports
gesetzt sind oder willst Du portübergreifend Bits auf einmal setzen ?
Holger P. schrieb:> So dachte ich es ginge auch sbr r16,(1<<PD5) + (1<<PD4) + (1<<PC5)
keine Ahnung ob das dein Assembler kann,
in C wäre es jedenfalls richtig:
1<<PD5 = 0b00100000
1<<PD4 = 0b00010000
-----------
0b00110000
etwas komisch allerdings deine Mischung aus PD und PC
Walter S. schrieb:> etwas komisch allerdings deine Mischung aus PD und PC
Nun ich habe 8 Eingänge und kein ganzen Port dafür übrig.
So habe ich PC0 bis PC5 für die ersten 6 genommen und PD4 und PD5 für
die restlichen zwei.
Port B habe ich schon als Ausgang benutzt.
Holger P. schrieb:> Nun ich habe 8 Eingänge und kein ganzen Port dafür übrig.> So habe ich PC0 bis PC5 für die ersten 6 genommen und PD4 und PD5 für> die restlichen zwei.>> Port B habe ich schon als Ausgang benutzt.
das habe ich mir gedacht und wie willst Du die Ports GLEICHZEITIG
ansprechen ?
Was machst du denn mit r16 nachdem Du da die Bits gesetzt hast ?
kopfkratzer schrieb:> Ja was willst Du nun, feststellen welche Bits in den genannten Ports> gesetzt sind oder willst Du portübergreifend Bits auf einmal setzen ?
Ich wollte die Bit's von PC0 bis PC5 zuzüglich PD4 und PD5 zu einem
Datenwort in R16 zusammenbasteln damit ich sie auf der RS232 versenden
kann.
Im gegensatz zum sbi, ist sbr ein alias fuer die ori operation, und das
argument kein bit index. (Ja, das find' ich auch ein bisserl pervers).
Vergleichen sie in der atmel appnote doc0856 die zwei opcodes, werden
sie sehen, dass die identisch sind (0110).
Bis jetzt habe ich PortC direkt in R16 geladen und danach die zwei Bits
verglichen und dementsprechend die in R16 überschrieben.
Aber eine Zuweisung und zwei vergleiche müssen es doch nicht sein dachte
ich.
Holger P. schrieb:> Aber eine Zuweisung und zwei vergleiche müssen es doch nicht sein dachte> ich.
Nochmal WIE willst Du GLEICHZEITIG zwei Ports ansprechen ?
kopfkratzer schrieb:> Holger P. schrieb:>> Aber eine Zuweisung und zwei vergleiche müssen es doch nicht sein dachte>> ich.>> Nochmal WIE willst Du GLEICHZEITIG zwei Ports ansprechen ?
Momentan lade ich ein Register mit dem PortC. Danch prüfe ich die Bit's
PD4 und PD5 und schiebe diese mir ins Register.
in r16, PORTC
andi r16,0x3f //kann evtl. entfallen
sbic PortD,4 ;skip, wenn das Bit 0 im Port gelöscht ist
sbi r16,6
sbic PortD,5 ;skip, wenn das Bit 0 im Port gelöscht ist
sbi r16,7
Hi
>Also ich habe es bis jetzt so gemacht:>....>sbr r16,192 ; Bit 8 und 7 setzen 128 + 64
Damit hast du die unleserlichste Darstellung gewählt, außer vielleicht
oktal, die es gibt.
MfG Spess
Spess53 schrieb:> Hi>>>Also ich habe es bis jetzt so gemacht:>>>....>>sbr r16,192 ; Bit 8 und 7 setzen 128 + 64>> Damit hast du die unleserlichste Darstellung gewählt, außer vielleicht> oktal, die es gibt.>> MfG Spess
Natürlich habe ich es so gemacht:
1
lds r16,PortC ; Inhalt von Port C ins Register 16
2
sbr r16,192 ; Bit 8 und 7 setzen 128 + 64
3
sbis PIND,PIND5 ; Überspringe den nächsten Befehl, fals Bit 5 in PIND gesetzt ist
4
cbr r16,128 ; Bit 8 löschen da PD5 0 ist
5
sbis PIND,PIND4 ; Überspringe den nächsten Befehl, fals Bit 4 in PIND gesetzt ist
6
cbr r16,64 ; Bit 7 löschen da PD4 0 ist
Hatte es durch das kopieren nicht richtig gemacht.
Wie meinst Du unleserlich? Ich dachte es wäre sehr übersichtilich. Also
ich blicke da durch wenn ich es mir später mal anschaue.
Holger P. schrieb:> Jetzt bin ich ein kopfkratzer ... da kann ich nicht mehr folgen.LOL
Du hast den Artikel oben auch komplett gelesen und verstanden ?
Genau deswegen nimmt man (1<<PORTPINXYZ) um nicht im Kommentar schreiben
"zu müssen" was man tut !
Hi
>Jetzt bin ich ein kopfkratzer ... da kann ich nicht mehr folgen.
Also du kannst z.B. aus 'sbr r16,170' auf Anhieb sagen, welche Bits
gesetzt sind?
MfG Spess
Spess53 schrieb:> Hi>>>Jetzt bin ich ein kopfkratzer ... da kann ich nicht mehr folgen.>> Also du kannst z.B. aus 'sbr r16,170' auf Anhieb sagen, welche Bits> gesetzt sind?>> MfG Spess
Nein so natürlich nicht.
Aber wenn Du es so schreibst wie ich:
1
sbr r16,170 ; Bit 8, 6, 4 und 2 setzen 128 + 32 + 8 + 2
Hi
>Aber wenn Du es so schreibst wie ich:>sbr r16,170 ; Bit 8, 6, 4 und 2 setzen 128 + 32 + 8 + 2
Und wenn ich z.B.
sbr r16, 0b10101010
schreibe, erübrigt sich so ein Kommentar. Dezimalzahlen machen nur Sinn,
wenn man wirklch diese Zahl meint. Um Bits darzustellen sind sie
ungeeignet.
Dein Kommentar ist übrigens auch falsch. Es sind Bit 7,5,3 und 1.
MfG Spess
eProfi schrieb:> in r16, PORTC> andi r16,0x3f //kann evtl. entfallen> in r17, PORTD> andi r17,0x20 //PD4 und PD5> shl r17 //auf Pos 6 und 7 schieben ; meinst Du lsl?> shl r17 ; 1> or r16,r17 //verknüpfen 1
= 7 Takte
eProfi schrieb:> in r16, PORTC ; 1> andi r16,0x3f //kann evtl. entfallen ; 1> sbic PortD,4 ;skip, wenn das Bit 0 im Port gelöscht ist ; 1 oder 2> sbi r16,6 ; 0 oder 2 => 2 oder 3 Takte für sbic und sbi> sbic PortD,5 ;skip, wenn das Bit 0 im Port gelöscht ist ; 1 oder 2> sbi r16,7 ; 0 oder 2 => 2 oder 3 Takte für sbic und sbi
= 6 bis 8 Takte
Deine neuere Variante ist nur schneller, wenn keines der beiden Bits in
PORTC gesetzt ist.
Es fragt sich nur, warum ein Programm ein PORTx abfragen sollte, wo doch
sämtliche Bits in PORTx seitens des Programms selber gesetzt werden, und
das Programm "wissen" sollte, was wo gesetzt wurde. Oder meinst Du gar
PINC?
Holger P. schrieb:>> Also du kannst z.B. aus 'sbr r16,170' auf Anhieb sagen, welche Bits>> gesetzt sind?> Nein so natürlich nicht.> Aber wenn Du es so schreibst wie ich:>
1
sbr r16,170 ; Bit 8, 6, 4 und 2 setzen 128 + 32 + 8 + 2
Nö, dann kann ich nur auf Anhieb sagen, was der Programmierer gemeint
hat. Ob er das so umgesetzt hat, muss ich bei verzweifelter Fehlersuche
trotzdem nachrechnen, um auf Nummer sicher zu gehen. Auch wenn es
stimmt, so verbrät man trotzdem die Zeit, das zu checken.
Wenn Du eh die einzelnen Werte in Deinen Sourcecode schreibst, dann
kannst Du das auch gleich links vom Kommentarzeichen im Ausdruck machen.
Das vermeidet Fehler, ist für andere leserlicher, und erzeugt keinen
zusätzlichen Code. Ob ein Unterschied in der Kompilierdauer messbar ist,
wage ich mal zu bezweifeln.
Außerdem: 1,2,4,8,16,32,64,128,256,512,1024,2048 und 4096 erkennt man
sofort, weil man sie schon tausend mal gesehen hat, aber bei 8192 und
den Folgenden müssen die meisten Programmierer kurz nachdenken.
Was machst Du, wenn Du mit 16-stelligen Bitmustern hantieren willst?
Holger P. schrieb:> Walter S. schrieb:>> etwas komisch allerdings deine Mischung aus PD und PC>> Nun ich habe 8 Eingänge und kein ganzen Port dafür übrig.> So habe ich PC0 bis PC5 für die ersten 6 genommen und PD4 und PD5 für> die restlichen zwei.
Ja, aber PC5 und PD5 haben den selben Wert, nämlich 5. Wenn du die in
einem Register setzt, wird beides mal das selbe Bit gesetzt, nämlich bit
5, bzw. wenn du sie addierst, wird nachher bit 5 gelöst und bit 6
gesetzt.
Holger P. schrieb:> Aber wenn Du es so schreibst wie ich:> sbr r16,170 ; Bit 8, 6, 4 und 2 setzen 128 + 32 + 8 + 2
Dann muß man hoffen, daß der Wert nicht irgendwann geändert wurde, ohne
dabei den Kommentar anzupassen. Code, der sich selbst beschreibt, ist
immer einer Kombination aus schlecht lesbarem Code mit Kommentaren, die
ihn beschreiben, vorzuziehen.
Aber Holger macht einen Fehler, er möchte den Wert von PortC in das
Register und dazu müsste er IN nehmen und nicht LDS.
Aber sein Lösungsweg ist richtig.
Und auch ein IN r16,PortC ist falsch da es ein IN r16,PINC sein muss.
Da ich gerade fast an dem gleichen sitzt fällt mir das auf.
Nun benutze ich mal diesen Thread und frage, kann man auch die PINC
erhalten wenn der Port ein Ausgang ist um so Informationen über den
Zustand zu bekommen?
Flami schrieb:> Und auch ein IN r16,PortC ist falsch da es ein IN r16,PINC sein muss.
In dem Fall nicht.
Er will die Bits am PORTC manipulieren. Dazu muss er sich den aktuellen
Wert vom PORTC holen, die Bits entsprechend umdrehen und dann wieder auf
PORTC rausschreiben.
Ihm geht es nicht darum, was extern am PINC anliegt, sondern wie PORTC
aktuell gesetzt ist. Daher
IN r16, PORTC
das ist schon richtig so.
> Nun benutze ich mal diesen Thread und frage, kann man auch die PINC> erhalten wenn der Port ein Ausgang ist um so Informationen über den> Zustand zu bekommen?
Das kommt im Detail darauf an, was du genau wissen willst.
Wenn es dir darum geht festzustellen, ob du selbst einen Pin auf 1
gesetzt hast, dann benutzt du PORTC um von dort einzulesen.
Wenn du wissen willst, ob der physikalische Pin dadurch auch wirklich
auf 1 gegangen ist, dann benutzt du PINC. Denn: Selbst wenn du auf PORTC
ein 1 Bit ausgibst, bedeutet das nicht automatisch, dass der
physikalische Pin auch wirklich auf 1 gegangen ist! Der versucht es
natürlich, aber gegen zb einen Kurzschluss nach Masse hat er keinen
Chance. In so einem Fall kriegst du vom PIN Register einen anderen Wert
als vom PORT Register. Das PORT Register sagt dir, was du per Programm
gesetzt hast und das PIN Register sagt dir, was davon tatsächlich "auf
der Leitung angekommen" ist.
Holger P. schrieb:> Ich wollte die Bit's von PC0 bis PC5 zuzüglich PD4 und PD5 zu einem> Datenwort in R16 zusammenbasteln damit ich sie auf der RS232 versenden> kann.
Kannst du natürlich machen.
Aber bitte: Miss den Port-Buchstaben in PC0, PC1, PC5, PD4, etc. nicht
zuviel Bedeutung zu!
Denn: Da ist in keiner Weise in irgendeiner Form der Port irgendwie
kodiert. Diese ganzen Bezeichnungen waren nicht sehr schlau. Man hätte
die Dinge einfach nur
BIT0, BIT1, BIT2, ....
nennen sollen. Denn genau das stellen sie dar
PC0 ist einfach nur ein Kürzel für Bit 0.
Genauso wie PD0 oder PB0 einfach nur ein Kürzel für
Bit 0 darstellt.
Hier ...
> So dachte ich es ginge auch sbr r16,(1<<PD5) + (1<<PD4) + (1<<PC5)
... steht also eigentlich nur:
Setze im Register R16 die Bits 5, 4 und 5
Und was immer du dann mit dem Ergebnis in diesem Register machst, das
machst du damit. Ob du das dann an den PORTD ausgibst oder an den PORTC,
ob du das per SPI irgendwo ausgibst oder nicht, ob du das an ein LCD
gibst oder per UART überträgst .... das alles ist NICHT Gegenstand
dieser Anweisung. In dieser Anweisung geht es nur darum, dass Bit 5, Bit
4 und nochmal BIt 5 gesetzt werden. Nicht mehr und nicht weniger. Das du
da einmal PD5 und einmal PC5 benutzt hast, ist irrelevant - beides steht
einfach nur für Bit 5 und sind so gesehen einfach nur 2 verschiedene
Bezeichnungen für eigentlich dasselbe.
muss ich dir nicht vertrauen. Da steht eindeutig in der Anweisung,
welche Bits gesetzt werden.
Und mit ein paar zusätzlichen .EQU wird dann zb daraus
1
.equ GUI_PORT PORTC
2
.equ SUMMER 1
3
.equ ERROR_LED 5
4
.equ READY_LED 7
5
.equ SHUTDOWN_LED 3
6
7
....
8
9
10
sbr r16, (1<<SUMMER) | (1<<ERROR_LED)
11
out GUI_PORT, r16
Und damit geht das Ganze dann sofort in die nächst bessere Runde. Denn
dann steht da nicht mehr, dass die Bits 1 und 5 am Port C gesetzt
werden, sondern im Code steht, dass ich am Port welcher für die
Benutzerinteraktion zuständig ist, den Summer und die Error LED auf 1
setze. OK, Ich muss noch wissen, dass ein gesetztes Bit ein bzw. aus
bedeutet, aber ich muss an dieser Stelle im Code nicht mehr Rätselraten,
was denn eigentlich die beiden Bits am PORTC für eine Bedeutung haben
... was sie bewirken. Da geht es um den Summer bzw. die Fehler-Led und
nicht um den Rollladen-Motor.
Klar. Ich könnte mir das auch im Kommentar dazuschreiben. Aber wozu im
Kommentar, wenn ich genau dasselbe auch im Code selbst ausdrücken kann!
Denn: Kommentare können auch falsch sein. Der Code ist aber immer der,
der dann auch tatsächlich am µC abläuft. So gesehen kann der nicht
falsch sein: Das was ich hinschreibe, passiert auch. Die Bits werden
tatsächlich gesetzt. Ob das in der jetzigen Situation die richtige
Aktion ist, ist damit nicht gesagt. Aber zumindest kann ich sicher
gehen, dass auch wirklich die beiden Bits geschaltet werden und nicht
irgendwelche andere, weil ich mich in der Nummerierung bzw. im Rechnen
verhaut habe. Egal was im Kommentar steht - gelten tut immer der Code.
Im Kommentar kann ich alles mögliche hinschreiben. Das lässt aber den µC
kalt.
Und je weniger potentielle Fehlerquellen ich mir selbst offen lasse,
desto besser. Als Programmierer macht man noch andere Fehler zu Hauf. Da
ist jede Änderung, mit der man eine potentielle Fehlerquelle abstellen
kann, eine gute Änderung.
Holger P. schrieb:> Mir ist aber nicht so klar was das 1<< macht bzw. 0<<
Ich beantworte jetzt mal die zweite und einfachere Hälfte des Problems:
Gar nichts! ;-)
So bin aus der Schule zurück.
@Karl Heinz Buchegger wow da danke ich ganz herzlich.
100% erklärt, ich werde es mal versuchen demnächst so zu machen.
@Flami auch Dir danke sonst hätte ich lange nach dem Fehler gesucht, so
geht es!
Allen anderen natürlich auch herzlichen dank. Soviel resonanz hätte ich
nun nicht erwartert.
Hätte da noch eine Frage aber das stelle ich drüben bei Platinen da es
mit Eagle zutun hat ;-)