TODOPIC

Microcontroladores PIC => Todo en microcontroladores PIC => Mensaje iniciado por: 8bits en 21 de Agosto de 2017, 20:27:48

Título: [SOLUCIONADO] ¿Cual es el modo adecuado de usar las interrupciones?
Publicado por: 8bits en 21 de Agosto de 2017, 20:27:48
Hola foreros ¿que hay?, el dia de hoy tengo una consulta. Resulta que estoy practicando un poco con las interrupciones, específicamente las realizadas por el TMR0. He jugado un poco cambiando de estado un led mediante la llamada de una ISR disparada por el desbordamiento del TMR0. Ahora quise complicarlo un poco, simulando el comportamiento de un semáforo, en donde los estados serán:


Todo esto de igual manera usando interrupciones por el desbordamiento del TMR0 como temporizador.
Pero me surge una duda, ¿cual es la manera correcta de usar la llamada de la rutina de interrupción ISR?, específicamente me refiero, si en la ISR, ¿va todo mi codigo, dejando el while vacio?, o es conveniente que la ISR solo maneje instrucciones cortas, por ejemplo usar banderas y dentro del while poner todo mi codigo correspondiente. ¿cual es la forma correcta?

No se si me explico  :shock:

NOTA: Uso MPLABX y XC8 con un PIC18F4550
Título: Re:¿Cual es el modo adecuado de usar las interrupciones?
Publicado por: Pinolillo16 en 21 de Agosto de 2017, 21:03:37
Lo correcto es dejar el menor codigo posible en ISR. Como lo indica solo interrumpe para hacer algo más importante, debes saber que en el datasheet indica que cuentas con interrupciones de alta y baja prioridad. Tu mismo las configuras, esto es cuando usas interrupciones distintas.

Ahora de acuerdo a como tu lo quieres hacer, usas la interrupción por timer para incremente un contador ya que es mucho tiempo para el timer.

Porque no haces lo siguiente, si ya trabajaste con timer. Has tu rutina normal y usa interrupcion RB0 para que obligue el  rojo simulando que es un peaton.

Saludos
Título: Re:¿Cual es el modo adecuado de usar las interrupciones?
Publicado por: KILLERJC en 21 de Agosto de 2017, 21:19:54
En el caso de un semaforo, que lo que vas a tener es la "maquina de estados" y luego activar una salida, podes hacerlo todo en la interrupcion ya que no es algo que sea excesivamente consumidor de tiempo, ( en el que pueda desbordarse el TMR0 de nuevo) y tampoco tenes otra interrupcion que te pueda afectar.

Me explico un poco mas, si lo que va a tener que hacer luego de que se cumpla el tiempo tarda demasiado en realizarse, va directo al while del main. ejemplos son los sprintf por ejemplo, a pesar de que son intrucciones suelen tardar demasiado, o por ejemplo una operacion matematica de divisiones y multiplicaciones, o con flotantes. Son operaciones que tardan demasiado, asi que eso mejor pasarlo al while del main y realizarlos alli con banderas. En tu caso que es preguntar por un contador + activar una salida segun el estado que estuvo antes, lo podes hacer enteramente en la interrupcion.
Título: Re:¿Cual es el modo adecuado de usar las interrupciones?
Publicado por: 8bits en 21 de Agosto de 2017, 21:28:16
Ya veo, bueno he realizado el programa, y he programado el PIC, conectado los leds correspondientes al protoboard y todo funciona. El código que use es este: 
NOTA: De acuerdo a lo que me recomiendas KILLERJC si utilice la maquina de estados. Por otra parte de acuerdo a lo que me comenta Pinolillo16 utilice la ISR solo para hacer los incrementos de un contador. Voy a poner la interrupción para simular un peaton y obligar al estado "luz roja".



#include <xc.h>
//////////////////////////Bits de configuracion////////////////////////////////
#define _XTAL_FREQ 48000000                                             //Se utiliza una frecuencia de reloj de 48MHz
#pragma config PLLDIV = 5                                               //Divisor de frecuencia con el postscaler
#pragma config CPUDIV = OSC1_PLL2                                       //Division de frecuencia con el prescaller
#pragma config FOSC = HSPLL_HS                                          //Modo de oscilacion externo con PLL de alta velocidad
#pragma config IESO = OFF                                               //Switchover
#pragma config MCLRE = OFF   

char estado = '0';
int contador;

void ConfigInit(){
    //Funcion para la configuracion inicial de todo el sistema
   
    //Entradas y salidas
    TRISB = 0;              //PORTB como salidas
    LATB = 0;               //Limpiando el LATCH del PORTB
   
   
    //Configuracion del TMR0 ********************************************
   
    //Registro de configuracion para el TMR0 T0CON
    T0CON = 0b11000101;     
    //Precarga para 1ms
    TMR0 = 68;         
    //Bandera del desbordamiento del timer
    INTCONbits.T0IF = 0;
 
    //Configuracion de interrupciones ********************************
   
    //Registro de configuracion para interrupciones INTCON
    //Interrupciones globales habilitadas
    INTCONbits.GIE = 1;
    //Interrupcion por el TMR0 habilitada
    INTCONbits.TMR0IE = 1;
   
   
}
void interrupt RutinaISR(){
    //Rutina de interrupcion de alta prioridad
    contador ++;
    TMR0 = 68;
    INTCONbits.TMR0IF = 0;
   
    if(contador == 500) estado = '1';
    if(contador == 3500) estado = '2';
    if(contador == 4500) estado = '3';
    if(contador == 7500){
        contador = 0;
        estado = '4';
    }
}


void main(void) {
    ConfigInit();
    while(1){
       
        switch(estado){
            case '0':
                PORTB = 0x00;
                break;
            case '1':
                PORTB = 0x01;
                break;
            case '2':
                PORTB = 0x02;
                break;
            case '3':
                PORTB = 0x04;
                break;
        }
       
    }
    return;
}

NOTA: Aprovechando este post, quisiera preguntar cual es la manera adecuada de configurar los registros, por ejemplo, setear todo el registro con la forma T0CON = 0xb...etc, o hacerlo bit por bit, por ejemplo. T0CONbits....etc.
Título: Re:¿Cual es el modo adecuado de usar las interrupciones?
Publicado por: KILLERJC en 21 de Agosto de 2017, 21:59:13
Ahi estas cargando el caracter '4' que si usas la tabla ASCII es igual a 0x34 o 52 decimal.

Código: C
  1. estado = '4';

Usa decimales:


Código: C
  1. estado = 4;
  2. case 0:

Citar
NOTA: Aprovechando este post, quisiera preguntar cual es la manera adecuada de configurar los registros, por ejemplo, setear todo el registro con la forma T0CON = 0xb...etc, o hacerlo bit por bit, por ejemplo. T0CONbits....etc.

Depende, algunos de la priemer forma y otros de la segunda forma. Por ahi es util que en la primer forma aclares que son los valores que pusiste, y en la segunda forma que hacen cada uno de los bits. Me refiero a los comentarios.

Código: C
  1. if(contador == 500) estado = '1';
  2.     if(contador == 3500) estado = '2';
  3.     if(contador == 4500) estado = '3';
  4.     if(contador == 7500){

Si tenes que crear una conmutacion en segundos por ejemplo. La idea es que con el TMR0 tengas un contador que llegue al segundo y luego vuelva.

Entonces tu TMR0 posee un contador que entra en cada segundo. Y ahi sabes que paso ya un segundo, luego tenes un codigo que aumentara ese segundero y cuando se cumpla la cantidad de segundos pasa al otro estado.