-1

stackoverflow-17135805中所述,如果中断被禁用,millis() 函数不会返回正确的时间,而 Arduino 必须检测 timer0 的溢出。

我有一个时间紧迫的程序,它使用了很多必须禁用中断的功能。所以我的程序运行 1:30,而它认为它只运行了 1:00。

是否有另一个计时器可以用来避免这个问题?

当我使用 GSM 模块时,它发生在我身上:

  // startpoint
  unsigned long t = 0;   
  unsigned long start = millis();

  while ( (millis()-start) < 30000 ){
    //read a chunk from the gprs module
    for (int i=0;i<8;i++)
      client.read();

    //do this loop every 10ms
    while( (millis()-start) < t*10 ){};
    t++;
  }
  //endpoint

从起点到终点应该需要 30 秒。相反,它需要 65 秒。

4

2 回答 2

2

您可以使用其他硬件计时器之一

跟踪时间。例如,在 Leonardo Timer 1 上是一个 16 位定时器。

要直接设置它(这消除了代码的可移植性),有几个步骤。

TCCR1A = 0;  

这会将计时器置于“正常”模式,这意味着它只运行到 0xFFFF 并返回到 0x0000。

TCCR3B = 0;
TCCR3B = _BV(CS11) | _BV(CS10);

这将启动计时器并将其设置为使用时钟/64 预分频器,这相当于每 4us 1 次。

检查时间:

long time;        // declared somewhere in scope. 

time = TCNT1;     // this reads the timer count register
time *= 4;        // this multiplies time by 4 to give you us. 

如前所述,TCNT1 在 0xFFFF = 65536 处回绕。因此,使用如上设置的预分频器,在您的程序需要将数据放入更大的变量之前,您可以进行大约 65536 * 4E-6 = .262 秒的计数(假设你关心)。希望每秒进行 4 次以上的轮询不是问题,这可以让您远离中断。

几个 arduino 核心功能使用这些计时器,因此您需要验证您需要的核心功能不依赖于您选择的计时器。例如,执行上述操作会破坏某些引脚上的 analogWrite()。

于 2015-03-28T00:25:01.143 回答
2

如果您必须如此频繁且如此长时间地禁用中断,那么最好的选择是使用外部计时器。我强烈推荐 DS3231。由于它具有内置晶体,因此比 1307 更容易设置,并且也更加准确。

于 2013-09-28T20:52:54.000 回答