Tengo algunas preguntas sobre temporizadores de software e interrupciones en un microcontrolador. Solo para información, uso un microcontrolador dsPIC33E.
El objetivo final es implementar un protocolo de comunicación serie: RS485 con Modbus. Logré transmitir y recibir un mensaje, y ahora tengo que hacer una parte de procesamiento de mensajes.
Dado que necesito un montón de temporizadores para todo tipo de tareas diferentes (por ejemplo, se necesita un retraso de 3,5 caracteres para la comunicación en serie, se necesita algo de retraso para eliminar el rebote de los botones, etc.), planeo implementar temporizadores en un software usando un solo temporizador de hardware. Por ejemplo, el período del temporizador de hardware se establece en 100 us, y se genera una interrupción en cada "desbordamiento", es decir, cada 100 us. En el ISR, solo actualizo los contadores globales, que son básicamente temporizadores de software con una resolución de 100 us, mientras que el temporizador de hardware ISR tiene la prioridad más alta. ¿Es esta una buena manera de hacer esto, o hay alguna mejor manera?
Cada contador (es decir, un temporizador de software) ha definido su propio período, y una vez que el contador alcanza su "valor de período", quiero llamar a alguna función. Ahora bien, no es una muy buena idea llamar a esta función desde el interior del temporizador de hardware ISR, porque esa función se procesará con la máxima prioridad ya que la rutina de llamada es el temporizador de hardware ISR. Lo que quiero es definir alguna función, digamos:
void Modbus_Protocol(void);
y poder definirlo como una interrupción, que no será de máxima prioridad. Solo el temporizador de hardware principal tiene la máxima prioridad en este concepto. De esa manera, una vez que el contador en el temporizador de hardware ISR alcanza su valor de período, no llamará a su función, sino que simplemente establecerá un indicador para activar una interrupción (por ejemplo, void Modbus_Protocol (void)), que será se activa después de que regresa el ISR principal, dependiendo de su prioridad. ¿Se puede hacer algo así, es decir, puedo definir interrupciones de software?
Sé que existe la posibilidad de usar interrupciones de hardware que no se usan, y simplemente establecer un indicador de interrupción desde el software. Pero no creo que esta sea una forma elegante de implementar interrupciones si las interrupciones de software definidas por el usuario son posibles.
No necesita "interrupciones de software" especiales. Eche un vistazo al siguiente código. Descuidé algunas cosas técnicas como la declaración de variables para mayor claridad.
Use su ISR solo para contar un temporizador (tick). En el main() está esperando para sincronizar con este temporizador. Use un temporizador dedicado para cada tarea que tenga que procesar. Todos estos temporizadores se incrementan cada tic de ISR.
Si el temporizador de la tarea expira, se procesa la tarea dedicada. Hay algunas características especiales en este tipo de implementación. Cuando resta el tiempo EXPITADO de su temporizador en lugar de establecerlo en 0, su software es más robusto si alguna de las tareas lleva más de 100 µs. Es una especie de criterio suave en tiempo real.
Obtienes un pseudo sistema multitarea.
isr() //100µs
{
tick++;
}
main()
{
while(true)
{
while(tick == last_tick);
last_tick = tick;
modbus_timer++;
task1_timer++;
task2_timer++;
if(modbus_timer >= MODEBUS_TIMER_EXPIRED)
{
modbus_timer -= MODEBUS_TIMER_EXPIRED;
Modbus_Protocol();
}
if(task1_timer >= TASK1_TIMER_EXPIRED)
{
task1_timer -= TASK1_TIMER_EXPIRED;
Task1();
}
if(task2_timer >= TASK2_TIMER_EXPIRED)
{
task2_timer -= TASK2_TIMER_EXPIRED;
Task2();
}
}//forever-loop
}// main()
Después de buscar en Google y debatir, me di cuenta de que intentaba lograr tareas priorizadas, que es básicamente un RTOS (sistema operativo en tiempo real). Aunque un RTOS se puede implementar en un microcontrolador, requiere una gran cantidad de recursos (RAM, etc.).
La otra opción es usar un programador como explicó Batuu. De esa manera, las tareas no se pueden priorizar (no hay multitarea) y todas las tareas deben terminar en un solo tic.
Nick B.
Marko Gulin
viejo contador de tiempo
viejo contador de tiempo
Marko Gulin