Desbordamiento de Pila en Proteus.

Hola, tengo una duda con el desboradmiento de pila. Estuve haciendo un codigo en asm, y a la hora de simularlo en proteus, salta muchos mensajes de stack underflow, y esto se da en el return de la subrutina PulsadorLibre1. Para comprobar si era culpa de Proteus, utilice el simulador de MPLAB y lo mismo se queda colgado en return de las subrutinas. Espero me puedan ayudar. Les dejo el codigo

Código:
INICIO		bcf		STATUS,RP0		;Banco 0
			clrf	        PORTB			;Limpio salidas
			clrf	        PORTC			
			bsf		STATUS,RP0		;Cambio al banco 1
			clrf	        TRISB			;Puerta B como salida
			movlw	b\'00000110\'		;Puerta A digital
			movwf	ADCON1
			movlw	b\'11111111\'		;Puerta A entrada
			movwf	TRISA

		        btfss	PORTA,0			;Pulsante subir esta pulsado?
			bsf	PORTB,0			;Si
			btfss	PORTA,1			;Pulsante Bajar esta pulsado?
			BSF	PORTB,1		;Si
			call	PulsadorLibre1
			call	PulsadorLibre2
			goto	Inicio

PulsadorLibre1	btfss	PORTA,0		;Boton esta en 1
			call	PulsadorLibre1	;No
			return					;Si
	
PulsadorLibre2	btfss	PORTA,1		;Boton esta en 2
			call	PulsadorLibre2	;No
			return
                        end
 
Última edición:
Eso pasa porque estás ejecutando una llamada a la rutina dentro de si misma.
Para eso debes usar un goto y no otro call.

Prueba de la siguiente forma, si es que es ésto lo que quieres hacer:
PHP:
inicio
    bsf        STATUS,RP0        ; Banco 1
    movlw    b'00000110'        ; Conversores AD = Off
    movwf    ADCON1
    movlw    b'11111100'        ; RB0 y RB1 como salidas
    movwf    TRISB
    bcf        STATUS,RP0        ; Banco 0
    clrf    PORTB            ; Bits de salida del puerto B en 0

programa
    btfss    PORTA,0            ; Comprobar si RA0 está en 0
    call    PulsadorLibre1    ; Si, ir a "PulsadorLibre1"
    btfss    PORTA,1            ; No, comprobar si RA1 está en 0
    call    PulsadorLibre2    ; Si, ir a "PulsadorLibre2"
    goto    programa        ; No, regresar la rutina principal.

PulsadorLibre1
    bsf        PORTB,0
    return

PulsadorLibre2
    bsf        PORTB,1
    return

    end
 
Última edición:
buenas noches mi gente en esta oportunidad realicé un programa en css compiler de un reloj decreciente ya que así me es necesario, es una subrutina de otro programa que estoy armando, trabaja pero cuando tiene que repetir el ciclo se desborda la pila y me general una alerta en el simulador del isis proteus, de antemano le agradezco si tienen idea de como corregir este problema ya les paso el código para que lo vean

CSS:
#include <16f883.h>
#fuses xt, nowdt
#use delay (Clock=4Mhz)
#define LCD_DATA_PORT getenv("SFR:PORTC")
#define LCD_ENABLE_PIN  PIN_A0                                   
#define LCD_RS_PIN      PIN_A2                                   
#define LCD_RW_PIN      PIN_A1                                   
#include <lcd.c>
#use standard_io(c)
int16 desbordamiento=0;
int s=0;
int m=0; 
int c=0;

 void pausa(void)
            {
            lcd_gotoxy(1,2);
            lcd_putc("TIEMPO RESTATNTE:   pausa\n");
                        
         while(input(pin_b0)==0){                                                // pulsa tecla stop se retorna
           if(input(pin_b6)==1){                                                 //pulsa la tecla play retorna y sigue decrementando
           do{           
             }
             while(input(pin_b6)==1);
               c=0;
               return;
              }
           }
         }
        
    
 void configuracion(void)                                                        //:::::::::: Funci�n de Configuraci�n ::::::::::
      {
         enable_interrupts(int_ext);                                             //Habilitamos la interrupci�n   externa
         ext_int_edge(l_to_h);                                                   // se habilita la interrupcion ext. de bajo a alto     
         setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);                              //Preescaler 256 Timer0
         set_timer0(224);                                                         //Establecemos el timer0 a 224 para obtener 10ms
         enable_interrupts(int_timer0);                                          //Habilitamos la interrupci�n del timer0
         enable_interrupts(global);                                              //Habilitamos todas las interrupciones del PIC
      }
  
    void inicio(void)                                                               //Funci�n Aplicacion de se�al MENU RUN::::::::::
      {
         configuracion();
         lcd_putc('\f');
         lcd_gotoxy(1,1);
         lcd_putc("Aplic.        \n");
         lcd_gotoxy(28,1);
         lcd_putc("% 00\n"); 
         lcd_gotoxy(1,2);
         lcd_putc("TIEMPO RESTATNTE:       \n");
      
  
   while (TRUE)
      {
         lcd_gotoxy(26,2);
         printf(lcd_putc,"(%02u:%02u)",m,s);
          }     
         }
  
  
 void tiempo()
      {
         lcd_putc('\f');       
         lcd_gotoxy(8,1);
         lcd_putc("*** MENU DE TIEMPO ***\n");
         lcd_gotoxy(1,2);       
         lcd_putc("TIEMPO RESTATNTE:       \n"); 
      while(true){
            
         lcd_gotoxy(26,2);
         printf(lcd_putc,"(%02u:%02u)",m,s);
         delay_ms(200);
         lcd_gotoxy(26,2);
         printf(lcd_putc,"(  :%02u)",s);
         delay_ms(200);
        
      }
     return;
   }
 
 

   void main(void)
   {
        
      lcd_init();         
      enable_interrupts(int_rb); 
      enable_interrupts(int_ext);                                                //Habilitamos la interrupci�n   externa
      ext_int_edge(l_to_h);
      enable_interrupts(global);
      delay_ms(300);
      
      while(true)
      {
         lcd_gotoxy(4,1);       
         lcd_putc("\f      menu main       \n");
         delay_ms(1500);
         break;
      }
     tiempo();
    }
    
    
 #int_timer0
 void timer_reloj(void)                                                          //Funci�n de Interrupci�n Timer,RELOJ:::::::::
       {         
         desbordamiento++;
      if(desbordamiento==10)                                                     // es 100 para 1 seg, pero se coloca 10 para hacerlo dinamico en la simulacion
         {
         desbordamiento=0;
        
      if(s!=0){
         s--;
         }
        
      if(m==0&&s==0)
            {
               m=0;
               s=0;
               disable_interrupts(int_timer0);
               clear_interrupt(int_timer1);
               clear_interrupt(int_rb);
               clear_interrupt(int_ext);
               main();
            }     
      
      if(s==0)
         {
         s=59;
        
         if(m!=0){
            s=59;
            m--;
            }   
           }
         }
         set_timer0(224);                                                        //se carga el timer0 de nuevo para 10 mseg
      }
 

#int_RB
   ext_isr(){

      if(input(pin_b4)==1){
         do {
            }
         while(input(pin_b4)==1);
            m=m+1;
      if(m==60){
            m=60;
         }
      }
      
      if(input(pin_b5)==1){
         do {
            }
         while(input(pin_b5)==1);     
      if(m!=0){
            m=m-1;
          }   
       }
        
     if(input(pin_b6)!=0){
         do {
            }
         while(input(pin_b6)!=0);
     if(c==1){
             pausa(); 
             }
            c++;
          inicio();
         }
      if((input(pin_b0)==1)||(input(pin_b7)==1))
               {
               do {
            }
         while((input(pin_b0)==1)||(input(pin_b7)==1));
               s=0;
               m=0;
               disable_interrupts(int_timer0);
               clear_interrupt(int_timer1);
               clear_interrupt(int_rb);
               clear_interrupt(int_ext);             
               main();
               }
          
   }

errores.JPG
proyecto.JPGerrores.JPGproyecto.JPG
 
Eduardo, lo de "Investigar" es un trabajo que mandas para casa?, no soy el mas indicado para comentar estas cosas pero es la primera vez que veo llamar al main desde una interrupcion, siempre crei que es la funcion principal y de hay parte todo lo siguiete, sera una manera nueva de programar, por cierto, en mi opinion creo que es mas sencillo hacer un contador hacia atras, esta claro que hay muchas formas de hacerlo pero mucho codigo para esa tarea me parece.
 
Estoy tratando de hacer un reloj con lcd y solo con querer mostrar los números me aparece este error :
Código:
[PIC16 CORE] PC=0x0026. Stack underflow executing RETURN instruction. [U1]
[PIC16 CORE] PC=0x0016. Stack overflow executing CALL instruction. [U1]
Controller received command whilst busy. [LCD1]
[PIC16 CORE] PC=0x0026. Stack underflow executing RETURN instruction. [U1]
[PIC16 CORE] PC=0x0053. Stack overflow executing CALL instruction. [U1]
[PIC16 CORE] PC=0x0059. Stack underflow executing RETURN instruction. [U1]
[PIC16 CORE] PC=0x0051. Stack overflow executing CALL instruction. [U1]
[PIC16 CORE] PC=0x0059. Stack underflow executing RETURN instruction. [U1]
[PIC16 CORE] PC=0x0051. Stack overflow executing CALL instruction. [U1]
[PIC16 CORE] PC=0x0059. Stack underflow executing RETURN instruction. [U1]
[PIC16 CORE] PC=0x0051. Stack overflow executing CALL instruction. [U1]
[PIC16 CORE] PC=0x0059. Stack underflow executing RETURN instruction. [U1]
[PIC16 CORE] PC=0x0051. Stack overflow executing CALL instruction. [U1]
[PIC16 CORE] PC=0x0059. Stack underflow executing RETURN instruction. [U1]
[PIC16 CORE] PC=0x0051. Stack overflow executing CALL instruction. [U1]
[PIC16 CORE] PC=0x0059. Stack underflow executing RETURN instruction. [U1]
Controller received command whilst busy. [LCD1]
[PIC16 CORE] PC=0x0053. Stack overflow executing CALL instruction. [U1]
[PIC16 CORE] PC=0x0059. Stack underflow executing RETURN instruction. [U1]
[PIC16 CORE] PC=0x0053. Stack overflow executing CALL instruction. [U1]
[PIC16 CORE] PC=0x0059. Stack underflow executing RETURN instruction. [U1]
[PIC16 CORE] PC=0x0053. Stack overflow executing CALL instruction. [U1]
[PIC16 CORE] PC=0x0059. Stack underflow executing RETURN instruction. [U1]
[PIC16 CORE] PC=0x0053. Stack overflow executing CALL instruction. [U1]
[PIC16 CORE] PC=0x0059. Stack underflow executing RETURN instruction. [U1]
Controller received command whilst busy. [LCD1]
[PIC16 CORE] PC=0x0053. Stack overflow executing CALL instruction. [U1]
[PIC16 CORE] PC=0x0059. Stack underflow executing RETURN instruction. [U1]
[PIC16 CORE] PC=0x0053. Stack overflow executing CALL instruction. [U1]
[PIC16 CORE] PC=0x0059. Stack underflow executing RETURN instruction. [U1]
[PIC16 CORE] PC=0x0053. Stack overflow executing CALL instruction. [U1]
[PIC16 CORE] PC=0x0059. Stack underflow executing RETURN instruction. [U1]
[PIC16 CORE] PC=0x0053. Stack overflow executing CALL instruction. [U1]
[PIC16 CORE] PC=0x0059. Stack underflow executing RETURN instruction. [U1]
Controller received command whilst busy. [LCD1]
Adjunto el asm y las librerías que usé.
 

Adjuntos

  • Reloj LCD.rar
    4.6 KB · Visitas: 6
Estoy tratando de hacer un reloj con lcd y solo con querer mostrar los números me aparece este error

El PIC16F84 solo tiene 8 niveles en la "pila", usa la depuración corriendo el programa paso a paso, si tienes anidadas mas de 8 llamadas (CALL) el programa es inestable (Se pierde la primera dirección de retorno).

Trata de programarlo de manera que no haya tantas llamadas anidadas o, al menos, que no supere la pila (Un call que llama a otro lado donde aparece otro call que llama a otro lado etc...).
 
El PIC16F84 solo tiene 8 niveles en la "pila", usa la depuración corriendo el programa paso a paso, si tienes anidadas mas de 8 llamadas (CALL) el programa es inestable (Se pierde la primera dirección de retorno).

Trata de programarlo de manera que no haya tantas llamadas anidadas o, al menos, que no supere la pila (Un call que llama a otro lado donde aparece otro call que llama a otro lado etc...)
no entendi, ¿que no puede haber 8 llamados en todo el codigo o en una subrutina?
¿Y el diagrama o simulación?
no se si esto es lo que pediste pero el proyecto no me lo deja pasar
Ayudaría que subas el código que usaste en la simulación, porque el que subiste es cualquier verdura (ni compila)
xdd, habia pasado dos librerias y el asm(convertidas en txt) pero no se que paso, hay lo paso de nuevo
 

Adjuntos

  • Screenshot_1.png
    Screenshot_1.png
    13.7 KB · Visitas: 1
  • Screenshot_2.png
    Screenshot_2.png
    15.1 KB · Visitas: 1
  • LCD.txt
    11.4 KB · Visitas: 1
  • relojlcd.txt
    387 bytes · Visitas: 4
  • RETARDOS.txt
    3.5 KB · Visitas: 1
Última edición:
A ver... Vos subiste esto:
Código:
LIST P=16F84A
INCLUDE "P16F84A.INC"
ORG 0
CBLOCK 0X0C
ENDC

INICIO
CALL LCD_Inicializa
START
MOVLW 1
CALL LCD_PosicionLinea1
MOVLW '0'
CALL LCD_Caracter
MOVLW '0'
CALL LCD_Caracter
MOVLW ':'
CALL LCD_Caracter
MOVLW '0'
CALL LCD_Caracter
MOVLW '0'
CALL LCD_Caracter

¿Con qué lo compilaste?
 
A ver... Vos subiste esto:
Código:
LIST P=16F84A
INCLUDE "P16F84A.INC"
ORG 0
CBLOCK 0X0C
ENDC

INICIO
CALL LCD_Inicializa
START
MOVLW 1
CALL LCD_PosicionLinea1
MOVLW '0'
CALL LCD_Caracter
MOVLW '0'
CALL LCD_Caracter
MOVLW ':'
CALL LCD_Caracter
MOVLW '0'
CALL LCD_Caracter
MOVLW '0'
CALL LCD_Caracter

¿Con qué lo compilaste?
con el mplab
 
no entendi, ¿que no puede haber 8 llamados en todo el codigo o en una subrutina?

Cada vez que se usa "CALL" se guarda la dirección en la pila para que el microcontrolador sepa donde volver al usar "RETURN".

Si se usa un "CALL" para ir a una subrutina se usa un lugar momentáneamente en la pila que será liberado cuando se use "RETURN". El problema viene si se usa un "CALL" a una subrutina -1 lugar usado en la pila- y antes de volver en la rutina se usa otro "CALL" -ahora hay 2 lugares ocupados en la pila-. Ahora, si la tercera subrutina usa otro "CALL" ya se tendrán 3 lugares ocupados de los 8 que hay. Ese proceso se llama anidar.

El problema viene si en la pila se tratan de guardar mas de 8 direcciones de retorno, en caso de pasar eso se van perdiendo las primeras y cuando el microcontrolador quiera volver no sabrá a donde (En realidad si, pero no será a la dirección correcta y el programa se vuelve loco).

Como tu usas un simulador, este sabe si se están usando mas de 8 lugares de la pila y te da ese error.

Deberás ver donde esta pasando eso y corregirlo.

Por cierto, si usas "CALL", como dije se usa una memoria que sera liberada al usar "RETURN" por lo que puedes crear miles de subrutinas sin problemas, el problema viene cuando se anidan.
 
Cada vez que se usa "CALL" se guarda la dirección en la pila para que el microcontrolador sepa donde volver al usar "RETURN".

Si se usa un "CALL" para ir a una subrutina se usa un lugar momentáneamente en la pila que será liberado cuando se use "RETURN". El problema viene si se usa un "CALL" a una subrutina -1 lugar usado en la pila- y antes de volver en la rutina se usa otro "CALL" -ahora hay 2 lugares ocupados en la pila-. Ahora, si la segunda subrutina usa otro "CALL" ya se tendrán 3 lugares ocupados de los 8 que hay. Ese proceso se llama anidar.

El problema viene si en la pila se tratan de guardar mas de 8 direcciones de retorno, en caso de pasar eso se van perdiendo las primeras y cuando el microcontrolador quiera volver no sabrá a donde (En realidad si, pero no será a la dirección correcta y el programa se vuelve loco).

Como tu usas un simulador, este sabe si se están usando mas de 8 lugares de la pila y te da ese error.

Deberás ver donde esta pasando eso y corregirlo.

Por cierto, si usas "CALL", como dije se usa una memoria que sera liberada al usar "RETURN" por lo que puedes crear miles de subrutinas sin problemas, el problema viene cuando se anidan.
Ok muchas gracias por la explicación, aunque ese no es el problema en la subrutinas solo uso goto
 
Ok muchas gracias por la explicación, aunque ese no es el problema en la subrutinas solo uso goto

Usas librerías que probablemente usen call, como no sabes cuantos nidos tienen puedes terminar en un overflow.

También pasa al olvidarse algún return.

Si crees que no es el problema usa otro simulador porque este te esta gritando que se desbordo la pila.


También pasa algo similar al usar un programa de mas de 256 instrucciones o, mejor explicado, tratar de saltar (CALL) desde una pagina a otra (problema de paginación). -Creería que el mensaje de error debería ser otro pero como no uso mucho proteus no sabría decirlo, pero a mi me indicaría lo primero-.
 
me explique mal, el return lo uso siempre pero quise decir que si tendría que usar el call de nuevo, no lo uso y uso el goto
Si usas el goto en lugar del call y volves con un return vas a lograr un stack underflow...que es el otro error que tenes.
Vas a tener que estudiar bastaaaante antes de seguir con los experimentos descabellados...
 
Atrás
Arriba