You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Arduino Nano 33 BLE Sense micros()耗时过高 求低时钟周期计时方案

方案1:使用Cortex-M4内核DWT周期计数器(最优)

NRF52840搭载的Cortex-M4内核自带DWT调试组件,其中CYCCNT寄存器会随内核时钟每周期自增1,读操作仅需1~2个时钟周期,精度为内核时钟周期(64MHz下为15.625ns),完全满足需求。
示例代码如下:

#include "nrf_gpio.h"

#define OUTPUT_PIN NRF_GPIO_PIN_MAP(1,11)

uint32_t start_cnt, end_cnt, cycle_diff;

// 初始化DWT计数器
void dwt_cycle_counter_init(void) {
    CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
    DWT->CYCCNT = 0;
    DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
}

void setup() {
  Serial.begin(115200);
  while (!Serial);

  nrf_gpio_cfg_output(OUTPUT_PIN);
  dwt_cycle_counter_init();
}

void loop() {
  // 测试读计数器的开销
  start_cnt = DWT->CYCCNT;
  end_cnt = DWT->CYCCNT;
  cycle_diff = end_cnt - start_cnt;
  Serial.print("读计数器耗时:");
  Serial.print(cycle_diff);
  Serial.println(" 时钟周期");

  // 测试减法操作耗时
  uint32_t arithmeticMinuend = 4294967295;
  uint32_t arithmeticSubtrahend = 2147483648;
  uint32_t arithmeticDifference;
  start_cnt = DWT->CYCCNT;
  arithmeticDifference = arithmeticMinuend - arithmeticSubtrahend;
  end_cnt = DWT->CYCCNT;
  cycle_diff = end_cnt - start_cnt;
  Serial.print("减法操作耗时:");
  Serial.print(cycle_diff);
  Serial.println(" 时钟周期");

  // 示波器验证用代码
  nrf_gpio_pin_toggle(OUTPUT_PIN);
  start_cnt = DWT->CYCCNT;
  end_cnt = DWT->CYCCNT;
  nrf_gpio_pin_toggle(OUTPUT_PIN);

  delay(1000);
}

该方案注意事项:

  • CYCCNT为32位寄存器,64MHz主频下约每67秒溢出一次,测量长间隔时需自行处理溢出逻辑
  • 无需占用片上外设资源,无额外配置开销

方案2:使用nrfx_timer硬件定时器

如果需要更长的计数周期或者不使用DWT组件,可以用NRF52840自带的硬件定时器,配置为计数器模式后读操作仅需2~3个时钟周期:
示例代码如下:

#include "nrfx_timer.h"
#include "nrf_gpio.h"

#define OUTPUT_PIN NRF_GPIO_PIN_MAP(1,11)
// 使用TIMER0,避免与mbed系统默认占用的TIMER1/TIMER2冲突
static const nrfx_timer_t s_timer = NRFX_TIMER_INSTANCE(0);
uint32_t start_cnt, end_cnt, time_diff;

void timer_init(void) {
    nrfx_timer_config_t timer_cfg = {
        .frequency = NRF_TIMER_FREQ_64MHz, // 可配置为1MHz/16MHz等,64MHz时精度为15.625ns
        .mode = NRF_TIMER_MODE_TIMER,
        .bit_width = NRF_TIMER_BIT_WIDTH_32,
        .interrupt_priority = NRFX_TIMER_DEFAULT_CONFIG_IRQ_PRIORITY,
        .p_context = NULL
    };
    // 无需中断,回调函数设为NULL
    nrfx_timer_init(&s_timer, &timer_cfg, NULL);
    nrfx_timer_enable(&s_timer);
}

void setup() {
  Serial.begin(115200);
  while (!Serial);

  nrf_gpio_cfg_output(OUTPUT_PIN);
  timer_init();
}

void loop() {
  start_cnt = nrfx_timer_capture(&s_timer, NRF_TIMER_CC_CHANNEL0);
  end_cnt = nrfx_timer_capture(&s_timer, NRF_TIMER_CC_CHANNEL1);
  time_diff = nrfx_timer_capture_diff_get(&s_timer, start_cnt, end_cnt);
  // 64MHz频率下时间单位为1/64us,转ns的话乘以15.625即可
  Serial.print("读定时器耗时:");
  Serial.print(time_diff);
  Serial.println(" 个定时器计数周期");

  delay(1000);
}

该方案注意事项:

  • 32位位宽+64MHz频率下,计数溢出周期约为67秒,位宽改为24位时溢出周期为0.26秒,可根据需求调整
  • 硬件捕获操作为硬件级实现,无软件开销,稳定性更高

内容的提问来源于stack exchange,提问作者Landon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 18:45:03