STM32F103: ¿Puede un temporizador interferir con uart?

5

Tengo un programa simple, que recibe datos de la interfaz UART y controla una tira de tira WS2812b. Por lo tanto, estoy usando USART3 para recibir datos (en modo IRQ) y T3C2 (temporizador 3, canal 2) para controlar los LED. Aquí está el código:

enlace

Si utilizo la interfaz uart sin habilitar un temporizador, todo funciona perfectamente, pero cuando habilito el temporizador empiezo a perder datos. Por ejemplo, aquí está el registro si envío 5 paquetes similares de 32 bytes [0x41..0x60]

read 29 byte(s): 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 
read 29 byte(s): 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 60 
read 28 byte(s): 41 42 43 44 45 46 47 48 49 4A 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5D 5E 5F 60 
read 29 byte(s): 41 42 43 44 45 46 47 48 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 5A 5B 5C 5D 5E 5F 60

cada vez que se pierden 3 ~ 4 bytes.

Intenté usar una velocidad de transmisión diferente, un puerto de usuario diferente, el resultado es el mismo. El intervalo del temporizador se establece en la línea 142:

timer_set_period(TIM3, WSP);

donde

#define TICK_NS (1000/72)
#define WSP (1300 / TICK_NS)

Si hago un comentario en esta línea, el problema desaparecerá, pero, por supuesto, no podré conducir los LED sin él.

Entonces, parece que no puedo conducir leds WS2812b y recibir datos de UART al mismo tiempo. ¿Se supone que se comporte así? ¿Alguna idea de cómo puedo solucionarlo?

    
pregunta Tutankhamen

2 respuestas

6

Viendo esto

#define TICK_NS (1000/72)
#define WSP (1300 / TICK_NS)

tu temporizador toma alrededor de 100 pasos (si lo obtuve de las especificaciones) y luego ejecuta cualquier rutina que le hayas dicho. No pude ver claramente cuánto tiempo le toma a su programa dar un paso, pero parece que su rutina de temporizador debería ejecutarse muy a menudo (un par de veces por segundo o más).

Ahora, si su rutina de uart funciona como se espera sin el temporizador, pero pierde datos cuando la introduce, sugiere fuertemente que el temporizador interrumpe su comunicación en serie.

Esto podría ser porque:

  1. tu rutina de temporizador se ejecuta a menudo
  2. la rutina del temporizador es demasiado larga
  3. la interrupción del temporizador tiene una prioridad más alta que la interrupción uart.

O tal vez los tres juntos.

Posibles soluciones:

  1. Un STM32 tiene algo llamado NVIC (Controlador de interrupción de vector anidado), que puede usar para cambiar las prioridades de interrupción.

  2. Cuando usa dos o más interrupciones, debe considerar que pueden ejecutarse casi al mismo tiempo (esto sucede con mayor frecuencia cuando ambas interrupciones se ejecutan en frecuencias similares), y una rutina puede perder información debido a esto ( especialmente con uart). Así que tienes que pensar en una forma de manejar este caso explícito - > mecanismo de bloqueo o alteración de las prioridades.

  3. Cuanto más tiempo tome su rutina, mayor será la posibilidad de que ingrese al caso descrito en el punto dos. Por lo general, es una buena práctica hacer que las rutinas de interrupción sean lo más cortas posible, y nunca usar retrasos o bucles dentro de una interrupción.

  4. Considera si hay una manera de ejecutar tu rutina de temporizador con mucha menos frecuencia. De esta manera, al menos minimiza la posibilidad de pérdida de datos, pero para descartarlo completamente, tendrá que hacer lo que se describe en el punto 1-3.

respondido por el user8837440
6

Creo que el problema es el tiempo empleado en la rutina de interrupción del temporizador y no ha configurado las prioridades. O haga que la rutina del temporizador sea lo suficientemente eficiente, o haga un búfer DMA para el UART, o aumente la prioridad (número de prioridad más bajo) de la interrupción de uart (lo que puede significar fallas visuales en la pantalla, en este caso, las partes críticas del código del temporizador no -interruptable y ver si es suficiente para ayudar al UART)

También puede unificarlos todos en una rutina de interrupción de temporizador. Puede hacer que la frecuencia del temporizador sea lo suficientemente rápida para el UART sin el búfer DMA y sondeo & ejecute el código del temporizador normal con una frecuencia menor, o cree un búfer DMA y ejecute el cronómetro tan lento como lo requiera el código normal y seleccione el búfer UART. Esto hace que las cosas sean más deterministas en contraste con el sondeo en el modo de proceso.

    
respondido por el Ayhan

Lea otras preguntas en las etiquetas