ndfweb.cn

arduinoTimer1定時中斷


2019-11-22 18:46:01 (11793)



arduino定時器包含定時器/計數器0,定時器/計數器1,定時器/計數器2三個。定時器/計數器0和定時器/計數器2是一個8位的計數器,定時器/計數器1是一個16位長的計數器。timer1最大值為65535,在使用之前我們需要進行一些設置,從而使得timer1可以運行起來。進行這些設置,我們需要用內置的寄存器來存儲這些設置。每一個定時器都有很多寄存器,本篇文章主要側重timer1 的介紹和使用。存儲這些初始值的寄存器的兩個寄存器TCCRXA,TCCRXB(其中X代表序號定時器的編號0,1,2).其中TCCR是英文Timer/Counter Control Register簡寫,下麵是TCCR1A和TCCR1B的具體情況。每個寄存器共8位,每位都存儲了一些值來進行定時器的設置。表引用自:http://www.atmel.com/dyn/product ... 60&part_id=4198

開始使用timer1的話,CS12, CS11和CS10的設置是很重要的。這三個值得設置可以讓定時器工作在不同的頻率。不同的設置的頻率如下表所示:


默認的,這些值都是為0的,我們用一個例子來說明問題。下邊這個例子是設置定時器1溢出中斷,在溢出的時候我們讓2號引腳連接的LED燈亮滅轉換。首先我們來進行初始化timer1。
//包含avr-lib庫
#include <avr/io.h>
#include <avr/interrupt.h>

#define LEDPIN 2

void setup()
{
    pinMode(LEDPIN, OUTPUT);

    // 初始化timer1
    cli();             //禁止全局中斷
    TCCR1A = 0;        //設置TCCR1A全為0
    TCCR1B = 0;

    // 設置允許timer溢出中斷
    TIMSK1 = (1 << TOIE1);
    //設置CS10位為1從而使定時器以時鍾的速度運行。
    TCCR1B |= (1 << CS10);
    /允許全局中斷
    sei();
}

在上邊這段代碼中TIMSK1代表的是Timer/Counter1 Interrupt Mask Register.這個寄存器控製著timer允許怎樣的中斷。其中TOIE1表示的溢出中斷。其他的後邊會繼續介紹。
由於我們上班設置了CS10,定時器1就會開始工作。當定時器1溢出時就會執行中斷服務程序中斷服務程序如下:
ISR(TIMER1_OVF_vect)
{
    digitalWrite(LEDPIN, !digitalRead(LEDPIN));
}
這樣,我們就可以讓loop不做任何事情了,加入我們要停止中斷隻用設置TCCR1B為0就可以了。
上班每次的中斷時間大概為((1/16)*e-6)*65535=0.0041us,時間比較短,假若我們想要更長的時間,我們可以設置CS11,CS12,組合來進行設置。這樣我們的時間就可以變化了。
比如下邊的例子:
void setup()
{
    pinMode(LEDPIN, OUTPUT);

    // 初始化timer1
    cli();             //禁止全局中斷
    TCCR1A = 0;        //設置TCCR1A全為0
    TCCR1B = 0;

    // 設置允許timer溢出中斷
    TIMSK1 = (1 << TOIE1);
    //設置CS10位為1從而使定時器以時鍾的速度運行。
      TCCR1B |= (1 << CS10);
      TCCR1B |= (1 << CS12);



    sei();
}
[size=1em]這樣我們的時間就(1/16000000)*1024*65536=4.1s,





再者,加入我們想要確定的時間而不是定時器溢出來做中斷,怎麼做呢,
在定時器中斷有另外一個模式叫做CTC(Clear Timer on Compare Match),在這個模式下,timer1不在是溢出中斷了,而是在寄存器中設定好的值進行比較,若大於則進入中斷,這種模式的設置例子如下:
void setup()
{
    pinMode(LEDPIN, OUTPUT);

    // 初始化timer1
    cli();          // 進製全局中斷
    TCCR1A = 0;     //設置TCCR1A全為0
    TCCR1B = 0;     // [size=1em]設置TCCR1B全為0


    //設置比較的值得大小
    OCR1A = 15624;
    // 開啟CTC模式
    TCCR1B |= (1 << WGM12);
    // 設置 CS10和CS12位
    TCCR1B |= (1 << CS10);
    TCCR1B |= (1 << CS12);
    // 允許比較中斷
    TIMSK1 |= (1 << OCIE1A);
    sei();          // 允許全局中斷
}
ISR(TIMER1_COMPA_vect)
{
    digitalWrite(LEDPIN, !digitalRead(LEDPIN));
}


在這裏:
目標時間=時間周期*(時鍾次數+1)
時鍾次數+1=目標時間/時鍾周期,
比如說我們要獲取一秒的時間,則定時器1 的數值改變次數為1000/((1/16000000)*1024)
如果想要獲取更長的時間;比如說10秒,又要防止溢出,可以這樣寫
ISR(TIMER1_COMPA_vect)
{
    seconds++;
    if (seconds == 10)
    {
        seconds = 0;
        readMySensor();
    }
}
本文版权:http://www.ndfweb.cn/news-737.html
  NDF俱乐部
  国际域名注册
  建站咨询
简体中文 NDF网站建设淘宝店 | ICO图标在线生成 | 外贸网站建设 | 联系我们
©2007-2024 NDF Corporation 鲁ICP备08005967号 Sitemap - RSSRSS订阅