Hi, die Frage ist mir ja fast schon peinlich, aber gibt es eine EINFACHE (2-3 Zeiler) Möglichkeit, die Bits 6 und 7 einer Variable (in meinem Fall "counter") auf den PORTB PB0 und PB1 auszugeben (also 6->PB0, 7->PB1), OHNE PB2...PB7 zu beeinflussen? Ich könnte jetzt pruefen, ob die Bits gesetzt sind und je nach dem an eine Sprungmarke springen und den entsprechenden Port mit SBI bzw. CBI setzen bzw. loeschen. Aber das muss doch einfacher gehen oder nicht!? Sorry fuer meine auf-dem-Schlauch-Steherei ;-) Danke Franz
Franz M. wrote:
> ach noch vergessen: Ich progge in Assembler
die beiden Bitposition von counter mittels einer AND Maskierung
freistellen. Um 6 Positionen nach unten schieben. PORTB einlesen, PB0
und PB1 definiert auf 0 setzen. Die vorher geschobenen beiden Bits mit
einem Oder drüberschreiben. Das Resultat wieder auf PORTB ausgeben.
-> die Lösung mit cbi/sbi dürfte einfacher sein. Vor allem das
Schieben um 6 Positionen wird viel Zeit verschlingen.
Wieso um 6 Stellen schieben? Ich komm auf drei, einfach durchs Carry schieben, man kann ja nach links und rechts schieben ;)
Michael wrote: > Wieso um 6 Stellen schieben? Ich komm auf drei, einfach durchs Carry > schieben, man kann ja nach links und rechts schieben ;) Hast recht. (Ich hol mir jetzt noch einen Kaffee)
Hihihi, na dann. Denke aber auch, dass die Bit-Operation SBI/CBI schneller sein würden.
Quick and dirty R16 = Variable sbrc R16,6 sbi PORTB,0 sbrs R16,6 cbi PORTB,0 sbrc R16,7 sbi PORTB,1 sbrs R16,7 cbi PORTB,1
Die Lösung wird auch davon abhängen, wo man atomar sein will/muss -- wenn man an den Ausgängen atomar sein muss, also Zwischenzustände vermeiden, die man garnicht ausgeben will, muss man auf den ganzen Port schreiben und sbi/cli ist obsolet -- wenn man intern atomar sein muss, weil auch eine ISR auf dem Port rumnudelt, dann ist ein Lesen/Schreiben des Ports problematisch: Es muss dann in cli/sei o.ä. oder man nimmt die sbi/cli-Lösung. Johann
Nun, da der TE nichts dergleichen erwähnte ist es wohl irrelevant. Man muss ja Aufgaben nicht verkomplizieren ;)
Ok habs jetzt so. nicht schoen, nicht schnell, aber es geht:
1 | swap count3 |
2 | lsr count3 |
3 | lsr count3 |
4 | cbi PORTB, 0 |
5 | cbi PORTB, 1 |
6 | |
7 | in temp, PORTB |
8 | or temp, count3 |
9 | out PORTB, temp |
Es fehlt einfach der richtige Befehl :( (Bit setzen in Abhaengigkeit eines anderen Bits oder sowas :P ) Danke fuer eure Hilfe!
Ist garantiert, dass in count3 keine anderen Bits gesetzt sind? swap count3 lsr count3 lsr count3 in temp, PORTB andi count3, 0x03 ori temp, 0x03 or temp, count3 out PORTB, temp
Hm, und immer noch ein 8-Zeiler. Mikki Mertens Vorschlag scheint mir die beste Lösung zu sein werden doch nur Bits gesetzt, die gesetzt werden sollen und man benötigt auch weiteren Variablen ;)
Ich merke grade, dass das oben von mir ja gar nicht funktioniert! Die nach dem SWAP sind die 4 low-bits ja im high-nibble und werden dann mit ver-odert. Aber man kann ja eh nicht "gleichzeitig" beide PBs aendern, ohne wie gesagt auf den ganzen PORTB zu schreiben. Also hat man immer einen "undefinierten" Zustand zwischendurch. Oder halt ziemlich großen Aufwand.... Ich mach jetz erstmal Fruehstueck und danach schreib ich euch meine Loesung
Wie gesagt, nimm den von Mikki Merten oben, da haste immer einen definierten Zustand ;)
1 | .def counter = r17 |
2 | |
3 | in r16, PORTB |
4 | bst counter, 6 |
5 | bld r16, 0 |
6 | bst counter, 7 |
7 | bld r16, 1 |
8 | out PORTB, r16 |
Stefan Ernst wrote:
> Über die ori-Zeile würde ich nochmal nachdenken. ;-)
Grrrrr. Brauch gleich noch einen Kaffee.
Beim Überlegen war das noch anders. Aber die Finger haben dann
ganz was anderes geschrieben.
swap count3
lsr count3
lsr count3
in temp, PORTB
andi count3, 0x03
andi temp, 0xFC
or temp, count3
out PORTB, temp
Johannes M. wrote:
>
1 | > .def counter = r17 |
2 | > |
3 | > in r16, PORTB |
4 | > bst counter, 6 |
5 | > bld r16, 0 |
6 | > bst counter, 7 |
7 | > bld r16, 1 |
8 | > out PORTB, r16 |
9 | > |
Das ist trickreich :-) Endlich hab ich mal verstanden, was so typische Einsatzfälle für das T-Flag sind. Merci für den Denkanstoss!
ja das is echt tricky :P Wenn sich jetzt nicht zwischen "in r16, PORTB" und "out PORTB, r16" was am PORTB aendert, ist alles OK ;-) Danke euch
Karl heinz Buchegger wrote: > Das ist trickreich :-) > Endlich hab ich mal verstanden, was so typische Einsatzfälle für das > T-Flag sind. Naja, ich finde, bst und bld fristen zu Unrecht ein Nischendasein. Ich vermute fast, dass sich selbst erfahrenere Assembler-Programmierer der Existenz dieser beiden Befehle oft übehaupt nicht bewusst sind. Ich finde die aber oft ziemlich praktisch. Wie oft hat man das Problem, dass man Bitzustände irgendwo herbekommt und in einer völlig anderen Reihenfolge woanders augeben muss. Und wie man sieht, gibt es bei wenigen Bits sogar bei Beibehaltung der Reihenfolge Codegrößen- und Performance-Vorteile. Ich musste es aber auch erst hinschreiben, um zu sehen, dass es tatsächlich kürzer ist als die anderen Vorschläge. Habe schon ziemlich lange nichts ernsthaftes mehr in Assembler programmiert... > Merci für den Denkanstoss! Keine Ursache. Weiß nicht, wie oft ich schon Denkanstöße von Dir bekommen habe (und ich glaube, das geht den meisten, die sich schon länger hier im Forum rumtreiben, so)...
Franz M. wrote: > ja das is echt tricky :P > > Wenn sich jetzt nicht zwischen "in r16, PORTB" und "out PORTB, r16" was > am PORTB aendert, ist alles OK ;-) Das Problem haste bei Read-Modify-Write-Zugriffen dummerweise immer. In dem Falle wäre tatsächlich die Methode mit sbi und cbi die einzig empfehlenswerte. Die ist aber länger... EDIT: OK, meist genügt es natürlich, für die Zeit vom in bis zum out die Interrupt-Bearbeitung zu sperren. Nur wenn irgendwelche Hardware (Timer, serielle Interfaces) auf PORTx zugreifen, genügt das nicht mehr.
Johann L. wrote: > Die Lösung wird auch davon abhängen, wo man atomar sein will/muss > > -- wenn man an den Ausgängen atomar sein muss, also Zwischenzustände > vermeiden, die man garnicht ausgeben will, muss man auf den ganzen Port > schreiben und sbi/cli ist obsolet Ganz genau umgekehrt ist es richtig, man muß SBI/CBI nehmen, um atomar zu sein! Nimmt man IN,AND,OR,OUT ist das nicht mehr atomar. Dann muß mit CLI/SEI geklammert werden, wenn auch Interrupts den Port benutzen. Peter
Peter Dannegger wrote: > Johann L. wrote: >> Die Lösung wird auch davon abhängen, wo man atomar sein will/muss >> >> -- wenn man an den Ausgängen atomar sein muss, also Zwischenzustände >> vermeiden, die man garnicht ausgeben will, muss man auf den ganzen Port >> schreiben und sbi/cli ist obsolet > > Ganz genau umgekehrt ist es richtig, man muß SBI/CBI nehmen, um atomar > zu sein! > > Nimmt man IN,AND,OR,OUT ist das nicht mehr atomar. > Dann muß mit CLI/SEI geklammert werden, wenn auch Interrupts den Port > benutzen. > > > Peter ALLES lesen, was ich schrieb :-) Ein wenn sich das "atomar" auf die Signale bezieht (keine seltsanmen Zwischenzustände), heisst das wohl "glitch" oder so im Fachchinesisch? Beispiel: mit sbi/cbi kommt man nicht ohne Zwischenzustand von 00 nach 11 oder 01 nach 10 etc. Das ist u.a. auch dann von Belang, wenn im Programm nicht asynchron auf die Ports gegriffen wird. Wenn asynchron auf die Ports gegriffen wird, dann "atomar" mit sbi/sbi wie ich schon schrieb. Beispiel: In der Anwendung werden .0 und .1 gesetzt, in einer ISR .6. Dann braucht man cli/sei. Johann
Johann L. wrote: > ALLES lesen, was ich schrieb :-) > > Ein wenn sich das "atomar" auf die Signale bezieht (keine seltsanmen > Zwischenzustände), heisst das wohl "glitch" oder so im Fachchinesisch? Du kannst nicht einfach dem Begriff "atomar" ne falsche Bedeutung geben. Wenn Du glitch meinst, dann ist das was völlig anderes als atomar. Atomar bedeutet nicht unterbrechbar, hat mit Glitches überhaupt nichts zu tun. Nicht atomar ist etwas, wenn ein Interrupt dazwischen haut und dann die Änderung des Interrupts verloren geht. > Beispiel: mit sbi/cbi kommt man nicht ohne Zwischenzustand von 00 nach > 11 oder 01 nach 10 etc. Das hat überhaupt nichts mit "atomar" zu tun, ist ne völlig andere Baustelle. Gleichzeitig ist eh nie ein Wechsel zweier Signale, Du hast immer unterschiedliche Schaltzeiten und wenn es nur Picosekunden sind. Wenn Du das willst, mußt Du Graycode nehmen oder die Signale mit einem Takt latchen, nachdem sie stabil sind. Schau Dir mal die NXP ARM7-TDMI an, die haben getrennte Set- und Clear-Register, d.h. Du kannst dort nichtmal im gleichen Maschinenzyklus mehrere Pins setzen und löschen. Sie sind aber extra dazu eingeführt worden, um atomar zuzugreifen, da bei den ARM7 ein Interrupt-Disable eine ziemliche Verrenkung ist (nicht im Usermode möglich). Sowohl atomar als auch (fast) gleichzeitig kann der ARM-Cortex M3, da er spezielle Bitbefehle hat. Peter
Peter Dannegger wrote: > Johann L. wrote: >> Beispiel: mit sbi/cbi kommt man nicht ohne Zwischenzustand von 00 nach >> 11 oder 01 nach 10 etc. > > Das hat überhaupt nichts mit "atomar" zu tun, ist ne völlig andere > Baustelle. Schon klar. Mir fehlt(e) da lediglich eine Vokabel. Wie heisst es denn korrekt?
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.