我最近在一个与Arduinos合作的模块中提供了这项任务。我们之前的任务是在C中,但是当谈到这一点时,我根本不知道该怎么做,甚至不知道如何在这种情况下开始。我们也没有提供任何类型的讲座或等等来涵盖这一点。任何人都可以帮助或只是让球滚动一点点,这样我可以更好地理解它吗?谢谢。
我必须编辑的第一段代码如下:
"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
答案 0 :(得分:1)
引用的字符串是您停止的asm()
调用中的汇编代码。编译时,字符串将按字面转换为相关的汇编指令。
在称为标签后带有冒号:
的名称,而函数调用只是跳转到标签。您还可以使用分支指令(例如brne
)跳转到函数内,如果之前的结果不是0,则跳转。
asm()
来电表示注册" r16"," r17"," r18"," r30",& #34; R 31"全部使用,但眨眼代码似乎只使用" 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"