2017-02-17 112 views
5

Donanım zamanlayıcılarından birine bir ofset eklemesi gereken bir mikroişlemci kesmesi yazıyorum. Bununla birlikte, zamanlayıcı ön ayarlayıcının çalışma biçimi nedeniyle, naif yaklaşım, zamanlayıcı yürütme zamanına göre zamanlayıcı yürütme zamanlamasına bağlı olarak birebir hata verebilir.Önceden tanımlı bir donanım zamanlayıcısına bir offset eklerken bu tek tek hatadan nasıl kurtulabilirim?

timing diagram of ISR off-by-one error

Bunun için bir ATmega328P (= Arduino) zamanlayıcıyı 1 kullanıyorum. Normal modda bir/8 prescaler ile kurdum ve bunu tetiklemek için zamanlayıcı yakalama interruptını kullanıyorum; kesme işleminin amacı, giriş yakalamayı tetikleyen olaydan sonra tam olarak period döngüsünü taşması için zamanlayıcıyı ayarlamaktır (başka bir kesme veya tetiklemenin devre dışı bırakıldığı başka bir durumda tetikleyici oluşması durumunda).

(PWM çıkışını, değişken bir AC faz ofsetinde iki şebeke optotriacını tetiklemek için, tüm CPU zamanını yakmak zorunda kalmadan kötüye kullanıyorum; kesinti, şebeke fazında sıfır geçiş detektörü tarafından tetiklenir.)

uint_16 period = 16667; 

ISR(TIMER1_CAPT_vect){ 
    TCNT1 = TCNT1 - ICR1 - period + (elapsed counter ticks during execution); 
} 

burada kritik aralık TCNT1 okunduğu zaman ve daha sonra tekrar yazıldığında arasındaki biridir: ISR için

kod böyle bir şey olurdu.

olarak bildiğim kadarıyla, doğrudan ön ölçekleme durumunu okumak için bir yolu yoktur, bu yüzden sadece uygulamak mümkün olduğunu sanmıyorum, farklı bir ISR zamanlama dayalı ofset.

ISR (GTCCR |= _BV(TSM); GTCCR |= _BV(PSRSYNC); GTCCR &= ~_BV(TSM);) eşitlenmeden önce önekleyiciyi sıfırlayabilirim, ancak yine de ISR zamanlamasına bağlı olarak zamanlayıcıya rastgele bir uzaklık tanıtır.

ben düşünüyorum bir diğer yaklaşım, ön ölçekleme ile senkronize bir kesme oluşturmak için bir zamanlayıcı kullanmaktır. Zaten çıkış 1'i her iki çıkış karşılaştırması kullanıyorum, ancak zamanlayıcı 0, önekleyiciyi paylaşabileceği şekilde paylaşıyor. Ancak, zamanlayıcı kesme yürütmesi başka bir kesme veya 'cli' bloğu tarafından ertelenebilir, bu nedenle bu çalışma garantisi yoktur.

Bu hatayı önlemek için kesilmemi nasıl yazabilirim?

+1

"TCNT1" hesaplamasının bir _always_ off (bir zamanlama 2?), Sadece _sometimes_ (zamanlama 1) olmadığını varsayalım? – chux

+0

@chux evet, 'TCNT1' yalnızca bir bazen kapalıdır. Bunu kelimelerle nasıl açıklayacağımı gerçekten bilmiyorum ama içerdiğim zamanlama şeması bunun nasıl olduğunu gösteriyor. – AJMansfield

+0

ISR rutin bir "clk_Tn" nabzını örneklemek ve kesin olarak algılamak için yeterince hızlı mı? Clk_Tn, ISR tarafından silinebilen bir bayrak ayarlayabilir mi? – chux

cevap

1

Eğer TCNT1 yazma böylece aynı ön ölçekleme 'faz' de, tam 24 döngüleri kayıt okunduğunu sonra gerçekleşmesi gerektiğini

ISR(TIMER1_CAPT_vect){ 
    int counter = TCNT1 - ICR1 - period + 3; 
    asm("nop"); 
    asm("nop"); 
    TCNT1 = counter; 
} 

olarak ISR yazarsanız. (Gerekirse nopların sayısı, örneğin, farklı mikrodenetleyici tipleri arasındaki varyasyonlar nedeniyle) ayarlanabilir. Ancak, çözüm, ICR1 ayarı ile TCNT1'un okunması arasında yer alan prescaler 'fazının' değişimini hesaba katmamaktadır.

İlgili konular