Estoy tratando de lograr una resolución de 32 bits usando el temporizador de 16 bits en STM32F103. Encontré que ST proporciona una nota de aplicación AN2592 , sin embargo, tengo dos preocupaciones al respecto:
1) No entiendo por qué están multiplicando MSB por 65535 (ver 3.1). ¿No debería ser 65536 en su lugar (suponiendo que uso un período de 65535)?
2) En 3.2, dicen que primero debe procesar la interrupción de la actualización (para actualizar MSB), para tener en cuenta la posible carrera entre la actualización y la captura. Creo que esto no es correcto.
En mi opinión, son posibles dos carreras: captura después del desbordamiento y desbordamiento después de la captura. Pueden suceder por varias razones, la más simple es que las interrupciones están deshabilitadas y ambas marcas se activan antes de que el controlador comience a ejecutarse. O el controlador comienza a manejar uno de ellos y antes de que el código procese el evento, ocurre otro evento.
Dependiendo de la carrera que se haya realizado, debe actualizar el evento de captura de procesamiento MSB antes o después . Entonces, la forma en que creo que debería hacerse es verificar primero el valor capturado. Si es "bastante bajo" (menos de, digamos, 10, 100, 1000, realmente no importa, ya que será muy bajo o muy alto para que ocurra la carrera) y el desbordamiento está pendiente, entonces ocurrió el evento de desbordamiento antes de la captura. De lo contrario, se produjo un desbordamiento después de la captura.
Este es mi controlador de interrupciones:
if (tim->SR & TIM_FLAG_CC1) {
tim->SR = ~TIM_FLAG_CC1;
uint32_t lsb = TIM2->CCR1;
// Captured value is very low and overflow is pending -- need to account for "msb" increment, as it happened
// before the capture event. Otherwise, we don't care -- if overflow interrupt is pending, we will handle
// it on the next handler invocation.
if (lsb < 1000 && (tim->SR & TIM_FLAG_UPDATE)) {
tim->SR = ~TIM_FLAG_UPDATE;
// Capture happened just after the overflow: need to increment upper "msb"
msb++;
}
msb_captured = msb;
lsb_captured = lsb;
msb = 0;
} else if (tim->SR & TIM_FLAG_UPDATE) {
tim->SR = ~TIM_FLAG_UPDATE;
msb++;
}
No lo he probado todavía (tengo que descubrir la mejor manera de probar el manejo de la carrera ...).
¿Parece plausible?