Comportamiento extraño de UART con PIC32

Soy nuevo en PIC32 MCU, escribí un pequeño código para ejecutar el UART.

El MCU es el Microchip PIC32MX795F512H , el código usa interrupciones para manejar la recepción y transmisión en el canal 5 de UART (UART5), básicamente el código devuelve la entrada del usuario.

El código es casi funcional, solo un comportamiento extraño: los primeros 8 bits se devuelven correctamente y luego se transmiten 3 caracteres a la consola.

La entrada es azertyay la MCU devuelve: azertyaaaa(agrega aaa, la letra a fue el primer carácter ingresado) y, a veces, azertyaÿÿÿ; luego, para una entrada de caracteres, devuelve los caracteres y otros tres (no aleatorios).

C Principal

            #include <p32xxxx.h>
            #include <plib.h>
            #include "uart.h" 

            #define GetSystemClock()                (80000000ul)
            #define GetPeripheralClock()                (GetSystemClock()/(1 << OSCCONbits.PBDIV))
            #define GetInstructionClock()               (GetSystemClock())

            #pragma config FPLLMUL = MUL_20, FPLLIDIV = DIV_2, FPLLODIV = DIV_1, FWDTEN = OFF
            #pragma config POSCMOD = HS, FNOSC = PRIPLL, FPBDIV = DIV_1

            #define US_TO_CT_TICKS      (CPU_CT_HZ/1000000UL)   

            #define UARTCH1 UART5


            /*------------------------- Interruptions -----------------------------------*/


            void __ISR(_UART_5_VECTOR, ipl2) IntUART5Handler(void){


                if(INTGetFlag(INT_SOURCE_UART_RX(UARTCH1)))
                {

                        INTClearFlag(INT_SOURCE_UART_RX(UARTCH1));


                        PutCharacter(UARTGetDataByte(UARTCH1), UARTCH1);

                        mPORTBToggleBits ( BIT_12 );
                }


                if ( INTGetFlag(INT_SOURCE_UART_TX(UARTCH1)) ){

                        INTClearFlag(INT_SOURCE_UART_TX(UARTCH1));

                        PutCharacter(UARTGetDataByte(UARTCH1), UARTCH1);

                        mPORTBToggleBits ( BIT_15); 
                }
            }
            /*---------------------------------------------------------------------------*/

            int main (void){

                    SYSTEMConfig(GetSystemClock(), SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE);

                    ConfUART(UARTCH1); 

                    mJTAGPortEnable(DEBUG_JTAGPORT_OFF);
                    mPORTBClearBits( BIT_15 | BIT_14 | BIT_13 | BIT_12 | BIT_11 | BIT_10 | BIT_9 | BIT_8 | BIT_7 | BIT_6 | BIT_5 | BIT_5 | BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0 );
                    mPORTBSetPinsDigitalOut( BIT_15 | BIT_14 | BIT_13 | BIT_12 | BIT_11 | BIT_10 | BIT_9 | BIT_8 | BIT_7 | BIT_6 | BIT_5 | BIT_5 | BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0 );

                    WriteToUART("Test1_Test2_Test3_Test4_Test5\n", UARTCH1);

                return 0;

            }

UART.c

            #include <plib.h>

            #define GetSystemClock()        (80000000ul)
            #define GetPeripheralClock()        (GetSystemClock()/(1 << OSCCONbits.PBDIV))
            #define T_RATE_X                    (9600) 

            void WriteToUART(const char *string, char UARTCH){ 

                while(*string != '\0')
                {
                    while(!UARTTransmitterIsReady(UARTCH));
                    UARTSendDataByte(UARTCH, *string);
                    string++;
                    while(!UARTTransmissionHasCompleted(UARTCH));
                }
            }

            void PutCharacter(const char character, char UARTCH){

                while(!UARTTransmitterIsReady(UARTCH));

                    UARTSendDataByte(UARTCH, character);

                    while(!UARTTransmissionHasCompleted(UARTCH));
            }

            void ConfUART(char UARTCH){

                UARTConfigure           (UARTCH, UART_ENABLE_PINS_TX_RX_ONLY);
                UARTSetFifoMode     (UARTCH, UART_INTERRUPT_ON_TX_NOT_FULL | UART_INTERRUPT_ON_RX_NOT_EMPTY);
                UARTSetLineControl  (UARTCH, UART_DATA_SIZE_8_BITS | UART_PARITY_NONE | UART_STOP_BITS_1); /* 8 Bits, Pas de parité, 1 STOP Bits */
                UARTSetDataRate     (UARTCH, GetPeripheralClock(), T_RATE_X);
                UARTEnable              (UARTCH, UART_ENABLE_FLAGS(UART_PERIPHERAL | UART_RX | UART_TX));

                INTEnable                           (INT_SOURCE_UART_RX(UARTCH), INT_ENABLED);
                INTSetVectorPriority            (INT_VECTOR_UART(UARTCH), INT_PRIORITY_LEVEL_2);
                INTSetVectorSubPriority     (INT_VECTOR_UART(UARTCH), INT_SUB_PRIORITY_LEVEL_0);


                INTConfigureSystem      (INT_SYSTEM_CONFIG_MULT_VECTOR);


                INTEnableInterrupts();

            }

Respuestas (2)

Su función de escritura UART está diseñada para dejar de transmitir cuando encuentra un carácter NULL en su cadena ('\ 0' o 0x00). No terminas en nulo tus cadenas. No sabe cuándo dejar de enviar, por lo que continúa y envía todo lo que encuentra hasta que encuentra un carácter NULL.

Para solucionar esto, siempre que envíe una cadena, debe agregar '\ 0' al final de la misma.

EDITAR: De acuerdo, la función PutChar corrige eso: ¿necesita borrar la interrupción manualmente? Parece que hay dos fuentes secundarias que se unen con OR para causar la interrupción principal: las borra, pero ¿necesita borrar también la interrupción principal? Eso podría causar este problema. ¿Ha probado su línea UART Tx y ha comprobado la velocidad en baudios de esa manera? Eso podría ser un problema: si está utilizando una fuente de reloj de baja precisión, es posible que no tenga en cuenta la velocidad en baudios.

También edite: ¿ve su puerto alternar cada vez que envía los bytes adicionales?

Intenté esto, eliminé la función writetouart (solo se usó una vez y no es realmente necesaria) pero el problema persiste: cuando inicio la MCU con el código, envío la cadena azerty, la MCU las captura y las devuelve correctamente, luego en el octava entrada devuelve el caracter y otros 3 (que son iguales). Me doy cuenta de que los caracteres devueltos no deseados son los ingresados ​​previamente (desde el primero). Por ejemplo: envío azerty (ok), azertya (ok), envío azertyaz y devuelve azertyazaaa.
De todos modos, su código tal como se publicó no funcionará por ese motivo. Si quieres que depure el otro código, publícalo.
¡Actualiza tu pregunta con eso! ¡Ese código en un comentario es solo un desastre!
El código publicado en el comentario ya está disponible en el archivo UART.c. Creo que es la función PutCharacter la que no está correctamente diseñada.

Corríjame si me equivoco, pero parece que está en la interrupción UART5, pero está borrando los indicadores RX y TX de UART1.