Как обычно импульсы поступают с частотой 50 Гц, длиной от ну скажем 1000 мкс до 2000 мкс.
Делал эту задачу на АТмега32-16 Мгц на внешних прерываниях - все работает как часы, проблем нет. Точность измерения очень высокая (256 положений отрабатывает без проблем)
Возникла необходимость перенести все на АТмегу168 (там можно делать внешнее прерывание сразу по всему порту)
И тут возникли проблемы с недостаточностью быстродействия. Кварц тоже 16 Мгц, делитель 1(плюс еще во фьюзах отключил).
CVAVR Программа примерно такая:
- Код: Выделить всё • Развернуть
void main(void)
{
// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
PORTD=0xFF; DDRD=0x00; // In/P
// Timer/Counter 1 initialization
// Clock value: 2000,000 kHz
TCCR1A=0x00; TCCR1B=0x02;
TCNT1H=0x00; TCNT1L=0x00;
ICR1H=0x00; ICR1L=0x00;
OCR1AH=0x00; OCR1AL=0x00;
OCR1BH=0x00; OCR1BL=0x00;
// External Interrupt(s) initialization
// Interrupt on any change on pins PCINT16-23: On
EICRA=0x00; EIMSK=0x00;
PCICR=0x04; PCMSK2=0xFF; PCIFR=0x04;
TIMSK0=0x00; TIMSK1=0x00; TIMSK2=0x00;
#asm("sei")
while (1) continue;
}
interrupt [PC_INT2] void pin_change_isr2(void)
{
unsigned int t;
t = (((unsigned int)TCNT1H)<<8) + (unsigned int)TCNT1L;
if(PIND & 0b00100000)
{
channel_3_start = t; // Старт импульса на канале 3
return;
}
if(PIND & 0b00010000)
{
channel_3_end = t; // Старт импульса на канале 4 и одновременно Стоп импульса на канале 3
return;
}
}
Проблема в том, что точность при таком измерении упала ниже плинтуса. Показания скачут в пределах 100/256, Т.е. можно более менее отследить короткий импульс 1000-1500 мкс, средний 1250-1750 и длинный 1500-2000. Т.е. вместо 256 градаций получается 3-5.
Есть большое подозрение, что хоть кварц выставлен на 16Мгц, Проц тактируется от 2Мгц или того меньше, хотя все вроде выставил как надо. Фьюзы сейчас у меня ВСЕ в 1 выставлены.
Длительность определяется как (channel_3_end - channel_3_start)/2 = длительность в мкс
В чем может быть проблема?