Hi Leute,
weis einer von euch vielleicht wie es möglich ist mit GNU den Assembler
Code "SBIC" zu implementieren?
Habe folgendes Problem:
Es wird in einer ISR ein Taster abgefragt, welcher entsprechend dem
Zustand eine Variable incrementiert.
if (PINB & 1<<PINB0)
{
counter1+=100;
}
Der Assembler Code sieht so aus:
if (PINB & 1<<PINB0)
00000036 SBIS 0x16,0 Skip if bit in I/O register set
00000037 RJMP PC+0x000B Relative jump
counter1+=100;
00000038 LDS R24,0x0062 Load direct from data space
0000003A LDS R25,0x0063 Load direct from data space
0000003C SUBI R24,0x9C Subtract immediate
0000003D SBCI R25,0xFF Subtract immediate with carry
0000003E STS 0x0063,R25 Store direct to data space
00000040 STS 0x0062,R24 Store direct to data space
Bitte versteht mich nicht falsch, das Programm funktioniert. Leider ist
es so, dass ich die internen Pullups meines ATmega8 verwende möchte,
welche mit einem Taster auf GND gezogen werden.
Was der µC jetzt macht, ist ständig die Variable zu erhöhen, weil er
natürlich einen logic 1 Pegel registiert.
Was muss nun in der Bedingung des IF-Befehlts verändert werden, damit er
anstatt des SIBS ein SBIC im assembler Code erzeugt?
- Andy
1 | if (!(PINB & ~(1<<PINB0))) { |
2 | ...
|
3 | }
|
Der AVR-GCC ist i.A. klug genug, aus der C-Logik die passende AVR-Assemblerinstruktion zu bauen, d.h. du musst nur die if-Abfrage entsprechend anpassen. Kümmer dich nicht um den Åssemblercode, es sei denn du bekommst konkrete Performance/Zeitprobleme. Der Lesbarkeit und Dokumentation halber würde ich der Konstanten ~(1<<PINB0) übrigens per #define einen sinnvollen Namen geben, z.B. "TasterXY", das macht es übersichtlicher und verständlicher.
Argh, vergiss meinen C-Code. Peter II hat natürlich recht. Hirnaussetzer. Aber das mit dem #define solltest du dir selbst zuliebe trotzdem machen.
Vielen Dank für die schnelle Antwort!
Das mit den #define ist ein guter Tipp danke!
Mir ging es ohnedies nicht um Performance sonder um den Code an sich.
if (!(PINB & 1<<PINB0))
ist übgrigens die richtige Lösung, sollte noch jemand das gleiche
Problem haben.
if (!(PINB & 1<<PINB0))
00000036 SBIC 0x16,0 Skip if bit in I/O register cleared
00000037 RJMP PC+0x000B Relative jump
Mit
if (!(PINB & ~(1<<PINB0))) {
...
}
erzeugt der Compiler folgendes:
if (!(PINB & ~(1<<PINB0)))
00000036 IN R24,0x16 In from I/O location
00000037 ANDI R24,0xFE Logical AND with immediate
00000038 BRNE PC+0x0B Branch if not equal
wobei ich nicht sagen kann ob das nur bei der von mir verwendeten
Version der Fall ist.(gcc Verion 4.5.1)
Andy S. schrieb: > Es wird in einer ISR ein Taster abgefragt, welcher entsprechend dem > Zustand eine Variable incrementiert. In der Regel macht man das nicht so. Bei Tasten interessiert oft nicht der Zustand, sondern die Zustandsänderung von Losgelassen nach Gedrückt. Das macht man dann bequemer Weise in einem Timerinterrupt, der dann die Taste gleich entprellt und gleich auch ein Autorepeat machen kann, wenn gewünscht. Beitrag "Universelle Tastenabfrage" Und da man oft mehrere Tasten hat, macht die Routine das gleich für den ganzen Port (8 Tasten) ohne jeden Mehraufwand. Peter
Peter Dannegger schrieb: > Das macht man dann > bequemer Weise in einem Timerinterrupt, der dann die Taste gleich > entprellt Genau das wird ja auch gemacht. Ein timer nimmt mit ca. 450 Hz die Tasterabfrage vor. Ich sollte vielleicht noch erwähnen, dass es sich um ein sehr einfaches Programm handelt, welches nur zu testzwecken mal "schnell" geschrieben wurde. (Vereinfacht ein Stobolicht, welches mit einem 16 bit Timer der vorgeladen wird, in der Frequenz verändert werden kann) Was ich aber nicht ganz verstehe: Peter Dannegger schrieb: > Bei Tasten interessiert oft nicht der Zustand, sondern die > Zustandsänderung von Losgelassen nach Gedrückt. Das würe in diesem Fall ja nichts bringen, ich möchte eben gerade, dass die Variable mit der Geschwindigkeit von 450 Hz geändert wird. Oder hab ich da was falsch verstanden?
Andy S. schrieb: > Oder hab ich da was falsch verstanden? Ich denke, du sprichst von ganz was anderem. Peter spricht von der Tastenauswertung. Du drückst die Taste nieder, das Stroboskop geht an. Du lässt die Taste los, das Stroboskop blinkt weiter. Du drückst die Taste nochmal, das Stroboskop geht wieder aus. Du lässt die Taste los, das Stroboskop bleibt aus. Eben ein ganz normaler Ein/Ausschalter, der eine Funktion durch Tastendruck aktiviert bzw. deaktiviert. Bei jedem mal Draufdrücken wird eine Aktion ausgelöst. Aber NUR beim Draufdrücken. Im Gegensatz dazu steht die Funktionalität: Mache was, solange eine Taste gedrückt IST. Auch das kann manchmal sinnvoll sein. Wenn du haben willst, dass dein Stroboskop dann arbeiten, wenn du mit dem Finger auf der Taste einschläfst, dann ist dieser Modus dein Ziel.
Andy S. schrieb: > Das würe in diesem Fall ja nichts bringen, ich möchte eben gerade, dass > die Variable mit der Geschwindigkeit von 450 Hz geändert wird. Das dürfte weit über dem menschlichen Reaktionsvermögen sein. Die Variable ist dann fast schon ein Zufallszahlengenerator. Ich benutze 5Hz (200ms) als Repeatfrequenz. Aber erst nach 500ms, d.h. man kann auch Einzeldrücke zählen. Peter
Peter Dannegger schrieb: > Andy S. schrieb: >> Es wird in einer ISR ein Taster abgefragt, welcher entsprechend dem >> Zustand eine Variable incrementiert. > In der Regel macht man das nicht so. Du weisst doch gar nicht, was er machen will.
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.