Документація micros () зазначає, що повернене значення завжди буде кратним 4.
Чи є спосіб отримати клацання мікросекунди з більшою роздільною здатністю, бажано до рівня 1 мікросекунда?
Зниження до рівня AVR є прийнятним.
Документація micros () зазначає, що повернене значення завжди буде кратним 4.
Чи є спосіб отримати клацання мікросекунди з більшою роздільною здатністю, бажано до рівня 1 мікросекунда?
Зниження до рівня AVR є прийнятним.
Відповіді:
Так, залежно від основної тактової частоти вашого Arduino. Наприклад, ось вхідні частоти лічильника таймера та періоди після попереднього масштабування, для лічильника таймера ATMega2560 2 та основної тактової частоти 16 МГц. Таймер має вбудовані параметри значення "докаскалер", які визначають частоту / період, показані в цій таблиці:
TCCR2B bits 2-0 Prescaler Freq [KHz], Period [usec] after prescale
0x0 (TC stopped) -- --
0x1 1 16000. 0.0625
0x2 8 2000. 0.500
0x3 32 500. 2.000
0x4 64 250. 4.000
0x5 128 125. 8.000
0x6 256 62.5 16.000
0x7 1024 15.625 64.000
Для кращої роздільної здатності часу ви використовуєте значення під назвою TCNT2. Існує вбудований лічильник, який йде від 0 до 255, оскільки таймер - 8 біт. Коли лічильник досягає значення, призначеного TCNT2, він запускає переривання. Ця переривання називається TIMER2_OVF_vect.
з огляду на цю інформацію, результуюча швидкість переривання буде: 16 МГц / (prescaler * (255 - TCNT2))
Ви можете змусити таймер працювати на повному 16 МГц (62,5nSec), хоча це швидше, ніж вам потрібно; 2 МГц з початковим числом (255-2) дасть вам швидкість переривання 1 МГц. Розділіть це на 2 у вашому ISR:
extern uint32_t MicroSecClock = 0;
ISR(TIMER2_OVF_vect) {// this is a built in function that gets called when the timer gets to the overflow counter number
static uint_8 count; // interrupt counter
if( (++count & 0x01) == 0 ) // bump the interrupt counter
++MicroSecClock; // & count uSec every other time.
digitalWrite(53,toggle);// pin 53 is arbitrary
TCNT2 = 253; // this tells the timer when to trigger the interrupt. when the counter gets to 253 out of 255(because the timer is 8 bit) the timmer will trigger an interrupt
TIFR2 = 0x00; // clear timer overflow flag
};
Лист даних для вашого MCU є основним ресурсом; Ця стаття дасть вам (і дала мені!) хороший початок.
Позначте, я вирішив написати новий набір функцій, заснований на Arduino Atmega328 Timer2, і використовуючи переповнення переповнення, щоб отримати точність до 0,5us. Мій код доступний для завантаження та використання тут:
Ось короткий опис: "Я написав" бібліотеку ", щоб отримати 0,5-точну точку функції заміни на" micros () ", щоб я міг отримати повторювані результати, читаючи сигнал PWM або PPM, в межах 1ус. Я шукав все навколо Інтернет і не міг знайти щось порівнюване (або це було просто у використанні, і підтримував здатність Arduino писати ШІМ-сигнали через Servo Libary), тому я думаю, що це мій перший великий внесок у світ Arduino і Radio Control ".
Якщо зниження до рівня AVR прийнятне (як ви згадували у своєму запитанні), ви можете встановити таймер і навіть отримати кліщі годинника AVR.
Потрібно звернутися до таблиці даних AVR, оскільки він відрізняється в різних ATMegas та ATTinys. Але процедура завжди однакова. Що вам потрібно зробити:
TCCR
Таким чином можна отримати точні галочки з реєстру таймерів, однак перерахунки потрібно рахувати вручну. Це максимально точно за технологією.
Ось кілька прикладів коду для застарілого AT90S2313, але він дає хороші підказки, що робити в основному:
/* uC: AT90S2313 */
#include <avr/io.h>
#include <avr/interrupt.h>
int main(void)
{
// set up timer 0
TCCR0 = (1<<CS01); // Prescaler 8
// enable overflow interrupt
TIMSK |= (1<<TOIE0);
// activate interrupts
sei();
while(1)
{
/* Do whatever you like */
}
}
ISR (TIMER0_OVF_vect)
{
/*
This gets called everytime there in an overflow in the timer register
*/
}
TIMSK
і TOIE0
т. Д. (Скопіюйте налаштування таймера з листа даних atmega328p). Схоже, ви не можете використовувати макрос ISR (), а замість цього використовувати arduino.cc/en/Reference/AttachInterrupt .