DMC.20 · Приём управления · ATmega328P
Задача
Измерять длительность импульса приёмника (1000–2000 мкс) по фронтам входного захвата.
Алгоритм
ICP1 (PB0): по нарастающему фронту фиксируем время, по спадающему — считаем разницу = ширина импульса.
Исходный код (C, avr-gcc)
#ifndef F_CPU
#define F_CPU 16000000UL
#endif
#include <avr/io.h>
#include <avr/interrupt.h>
volatile uint16_t width_us=1500;
volatile uint16_t rise=0;
ISR(TIMER1_CAPT_vect){
uint16_t t=ICR1;
if(TCCR1B & (1<<ICES1)){ rise=t; TCCR1B&=~(1<<ICES1); } // был фронт вверх -> ждём спад
else { width_us=(uint16_t)((t-rise)/2); TCCR1B|=(1<<ICES1); }
}
int main(void){
DDRB&=~(1<<PB0); // ICP1 вход
TCCR1B=(1<<ICES1)|(1<<CS11); // захват по фронту вверх, /8
TIMSK1=(1<<ICIE1);
sei();
DDRB|=(1<<PB5);
for(;;){ if(width_us>1500) PORTB|=(1<<PB5); else PORTB&=~(1<<PB5); }
}
Сборка: avr-gcc -mmcu=atmega328p -DF_CPU=16000000UL -Os файл.c -o файл.elf
Пояснения
Тик 0.5мкс при /8. Значение делим на 2 для перевода в мкс. Переключаем фронт захвата после каждого события.