【问题标题】:Enabling I2C interrupt within timer interrupt on nRF52 Arduino在 nRF52 Arduino 上的定时器中断内启用 I2C 中断
【发布时间】:2017-07-01 15:24:10
【问题描述】:

我正在使用 Redbear Arduino 库为基于 nRF52 的开发板编写程序。有效地将我的电路板视为 BLE Nano 2。

我有一个每 x 毫秒计时一次的计时器,例如 50 毫秒。

在该计时器内,我想从 I2C 传感器读取数据并将读数添加到缓冲区。

我知道默认情况下,在定时器 ISR 内时,中断被禁用。我想知道如何短暂地重新启用 I2C 中断,并获取传感器读数,然后再次禁用中断。

传感器读数之间的间隔很关键,我不只是想在计时器 ISR 中设置一个标志,因为我不知道需要多长时间才能检查该标志。

请有人指导我如何从定时器 ISR 中简要启用 I2C 中断?

我已经尝试过:

__disable_irq();

__enable_irq();

NVIC_EnableIRQ(SPI0_TWI0_IRQn);

NRF_TWI0->INTENSET = 1;

对其中任何一个都不满意,我知道其中一些只能在软件中的某些位置工作,因此在 ISR 中无法正常运行。

void setup() {
  // put your setup code here, to run once
  NVIC_SetPriority (TIMER0_IRQn, 2);
  NVIC_SetPriority (TIMER1_IRQn, 2);
  NVIC_SetPriority (TIMER2_IRQn, 2);
  NVIC_SetPriority (SPI0_TWI0_IRQn, 3);
  NVIC_SetPriority (SPI1_TWI1_IRQn, 3);
  Serial.begin(9600);
  Serial.println("Start ");
  Serial.print("Priority of TWI0: ");
  Serial.println(NVIC_GetPriority (SPI0_TWI0_IRQn));
  Serial.println(NVIC_GetPriority (SPI1_TWI1_IRQn));
  Serial.print("Priority of Ticker: ");
  Serial.println(NVIC_GetPriority (TIMER0_IRQn));
  Serial.println(NVIC_GetPriority (TIMER1_IRQn));
  Serial.println(NVIC_GetPriority (TIMER2_IRQn));


  Wire.begin();
  __disable_irq();
  __enable_irq();
  ticker1s.attach(task_handle, 1);
  Wire.requestFrom(0x02,6);

}

void task_handle(void) {
  __enable_irq();
  Serial.println("Task handle ");
  Serial.println("-IRQ enable status: ");
  Serial.println(NVIC_GetEnableIRQ(SPI0_TWI0_IRQn));
  Serial.println(NVIC_GetEnableIRQ(SPI1_TWI1_IRQn));
  NVIC_EnableIRQ(SPI0_TWI0_IRQn);
  NRF_TWI0->INTENSET = 1;

  NVIC_EnableIRQ(SPI1_TWI1_IRQn);
  NRF_TWI1->INTENSET = 1;
  Serial.println("-IRQ enable status: ");
  Serial.println(NVIC_GetEnableIRQ (SPI0_TWI0_IRQn));
  Serial.println(NVIC_GetEnableIRQ (SPI1_TWI1_IRQn));
  delay(1000);
  Wire.requestFrom(0x02,6);

}

【问题讨论】:

  • 我还尝试使用 NVIC_GetPriority 和 NVIC_SetPriority 使所有 SPIx_TWIx_IRQn 中断高于和低于所有 TIMERx_IRQn 优先级的优先级。 NVIC_GetPriority 正在确认优先级已设置,但仍然没有乐趣

标签: arduino arm isr nrf51


【解决方案1】:

默认情况下,Cortex-M 上的 ISR 不会禁用中断,而是根据 NVIC 中设置的优先级抢占中断(因此 NVIC 的“嵌套”部分)。这意味着您应该像往常一样简单地启用 I2C 中断,然后使用NVIC_SetPriority(IRQn, priority) 设置优先级。

但是请注意,优先级编号是按倒序排列的,因此优先级 0 会抢占优先级 6。在这种情况下,您可以将定时器中断优先级设置为 1,而I2C中断为0。

【讨论】:

  • 谢谢,我假设是这样,我尝试将所有定时器优先级设置为 2,并将所有 SPIx_TWIx 中断设置为 1,然后在单独的测试中设置为 3。我检查了是否已设置使用 NVIC_GetEnableIRQ,他们似乎报告了正确的值,但是如果我在计时器 ISR 中使用它,我的 I2C 调用仍然会导致我的程序挂起
  • @Steve 我看到你已经包含了你的草图,但是我注意到 I2C 控制器的 ISR 丢失了,默认情况下我不认为 Arduino 内核使用中断来处理 I2C,所以当你启用中断它将跳转到默认处理程序,这是一个无限循环。这可能解释了这个问题。
  • 另外,我注意到您正在使用“Ticker”对象作为“计时器”,但请记住,它们通常使用每个 Cortex-M 上可用的 SysTick 计时器及其中断优先级来实现与 NRF52 上可用的普通“计时器”分开。
  • 感谢您的 cmets。我真的不明白挂起的原因。 I2C 调用在定时器 ISR 之外完美工作,但不在其中。请您建议我如何让 I2C 调用在这个(或另一个)基于计时器的 ISR 中工作?
  • 您是否尝试过简单地调用 I2C 函数,而不启用 I2C 中断?正如我所提到的,Arduino I2C 代码不使用中断。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-19
  • 2011-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多