【发布时间】:2021-11-11 06:55:14
【问题描述】:
我首先在 Arduino 论坛上发布了这个问题,但我的问题最近没有受到太多关注,所以这里......
我非常努力地制作了一个简单的草图,以证明 micros() 方法在 Nano 33 BLE Sense 上的速度有多慢:
#include "mbed.h"
#include "nrf_delay.h"
#include "nrf_gpio.h"
#define OUTPUT_PIN NRF_GPIO_PIN_MAP(1,11)
unsigned long startClock;
unsigned long stopClock;
unsigned long arithmeticMinuend = 4294967295;
unsigned long arithmeticSubtrahend = 2147483648;
unsigned long arithmeticDifference = 0;
unsigned long timeDifference1 = 0;
unsigned long timeDifference2 = 0;
//Assume 1 to 4 clock cycles (15.625 to 62.5 ns) is required for every...
//* call of micros();
//* subtraction of two unsigned longs.
//Therefore we should not be able to measure the time to execute either task by using the micros() - startClock technique, as...
//* micros() - startClock = 0 in either case.
void setup() {
Serial.begin(115200);
while (!Serial);
nrf_gpio_cfg_output(OUTPUT_PIN);
startClock = micros();
stopClock = micros();
}
void loop() {
timeDifference1 = microsecondsToSubtract2LongsOnce();
timeDifference2 = microsecondsToSubtract2LongsTwice();
Serial.print("timeDifference1 = ");
Serial.print(timeDifference1);
Serial.print(" us.\ntimeDifference2 = ");
Serial.print(timeDifference2);
Serial.println(" us.");
microsecondsToSubtract2LongsOnceMeasuredWithScope();
delay(100);
microsecondsToSubtract2LongsTwiceMeasuredWithScope();
delay(100);
microsecondsToToggleOutputPinMeasuredWithScope();
while(1) {
}
}
//Prints 8 us:
unsigned long microsecondsToSubtract2LongsOnce() {
startClock = micros();
stopClock = micros();
return stopClock - startClock;
}
//Prints 9 us:
unsigned long microsecondsToSubtract2LongsTwice() {
startClock = micros();
arithmeticDifference = arithmeticMinuend - arithmeticSubtrahend;
stopClock = micros();
return stopClock - startClock;
}
//Measured 18 us on scope:
void microsecondsToSubtract2LongsOnceMeasuredWithScope() {
nrf_gpio_pin_toggle(OUTPUT_PIN);
startClock = micros();
stopClock = micros();
nrf_gpio_pin_toggle(OUTPUT_PIN);
}
//Measured 18 us on scope:
void microsecondsToSubtract2LongsTwiceMeasuredWithScope() {
nrf_gpio_pin_toggle(OUTPUT_PIN);
startClock = micros();
arithmeticDifference = arithmeticMinuend - arithmeticSubtrahend;
stopClock = micros();
nrf_gpio_pin_toggle(OUTPUT_PIN);
}
//Measured 500 ns on scope:
void microsecondsToToggleOutputPinMeasuredWithScope() {
nrf_gpio_pin_toggle(OUTPUT_PIN);
nrf_gpio_pin_toggle(OUTPUT_PIN);
}
我将使用示波器进行的时间测量与使用 micros() 进行的时间测量进行比较。通过数学计算,我们得到一个 micros() 调用所需的时钟周期数 (CC) = (0.5*(18000 - 500) ns)/15.625 ns = 560 CC!!!
有人可以举个例子来测量这个板上不需要超过 10 CC 的时间吗???
根据我的阅读,我认为更快的 (theoretically 1 CC) 策略将涉及使用方法 nrf_drv_timer 或更新的 nrfx_timer(两种策略都需要设置计时器以在计数器模式下运行),但我不能找不到在我的 Arduino 的 NRF52840 上使用的具体示例。
编辑:
我也尝试使用 mbed 的 us_ticker 来缩短时间,但计时结果完全相同。这是我用于该测试的代码:
#include "mbed.h"
#include "nrf_delay.h"
#include "nrf_gpio.h"
#define OUTPUT_PIN NRF_GPIO_PIN_MAP(1,11)
mbed::Timer timer;
uint32_t startClock;
uint32_t stopClock;
uint32_t arithmeticMinuend = 4294967295;
uint32_t arithmeticSubtrahend = 2147483648;
uint32_t arithmeticDifference = 0;
uint32_t timeDifference1 = 0;
uint32_t timeDifference2 = 0;
//Assume 1 to 4 clock cycles (15.625 to 62.5 ns) is required for every...
//* call of micros();
//* subtraction of two unsigned longs.
//Therefore we should not be able to measure the time to execute either task by using the micros() - startClock technique, as...
//* micros() - startClock = 0 in either case.
void setup() {
Serial.begin(115200);
while (!Serial);
nrf_gpio_cfg_output(OUTPUT_PIN);
timer.start();
startClock = timer.read_us();
stopClock = timer.read_us();
}
void loop() {
timeDifference1 = microsecondsToSubtract2LongsOnce();
timeDifference2 = microsecondsToSubtract2LongsTwice();
Serial.print("timeDifference1 = ");
Serial.print(timeDifference1);
Serial.print(" us.\ntimeDifference2 = ");
Serial.print(timeDifference2);
Serial.println(" us.");
microsecondsToSubtract2LongsOnceMeasuredWithScope();
timer.stop();
delay(100);
timer.start();
microsecondsToSubtract2LongsTwiceMeasuredWithScope();
timer.stop();
delay(100);
timer.start();
microsecondsToToggleOutputPinMeasuredWithScope();
timer.stop();
while(1) {
}
}
//Prints 8 us:
unsigned long microsecondsToSubtract2LongsOnce() {
startClock = timer.read_us();
stopClock = timer.read_us();
return stopClock - startClock;
}
//Prints 9 us:
unsigned long microsecondsToSubtract2LongsTwice() {
startClock = timer.read_us();
arithmeticDifference = arithmeticMinuend - arithmeticSubtrahend;
stopClock = timer.read_us();
return stopClock - startClock;
}
//Measured 18 us on scope:
void microsecondsToSubtract2LongsOnceMeasuredWithScope() {
nrf_gpio_pin_toggle(OUTPUT_PIN);
startClock = timer.read_us();
stopClock = timer.read_us();
nrf_gpio_pin_toggle(OUTPUT_PIN);
}
//Measured 18 us on scope:
void microsecondsToSubtract2LongsTwiceMeasuredWithScope() {
nrf_gpio_pin_toggle(OUTPUT_PIN);
startClock = timer.read_us();
arithmeticDifference = arithmeticMinuend - arithmeticSubtrahend;
stopClock = timer.read_us();
nrf_gpio_pin_toggle(OUTPUT_PIN);
}
//Measured 500 ns on scope:
void microsecondsToToggleOutputPinMeasuredWithScope() {
nrf_gpio_pin_toggle(OUTPUT_PIN);
nrf_gpio_pin_toggle(OUTPUT_PIN);
}
【问题讨论】:
-
micros() 使用 mbed 的计时器实现。参见 core 中的 Wiring.cpp
-
您使用示波器真是太好了。放弃图书馆会让你更接近。不要相信任何图书馆调用,除非你能确认它做了它应该做的事情。
标签: timer arduino timing nrf52 arduino-nano