ken789258 发表于 2012-9-19 14:42:04

求助大大 Timer正确用法

我用http://coopermaa2nd.blogspot.tw/2011/07/41-blink-with-timer.html 的Timer来打到我的自走车程式

但我用视波器用不出波形没办法在1mS内执行,所以想请教各位大大准确的Timer用法

lanxix 发表于 2012-9-19 14:45:54

那个网页打不开

ken789258 发表于 2012-9-19 14:53:02

我PO程式码
const int ledPin = 13;

void setup() {

  pinMode(ledPin, OUTPUT); // 把ledPin 设置成output pin


  TCCR1A = 0x00; // Normal mode, just as a Timer

  TCCR1B |= _BV(CS12); // prescaler = CPU clock/1024

  TCCR1B &= ~_BV(CS11);

  TCCR1B |= _BV(CS10);

 

  TCNT1 = 0;

}

 

void loop() {

  digitalWrite(ledPin, HIGH); // 打开LED 灯号

  delay1s(); // 延迟一秒钟

  digitalWrite(ledPin, LOW); // 关闭LED 灯号

  delay1s(); // 延迟一秒钟

}

 

void delay1s()

{

  while (TCNT1 <15625) // Ticks for 1 second @16 MHz,prescale=1024

    ; // do nothing

  TCNT1 = 0;

}

以Arduino UNO 或Duemilanove 为例,它们的时脉频率是16 MHz,如果把Ti​​mer1 的prescaler 设成CPU clock/1024,那么Timer1 的clock 便是:

Timer1 的时脉 = 16 MHz/1024 = 15625Hz

所以Timer1 从0 数到15625 就是一秒钟的时间。 Timer1 是16-bit 的,最大值可以到65535。

把 Prescaler 设成 CPU clock/1024 的方法是:


TCCR1B |= _BV(CS12); // prescaler = CPU clock/1024

TCCR1B &= ~_BV(CS11);

TCCR1B |= _BV(CS10);

ken789258 发表于 2012-9-19 17:11:16

lanxix 发表于 2012-9-19 14:45 static/image/common/back.gif
那个网页打不开

我已把程式放上

lanxix 发表于 2012-9-22 00:46:42

前几天正好研究了一下AVR的定时器,这段程使用的是16位定时器Timer1,其实注释里面已经说得挺好了,你应该找本AVR的书来看一下,我也是这样的,这样学系统点~~

lanxix 发表于 2012-9-22 01:13:12

static volatile unsigned long CurrentTime;
static volatile unsigned long Count=0;

void setup()
{
Serial.begin(9600);
CurrentTime=millis();

TCCR1A = 0;
TCCR1B = _BV(CS11);//8分频
TIFR1 |= _BV(OCF1A);
TCNT1=0;
OCR1A=2000;

TIMSK1 |= _BV(OCIE1A) ;
}

void loop()
{
if(millis()-CurrentTime>=1000)
{
    Serial.println(Count);
    Count=0;
    CurrentTime=millis();
}
}

static inline void handle_interrupts(volatile uint16_t *TCNTn, volatile uint16_t* OCRnA)
{
Count++;
*TCNTn=0;
}

SIGNAL (TIMER1_COMPA_vect)
{
handle_interrupts(&TCNT1, &OCR1A);
}



//我做的一个定时器测试,这个程序的功能就是统计每秒定时器的累加数,你可以看成频率发生器

TCNT1=0;这个是初始值
OCR1A=2000; 这个是对比值

我程序使用8分频,16位定时器,使用普通对比模式,也就是当 TCNT1=OCR1A时发生中断.我的程序每1ms发生一次中断,1ms就是OCR1A=2000.
这个2000怎么来的呢?有如下公式:
定时器初值=65536-(时钟频率/分频系数)*T
T是周期,我这里使用1ms,就是0.001s
上面的公式是定时器的初值,也就是TCNT1的值,那么OCR1A就设成65535了.
如果TCNT1=0,那么OCR1A就是(时钟频率/分频系数)*T
所以,16000000/8*0.001=2000

不知道你懂不懂,反正我也是学了几天定时器而已,以上的公式是看书上的,现在暂时明白了

lanxix 发表于 2012-9-22 01:15:01

忘了说了,上面的程序频率达不到1000,我的1280板只能达到996与997互跳

ken789258 发表于 2012-9-26 16:48:24

lanxix 发表于 2012-9-22 01:13 static/image/common/back.gif
static volatile unsigned long CurrentTime;
static volatile unsigned long Count=0;



可以说明一下程式内容吗?我是初学者有点看不懂
还是有其他的方法吗?
页: [1]
查看完整版本: 求助大大 Timer正确用法