PIC: la transmisión de UART está dañada después de la suspensión del watchdog

6

Tengo un PIC16 (hoja de datos aquí ) para la que funciona la transmisión de UART, excepto justo después de un sueño de vigilancia, donde los primeros caracteres están dañados.

He publicado mi código reducido a continuación. ¿Qué podría causar la corrupción de los primeros caracteres de transmisión de UART justo después de un sueño de vigilancia?

// Baud rates
#define BAUD_115200 0
#define BAUD_9600 1

// Watchdog sleep times
#define WATCHDOG_SLEEP_4S 0b01100

/* Note: The watchdog operating mode configuration is done in configuration word 1 */
void watchdog_configure(char interval) {
    // Configure the watchdog interval (e.g. 10010 for 256 seconds)
    WDTCONbits.WDTPS = interval & 0b11111;
}

void watchdog_sleep(void) {
    WDTCONbits.SWDTEN = 0b1;
    SLEEP();
    WDTCONbits.SWDTEN = 0b0;
}

void UART_setBaudRate(const unsigned char type) {
    // See table 25-5
    if(type == BAUD_115200) {
        SPBRG = 68;
    } else {
        SPBRGH = (832 >> 8);
        SPBRGL = 832 & 0b11111111;
    }
}

/* Configure the UART for full-duplex asynchronous transmission */
void UART_initialise(void) {
    UART_setBaudRate(BAUD_115200);

    // Configure the RX/DT pin as an input
    TRISCbits.TRISC4 = 0b1;

    // Enable the asynchronous transceiver
    TXSTAbits.TXEN = 0b1;
    TXSTAbits.SYNC = 0b0;
    RCSTAbits.SPEN = 0b1;
    RCSTAbits.CREN = 0b1;
    TXSTAbits.BRGH = 0b1;

    // Use 16 bits for the baud rate
    BAUDCONbits.BRG16 = 0b1;
}

void UART_write(const unsigned char character) {
    // Wait while the transmit shift register empties
    while(!PIR1bits.TXIF) {}

    // Indicate the character to be written to the Transmit Shift Register
    TXREG = character;

    // Add a one cycle delay to ensure that the TXIF flag is valid
    _delay(1);
}

void UART_writeString(const unsigned char *string) {
    unsigned char i = 0;

    while(*(string + i) != '
// Baud rates
#define BAUD_115200 0
#define BAUD_9600 1

// Watchdog sleep times
#define WATCHDOG_SLEEP_4S 0b01100

/* Note: The watchdog operating mode configuration is done in configuration word 1 */
void watchdog_configure(char interval) {
    // Configure the watchdog interval (e.g. 10010 for 256 seconds)
    WDTCONbits.WDTPS = interval & 0b11111;
}

void watchdog_sleep(void) {
    WDTCONbits.SWDTEN = 0b1;
    SLEEP();
    WDTCONbits.SWDTEN = 0b0;
}

void UART_setBaudRate(const unsigned char type) {
    // See table 25-5
    if(type == BAUD_115200) {
        SPBRG = 68;
    } else {
        SPBRGH = (832 >> 8);
        SPBRGL = 832 & 0b11111111;
    }
}

/* Configure the UART for full-duplex asynchronous transmission */
void UART_initialise(void) {
    UART_setBaudRate(BAUD_115200);

    // Configure the RX/DT pin as an input
    TRISCbits.TRISC4 = 0b1;

    // Enable the asynchronous transceiver
    TXSTAbits.TXEN = 0b1;
    TXSTAbits.SYNC = 0b0;
    RCSTAbits.SPEN = 0b1;
    RCSTAbits.CREN = 0b1;
    TXSTAbits.BRGH = 0b1;

    // Use 16 bits for the baud rate
    BAUDCONbits.BRG16 = 0b1;
}

void UART_write(const unsigned char character) {
    // Wait while the transmit shift register empties
    while(!PIR1bits.TXIF) {}

    // Indicate the character to be written to the Transmit Shift Register
    TXREG = character;

    // Add a one cycle delay to ensure that the TXIF flag is valid
    _delay(1);
}

void UART_writeString(const unsigned char *string) {
    unsigned char i = 0;

    while(*(string + i) != '%pre%') {
        UART_write(*(string + i));
        i += 1;
    }
}

void main(void) {
    // Perform initialisations
    watchdog_configure(WATCHDOG_SLEEP_4S);
    UART_initialise();

    watchdog_sleep();
    UART_writeString("UART TESTING");
}
') { UART_write(*(string + i)); i += 1; } } void main(void) { // Perform initialisations watchdog_configure(WATCHDOG_SLEEP_4S); UART_initialise(); watchdog_sleep(); UART_writeString("UART TESTING"); }
    
pregunta Randomblue

3 respuestas

5

Supongo que el problema no se produce realmente cuando el PIC se despierta, sino cuando se duerme. Si el PIC se pone en suspensión entre el momento en que el código pone en cola un carácter para la transmisión y el momento en que UART termina de enviarlo, algunos bits de ese carácter se enviarán antes de que el PIC se duerma y otros se enviarán después de que se active. El primer flanco descendente que se produce después de que se despierte el PIC probablemente será interpretado por el receptor como un bit de inicio en lugar de un bit de datos. Si se produce un bit de inicio dentro de los 8 bits de tiempo, el receptor no lo detectará como un bit de inicio, sino que detectará el siguiente flanco descendente (que puede ser otro bit de datos). Esta condición se conoce como un "error de trama"; tenga en cuenta que casi todos los errores de trama causarán que se reciban datos incorrectos, pero solo algunos causarán que se establezca el bit "FE".

Vale la pena tener en cuenta que al enviar un valor de byte de 00, 80, C0, E0, F0, F8, FC, FE o FF, es posible que un bit de inicio mal detectado cause que se reciba un valor incorrecto. byte, pero el byte que sigue a uno de los valores anteriores debe recibirse correctamente en cualquier caso (ya que no habrá flanco descendente entre el bit de inicio de cualquiera de los valores indicados y el bit de inicio del siguiente byte). Por el contrario, si se produce un error de trama en el valor del byte en el rango 40-7F, es probable que el siguiente byte también se corrompa, ya que hay un borde descendente entre los bits 6 y 7.

    
respondido por el supercat
3

De acuerdo con la hoja de datos, como se cita, el despertar debe ser todo ceros, aunque esto parece ser para la línea RX. Dice cualquier cantidad de tiempos de bits para dispositivos RS232 normales.

Intente simplemente reinicializando el periférico, borrando las interrupciones / marcas y / o enviando un par de caracteres cero al despertar, luego proceda a enviar sus datos reales.

    
respondido por el Oli Glaser
2

Un oscilador de reloj requiere algo de tiempo para estabilizarse después de iniciarse, como después de un reinicio del temporizador de vigilancia / SLEEP.

Hasta que ocurra esta estabilización, la sincronización del UART permanecerá inestable.

Una solución simple sería agregar un breve retraso después de que finalice el SLEEP, antes de comenzar a transmitir su flujo de bits. Continúe con un byte o dos de valor 0, antes de enviar su primer paquete de datos útil.

    
respondido por el Anindo Ghosh

Lea otras preguntas en las etiquetas