TCNT0'ı güncellemeye çalışmak yerine, ADC dönüşümlerinde kaybedilen döngülerin sayısını izlemek ve bir ara rutinde - örneğin, omillis ()
- bu döngüleri telafi etmek daha iyi olabilir. [Düzenleme: Aşağıda daha iyi bir alternatif görün]
Daha ayrıntılı olarak:
• Her dönüşümde yaklaşık 128 · 13 döngü (veya belki de 128 · 13.5, ortalama ön ölçekleyici gecikmesini hesaba katmak için) bir döngü sayacına:
uzun kayıp çevrimler; ...; lostcycles + = ADCcycles;
• Her omillis ()
çağrısında, return millis () + lostcycles / 16000
p deyin >
• Veya bir bölümde zaman kaybetmemek için return millis () + lostcycles>>14
deyin. Bu, düzeltmede% 2 oranında düşecektir, ancak düzeltmenin küçük olduğunu varsayıyorum, örneğin toplam sürenin% 5'i, bölme yerine bir kaydırma kullanılması nedeniyle yaklaşık% 0.1 hataya yol açıyor.
Re: “ADC dönüşümü TCNT0> 230 ile her başlatıldığında taşma olayını (Arduino'nun dahili olarak zaman izleme için kullandığı olay) kaçırırdım”
Bu yanlış [önerilen kullanıyorsanız yaklaşmak]. Zamanlayıcı 0 taşması yüz mikrosaniye gecikmeli olarak ele alınsa bile, sorunsuz olarak ele alınacaktır. [Edgar Bonet'in yorumunda belirtildiği gibi, orijinal yaklaşımda olduğu gibi aritmetik taşmayı kontrol etmeden TCNT0'a eklenen bir yöntem, bir zamanlayıcı işaretini kaçırabilir.]
SLEEP_MODE_ADC Arduino'daki ADC dönüşümünün "Okuma sırasında uyku" bölümünde bulunan / code>, bir ADC dönüşümü sırasında bir zamanlayıcı veya başka bir kesintinin meydana geldiği durumu kontrol etmesini önerir. SLEEP_MODE_ADC
clk I / O , clk CPU ve clk FLASH 'ı durdururken, Timer 2, WDT, ve diğer bazı olası kesinti kaynakları etkin.
Daha iyi bir alternatif:
Gerben'in işaret ettiği gibi, ara bir rutin kullanmak yerine millis ()
tarafından tutulan count değişkenini güncellemek biraz daha temizdir. Arka plan için önceki bir soruya verdiği cevaba bakın. İşte fikrin mevcut duruma uyarlanması [denenmemiş]:
unsigned int lostcycles = 0; ...; void accountForADC () {enum {ADCcycles = 13 * 128 + 64; ms_cycles = 16000}; // harici uçucu işaretsiz uzun timer0_millis'i uygun şekilde ayarlayın; kayıp çevrimler + = ADCcycles; while (lostcycles > = ms_cycles) {// Bu döngü genellikle yalnızca bir geçiş çalıştırır byte statusReg = SREG; // kesinti durumunu kaydet cli (); // kesintileri kapat ++ timer0_millis; // Atomiklik için kesintilerin kapatılması gerekiyor SREG = statusReg; // Eski durum kayıp döngülerini geri yükleyin - = ms_cycles; }}
Başladıktan sonra, onuncu accountForADC ()
çağrısında bu kod bir milisaniyeyi hesaba katmak için timer0_millis
'e 1 ekler ADC dönüşümlerinde kaybetti. lostcycles - = ms_cycles
, lostcycles
'ı 1280 olarak ayarlar. Başka 9 aramadan sonra tekrar timer0_millis
' e 1 ekler ve kayıp döngüleri
; ve benzeri.