Forum: Mikrocontroller und Digitale Elektronik Frage zu ASM in C (Loop- Schleife und Port-Pin)


von Marcel K. (viewer)


Lesenswert?

Hallo Forumgemeinde,
ich habe mich jetzt etwas in das Tema ASM in C eingearbeitet. Ich möchte 
ein Datenbyte über ein Portpin versenden. Dazu habe ich im Netz 
folgenden Code gefunden.
1
#define send_byte(data_byte) \
2
__asm__ __volatile__ (        \
3
"out %[port], %[shift_value] \n\t" \
4
"lsl %[shift_value]       \n\t" \
5
"out %[port], %[shift_value] \n\t" \
6
"lsl %[shift_value]       \n\t" \
7
"out %[port], %[shift_value] \n\t" \
8
"lsl %[shift_value]       \n\t" \
9
"out %[port], %[shift_value] \n\t" \
10
"lsl %[shift_value]       \n\t" \
11
"out %[port], %[shift_value] \n\t" \
12
"lsl %[shift_value]       \n\t" \
13
"out %[port], %[shift_value] \n\t" \
14
"lsl %[shift_value]          \n\t" \
15
"out %[port], %[shift_value] \n\t" \
16
"lsl %[shift_value]       \n\t" \
17
"out %[port], %[shift_value] \n\t" \
18
::[port] "I" (_SFR_IO_ADDR(PORTA)),\
19
[shift_value] "r" (data_byte)
20
);

Also diese ASM- Zeilen verstehe ich schon. Es wird das Datenbyte in das 
Port- Register geschrieben. Dann wird das Datenbyte ein Mal nach links 
geschoben und wieder neu in das Portregister geschrieben. Was mir aber 
daran gar nicht gefällt, ist das der komplette PortA belegt ist. Ich 
möchte eigentlich nur ein einzelnes Bit verwenden. Daher habe ich mich 
etwas in ASM eingelesen. Dann ist bei mir folgender Codeschnipsel 
entstanden.
1
#define send_byte(data_byte)       \
2
__asm__ __volatile__(             \
3
"LOOP:            \n\t" \
4
"lsl %[shift_value]          \n\t" \
5
"BRCS SET_OUTPUT_HIGH       \n\t" \
6
"cbi %[port], %[portpin]     \n\t" \
7
"rjmp LOOP_END         \n\t" \
8
"SET_OUTPUT_HIGH:        \n\t" \
9
"sbi %[port], %[portpin]     \n\t" \
10
"LOOP_END:           \n\t" \
11
"dec %[i]         \n\t" \
12
"brne LOOP         \n\t" \
13
..[port] "I" (_SFR_IO_ADDR(PORTA)),\
14
[portpin] "i" (7),        \
15
[shift_value] "r" (data_byte),     \
16
[i] "r" (8)
17
);

Also ich schiebe das Datenbyte nach links und prüfe das „Carry-Bit“. 
Wenn dieses dann „1“ ist, setze ich auch den Port-Pin auf „1“. Falls es 
„0“ ist dann der Portpin auf „0“. Das mache ich dann 8-mal.
Generell funktioniert das ganze zwar aber wenn ich mir den Portpin auf 
dem Oszi anschaue, dann braucht mein neuer Code fiel länger. Naja, wenn 
ich die einzelnen Taktzyklen zusammenzähle dann ist mir das auch klar.
Meine Frage ist jetzt, gibt es denn noch eine andere Möglichkeit über 
einen einzelnen Pin die Daten rauszuschieben? (Ich weiß es würde auch 
über SPI gehen aber das geht bei mir nicht, das wird für etwas anderes 
benötigt)


Was mich auch noch interessieren würde. Ich habe in meinem AVR- Studio6 
das ganze über den „Optimizationlevel „non“ eingestellt. Wenn ich das 
ganze auf „Optimize most“ einstelle, bekomme ich die Fehlermeldung dass 
„LOOP“, „SET_OUTPUT_HIGH“, „LOOP_END“… bereits definiert wurde. Ich kann 
mir nicht erklären woher das kommt. Hat jemand einen Hinweis für mich?

Danke schon mal für Eure Antworten und Mühe.
Ich wünsch Euch auf jeden Fall noch einen schönen Sonntag.
Grüße,
Marcel

von Karl H. (kbuchegg)


Lesenswert?

Marcel K. schrieb:

> Was mich auch noch interessieren würde. Ich habe in meinem AVR- Studio6
> das ganze über den „Optimizationlevel „non“ eingestellt. Wenn ich das
> ganze auf „Optimize most“ einstelle, bekomme ich die Fehlermeldung dass
> „LOOP“, „SET_OUTPUT_HIGH“, „LOOP_END“… bereits definiert wurde. Ich kann
> mir nicht erklären woher das kommt. Hat jemand einen Hinweis für mich?


Das wird wohl daher kommen, dass dein Makro für sich alleine genommen ja 
noch nichts macht, sondern ja auch irgendwo verwendet werden muss. Und 
wenn dieses Makro dann an 2 verwendenden Stellen expandiert wird, dann 
hast du eben die Labels doppelt drinnen.

von W.S. (Gast)


Lesenswert?

Marcel K. schrieb:
> Ich möchte
> ein Datenbyte über ein Portpin versenden. Dazu habe ich im Netz
> folgenden Code gefunden.

Glaube bitte nicht, daß all das, was man so im Inet findet, auch 
wirklich als gutes Beispiel herhalten kann. Ganz konkret finde ich, daß 
du das gezeigte Beispiel eher ansehen solltest als etwas das man SO 
besser nicht machen sollte.

Es ist eigentlich so gut wie immer viel besser, Quellen auseinander zu 
halten, also kein Assembler in C-Quellen (auch wenn die Toolchain das 
ermöglicht), sondern Assembler eben in eine separate Assemblerquelle 
schreiben und natürlich auch separat übersetzen.

Ansonsten sollte sich das, was du beabsichtigst, auch bequem in C 
ausdrückbar sein.

W.S.

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
Noch kein Account? Hier anmelden.