2017-05-03 70 views
0

我最近在一個與Arduinos合作的模塊中提供了這項任務。我們以前的任務是C語言,但是當涉及到這個時,我根本不知道該怎麼做,甚至不知道該如何開始。我們也沒有提供任何類型的講座或其他方式來解決這個問題。任何人都可以幫助或只是讓球滾動一點,這樣我就能更好地理解它?謝謝。AVR彙編語言 - 交通燈

的,我不得不修改代碼的第一位是如下:

"delay_ms%=: nop     ; code to replace nop \n" 
"delay_100us%=: nop     ; code to replace nop \n" 
"delay_1us%=: nop     ; code to replace nop \n" 
"    sbiw r30,1   ; decrement ms count (r31:r30)\n" 
"    brne delay_ms%=  ; loop to delay_ms while > 0 \n" 
"    ret     ; return from subroutine  \n" 

,然後將代碼的其餘部分是這樣的:

" blink%=:        ; start of blink code \n" 
// 
// turn onboard LED on 
// 
"    ldi r18,0x20   ; bit 5 (pin 13) = high \n" 
"    out 5,r18    ; output to port B  \n" 
// 
// delay by value in millisecs variable 
// 
"    lds r30,millisecs  ; r30 = hi byte   \n" 
"    lds r31,millisecs + 1 ; r31 = lo byte   \n" 
"    call delay_ms%=   ; call millisec delay sub \n" 
// 
// turn onboard LED off 
// 
    "    ldi r18,0x00   ; value for all LEDs off \n" 
    "    out 5,r18    ; output to port B  \n" 
// 
// delay by value in millisecs variable 
// 
"    lds r30,millisecs  ; r30 = hi byte   \n" 
"    lds r31,millisecs + 1 ; r31 = lo byte   \n" 
"    call delay_ms%=   ; call millisec delay sub \n" 

::: "r16", "r17", "r18", "r30", "r31"); // clobbered registers 

//-------------------------------------------------------------------------  ------- 
// calculate the execution time of the blink routine, and print details 
long endtime = millis();     // make a note of the end time 
float ms = endtime-starttime;    // calculate the interval 
float expected = 2 * millisecs;   // expected delay is millisecs *  2 (2 delays in blink) 
float overheads = 17;      // overheads due to the timing 
expected = expected + overheads; 
float error_percent = 100.0*(ms-expected)/expected; 
Serial.print("delay="); Serial.print(ms); Serial.print("ms "); 
Serial.print("error: "); 
if(error_percent>0) 
Serial.print("+"); 
Serial.print(error_percent);Serial.println("%"); 
} 

的指令集是在這裏:http://www.atmel.com/images/Atmel-0856-AVR-Instruction-Set-Manual.pdf

回答

1

引用的字符串是在您離開的asm()調用中的彙編代碼。編譯時,字符串將被直接轉換爲相關的彙編指令。

名稱冒號:被稱爲標籤後,函數調用只是跳轉到標籤。如果以前的結果不爲0,也可以跳轉到具有分支指令的分支指令內。

asm()調用指示寄存器「r16」,「r17」,「r18」,「r30」 「r31」全部使用,但閃爍代碼似乎只使用「r18」,「r30」,「r31」。這意味着您打算在您的延遲代碼中使用「r16」和「r17」。

延遲碼到目前爲止僅僅是倒計時的雙寄存器R31的值一個循環:R30

"delay_ms%=: nop     ; code to replace nop \n" 
"    sbiw r30,1   ; decrement ms count (r31:r30)\n" 
"    brne delay_ms%=  ; loop to delay_ms while > 0 \n" 
"    ret     ; return from subroutine  \n" 

它分支回到循環,直至數爲0的頂部,當它返回。

您需要在該循環內插入一些代碼,以計算您自己的需要1毫秒的循環。您需要知道時鐘速度以確定數量。使用r17:r16作爲計數,類似於延遲計數的設置方式,除非您使用ldi,立即加載。

"delay_ms%=: ldi ...    ; set up r17 and r16 in a few instructions \n" 
"delay_1us%=: sbiw r16,1   ; decrement count n" 
"    brne delay_1us%= ; loop to while > 0 \n" 
"    sbiw r30,1   ; decrement ms count (r31:r30)\n" 
"    brne delay_ms%=  ; loop to delay_ms while > 0 \n" 
"    ret     ; return from subroutine  \n"