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