替换Arduinos millis(),对于禁用的中断也是可靠的

时间:2013-09-26 07:59:44

标签: arduino interrupt clock

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

我有一个时间关键程序,它使用许多必须禁用中断的函数。所以我的程序运行1:30,而它认为它只在1点运行。

我可以用另一个计时器来避免这个问题吗?

当我使用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秒。

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

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

跟踪时间。例如,莱昂纳多定时器1是一个16位定时器。

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

TCCR1A = 0;  

这会使计时器进入&#34;正常&#34;模式,意味着它只运行到0xFFFF并回绕到0x0000。

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

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

检查时间:

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()。