Bit Banging UART PIC32mx

0

Estoy tratando de golpear un puerto UART usando PIC32MX con temporizador5 (el único disponible en este momento) pero estoy teniendo problemas para configurar el temporizador para una velocidad de baudios de 115200 bps. No quiero un control de flujo ni siquiera para lidiar con la paridad. Si es posible, ¿puede alguien explicarme sobre un procedimiento paso a paso?

Mis definiciones son:

    #define GetSystemClock()            48000000UL              // System clock frequency (Hz)
    #define GetPeripheralClock()        48000000UL              // Peripheral clock frequency
    #define GetInstructionClock()       (GetSystemClock())      // Instruction clock frequency

    #define MILLISECONDS_PER_TICK       10                  // Definition for use with a tick timer
    #define TIMER_PRESCALER             TIMER_PRESCALER_8   // Definition for use with a tick timer
    #define TIMER_PERIOD                37500               // Definition for use with a tick timer

    #define SYS_FREQ                    40000000UL

    #pragma config FPLLMUL = MUL_20    // PLL Multiplier
    #pragma config FPLLIDIV = DIV_1 // PLL Input Divider
    #pragma config FNOSC = FRC // Oscillator Selection
    #pragma config POSCMOD = EC // Primary Oscillator
    #pragma config FPLLODIV = DIV_2 // PLL Output Divider
    #pragma config FPBDIV = DIV_1 // Peripheral Clock divisor
    #pragma config FWDTEN = OFF // Watchdog Timer (controlled by software)
    #pragma config WDTPS = PS65536 // Watchdog Timer Postscale 1048s
    #pragma config FCKSM = CSECMD // Clock Switching Enable & Fail Safe Clock Monitor Disable
    #pragma config OSCIOFNC = OFF // CLKO Disable
    #pragma config IESO = ON // Internal/External Switch-over
    #pragma config FSOSCEN = ON // Secondary Oscillator (KLO was off)


    void initTIMER5( void ){ // Initialize Timer 5

    T5CON = 0x0;   
    TMR5 = 0; 

    T5CONbits.TCKPS = 0b111;//1:256 prescale value

    IFS0bits.T5IF = 0;
    IPC2bits.T2IS = 0; 
    IPC2bits.T5IP = 2;
    IEC0bits.T5IE = 1;

    T5CONSET = 0x8000;
    }

Por ahora creo que solo necesito configurar el T5CONbits.TCKPS y el registro PR5 para sincronizar con la velocidad en baudios, ¿no?

Realmente necesito tu ayuda con estos chicos.

    
pregunta scuba

1 respuesta

3

Tanto para el envío como para la recepción, debe configurar una interrupción del temporizador.

El tiempo de un bit para 115.200 baudios es:

$$ {1,000,000 \ sobre 115,200} = 8.68 \ espacio µs $$

Si está ejecutando un reloj periférico de 48 MHz, esto corresponde a un período de 20.8 ns, o 0.0208 µs:

$$ {1,000,000 \ sobre 48,000,000} = 0.0208 \ espacio µs $$

El número de conteos para el temporizador es entonces:

$$ {8.68 \ sobre 0.0208} = 417 $$

Así que la transmisión es fácil, solo configure un contador, y en cada interrupción, salga el bit de inicio, seguido de 8 bits de datos, seguido de un bit de parada que dura dos intervalos de temporizador.

Recibir es un poco más complicado. Para capturar el borde descendente del cable RX, que indica el comienzo del bit de inicio, puede usar una Notificación de cambio como mencionó en un comentario. O, si tiene un pin de interrupción (INTx) no utilizado, puede usarlo en su lugar.

Cuando se produce la interrupción de la Notificación de cambio, usted desea restablecer su temporizador programado por la mitad del período, es decir, 4.34 µs, o 208 cuentas. Luego, cuando llega la interrupción del temporizador, debe estar en el medio del bit de inicio. Si ha vuelto a ser alto, entonces esto fue solo ruido. De lo contrario, vuelva a cambiar el temporizador a un tiempo de bit (8,68 µs), y en cada interrupción del temporizador estará muestreando la mitad de cada bit de datos.

Lo ideal sería escanear cada bit más de una vez. Entonces, si configura su temporizador inicial después de la interrupción de la notificación de cambio para 3.34 µs (160 conteos) en lugar de 4.34 µs, estará muestreando la mitad del bit de inicio menos uno µs. Luego espere 1 µs y muestre nuevamente (ahora está en el medio), y luego una vez más (1 µs más allá del medio). Ahora tiene tres muestras para ver, por lo que puede tomar el valor mayoritario. Espere 6,68 µs (321 recuentos) esta vez y repita para cada bit de datos.

El UART de hardware normalmente muestra 16 veces por cada tiempo de bit.

Es posible que desee que la versión más simple funcione primero (escaneando solo una vez en el medio).

EDIT:

No creo que tu configuración sea correcta. La segunda línea de su lista asume que su reloj periférico es de 48 MHz, pero mirando la configuración de su reloj, creo que solo está funcionando a 8 MHz.

Sin un cristal externo, la única forma de obtener frecuencias superiores a 8 MHz es usar el PLL. Sin embargo, tiene la selección del oscilador configurada en solo FRC, que utiliza el oscilador interno de 8 MHz directamente. Para obtener 48 MHz, necesitarías algo como las siguientes configuraciones:

#pragma config FPLLMUL = MUL_24    // PLL Multiplier
#pragma config FPLLIDIV = DIV_2    // PLL Input Divider
#pragma config FNOSC = FRCPLL      // Oscillator Selection
#pragma config POSCMOD = OFF       // No Primary Oscillator
#pragma config FPLLODIV = DIV_2    // PLL Output Divider
#pragma config FPBDIV = DIV_1      // Peripheral Clock divisor
#pragma config IESO = OFF          // No Internal/External Switch-over

En la Figura 8-1, página 141 de la hoja de datos, dice que Fin debe tener entre 4 y 5 MHz. Eso significa que debe dividir el reloj RC interno por 2 (FPLLIDIV). Luego lo multiplicas por 24 (FPLLMUL) y lo divides por 2 (FPLLODIV) para obtener 48 MHz.

No sé para qué se usa SYS_FREQ #define. Parece que debería coincidir con GetSystemClock.

No dijiste qué procesador PIC32MX estás usando. Si es uno en la familia PIC32MX575 / 675/695/775/795, el reloj FRC interno solo tiene una precisión de ± 2% (Tabla 31-19, página 376). Es posible que esto no sea lo suficientemente bueno para realizar UART a 115.200 baudios; generalmente las tasas de baudios deben estar dentro del 1.5%. Realmente deberías usar un cristal de 8 MHz (con la configuración del reloj actualizada una vez más) en lugar del reloj FRC interno.

    
respondido por el tcrosley

Lea otras preguntas en las etiquetas