PIC MCU: ¿retraso de software o hardware?

Al experimentar con LED parpadeantes, aprendí a crear retrasos con un bucle de software o un tiempo de espera de un temporizador. Sé que para un programa de LED parpadeante simple, donde los procesos no son tan complicados y el tiempo no es crucial, usar cualquiera de los dos no importaría. Pero en más de un contexto multitarea crucial en el tiempo, ¿cuáles son los beneficios y/o desventajas de ambos?

Muchas gracias, así es como los configuré:

Retraso del programa:

void softwaredelay()
{
    int i;
    for(i=0; i<1000; i++)
    {/*Timer Stuff*/}
}

Retardo de hardware (específico para PIC16 mcu):

void timerdelay()
{
    OPTION_REGbits.PSA = 0;
    OPTION_REGbits.PS.  = 0b111;
    OPTION_REGbits.T0CS =  0;

    INTCONbits.T0IF = 0;
    TMR0 = 0b11111000;
    INTCONbits.T0IE = 1;

    while(INTCONbits.T0IF==0)
    {/*Timer Stuff*/}
}
Supongo que en proyectos profesionales nadie piensa siquiera en implementar interrupciones de software, así que te sugiero que te acostumbres a manejar los temporizadores :).
Hay una tercera opción, que es crear una variable 'tick' global que se actualice dentro de un controlador de interrupción de temporizador periódico (generalmente hago que se actualice una vez cada milisegundo). Puede usar ese tiempo global para administrar tareas periódicas en su bucle principal sin bloqueos y sin tener que dedicar un temporizador periférico a cada tarea

Respuestas (3)

Tienes que ir al banco (que está a la vuelta de la esquina) y lavar la ropa. Ir a la lavandería requiere que espere a que termine la lavadora y luego espere a que termine la secadora.

¿Cómo haría para realizar estas tareas?

En un día de descanso, podría simplemente lavar la ropa y luego ir al banco. No es tan importante. A quién le importa.

Pero en un día ajetreado, donde tiene otras cosas que hacer, como ver una película, estudiar o lo que sea, lo más eficiente es cargar la primera parte de la ropa, luego ir al banco y luego cargar la segunda. parte del lavadero. Ahora eres libre de hacer otras cosas. Eso es maximizar tu tiempo para que puedas hacer otras tareas.

Ahora, para un microcontrolador o cualquier sistema integrado, lo mismo es cierto. Si no le importa la energía, el tiempo ni nada, elija un retraso controlado por software. Es más fácil de implementar y puede escalarlo tan alto como desee con gran facilidad.

Si le preocupa la energía, el tiempo o la eficiencia, entonces un temporizador de hardware es el camino a seguir. Mientras espera, puede irse a dormir o realizar otra tarea. Es un poco más complicado de configurar, y si varias tareas requieren demoras, es posible que se quede sin temporizadores de hardware y luego tenga que recurrir a un sistema más complicado para administrar el tiempo y las demoras.

Si le importa algo más que la facilidad de uso: Temporizador de hardware

Si solo te importa la facilidad de uso: Software

Depende en gran medida de lo que quieras lograr.

Para un retraso de bloqueo de software como el que ha configurado, no podrá atender las interrupciones y mantener un intervalo constante. Si agrega más código al ciclo, la demora cambiará, potencialmente de manera impredecible o inconsistente si tiene bloques de flujo de control variable. Sospecho que nada de esto importa mucho para un programa parpadeante simple, pero usted preguntó acerca de las aplicaciones críticas en el tiempo.

El "retraso del software" es una solución ingenua. Nunca debe usar dicho código en ningún programa de microcontrolador porque nunca hay una razón para hacerlo: siempre tendrá temporizadores de hardware. "Retrasos de software" no es profesional, ya que tiene los siguientes problemas:

  • Bloquea la CPU para que no haga nada útil.
  • El tiempo es muy inexacto y depende de cómo se traduzca el código C a código de máquina. Escribir "retrasos de software" confiables requiere que desensambles el código C y verifiques las marcas de la CPU según las instrucciones del ensamblador. Bastante tedioso y tiene que hacerse una y otra vez, tan pronto como se cambie el código o las opciones del compilador.
  • Las interrupciones también harán que el tiempo sea inexacto.
  • El retraso depende del reloj del sistema. Si se cambia el reloj, el retraso también cambiará.
  • El optimizador podría eliminar todo el código de "retraso de software" si descubre que no hace nada. Es posible que necesite varios trucos inteligentes para evitar que esto suceda.
  • Mantiene el consumo de corriente de la CPU al 100%.

Si bloquear la CPU no es un problema, es decir, si su programa no tiene nada útil que hacer mientras espera, entonces debe configurar un temporizador de hardware y sondear ese indicador de temporizador como en su segundo ejemplo.

Para requisitos de tiempo real más difíciles, tendrá que usar interrupciones de temporizador.

Si el consumo de corriente es un problema y la MCU admite suspensión/reactivación, generalmente puede configurar la MCU para que entre en modo de suspensión hasta que haya transcurrido el tiempo.

Muy de acuerdo, pero "nunca" es un término muy fuerte. Ciertamente, hay casos en los que un retraso de software es perfectamente aceptable y puede ser la respuesta correcta. Si está hambriento de recursos para relojes periféricos porque está en hardware heredado o simplemente está tratando de ahorrar dinero en la lista de materiales, por ejemplo, o si el retraso es obscenamente largo con respecto al ancho del temporizador y no quiere agregue las partes para un RTC lento. Sin duda, existen numerosas ventajas en el uso de temporizadores para retrasos que podrían hacer que uno elija ese camino, pero nada supera la comprensión de cuándo está bien romper las reglas.
@ScottSeidman De todo el código incrustado que he leído, no recuerdo haber visto nunca tales retrasos porque a la MCU no le quedaban temporizadores de hardware. Hasta ahora, en todo el código que he leído, la única razón por la que se usaron tales retrasos fue la incompetencia, punto. Y dado que debe ser algo competente para obtener una demora precisa, las mismas personas casi siempre no las implementan con la precisión suficiente. Lo que a su vez genera todo tipo de errores oscuros, como fallas aleatorias en los protocolos de comunicación, LCD: se comporta mal y muestra basura, etc.
@ScottSeidman De hecho, "quedarse sin temporizadores de hardware" no es un argumento válido, ya que debe reservar al menos un temporizador para tareas de temporizador de propósito general. Puede envolver este temporizador de hardware único dentro de un controlador que permite crear múltiples temporizadores de software. El código de gastos generales creará una ligera inexactitud en el temporizador, por lo que se utiliza un temporizador de propósito general para tareas de baja prioridad, como los retrasos. Esta es la programación integrada cotidiana; incluso un principiante debería poder escribir un controlador de este tipo y hacerlo algo útil.
@ScottSeidman De manera similar, si el retraso es extremadamente largo, escribe un software para contar cada vuelta del cronómetro. Tendrá que usar un oscilador bastante preciso, pero no son muy caros. Si necesita precisión durante un largo período de tiempo, debe usar un RTC externo de todos modos.
Lo mantendré. "Nunca" es un absurdo de ingeniería. "Precisión" es una especificación que pones en este problema, no el OP. Es un factor que podría señalarle el uso de un temporizador. Un oscilador "no muy costoso" podría forzar un rediseño costoso de una placa, podría generar ruido si el diseño original no se apiló correctamente, podría requerir una costosa prueba de la FCC, o esos pocos centavos en la lista de materiales podrían tener un gran impacto en el resultado final de un artículo básico. Hay muchas situaciones en las que los retrasos de bloqueo son aceptables y no se requiere precisión.
Si estoy inicializando un SPI ADC, y no me importa si las pausas entre los comandos son de 30 ms o 3000 ms, y no hay interrupciones habilitadas, ¿sigue siendo incorrecto un retraso de bucle simple? Si necesitaba precisión y no me importaba el bloqueo, y escribí mi puñado de líneas en ensamblaje para dar cuenta de cada tic del reloj en un microcontrolador no canalizado, ¿está mal? No estoy diciendo que un temporizador esté mal, estoy diciendo que "nunca" es una tontería. Incluso si los temporizadores fueran su religión, no puedo imaginar a un programador integrado pidiendo el rediseño de una placa en su ejemplo de oscilador cuando un simple bucle de retardo es lo suficientemente bueno.
@ScottSeidman ¿Hay alguna razón por la que no usaría el temporizador de propósito general que tendrá que escribir para esta MCU en particular de todos modos? Los temporizadores integrados tendrán la misma precisión que el reloj del sistema. No puede lograr una mayor precisión con un retraso de software, en el mejor de los casos puede lograr la misma precisión, lo más probable es que la tenga peor.
@ScottSeidman En cuanto a "nunca es un término fuerte", la demografía integrada de la industria para los programadores es más o menos así: <10 % de veteranos capacitados, 30 % de veteranos mediocres y 60 % de principiantes/incompetentes. Solo debes considerar romper las reglas si perteneces al raro <10%.
@tcrosley ¿Cómo es exactamente una llamada de función simple a su controlador de temporizador más trabajo que escribir un bucle de retraso oscuro, desarmarlo, contar los tics de la CPU, habilitar optimizaciones, desensamblar nuevamente, comparar el código de la máquina con lo que tenía anteriormente, hacer ajustes al código C si es necesario, volver a desmontar... y así sucesivamente. ¿Cinco segundos de trabajo es más que una hora de trabajo ahora? En realidad, el tiempo que dedica el desarrollador es otra gran razón por la que no debe usar bucles de retardo de software.
@tcrosley ¿Pero tiene tiempo suficiente para llamar a la función de retraso de su software? Si tiene tan poco tiempo que tiene que codificar en línea, entonces ese es otro asunto que no está relacionado en absoluto con la discusión. Porque si tiene que alinear un bucle de retardo de software, también puede alinear una configuración de temporizador de hardware.
@tcrosley Esta discusión se está volviendo tonta. Ese no es un algoritmo de retraso de software, es solo una forma codificada de grabar algunos tics de CPU. También puede escribir asm NOP;un par de veces. Dicho esto, realmente no veo por qué REG1=COUNTER+1; while(!(REG2 & flag));generaría ese código mucho más lento que su ejemplo. Por el contrario, tiene la ventaja de ser determinista ya que todos los registros involucrados son volátiles. El hecho de que no te hayas declarado ivolátil muestra que no deberías estar haciendo cosas como esta. Su "retraso" desaparecerá en el aire.
@tcrosley O no se declara icomo volátil y todo su ciclo desaparecerá en el aire. O lo declara icomo volátil, en cuyo caso no terminará en un registro de la CPU.