TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: Pchuqui_1 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;
}
}
}
}
}
-
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;
}
-
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
-
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.
-
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.
-
Muchas gracias. Me quedó re claro el error. ((:-)) ((:-))