Как использовать Timer1 (AT328Mega) для измерения времени между восходящими фронтами двух входных сигналов
Я хотел бы использовать Timer1 для измерения времени между восходящими фронтами двух входных сигналов. В частности, используйте Tn для запуска счетчика таймера и IPCn для фиксации времени, прошедшего с момента нарастающего фронта входного сигнала Tn. Цель состоит в том, чтобы измерить время между восходящими фронтами двух входных сигналов. Есть ли там библиотека Timer1, которая alread делает это? Предложения по коду приветствуются.
@w5cdt, 👍3
Обсуждение2 ответа
Это не идеально подходит для вашей более простой задачи, но вот ссылка на скетч, который я использовал для записи импульсов, используя захват ввода Timer1.
Короче говоря, настройте прерывание
void initTimer(void) {
// ICNC1: Включить Шумоподавитель захвата ввода
// ICES1: =1 для триггера на восходящей кромке
// CS10: =1 установка прескалера на 1x системных часов (F_CPU)
TCCR1A = 0;
TCCR1B = (0<<ICNC1) | (0<<ICES1) | (1<<CS10);
TCCR1C = 0;
//catchFallingEdge(); // инициализируйте, чтобы поймать
{ TCCR1B &= ~(1<<ICES1); TIFR1 |= (1<<ICF1); rising = 0; }
// Настройка прерывания
// ICIE1: Захват ввода
// TOIE1: Переполнение Timer1
TIFR1 = (1<<ICF1) | (1<<TOV1); // очистить очередь
TIMSK1 = (1<<ICIE1) | (1<<TOIE1); // и задействовать
// Настройте входной вывод захвата, ICP1, который соответствует PIN
pinMode(8, INPUT);
digitalWrite(8, 0); // оставьте плавающим, чтобы считать 60 Гц и т. Д.
//digitalWrite(8, 1); // или включите съемный пакет
Затем обслужите его
ISR(TIMER1_CAPT_vect) {
union twobyte {
uint32_t word;
uint8_t byte[2];
} timevalue;
timevalue.byte[0] = ICR1L; // захватить захваченное значение таймера
timevalue.byte[1] = ICR1H; // захватить захваченное значение таймера
// следите за другим краем, чтобы уловить ширину полуимпульса
//rising ? catchFallingEdge() : catchRisingEdge();
if (rising) {
TCCR1B &= ~(1<<ICES1);
TIFR1 |= (1<<ICF1);
rising = 0;
}
else {
TCCR1B |= (1<<ICES1);
TIFR1 |= (1<<ICF1);
rising = 1;
}
}
Для получения дополнительной помощи и информации, а также многих примеров различных подробных аспектов таймеров, ознакомьтесь со статьями Ника Гэммона здесь: http://www.gammon.com.au/interrupts и вот здесь: http://www.gammon.com.au/timers
По первой ссылке выполните поиск "Скетча ниже, умножающего интервалы между прерываниями ПОДЪЕМА", например, чтобы найти один сегмент кода.
Теперь важный вопрос: каково минимальное время, которое вам нужно измерить между событиями? Мы говорим о миллисекундах, микросекундах или наносекундах? В первом случае вы можете использовать опрос контактов, внешние прерывания или прерывания смены контактов, а также функции millis() или micros() Arduino для захвата временных меток. Для разрешения в микросекундах все зависит от обстоятельств. Даже функция micros() имеет разрешение только 4us, поэтому вам придется настроить таймер самостоятельно, если вы хотите получить метки времени с разрешением выше 4us, или вы можете использовать библиотеку timer2_counter (http://electricrcaircraftguy.blogspot.com/2014/02/Timer2Counter-more-precise-Arduino-micros-function.html) или ваше собственное решение по индивидуальному таймеру для временных меток с разрешением 0,5 мкс.
Для наносекундного разрешения (с временными шагами до 62,5 нс) вы можете. необходимо использовать захват ввода Timer1, как показано в другом ответе. Вы также можете выполнить поиск "Определение времени интервала с помощью блока захвата ввода" по 2-й ссылке выше, для другого сегмента кода в этом.
- Как использовать SPI на Arduino?
- Как решить проблему «avrdude: stk500_recv(): programmer is not responding»?
- Как создать несколько запущенных потоков?
- Как подключиться к Arduino с помощью WiFi?
- avrdude ser_open() can't set com-state
- Как узнать частоту дискретизации?
- Что такое Serial.begin(9600)?
- Я закирпичил свой Arduino Uno? Проблемы с загрузкой скетчей на плату
Какова минимальная ожидаемая длительность между двумя последовательными восходящими фронтами вашего сигнала?, @jfpoilpret
`// ICNC1: Enable Input Capture Noise Canceler // ICES1: =1 for trigger on rising edge // CS10: =1 set prescaler to 1x system clock (F_CPU) TCR1A = 0; TCR1B = (0<, @mypgp