domingo, 29 de marzo de 2020

Timer_PIC32MM

Práctica 3, el temporizador (Timer)
Versión PIC32MM0064GPL028


Esta práctica tiene como objetivo, entrenarse en el uso del temporizador (Timer).

Equipo:
    • Computadora personal
    • Fuente de poder de laboratorio
    • Osciloscopio digital
    • Programador ICD3, PICkit3 o equivalente
Material:
Cantidad     Descripción
1        PIC32MM0064GPL028
1        Resistencia de 10kΩ
2        Resistencia de 1 kΩ
2        Diodo Emisor de luz (Led)
1        Tablilla para prototipo (Protoboard)

Conceptos básicos:

Fosc = Frecuencia de oscilación. Esta frecuencia es generada por el oscilador seleccionado del microcontrolador. La familia PIC32 dispone de 4 osciladores. En esta práctica se seguirá usando el oscilador “Internal Fast RC oscillator(FRC)”, el cual genera una frecuencia de 8MHz.

Fcy =     Frecuencia de instrucción. Esta familia de microcontroladores realiza una instrucción cada Fosc. En contraste los DsPICS realizan una instrucción cada 4 Fosc.

    Para el PIC32 usando el oscilador FRC
     Fcy = 8MHz

Tcy = 1/Fcy = 1/8,000,000 =  0.000000125 seg = 125 ns

Esto significa que el microcontrolador con esta configuración del oscilador, es capaz de realizar 8 millones de instrucciones por segundo. O dicho de otra manera, es capaz de realizar una instrucción cada 125 microsegundos.

En esta práctica se usará el “timer 1”.

El “timer” es un periférico que funciona en paralelo con el resto de periféricos incluyendo al CPU, es decir funcionan al mismo tiempo. El “timer” puede tener diversas aplicaciones, una de ellas es hacer que el CPU espere un cierto tiempo para realizar una tarea. El “timer 1” funciona como un contador cuyo resultado se almacena en TMR1. Para especificar un cierto tiempo, por ejemplo un milisegundo, se calcula cuantas instrucciones se realizan en un milisegundo y esa cantidad se pone en PR1, ya que realizar la tarea de contar y almacenar el resultado de esa cuenta le toma al “timer 1” exactamente un Tcy. Cuando el número que se está contando y almacenando en TMR1  es igual al que se está puesto PR1, el “timer 1”, levanta una bandera. De esa manera el CPU puede enterarse que ha transcurrido el tiempo especificado.

Los registros del “timer 1”, son de 32 bits, pero solo se usan los 16 bits menos significativos, eso significa que puede contar desde 0 a (2^16)-1, es decir hasta 65535.

Cada cuenta tarda un tcy, por lo tanto, para que el “timer” cuente hasta 65535, tarda 0.008191875 segundos, es decir, que el máximo retardo  es de 8.191875 ms

El registro de configuración del timer 1 es el T1CON.  Cuando el bit 15 de este registro se pone a 1, el timer 1 se arranca a contar.

Para poder crear retardos más largos se usa un “prescaler”(divisor de frecuencia) del “timer”.
Los bits 5 y 4 de T1CON establecen el “prescaler”, ver tabla 3.1


Bit 5
Bit 4
Prescaler(divisor)
0
0
1:1
0
1
1:8
1
0
1:64
1
1
1:256
Tabla 3.1





Ejemplo 0: Generar una onda cuadrada con un ancho de pulso = 100microsegundos:

Con una frecuencia de oscilación Fcy = 8,000,000 MHz

8,000,000 = 1,000,000 microsegundos
       x       =  100 microsegundos

x = (8,000,000/100000)100
x = (8)(100)
x = 800

Debido a que el “timer” inicia contando desde cero, entonces las 800 cuentas se alcanzan en 800-1, es decir 799.

Entonces el timer va a contar desde cero hasta 799. Este número es el periodo y se va guardar en el registro del timer uno donde se pone el periodo, este registro es PR1, el uno es porque pertenece al timer uno.

En este ejemplo es suficiente un prescaler 1:1, ya que el número hasta donde contará el “timer 1” (799), se puede acomodar correctamente en el registro PR1 que es de 16 bits.

/*
 * xc32_03a.c
 * Autor:Jesus Acosta Elias
 * Abril 14 2020
* Uso del timer
* En esta familia de microcontroladores, Tcy = Tosc

* Genera una señal con un ancho de pulso
* aproximadamente de 100microsegundos y periodo=200microsegundos

*
*/

#include <p32xxxx.h>

#pragma config ICS = PGx1
#pragma config FNOSC = FRCDIV       //Fast RC oscillator (FRC) with
                                    //divide-by-N
                                    //8mhz
   
int main(void);    //Prototipo funcion main
void retardo100_microseg(void);
//************** Programa principal **********************

int main(void){
        TRISA = 0x0000;     //Se configura PORTA como salida

    while(1){
        LATAbits.LATA4=1;
         retardo100_microseg();
        LATAbits.LATA4=0;
          retardo100_microseg();
    }
}

void retardo100_microseg(void ){
    /* ensure Timer 1 is in reset state */
    T1CON = 0;
    TMR1 = 0;

    PR1 = 799;        //Set Timer 1 period register
    IFS0bits.T1IF = 0;    //Clear the timer1 interrupt status flag
    IEC0bits.T1IE = 0;    //Disable Timer1 interrupts

    T1CON = 0x8000;    //Configura T1CON=1000 0000 0000 0000
                        //Bits 5 y 4 prescaler 01 = 1:8
                        //                     10 = 1:64
                        //                     11 = 1:256
    while(IFS0bits.T1IF==0);
        return;
}  







Simular el timer con MPLABX

En el simulador de mplabx se puede configura la velocidad del reloj, esta velocidad es por default igual  1Mhz. Así lo vamos a dejar, entonces es necesario ajustar el periodo PR1 para esta otra velocidad de reloj.   Entonces realiza un millón de instrucciones por segundo, cuantas instrucciones son necesarias para 100 microsegundos?

1,000,000          1,000,000 microsegundos
       x                  100

x = (1,000,000)(100)/1,000,000
x= 100

Por lo  tanto en PR1 se pone un 99 en lugar del 799


1.- Poner el programa anterior como código fuente del proyecto. Antes borrar el programa anterior(Remove from project). Y compilarlo pare ver que no tenga errores. Después compilarlo para depuración Debug→ Discrete Debugger Operation → Build for Debugging (project)


2.-   Después ir a Window→ Simulator → Logic Analizer


3.- Les aparacerá la ventana de Logic Analizer, la hacen flotante y la escalan, hasta ver como la siguiente figura:

En el analizador lógico, llevar el apuntador del ratón  a la esquina inferior izquierda(settings) y presionar el botón izquierdo.  Buscar en Available Pin y seleccionarlo, en este caso es RA4 y presionar flechita derecha para que este pin pase a Selected Pin(s)



Ya que esté seleccionado, se verá como en la siguiente figura:



Ya solo bastaría con darle click al boton izq del ratón sobre OK y listo.

Ya solo arrancan el simulador Debug→ Discrete Debuguer Operation → Launch Debuguer
Ya que esté el simulador ejecutándose, presionar icono “reset” y debería verse algo como:


Al seguir presionando el icono “ Setep Into(F7)” para ir saltando a la siguiente instrucción, llegará un momento en que se vea:



Observar que el pulso dura mas de 100 microsegundos, porqué será?


Práctica 2 (Para viernes 15)

Modificar el programa de la práctica anterior para que quede codificado de la siguiente manera:


  
/*
 * xc32_03b.c
 * Autor:Jesus Acosta Elias
 * Abril 14 2020
 * Uso del timer
 * En esta familia de microcontroladores, Tcy = Tosc

 *
  */

#include <p32xxxx.h>

#pragma config ICS = PGx1
#pragma config FNOSC = FRCDIV   //Fast RC oscillator (FRC) with divide-by-N
                                //8mhz

   
int main(void);    //Prototipo funcion main
void retardo100_microseg(void);
//************** Programa principal **********************

int main(void){
        TRISA = 0x0000;     //Se configura PORTA como salida

    while(1){
        LATAbits.LATA4=1;
 //-------------------------------------------------------------      
    T1CON = 0;
    TMR1 = 0;

    PR1 = 1;        //Set Timer 1 period register
    IFS0bits.T1IF = 0;    //Clear the timer1 interrupt status flag
    IEC0bits.T1IE = 0;    //Disable Timer1 interrupts

    T1CON = 0x8000;     //Configura T1CON=1000 0000 0000 0000
                        //Con los bits 5 y 4 se define el prescaler

                        //                     00 = 1:1
                        //                     01 = 1:8
                        //                     10 = 1:64
                        //                     11 = 1:256
    while(IFS0bits.T1IF==0);       
 //---------------------------------------------------------------      
       
        LATAbits.LATA4=0;
        asm("nop");
    }
}

void retardo100_microseg(void ){
    /* ensure Timer 1 is in reset state */
    T1CON = 0;
    TMR1 = 0;

    PR1 = 1;        //Set Timer 1 period register
    IFS0bits.T1IF = 0;    //Clear the timer1 interrupt status flag
    IEC0bits.T1IE = 0;    //Disable Timer1 interrupts

    T1CON = 0x8000;     //Configura T1CON=1000 0000 0000 0000
                        //
Con los bits 5 y 4 se define el prescaler
                        //                     00 = 1:1
                        //                     01 = 1:8
                        //                     10 = 1:64
                        //                     11 = 1:256
    while(IFS0bits.T1IF==0);
    return;
}


Y simular con mplabx, obteniéndose un resultado como el que se ve en la siguiente imagen:





Es muy importante estudiar este resultado.