STM32 inicia el tiempo de espera para recibir datos UART después de leer 1 byte

1

Tengo problemas para usar el UART en el STM32F103 donde deja de recibir datos, pero no configuro ninguna de las marcas de error.

El dispositivo UART es un ESP8266 a 115.200 baudios. Lo estoy enviando AT\r\n . El ESP8266 devuelve un eco a cada byte que envío, puedo recibir estos ecos. Sin embargo, cuando se trata de leer la respuesta después de los ecos ( OK + algunas líneas nuevas), se agota el tiempo de espera después de recibir un byte.

Aquí está la transacción completa, como se ve en un analizador lógico.

STM32sends:AT\r\n
ESP8266sends:AT\r\r\n\r\nOK\r\n

Enmicódigo,envíounbyte,luegorecibounbytehastaqueseenvíalacargaútil.Luego,estoyintentandoescucharlos7bytesrestantes(\n\r\nOK\r\n)unoporuno.Reciboel\n,luegolacomunicaciónseapagadespuésde5segundos(usandoeldepurador,veoqueestáesperandoenelindicadorRXNE).

Cuandoseagotaeltiempodeespera,veoqueningunodelosindicadoresdeerror(ORENEFEPE)estánestablecidosenelregistroSR.

Siintentoleerdosbitsalavez,seagotaeltiempodeesperadelaprimeraHAL_UART_Receive.

Elprogramacreaciertainformacióndedepuración(acontinuación)amedidaqueenvíacadabyteyrecibeeleco,luegointentarecibirlarespuesta.Elcódigo para el programa está en una lista.

He estado golpeando mi cabeza contra esto durante varias horas. ¿Qué podría causar este comportamiento?

Sending 4 bytes: AT(\r\n)
  Echo:
    Byte 0: sent 65, echo 65 (ORE 0) // A
    Byte 1: sent 84, echo 84 (ORE 0) // T
    Byte 2: sent 13, echo 13 (ORE 0) // \r
    Byte 3: sent 10, echo 13 (ORE 0) // \n, echo \r
  Receive:
    Recv 10  // \n
    Recv fail
    RXNE: 0 ORE: 0 NE: 0 FE: 0 PE: 0

Extracto del código que intenta leer los bytes una vez finalizado el envío ( código completo ):

while (1) {
    uint8_t recvChar;
    if (HAL_UART_Receive(&Device_UART_Handle, &recvChar, 1, 5000) != HAL_OK) {
        printf("    Recv fail\r\n");
        printf("    RXNE: %d ORE: %d NE: %d FE: %d PE: %d\r\n",
            __HAL_UART_GET_FLAG(&Device_UART_Handle, UART_FLAG_RXNE),
            __HAL_UART_GET_FLAG(&Device_UART_Handle, UART_FLAG_ORE),
            __HAL_UART_GET_FLAG(&Device_UART_Handle, UART_FLAG_NE),
            __HAL_UART_GET_FLAG(&Device_UART_Handle, UART_FLAG_FE),
            __HAL_UART_GET_FLAG(&Device_UART_Handle, UART_FLAG_PE));
        while(1) {}
    }
    printf("    Recv %d\r\n", recvChar);
}
    
pregunta Thomas R

2 respuestas

3

Es probable que falte la mayor parte de la respuesta porque el registro extenso en su ciclo de recepción tarda tanto que no puede capturar el siguiente carácter. Incluso si lo que está enviando a la salida de printf () es un orden de magnitud más rápido que la respuesta de 115200 baudios del ESP8266, está generando tantos caracteres de salida para cada uno recibido que es muy probable que no pueda continuar.

Durante la etapa inicial, cuando solo se generaba un carácter de respuesta para cada carácter enviado, tal vez podría salirse con la suya, pero una vez que el ESP8266 es libre para mantener un canal de 115200 baudios lleno, debe poder mantenerse al día. con eso.

El resultado de la consola es realmente útil, pero debes tener en cuenta el tiempo que lleva, ponerlo en cola para su posterior salida, colocar los caracteres entrantes en una cola de recepción con un ISR de UART, o algo así.

    
respondido por el Chris Stratton
1

Estoy de acuerdo con Chris Stratton en que existe una cantidad increíblemente grande de registros.

También parece que el código se bloquea con un bucle while(1) {} infinito:

while (1) {
    uint8_t recvChar;
    if (HAL_UART_Receive(&Device_UART_Handle, &recvChar, 1, 5000) != HAL_OK) {
        printf("    Recv fail\r\n");
        printf("    RXNE: %d ORE: %d NE: %d FE: %d PE: %d\r\n",
            __HAL_UART_GET_FLAG(&Device_UART_Handle, UART_FLAG_RXNE),
            __HAL_UART_GET_FLAG(&Device_UART_Handle, UART_FLAG_ORE),
            __HAL_UART_GET_FLAG(&Device_UART_Handle, UART_FLAG_NE),
            __HAL_UART_GET_FLAG(&Device_UART_Handle, UART_FLAG_FE),
            __HAL_UART_GET_FLAG(&Device_UART_Handle, UART_FLAG_PE));
        while(1) {}  // <================= block everything forever?
    }
    printf("    Recv %d\r\n", recvChar);
}

cuando se recibe un error.

¿Es eso lo que querías que sucediera? Si esto se dispara, debido a que el registro lleva demasiado tiempo, se atasca para siempre.

Editar: (de mi comentario):
Si tiene el control del código en ambos extremos de la conexión UART (STM32 y ESP8266), implemente un protocolo que garantice que no se pierdan bytes.

Por ejemplo, envíe un acuse de recibo en cada byte recibido. Esto lo haría más complejo, pero también lo haría robusto al usar sentencias de depuración.

Esto se parece a un "efecto Heisenberg" clásico, donde se trata de procesos sensibles al tiempo, pero observarlos presenta retrasos difíciles de definir.

Un enfoque alternativo para el registro de las impresoras, que sería mucho más rápido y por lo tanto tendría menos impacto, sería encender los LED cuando se detectan errores y cuando se detecta una transmisión válida.

    
respondido por el gbulmer

Lea otras preguntas en las etiquetas