題:
loop()在Arduino中運行有多快
FiftyShadesGreyAbhi
2017-08-24 16:09:02 UTC
view on stackexchange narkive permalink

嗨,我正在使用 Arduino Nano 遊戲化我在Unity3D上的經驗。我知道Unity3D中的 Update()每秒運行每一幀,但我因為我不是電子專家,所以我不知道 loop()函數如何在Arduino上運行

這取決於CPU週期數(如果是Arduino,則取決於微處理器芯片)還是什麼?請解釋。我在遊戲中面臨一些滯後。僅當知道loop()函數如何在Arduino上運行時才能修復它們

在arduino 文檔中沒有關於 loop()的很多信息

“每秒運行每一幀”不能確保您完全理解幀,或者可能只是拼寫錯誤。但是在Unity3D中,每個幀都盡可能快地運行,它們不是故意的,而是幀的延遲
*在幀中放置*延遲(無法編輯嗎?以為我可以)
簡短的答案似乎是“盡可能快”。
五 答案:
Majenko
2017-08-24 16:14:54 UTC
view on stackexchange narkive permalink

只要循環需要運行,循環就會運行。

CPU中的指令按順序運行。指令越多,運行時間就越長。

放入循環的代碼越多,循環將運行的時間越長。

有兩種方法可以知道循環的每次迭代要花多長時間:

  1. 分析:主動提醒每次循環一次,儘管會被警告,但計時動作會影響所花費的時間。
  2. 週期計數。將源代碼編譯為彙編代碼,並總計所有指令(包括對函數的調用)所需的時鐘週期數。
  3. ol>

    還請注意,許多外部因素會影響loop()的運行時間,例如串行通訊速度等。 ol>

    >

不要忘記中斷,例如每16000個時鐘週期更新一次毫秒值(對於16Mhz振盪器)。它們會定期停止執行程序,並阻止arduino成為良好的PWM源。 (是的,您可以將其關閉)
@FilipFranik: 1.更新`millis()`值的中斷每隔1024 µs或16384 CPU週期以16 MHz運行一次。 2.中斷會影響軟件PWM輸出的質量(例如,伺服庫)。它們對硬件生成的PWM(例如,使用`analogWrite()`)沒有影響。
ratchet freak
2017-08-24 16:17:48 UTC
view on stackexchange narkive permalink

loop()結束與下一次運行之間的指令是ret,jmp和調用。

您可以認為main函數是有效的:

  void main(){init(); while(1)loop();}  

儘管實際上在 init()之前已經進行了一些設置,以使 millis()以及類似的工作。

此外,循環後還有串行事件代碼。
@Majenko不能用中斷來完成嗎?
不,這不對。它只是在循環結束時調用。它非常粗糙,許多人不了解它到底是多麼毫無意義。
我認為loop()是由編譯器優化的,因此不會出現實際的jmp或ret。該代碼轉換為:while(1)yourLoopCode;沒有函數調用。但是我在GCC上看到了可怕的愚蠢的事情...
我越關注arduino的標準運行時,就越不滿意...
@next-hack:較新版本的Arduino IDE調用帶有-flto選項的gcc,該選項可啟用鏈接時間優化,並可能導致內聯loop()。較舊的版本不使用此選項,因此將loop()編譯為一個實函數,並由main()反複調用。
dannyf
2017-08-24 16:13:01 UTC
view on stackexchange narkive permalink

這取決於循環中的內容。從幾個時鐘週期到無限死機。

Richard
2018-02-01 19:13:38 UTC
view on stackexchange narkive permalink

查看文件中的main.cpp(用於我的安裝中的avr代碼):

  C:\ Program Files(x86)\ Arduino \ hardware \ arduino \ avr \ cores \ arduino \ main.cpp  

顯示Arduino在無限循環中與serialEventRun()交替運行loop():

  int main(void){init (); initVariant(); #if defined(USBCON)USBDevice.attach();#endif setup();對於(;;){loop();如果(serialEventRun)serialEventRun(); } return 0;}  

對HardwareSerial.cpp的檢查表明,如果您已在草圖中定義了serialEventRun(),則只需調用serialEvent()即可。

這意味著您可以安全地在loop()中編寫自己的無限循環,除非您已編寫了serialEvent()代碼並期望其能夠正常運行。

問題:如果使用loop()順序調用serialEvent(),如果loop()從不返回,則將調用serialEvent()嗎?換句話說,serialEvent()是由中斷驅動的,還是在loop()返回時被調用的?快速測試-見下文-表明它不是不是中斷驅動的,因此上一段是正確的。

  / *串行事件檢查器一個草圖,查看是否serialEvent()是中斷驅動的。如果loop()永不返回,將調用serialEvent()嗎?此代碼基於Tom Igoe的SerialEvent示例。在(至少)Arduino Uno上,我們發現serialEvent()僅與loop()順序運行。當loop()從不返回時,永遠不會調用serialEvent()。注意:serialEvent()功能在基於Leonardo,Micro或其他基於ATmega32U4的板上不可用。 R Symonds-Tayler 2018-02-01此示例代碼在公共領域中。* / String inputString =“”; //用於保存傳入數據的String無效setup(){//初始化serial:Serial.begin(115200); //為inputString保留200個字節:inputString.reserve(200);} //註釋掉該定義,以允許loop()返回#define INFINITE_LOOPvoid loop(){#ifdef INFINITE_LOOP
while(1);#endif} / *每當新數據進入硬件串行RX時,都會發生SerialEvent。該例程在每次loop()運行之間運行,因此在循環內部使用delay可以延遲響應。 * / void serialEvent(){while(Serial.available()){//獲得新的字節:char inChar =(char)Serial.read(); //將其添加到inputString中:inputString + = inChar; //如果輸入的字符是換行符,則設置一個標誌,以便主循環可以//對它做一些事情:if(inChar =='\ n'){Serial.print(“ Got:'”); Serial.print(inputString); Serial.println(“'”); //清除字符串:inputString =“”; }}}  

這意味著serialEvent()代碼也可能會在以下位置進入您的主loop():

  if(serial.available ()){//您的代碼在這裡...}  

塊。

user37632
2017-08-24 20:54:18 UTC
view on stackexchange narkive permalink

嘗試查找arduino函數micros()和delayMicroseconds()如果您可能需要循環等待超過16000微秒,則還要查找另一個毫秒級的delay()函數。

內部時鐘會略微關閉,並且會隨室溫而變化,因此不要依賴它在沒有握手的情況下與其他設備保持同步。

“ micros()”和“ delayMicroseconds()”使用32位整數(“ unsigned long”),可以管理的持續時間最長為2³²µs,或約1.19小時。


該問答將自動從英語翻譯而來。原始內容可在stackexchange上找到,我們感謝它分發的cc by-sa 3.0許可。
Loading...