Estoy usando una interrupción externa para medir la frecuencia de una señal, el reloj AVR está en 8MHz. Básicamente, estoy contando los tics entre las alternaciones de pin con un temporizador de 16 bits (con algo de manejo para los desbordamientos de señales lentas).
El código de esqueleto es el siguiente:
int main(void){
clearbit(DDRD,PD2);
PCMSK3 = 0x00;
setbit(PCMSK3, PCINT26);
setbit(PCICR,PCIE3);
setbit(TIMSK1,TOIE1);
setbit(TCCR1B, CS10);
while(1){
}
return 0;
}
ISR(PCINT3_vect){
togglebit(PORTD, PD1);
countl = TCNT1L;
counth = TCNT1H;
soverflow = overflow;
overflow = 0;
TCNT1 = 0x0000;
return;
}
/* Overflow timer */
ISR(TIMER1_OVF_vect){
overflow++;
return;
}
Esto funciona prácticamente como se desea, sin embargo, no puedo medir nada más corto que alrededor de 49 ciclos. Las dos imágenes de alcance muestran el problema. La traza amarilla es del oscilador externo, la traza azul es la palanca de pin dentro del controlador de interrupción. No hay nada en el bucle principal, y tener cosas allí no cambia los resultados significativamente. Todas las variables son uint8_t
. La lectura de la cuenta en bytes altos y bajos ganó un poco de velocidad (en comparación con una sola lectura / escritura de 16 bits).
Lo mejor que he podido hacer es ~ 95kHz, pero tengo curiosidad por saber hacia dónde van los ciclos perdidos. Las asignaciones no pueden durar más de unos pocos ciclos y, si entiendo bien, ISR básicamente llama a cli () en la entrada y sei () en la salida, por lo que lo único que sucede es que el temporizador se reinicia, la función regresa y nosotros espera el siguiente cambio.
EDIT
void get_count(void){
uint8_t i=0, oldpin, newpin;
setbit(TIMSK1,TOIE1);
setbit(TCCR1B, CS10);
sei();
while(getbit(PIND, PD2) != 0){
continue;
}
while(getbit(PIND, PD2) != 1){
continue;
}
TCNT1 = 0;
while(getbit(PIND, PD2) == 1){
continue;
}
countl = TCNT1L;
counth = TCNT1H;
TCNT1 = 0;
soverflow = overflow;
overflow = 0;
clearbit(TIMSK1,TOIE1);
clearbit(TCCR1B, CS10);
cli();
return;
}
Esto me lleva a alrededor de 400kHz antes de que las cosas empiecen a ponerse dudosas. No estoy seguro de que haya mucho más que pueda hacer para reducirlo. Espero a que el pin pase a 1, comienzo el temporizador y el tiempo que tarda en llegar a cero, es decir, en medio ciclo de reloj.