PIC de 8 bits: timer1 operación asíncrona frente a síncrona

La familia PIC de 8 bits (estoy trabajando con pic18f46k22) ofrece algunos temporizadores (timers1/3/5) que pueden funcionar tanto en modo asíncrono como síncrono cuando se sincronizan desde una fuente externa.

Las diferencias obvias son:

  1. la operación asíncrona ofrece la posibilidad de que el temporizador se ejecute en modo de suspensión
  2. Una fuente asíncrona puede cronometrar el temporizador más rápido ya que es independiente del reloj del sistema (tabla 27-12):especificaciones de tiempo

y en cuanto a las ventajas de sincronizar la fuente de reloj externa... bueno, no veo ninguna. Una desventaja a tener en cuenta es la posible corrupción de datos si la CPU intenta leer el contador mientras se incrementa, pero la hoja de datos establece:

12.5.1 LECTURA Y ESCRITURA DEL TEMPORIZADOR 1/3/5 EN MODO DE CONTADOR ASINCRÓNICO: La lectura de TMRxH o TMRxL mientras el temporizador está funcionando desde un reloj asíncrono externo garantizará una lectura válida (cuidado en el hardware).

¿Alguien puede explicar por qué agregaron la posibilidad de sincronizar la fuente del reloj externo con los relojes de fase internos? Siento que me falta algo. Muchas gracias

Respuestas (3)

Algunas operaciones en el temporizador no funcionan cuando podría cambiar en medio de un ciclo. Este temporizador también se utiliza junto con los módulos CCP. Lea la sección de la hoja de datos sobre los módulos CCP y probablemente encontrará restricciones sobre cuándo debe ejecutarse en modo síncrono.

Por ejemplo, la comparación con un valor particular puede ser inestable si el valor del temporizador puede cambiar en medio de la operación de comparación, o puede incrementarse más allá del punto de comparación entre comprobaciones.

Eso puede explicar muchas cosas: 14.1.2 RECURSO DEL MODO TEMPORIZADOR 1 El recurso del temporizador de 16 bits debe estar ejecutándose en el modo Temporizador o en el modo Contador sincronizado para que el módulo CCP use la función de captura. En el modo Contador asíncrono, es posible que la operación de captura no funcione. Esta es probablemente una razón para agregar la opción de sincronización

Si necesita un temporizador para operar en modo de suspensión, debe configurarse en modo asíncrono, y si el temporizador está configurado en modo asíncrono, cualquier cambio para cambiar su estado bajo el control del procesador (incluido el cambio entre modo síncrono y asíncrono) que ocurre en el al mismo tiempo que un pulso entrante puede causar que su estado se corrompa de manera arbitraria.

Si tiene dos temporizadores con capacidad asíncrona, le sugiero que configure uno de ellos para que se ejecute continuamente y nunca haga nada con él excepto leer su valor. Dichas lecturas deben realizarse leyendo el byte bajo, luego el byte alto y luego el byte bajo nuevamente. Si el byte bajo cambió entre las dos lecturas, repita el proceso. El otro temporizador puede configurarse para eventos de activación, pero con algunas advertencias:

  1. Escriba el byte bajo del temporizador antes de hacer cualquier otra cosa para cambiarlo y léalo después. Si el byte bajo ha cambiado, suponga que el temporizador podría haberse corrompido arbitrariamente y comience de nuevo desde cero.

  2. En al menos algunas partes, la interrupción del temporizador ocurre en el borde del reloj después de un borde del reloj que avanza el temporizador de 0xFFFE a 0xFFFF. Programar el temporizador con un valor de 0xFFFF no provocará una interrupción en el primer tic que sigue a dicha acción, sino en el tic 65.537. No sé si hay una manera de configurar el temporizador para que se interrumpa en el siguiente tic.

Usando estas técnicas juntas, es posible combinar lógicamente los dos temporizadores con capacidad asíncrona para producir la funcionalidad que estaría disponible en un temporizador con una función de comparación asíncrona.

Hola, estaba esperando tu respuesta mientras leía tu publicación sobre un problema similar... De hecho, no tengo ningún problema de diseño y solo estaba configurando el temporizador para que funcionara como un contador de bordes. Pero me quedé con la opción de sincronización... Mi pregunta era que no puedo entender por qué hay una opción para sincronizar la fuente de reloj externa si la operación asíncrona es obviamente más ventajosa.
el microcontrolador también tiene la función de amortiguar el byte alto cuando lee el byte bajo y no puedo entender por qué no debería usar este modo. Debería resolver el problema que señaló y siempre devolver una buena lectura. lo mismo es correcto para las escrituras, ya que el valor almacenado en el búfer del byte alto se escribe cuando se escribe el byte bajo y, por lo tanto, garantiza una buena escritura
@fhlb: si el temporizador está en modo asíncrono, uno debe leer el byte inferior dos veces, incluso si no le importa el byte superior, y tendría que leer el byte superior dos veces si nunca mirara el byte inferior. Si uno lee un byte en el momento exacto en que cambia de 0x7F a 0x80, o de 0xFF a 0x00, podría informar cualquier valor, y el pestillo del byte superior no hace nada para evitar ese problema. Si dos lecturas arrojan el mismo valor y no es posible que el contador haya aumentado un múltiplo de 256 veces entre las lecturas, se garantiza que el valor es correcto, pero definitivamente se requieren dos lecturas.
Entiendo que leer un contador asíncrono puede presentar los riesgos que señaló, pero la hoja de datos establece claramente que una lectura válida siempre está asegurada y que el problema es cuando el temporizador se desborda entre la lectura del byte más bajo y la lectura del byte más alto. byte. No soy ese gurú de la electrónica sincronizada y no puedo decir cómo es eso posible, pero ¿no deberíamos confiar en la hoja de datos?
12.5.1 LECTURA Y ESCRITURA DEL TEMPORIZADOR 1/3/5 EN MODO DE CONTADOR ASINCRÓNICO: La lectura de TMRxH o TMRxL mientras el temporizador está funcionando desde un reloj asíncrono externo garantizará una lectura válida (cuidado en el hardware). Sin embargo, el usuario debe tener en cuenta que la lectura del temporizador de 16 bits en dos valores de 8 bits plantea ciertos problemas, ya que el temporizador puede desbordarse entre las lecturas.
@fhlb: hay varias formas en que un fabricante de CPU podría intentar hacer que tales lecturas sean confiables. Muchos de ellos reducirán la probabilidad de falla pero no la eliminarán. Dada la errata con la que he tenido que lidiar a lo largo de los años, no confío en que Microchip haya implementado tales medidas correctamente, especialmente dado que hacerlo requiere una gran cantidad de circuitos adicionales. Además, el código que usa la técnica de búfer de byte alto puede tener problemas si hay interrupciones que podrían necesitar leer el estado del temporizador, ya que puede ser una secuencia de eventos problemática:
1. El código principal lee el valor de byte bajo de FF y captura el byte alto; 2. Incrementos del contador 3. La interrupción lee el byte bajo y captura el byte alto; 3. El código principal lee lo que espera que sea el byte alto almacenado en búfer. Si puede ocurrir una interrupción y leer el temporizador después de que el código de la línea principal haya leído el byte bajo, el código de la línea principal debe protegerse contra eso; protegerse contra esa posibilidad leyendo el byte bajo del temporizador dos veces en el código de la línea principal es tan fácil como usar cualquier otro medio, por lo que no veo ninguna razón para no usar ese enfoque, en cuyo caso no importará si lee son 100% fiables.
Por cierto, determinar si algún evento ocurrió antes de un ciclo de reloj en particular es un problema fundamentalmente difícil, y no hay un límite estricto sobre el tiempo que puede llevar tal determinación. Lo mejor que se puede hacer es decidir, en el próximo ciclo, si el sistema ya había decidido que el evento tuvo lugar; la lógica para detectar la invención original podría tomar más de un ciclo para decidir que un evento que ocurrió casi con precisión en el límite de un ciclo de reloj realmente ocurrió antes del reloj, pero es poco probable llegar a esa conclusión en el momento preciso en que llega el próximo reloj.
Su procedimiento de lectura del temporizador multibyte está al revés. Lee el byte alto, el byte bajo, luego el byte alto nuevamente, y conserva los dos primeros si el segundo byte alto coincide con el primero. Si no, hazlo de nuevo. No importa si el byte bajo cambia entre lecturas, solo que no haya acarreo del byte bajo al alto entre lecturas.
@OlinLathrop: No estoy dispuesto a confiar en el resultado de una sola lectura de una cantidad de varios bits de un dominio asíncrono a menos que sepa algo sobre los mecanismos de sincronización utilizados. Leer bajo-alto-bajo funcionará incluso si una de las lecturas arroja un valor falso porque el byte bajo se incrementó de 0x7F a 0x80. Leer alto-bajo-alto fallaría en ese caso.
@supe: No, no fallaría. Piense en cada uno de los posibles casos en los que puede ocurrir un incremento y un acarreo. High-inc-low-high arroja el valor incrementado. High-low-inc-high produce el valor no incrementado. High-carry-low-high es una repetición. También lo es alto-bajo-llevar-alto. Muéstrame un caso en el que no funcione.
@OlinLathrop: el pulso del reloj temporizador entrante llega precisamente al umbral de ser notificable a través de la lectura actual, de modo que el circuito de enganche que se supone que indica si ese pulso de reloj debería afectar la lectura actual se vuelve metaestable, lo que hace que algunos bits informen el nuevo valor del reloj y otros para informar el valor del reloj anterior.
@OlinLathrop: Tal vez Microchip logró implementar correctamente una de las soluciones solo de hardware para evitar tal corrupción, pero requieren una buena cantidad de silicio que no es necesario si el código usa el enfoque que describo. Tenga en cuenta que hay algunas medidas baratas que hacen que una lectura de "división" sea menos probable de lo que sería si no se aplicaran medidas para reducir ese riesgo, pero los miembros baratos aún tienen una probabilidad de falla no trivial.

supercat mencionó leer las erratas del microchip... mire la errata de silicio PIC18(L)F26/46K22 Rev. A2/A4 y la aclaración de la hoja de datos (este microcontrolador que está usando):

  1. Módulo: Temporizador 1/3/5

Cuando Timer1, Timer3 o Timer5 se opera en el modo de entrada externa asíncrona, puede ocurrir una generación de bandera de interrupción inesperada si un borde de reloj externo llega demasiado pronto después de una escritura de firmware en los registros TMRxH:TMRxL. También puede ocurrir un evento de indicador de interrupción inesperado cuando se habilita el módulo o se cambia del modo síncrono al modo asíncrono.

Solución alterna:

Este problema solo se aplica cuando se opera el temporizador en modo asíncrono. Siempre que sea posible, opere el módulo del temporizador en modo síncrono para evitar interrupciones falsas del temporizador.

Una búsqueda rápida en Google también muestra otros problemas con el modo de temporizador asíncrono con otros microcontroladores (ejemplo: errata pic18f4550: falla del mecanismo de lectura en búfer y la errata de la familia pic18f97j60), por lo que probablemente sea un buen punto para no confiar demasiado en el temporizador asíncrono y agregue las dos líneas adicionales de código para verificar cualquier lectura/escritura. y no olvide el código de muestra proporcionado en la fe de erratas para borrar la generación de bandera de interrupción inesperada en una escritura de temporizador