Autor Tema: Problema con interrupción TIMER1 y PROTEUS  (Leído 2137 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Pchuqui_1

  • PIC16
  • ***
  • Mensajes: 187
Problema con interrupción TIMER1 y PROTEUS
« en: 09 de Abril de 2012, 13:38:39 »
Hola a todos. Hice un pequeño programa para simular en PROTEUS, pero a la hora de correrlo, cuando la interrupción por TIMER1  se ejectuja la PILA del micro se llena de golpe y el PROTEUS no lo simula, (me da el error: "Stack underflow executing RETLW instruction"). Será un error del simulador o estoy haciendo macana en el programa. Muchas gracias. 


#include <16F887.h>
#fuses HS,NOPROTECT,NOWDT,NOLVP
#use delay(clock=20000000)
//#use rs232(baud=7000, xmit=PIN_c6, rcv=PIN_c7,PARITY=E,STOP=2, bits=8,STREAM=entrada_8251) //manejo del RS232, Parity =E = PAR

// Definición de pines de control
#define DATA       PIN_B0//PIN_A0            //Pin pertenecientes al SPI_1 controla los numeros (menos las decimas y el periodo)
#define CLOCK       PIN_B1//PIN_A1
#define STROBE       PIN_B2//PIN_A2
#define OE         PIN_B3//PIN_A3

#define DATA_1      PIN_A0//PIN_B0            //Pin pertenecientes al SPI_2 controla las decimas y el periodo
#define CLOCK_1      PIN_A1//PIN_B1
#define STROBE_1   PIN_A2//PIN_B2
#define   OE_1      PIN_A3//PIN_B3


#define DATA_2      PIN_D0            //Pin pertenecientes al SPI_3 controla las faltas
#define CLOCK_2      PIN_D1
#define STROBE_2   PIN_D2
#define   OE_2      PIN_D3


int t,x,and,unidad,decena,t1,bcd,segmentos_1, cuenta_bits;
int bandera_decima,bandera_visita,primer_dato,segundo_dato;
int contador_FF;
int y_bufer,y1_bufer;

int xbuff=0x01;                     // Índice: siguiente char en cbuff
char cbuff[33];                   // Buffer


void escribir_4094(int caracter);
void escribir_4094_1(int caracter);
void escribir_4094_3(int caracter);
void escribir_4094_3_refresco(int caracter);
void bin2bcd(int valor);
void crea_unidad_decena(int segmentos);
void crea_unidad_decena_1(int segmentos);
void crea_unidad_decena_refresco(int segmentos_1);

int const segmentos[88]={0xFF,0xFF,0x11,0xAA,0x11,0x01,0xFC,0xFF,0xFF,0xFF,0x15,0x45,0x30,0x15,0x66,0x44,0x01,/*BOCINA*/0x00,/*Falta_local*/0x3E,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F
0x3F,0x3F,/*comienza visitas*/ 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x99,0xFE,0xFF,0xFF,0x01,0xFC,0xFF,0xFF
,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xFC,0xFF,0xFF,0x01,0xFC,0xFF,0xFF,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFB,0xFF,0xFF,0x01,0xFC,0xFC,0x11,0x23};

//////////////////////////////////////////////////////////////////////////////

#int_TIMER1
void  TIMER1_isr(void)
{

for(t=1;t<=32;t++){                              
segmentos_1=cbuff[t];
cuenta_bits ++;

if ((cuenta_bits <= 6))                                
{
crea_unidad_decena(segmentos_1);
}
   

if(cuenta_bits==7){                           
crea_unidad_decena_1(segmentos_1);                  
}      


if(cuenta_bits==8){                                          
               }      


if((cuenta_bits >=9)&& (cuenta_bits <=20)){            
escribir_4094_3(segmentos_1);                     
           }   


if((cuenta_bits >=21) && (cuenta_bits <=32)){         


bandera_visita ++;                              
if(bandera_visita==1){                              
primer_dato=segmentos_1;                        
cuenta_bits --;                                 
               }               


if(bandera_visita >=2){
segundo_dato=segmentos_1;               
escribir_4094_3(segundo_dato);
cuenta_bits ++;
escribir_4094_3(primer_dato);
bandera_visita=0;   
              }               

      }


}

output_high(PIN_E0);
set_timer1(34286);
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////


                                          

void  main(){

//enable_interrupts(int_rda);                     
setup_timer_1(T1_INTERNAL|T1_DIV_BY_4);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
set_timer1(34286);

contador_FF=0;
cuenta_bits=0;
bandera_decima=0;
bandera_visita=0;                              
                                           muestran alternados.
primer_dato=0;
segundo_dato=0;

while(true){

for(t=0;t<=87;t++){                              
segmentos_1=segmentos[t];

if(contador_FF == 3){
cuenta_bits ++;

if((cuenta_bits>=1)&& (cuenta_bits<=32)){
cbuff[xbuff++]=segmentos_1;
                              }
if((cuenta_bits==32)){
cuenta_bits=0;
contador_FF=0;               
}

}

else
{
if(segmentos_1 == 0xFF)
contador_FF ++;
else
{
contador_FF = 0;
}
}


}


}               

}

Desconectado MerLiNz

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2463
Re: Problema con interrupción TIMER1 y PROTEUS
« Respuesta #1 en: 09 de Abril de 2012, 15:04:09 »
simulalo paso por paso y ves donde te da el error. Pero tiene toda la pinta de ser porque estas llamando a funciones dentro de la interrupcion. Vamos que tienes demasiado codigo en la interrupcion.

Las interrupciones deben ser lo mas ligeras posible, por ello se debe evitar poner mucho codigo dentro y sobretodo llamar a funciones, divisiones, multiplicaciones...

Deberias ponerlo de la siguiente manera:

char fTIMER=0;

timer1_isr() {
output_high(PIN_E0);
set_timer1(34286);
fTIMER=1;
}

y dentro del while pones

if(fTIMER) {
//aqui todo tu codigo que tenias dentro de la interrupcion

fTIMER=0;
}

Desconectado Pchuqui_1

  • PIC16
  • ***
  • Mensajes: 187
Re: Problema con interrupción TIMER1 y PROTEUS
« Respuesta #2 en: 10 de Abril de 2012, 14:24:04 »
Creo que el problema está, que cuando se llama a la interrupción, como el programa se esta ejecutando en varios if, eso lleña la pila del micro. Ya que estoy pregunto, no saben si es posible aumentar el tamaño por software de la pila de los PIC?? Saludos

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Problema con interrupción TIMER1 y PROTEUS
« Respuesta #3 en: 10 de Abril de 2012, 14:34:28 »
  Las sentencias "if" no deberían llenar la pila. En assembler se produce el llenado de la pila por los "call" anidados, pero en C me imagino que el compilador usará otro método para procesar las funciones.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado MerLiNz

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2463
Re: Problema con interrupción TIMER1 y PROTEUS
« Respuesta #4 en: 10 de Abril de 2012, 20:01:44 »
los if no llenan la pila, lo que hace el compilador cuando pones if(variable==10) es restar 10 a la variable y si es CERO hace un salto, en caso contrario no sigue su curso, pero en ningun momento usan la pila.

Sin embargo al llamar a una funcion se utiliza un call y se guarda la direccion de regreso en la pila.

Como ya te he dicho tu problema esta en que estas utilizando la interrupcion de forma incorrecta, al meterle llamadas a funciones estas haciendo que se almacenen muchos datos en la pila provocando probablemente un lio en la pila. Tu problema no es OVERFLOW es UNDERFLOW, osea cuando se ejecuta la funcion RETLW la pila llega a 0 y se pondria a -1 (error) por eso te dice UNDERFLOW.

Aunque le pongas el 100% de ram a la pila no conseguirias nada, tu problema no es desbordamiento por falta de memoria.


Desconectado Pchuqui_1

  • PIC16
  • ***
  • Mensajes: 187
Re: Problema con interrupción TIMER1 y PROTEUS
« Respuesta #5 en: 11 de Abril de 2012, 00:58:01 »
Muchas gracias. Me quedó re claro el error.  ((:-)) ((:-))


 

anything