极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 16904|回复: 8

求助大大 Timer正确用法

[复制链接]
发表于 2012-9-19 14:42:04 | 显示全部楼层 |阅读模式
我用http://coopermaa2nd.blogspot.tw/2011/07/41-blink-with-timer.html 的Timer来打到我的自走车程式

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

使用道具 举报

发表于 2012-9-19 14:45:54 | 显示全部楼层
那个网页打不开
回复 支持 反对

使用道具 举报

 楼主| 发表于 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()

{

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

&#160;&#160;&#160;&#160;; // do nothing

&#160;&#160;TCNT1 = 0;

}

以Arduino UNO 或Duemilanove 为例,它们的时脉频率是16 MHz,如果把Ti&#8203;&#8203;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);
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-9-19 17:11:16 | 显示全部楼层
lanxix 发表于 2012-9-19 14:45
那个网页打不开

我已把程式放上
回复 支持 反对

使用道具 举报

发表于 2012-9-22 00:46:42 | 显示全部楼层
前几天正好研究了一下AVR的定时器,这段程使用的是16位定时器Timer1,其实注释里面已经说得挺好了,你应该找本AVR的书来看一下,我也是这样的,这样学系统点~~
回复 支持 反对

使用道具 举报

发表于 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

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

回复 支持 反对

使用道具 举报

发表于 2012-9-22 01:15:01 | 显示全部楼层
忘了说了,上面的程序频率达不到1000,我的1280板只能达到996与997互跳
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-9-26 16:48:24 | 显示全部楼层
lanxix 发表于 2012-9-22 01:13
static volatile unsigned long CurrentTime;
static volatile unsigned long Count=0;

可以说明一下程式内容吗?我是初学者有点看不懂
还是有其他的方法吗?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-5-3 16:19 , Processed in 0.048173 second(s), 18 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表