TODOPIC

Microcontroladores PIC => Almacén del Assembler => Mensaje iniciado por: microcom en 04 de Octubre de 2006, 16:55:28

Título: CALL vs RETURN
Publicado por: microcom en 04 de Octubre de 2006, 16:55:28
supuestamente  hablaN que despues de un call debe venir un return y si no es asi que pasa?
puesto que si yo acciono un pulsador en preguntas ese return no se ejecuta.
esto lo hice una vez para que un pulsador quedará sencibles a la pulsada.
o de que otra manera ese  pulsador puede quedar sensible  que el pic lo atienda inmediatamente.
ejemplo:
 
call retardo

retardo

         movlw .250
        movwf reg1
        decfsz  reg1
        goto  preguntas
        return

preguntas
       btfsc porta,0
       goto   rot1
       btfsc porta,1
       goto   rot2
       btfsc porta,2
       goto   rot3
       goto   retardo

gracias caballeroS.
le agradesco la colaboracion
Título: Re: CALL vs RETURN
Publicado por: maunix en 04 de Octubre de 2006, 17:10:11
supuestamente  hablaN que despues de un call debe venir un return y si no es asi que pasa?
El call carga en la PILA (o stack) la dirección desde donde se está llamando a la subrutina.  Esto permite que al ejecutar RETURN el PIC tome esa dirección+1 para seguir ejecutando instrucciones (o +2 en caso de los PIC18). 

El return no tiene que venir necesariamente después del call, debe venir en "algun momento" a los fines de que el pic vacíe su stack y el software siga su curso normal.

El CALL se usa para llamar a una subrutina pero el software debe continuar donde estamos y no en otro lado.   Es un "salto con memoria" por decirlo así, que nos permite volver al punto inmediato después de donde estabamos antes de llamar a la subrutina.

El GOTO en cambio es un salto a otro lugar, pero no tiene 'registro o referencia' desde donde venía.


puesto que si yo acciono un pulsador en preguntas ese return no se ejecuta.
esto lo hice una vez para que un pulsador quedará sencibles a la pulsada.
o de que otra manera ese  pulsador puede quedar sensible  que el pic lo atienda inmediatamente.
ejemplo:
 
call retardo

retardo

         movlw .250
        movwf reg1
        decfsz  reg1
        goto  preguntas
        return

preguntas
       btfsc porta,0
       goto   rot1
       btfsc porta,1
       goto   rot2
       btfsc porta,2
       goto   rot3
       goto   retardo

En tu caso, haces un call a "retardo".  Inmediatamente en retardo, pones una variable en 250 y la decrementas.  Si la variable es 0, haces el RETURN y el software regresa a la instrucción justo por debajo de "call retardo" (en este pequeño ejemplo volvería a ejecutar retardo: porque no hay mas instrucciones después de call retardo)

Sigamos analizando.  Si RA0, RA1 o RA2 están en 1, el flujo del programa seguirá por rot1, rot2 y rot3.  Si nunca nunca se hace un return, el stack quedará cargado con un valor que no tiene mayor sentido.

No se qué se haga en rot1, rot2 y rot3, pero lo más certero sería que en esa parte "haga algo" y luego haga un return, para volver justamente a donde se llamó a la subrutina.

Espero haber aclarado la duda, sino, vuelve a preguntar.   :)
Título: Re: CALL vs RETURN
Publicado por: microcom en 05 de Octubre de 2006, 15:24:05
bueno muy bien entendido caballero.
al momento de ejecutar el call y no el  return de ese call y el programa sigue y para estar seguro de que ese return que no hice no me afecte el programa como se haria para eliminar ese return que queda esparando en el call.

se que es confusa la pregunta

gracias caballero.
Título: Re: CALL vs RETURN
Publicado por: maunix en 05 de Octubre de 2006, 16:55:12
bueno muy bien entendido caballero.
al momento de ejecutar el call y no el  return de ese call y el programa sigue y para estar seguro de que ese return que no hice no me afecte el programa como se haria para eliminar ese return que queda esparando en el call.

se que es confusa la pregunta

gracias caballero.

Es que en ese caso, no debieras usar el call, sino un GOTO.   

Si no quieres hacer 'return' llamar a la subrutina con un goto. 

Si quieres hacer un call para que en algun momento vuelva a donde lo llamaste, debieramos ver otro ejemplo porque el qu e subiste está incompleto.   :)
Título: Re: CALL vs RETURN
Publicado por: microcom en 05 de Octubre de 2006, 18:37:33
ahi va caballero.

retardo
   movlw   .200
   movwf   contador
ggg   decfsz  contador,1
   goto     ooo
   return
ooo   btfsc     porta,1
   goto    PRIMER_ROT
           btfsc     porta,2
   goto   SEGUNDO_ROT
   btfsc     porta,3
   goto    TERCER_ROT
   goto       ggg       
     

   

UNO_SEG 
   movlw     .14       
          movwf     PDel0   
PLoopx    movlw     .72   
           movwf     PDel1   
PLoopy     movlw     .247     
           movwf     PDel2 
PLoopz     clrwdt             
   btfsc     porta,0
   goto      FIJO   
           btfsc     porta,2
   goto   SEGUNDO_ROT
   btfsc     porta,3
   goto   TERCER_ROT
   decfsz    PDel2, 1 
           goto      PLoopz   
           decfsz    PDel1,  1
          goto      PLoopy   
          decfsz    PDel0,  1
           goto      PLoopx   
PDelL1     goto PDelLx       
PDelLx     clrwdt             
        return             


TRES_SEG  
   movlw     .67     
           movwf     PDel0   
PLoop0     movlw     .91     
           movwf     PDel1   
PLoop1     movlw     .122   
           movwf     PDel2     
PLoop2     clrwdt           
   btfsc     porta,0
   goto     FIJO   
                btfsc     porta,1
   goto   PRIMER_ROT
   btfsc     porta,3
   goto   TERCER_ROT
           decfsz    PDel2, 1
           goto      PLoop2 
          decfsz    PDel1,  1
           goto      PLoop1   
           decfsz    PDel0,  1
           goto      PLoop0   
PDelL6     goto PDelL2       
PDelL2     clrwdt             
           return       

CINCO_SEGUNDOS 
   movlw     .165     
           movwf     PDel0   
PLoopv     movlw     .41     
          movwf     PDel1   
PLoopw  movlw     .147     
           movwf     PDel2   
PLoopm  clrwdt           
           clrwdt             
   btfsc     porta,0
   goto      FIJO  
                btfsc     porta,1
   goto    PRIMER_ROT
   btfsc     porta,2
   goto    SEGUNDO_ROT
           decfsz    PDel2, 1
           goto      PLoopm   
           decfsz    PDel1,  1
           goto      PLoopw   p
           decfsz    PDel0,  1
           goto      PLoopv   
           return             



EMPEZAR                         
                  btfss     porta,0         
                goto      UNO_ROT
   call       anti
   btfss     porta,0
   goto      UNO_ROT 
                goto  FIJO
UNO_ROT  btfss     porta,1       
               goto     DOS_ROT
   call       anti
   btfss     porta,1     
   goto       DOS_ROT
                goto       PRIMER_ROT

DOS_ROT  btfss     porta,2       
                  goto      TRES_ROT   
                call      anti
   btfss     porta,2     
   goto       TRES_ROT
                  goto      SEGUNDO_ROT

TRES_ROT btfss     porta,3       
               goto      EMPEZAR
   call      anti
   btfss     porta,3     
   goto      EMPEZAR
                   goto      TERCER_ROT




FIJO   movlw   H'ff'
   movwf   portb
   call    retardo
   goto   FIJO

PRIMER_ROT 
   clrf      contador
repit         movf       contador,0
   call      tabla
   movwf  portb
                call      uno_seg
                incf     contador,1
                movlw  .7
   xorwf  contador,0
                   btfss   status,2
                goto     repit
    goto    PRIMER_ROT 



                            
SEGUNDO_ROT       
   clrf      contador
repit1          movf       contador,0
   call      tabla
   movwf  portb
                  call      tres_seg
                 incf     contador,1
                 movlw  .7
   xorwf  contador,0
                btfss   status,2
                goto     repit1
    goto    segundo_rot                                               

TERCER_ROT  
   clrf      contador
repit2       movf       contador,0
   call      tabla
   movwf  portb
                  call      cinco_seg
                incf     contador,1
                movlw  .7
   xorwf  contador,0
                   btfss   status,2
                goto     repit2
    goto    TERCER_ROT                                              

      end


muchas gracias


Título: Re: CALL vs RETURN
Publicado por: maunix en 05 de Octubre de 2006, 21:58:37
microcom,

¿Ese es todo el código?

¿Dónde comienza?
Título: Re: CALL vs RETURN
Publicado por: microcom en 06 de Octubre de 2006, 20:07:50
caballero disculpas por el descuido en el programa

omiti unas etiquetas de inicio para aminarar el espacio en el programa.

el programa empieza en empezar y ahi pregunto por los pulsadores y cada pulsador me lleva a 4 diferentes rutinas.
ya al momento de darles el retardo requerido ahi tambien coloco las preguntas para los pulsadores.


ya puedes ver el programa resalté con mayusculas las etiquetas.
 
saludos y muchas gracias .
Título: Re: CALL vs RETURN
Publicado por: BrunoF en 08 de Octubre de 2006, 01:20:00
Perdona microcom, pero se ve que ando lelo hoy.
¿Que es lo que queres reformar de ese programa?
Saludos.
Título: Re: CALL vs RETURN
Publicado por: maunix en 09 de Octubre de 2006, 08:22:57
Perdona microcom, pero se ve que ando lelo hoy.
¿Que es lo que queres reformar de ese programa?
Saludos.

Te cuento un poco Bruno.  Este tema surge de una inquietud que me manifestó microcom en privado sobre si en un determinado software un call "no seguido" de un return podría afectar al "stack".

Le dije que su pregunta era conveniente subirla al foro ya que dicha duda podría ser la de algún otro usuario. 

Aún no he tenido tiempo de analizar y simular su software, pero básicamente lo que hay que ver es si están bien encadenados los calls y gotos de manera de que luego de algunas cuantas ejecuciones el stack siga cómo debe ser y no se llene innecesariamente porque en algún "camino" de los saltos de decisión se haga un call pero que se retorne por algún goto en vez de su correspondiente return.

PD: microcom , como he dicho no le he respondido por falta de tiempo pero no por falta de interés en darte una mano con este software.    :?

Bruno, aclaro que tampoco me molesta que otro postee una solución al tema, ya que no considero "invasión de post" el que otro quiera aportar algo más :)



Título: Re: CALL vs RETURN
Publicado por: BrunoF en 09 de Octubre de 2006, 18:33:18
Bueno, por lo que veo hay errores.
Se van a producir Overflows del STACK.
Dejame ver si me hago un tiempo y lo corrijo.
Saludos.
Título: Re: CALL vs RETURN
Publicado por: microcom en 19 de Octubre de 2006, 18:09:12
caballeros
para anular ese return que se puede hacer.
o sea despues del call si no biene un return como se hace para normalizarl a pila sin llevar a cabo ese return.

o eso no tiene solucion sino es con un return

gracias y saludos.

Título: Re: CALL vs RETURN
Publicado por: BrunoF en 20 de Octubre de 2006, 23:49:56
¿Cual es el problema microcom?

Si cargas el STACK con un CALL, tenes que liberarlo con un RETURN o un RETLW.
Un RESET tambien produce una descarga completa del STACK, pero bueno...¡hace un RESET!

Saludos.
Título: Re: CALL vs RETURN
Publicado por: maunix en 21 de Octubre de 2006, 11:34:51
caballeros
para anular ese return que se puede hacer.
o sea despues del call si no biene un return como se hace para normalizarl a pila sin llevar a cabo ese return.

o eso no tiene solucion sino es con un return

gracias y saludos.



microcom Como te dijo bruno , en los 16F la única forma sería organizar bien el código.  Siempre de alguna forma debes corresponder con un return al call.  Si por alguna razón te queda mal es porque hay un problema de lógica.

En los 18F podrías hacer una triquinuela con el stack (porque se tiene acceso al puntero del stack ) pero no es recomendable para nada.

Título: Re: CALL vs RETURN
Publicado por: microcom en 23 de Octubre de 2006, 16:56:54
caballeros muchas gracias por lo correspondido y las explicaciones dadas.

como se puede hacer para que un pulsador o pregunta se a atendida inmediatamente.
sin recurrir al las interrupciones.
para un retardo de 1seg tiene que pasar este tiempo para que el pulsador sea atendido
yo sierta ocacion dentro de un retardo coloque un pregunta y el pulsador quedó inmediatamenta sencible a la puldada.esa pila quedo cargada con un call
y el programa no tubo inconvenientes.

caballeros disculpen si las preguntas son poco invenientes o triviales.


saludos desde sucre.
Título: Re: CALL vs RETURN
Publicado por: BrunoF en 23 de Octubre de 2006, 18:18:12
caballeros muchas gracias por lo correspondido y las explicaciones dadas.

como se puede hacer para que un pulsador o pregunta se a atendida inmediatamente.
sin recurrir al las interrupciones.
para un retardo de 1seg tiene que pasar este tiempo para que el pulsador sea atendido

Ok. Dejame ver si entendi bien.

Quieres revisar el estado de un pulsador, sin necesitar de interrupciones.
Si el pulsador es presionado, debe mantenerse al menos 1 segundo presionado para que se ejecute cierta rutina. Si se suelta antes de completado el segundo, se ignora la pulsación.

Pensemos lógicamente.

Inicio:

¿Pulsador Presionado?
NO -->  Volver a Inicio
SI --> ¿Pulsador presionado durante al menos 1 segundo?
           NO--> Ignorar pulsacion y volver a Inicio
           SI-- > Ejecutar rutina predefinida para el pulsador.

Pensemoslo ahora, un poco más orientado al código que debes generar.
Si RA0 = 1 pulsador no presionado
Si RA0 = 0 pulsador presionado

Código: ASM
  1. ;Registros a declarar:
  2.  
  3. Flag    EQU     0x??
  4. PDel0   EQU     0x??
  5. Pdel1   EQU     0x??
  6. Pdel2   EQU     0x??
  7.  
  8.  
  9. ;////////////////////////////////////////////////////////////////
  10.  
  11. ;Porcion de programa:
  12.  
  13. Inicio
  14.  
  15.         btfss   PORTA,0                 ;¿pulsador presionado?
  16.         call    CheckearPulsador        ;SI
  17.  
  18.         goto    Inicio                  ;NO
  19.  
  20. ;////////////////////////////////////////////////////////////////
  21.  
  22. CheckearPulsador
  23.         call    Antirebote              ;Esperar durante 60ms para evitar rebotes mecánicos
  24.         call    Demora1Seg              ;Revisar si se mantiene durante al menos 1 segundo presionado
  25.         movwf   Flag                    ;Volcar valor retornado por la funcion previa en la variable Flag
  26.         movf    Flag,F                  ;Sobreescribir contenido de Flag para afectar flag Z
  27.         btfsc   STATUS,Z                ;Aqui: Z= 1 indica que se solto antes del segundo. Z = 0 indica que se cumplio el segundo presionado
  28.         return                          ;Z= 1. Volver sin hacer nada
  29.  
  30.         nop                             ;Z=0. Aqui va el codigo de lo que debe hacerse
  31.         return                          ;Volver para descargar el STACK
  32.  
  33. ;////////////////////////////////////////////////////////////////
  34.  
  35.  
  36. Antirebote
  37.         movlw   .66
  38.         movwf   PDel0
  39. PLoop1  movlw   .181
  40.         movwf   PDel1
  41. PLoop2  clrwdt
  42.         clrwdt
  43.         decfsz  PDel1,1
  44.         goto    PLoop2
  45.  
  46.         decfsz  PDel0,1
  47.         goto    PLoop1
  48.  
  49.         clrwdt
  50.         return
  51.  
  52. ;////////////////////////////////////////////////////////////////
  53.  
  54. Demora1Seg
  55.         movlw   .14
  56.         movwf   PDel0
  57. PLoop0  movlw   .72
  58.         movwf   PDel1
  59. PLoop1  movlw   .247
  60.         movwf   PDel2
  61. PLoop2
  62.         btfsc   PORTA,0 ;¡REVISAR PULSADOR PRESIONADO!
  63.         retlw   0       ;SE HA SOLTADO ANTES DEL SEGUNDO. Volver con FALSE(0)
  64.  
  65.         decfsz  PDel2,1
  66.         goto    PLoop2
  67.  
  68.         decfsz  PDel1,1
  69.         goto    PLoop1
  70.  
  71.         decfsz  PDel0,1
  72.         goto    PLoop0
  73.  
  74. PDelL1  goto    PDelL2
  75. PDelL2  clrwdt
  76.         retlw   1       ;Se mantuvo presionado durante un segundo. Volver con TRUE(1)
  77.  
  78. ;////////////////////////////////////////////////////////////////

Con respecto a lo otro.
Si no descargas correctamente el STACK...

Ejemplo:

Código: ASM
  1. Inicio
  2.  
  3.         btfss   PORTA,0
  4.         call    Pulsado
  5.  
  6.         goto    Inicio
  7.  
  8. ;////////////////////////////////////////////////////////////////
  9.  
  10. Pulsado
  11.         movlw   .1
  12.         movwf   PORTB
  13.         goto    Inicio
  14.  
  15. ;////////////////////////////////////////////////////////////////


El programa funcionara bien, hasta que presiones por novena vez el pulsador. En este punto, el PIC volvera al vector 0x00 ya que produjiste un OVERFLOW del STACK

En este otro ejemplo, un UNDERFLOW del STACK (produce lo mismo que el OVERFLOW)

Código: ASM
  1. Inicio
  2.  
  3.         btfss   PORTA,0
  4.         goto    Pulsado
  5.  
  6.         goto    Inicio
  7.  
  8.  
  9. ;////////////////////////////////////////////////////////////////
  10.  
  11. Pulsado
  12.         movlw   .1
  13.         movwf   PORTB
  14.         return
  15.  
  16. ;////////////////////////////////////////////////////////////////


Saludos.
Título: Re: CALL vs RETURN
Publicado por: microcom en 23 de Octubre de 2006, 19:18:45
brunof muchas gracias por lo recomendado
al estoy atento a sus explicaciones
retlw al ser pusado un pulsador cualquira me da a entender que yo puedo preguntar en ese retardo por tres pulasores
retlw  .1  para   ra0
retlw  .2   para ra1
retlw   .3    para ra2


UNO_SEG 
   movlw     .14       
          movwf     PDel0   
PLoopx    movlw     .72   
           movwf     PDel1   
PLoopy     movlw     .247     
           movwf     PDel2 
PLoopz     clrwdt             
   btfsc     porta,0
   retlw      .1
           btfsc     porta,2
   retlw      .2

   btfsc     porta,3
   retlw      .3

   decfsz    PDel2, 1 
           goto      PLoopz   
           decfsz    PDel1,  1
          goto      PLoopy   
          decfsz    PDel0,  1
           goto      PLoopx   
PDelL1     goto PDelLx       
PDelLx     clrwdt             
        return             



al ser puldada cualquiera de esos pulsadores el programas vuelve con el retlw cargago con x# y lo comparo para mandar el progarama segun el numero cargado en retlw


movwf  fag
movlw .1
xorwf flag,0
btfsc  status,2
goto    prog1
movlw  .2
xorwf  flag,0
btfsc  status,2
goto   prog2
movlw  .3
xorwf  flag,0
btfsc  status,2
goto   prog3
movlw  .4
xorwf  flag,0
btfsc  status,2
goto   prog3
goto   siga

muchas gracias

Título: Re: CALL vs RETURN
Publicado por: BrunoF en 24 de Octubre de 2006, 01:18:01
Hola microcom.

Ahora me agregaste más pulsadores. Así no vale. :D
Lamentablemente ese algorítmo no va a funcionar como queres. Fijate que estas poniendo 3 condiciones dentro de la demora. Para que transcurra el segundo entero de demora necesitarias tener mantenidos los 3 pulsadores simultáneamente sin soltar ninguno.

Fijate siguiendo la lógica del código que si al menos un pulsador no está presionado el programa sale del retardo ignorando el resto de los pulsadores.

Una cosa más. En el ejemplo que yo te pase, el retardo se mantenía en 1 segundo aprox. Ojo con eso. Mira que acá agregaste más lineas de las que tenía calculada la rutina de demora original. Tenes que recalcularla si necesitás mucha precisión.



Yo lo haría así:


Código: ASM
  1. movlw   b'00001111'     ;indiquemos los bits a revisar del PUERTOA!(RA0,RA1,RA2,RA3)
  2.         call    UNO_SEG
  3.  
  4.         btfsc  Mascara,0        ;Pulsador RA0 mantenido durante 1 seg?
  5.         goto    prog1           ;Si. Saltar a prog1
  6.        
  7.         btfsc  Mascara,1        ;Pulsador RA1 mantenido durante 1 seg?
  8.         goto   prog2            ;Si. Saltar a prog2
  9.  
  10.         btfsc  Mascara,2        ;Pulsador RA2 mantenido durante 1 seg?
  11.         goto   prog3            ;Si. Saltar a prog3
  12.  
  13.         btfsc  Mascara,3        ;Pulsador RA3 mantenido durante 1 seg?
  14.         goto   prog3            ;Si. Saltar a prog3
  15.  
  16.         goto   siga
  17.  
  18. UNO_SEG  
  19.         movwf   Mascara         ;Volquemos los bits a revisar del PUERTOA en una variable
  20.         movlw     .14      
  21.         movwf     PDel0    
  22. PLoopx  movlw     .72    
  23.         movwf     PDel1  
  24. PLoopy  movlw     .247    
  25.         movwf     PDel2  
  26.  
  27. PLoopz  comf    PORTA,W         ;invertir bits del registro PORTA y guardarlos en W
  28.         andwf   Mascara,F       ;Multiplicacion de los bits de ambos registros
  29.         btfsc   STATUS,Z        ;Revisar si no hay ningun pulsador presionado.
  30.         return                  ;Nada presionado. Volver.
  31.  
  32.         decfsz  PDel2, 1  
  33.         goto    PLoopz  
  34.         decfsz  PDel1,  1
  35.         goto    PLoopy  
  36.         decfsz  PDel0,  1
  37.         goto    PLoopx    
  38. PDelL1  goto    PDelLx        
  39. PDelLx  clrwdt            
  40.         return

Si hay instrucciones a mi parecer útiles en la programación, son las de comparación lógica. Siempre me ha facinado emplearlas y combinarlas entre sí para obtener resultados asombrosos.

El potencial de las instrucciones AND, IOR y XOR usados correctamente es enorme.

Y parece poco código, pero esa es la magia de estas instrucciones.

Te explíco el funcionamiento.

Primero se carga W poniendo en 1 todos los bits análogos a los del PUERTOA de los cuales se desea saber si se mantiene 1 seg presionado el pulsador.
El resto se pone en 0.

Ahora llama a la subrutina UNO_SEG y vuelco ese valor de W en la variable Mascara.

Dentro del retardo UNO_SEG lo primero que hago es complementar el registro PORTA.
Esto invierte todos los bits del PUERTOA. Los 1 valdrán ahora 0 y los 0 valdrán 1.
Guardo el resultado de dicho complemento en W para compararlo con la variable Mascara.
Haciendo una AND entre W y Mascara, obtienes el resultado de una multiplicación bit a bit.
Por lo tanto, lo que hago allí es:
Si bit de Mascara Y bit Puerto A AMBOS en alto ENTONCES: bit de Mascara en alto. Sino: bit de Mascara en bajo.

Lo importante de la AND, en este caso, es que comence controlando una de las variables a multiplicar: Mascara.
Si durante el retardo se suelta un pulsador, ese bit de Mascara pasará a valer 0( recordemos que 0 * X = siempre 0) y ese bit de Mascara no hay manera que vuelva a valer 1 dentro de la subrutina UNO_SEG.

Si se ha mantenido durante el segundo un pulsador(o más de uno) en PORTA sin soltarlo, ese bit de mascara saldra del retardo valiendo 1.

El btfsc STATUS,Z hace que si no hay ningun pulsador presionado entre los seleccionados, salga de la subrutina antes de esperar el segundo completo.

Saludos.












Título: Re: CALL vs RETURN
Publicado por: BrunoF en 24 de Octubre de 2006, 01:24:02
PD: Seguimos con la misma logica. Cuando se presiona un pusador, ese bit del Puerto A se pone en 0.
Saludos.
Título: Re: CALL vs RETURN
Publicado por: microcom en 24 de Octubre de 2006, 16:29:23
buena caballero y yo que me encontraba 0.00001% de estas instrucciones y ejemplos que me estas indicando estan callendo en el punto.

ademas siempre tengo la costumbre de colocar una resistencia a tierra y preguntar por unos pero eso no es un inconveniente en esto..

bueno ahi biene la pregunta si yo pregunto por unos o sea coloco una resistencis a tierra y conecto el pulsador a vcc. entonces cogeria

clrf    mascara
movf   porta,0
andwf mascara,1
btfss   status,2
return
sigue el retardo

ahi se eliminaria le complemento de comf  porta ya que no seria necesario.


como el puerto esta a tierra y al hacer AND con mascara que tambien es 0
se me activa el bit 2 de status lo cual no hay ningun pulsador presionado y el progarama sigue su retardo normal hasta que se acabe.
siguen rotando los leds con 5seg de retardo y sigo preguntado.

al salir del retardo por un pulsador
btfsc   mascara,0
goto    primer
btfsc   mascara,1
goto    segundo
btfsc   mascara,2
goto    tercer
 
caballero digame como boy .

el retardo sigue si no pulso ningun pulsador ya aqui no se toma en cuenta el tiempo pulsado en el pulsador si no que se debe atender el pulsador inmediatamente sin esperar nada.

con el programa que usted me corrigio en el otro link que el problema era del direccines generales del pic 16f873A.

tengo un retardo de 5seg y como la pregunta de los pulsadores la tengo es fuera de retardo tengo que demorar un largo rato presionando culaquier pulsador para que sea atendido.

y con esta explicacion ya se como es atendido inmediatemente sin alterar el stack de la pila y reducindo el programa.

caballero si no es un  inconveniente de seguirle preguntando de esto ya que me quedan mas dudas.

gracias y saludos

Título: Re: CALL vs RETURN
Publicado por: micro_cadaver en 24 de Octubre de 2006, 17:06:52
hola microcom, estaba siguiendo tu post, jejeje me perdi no se donde, me puedes mandar tu programa final (bueno el q tienes hasta ahora) para revisarlo, tambien quiero colaborar, es una epidemia creo  :mrgreen:
Título: Re: CALL vs RETURN
Publicado por: microcom en 24 de Octubre de 2006, 17:30:44
hola micro_cadaver  no es un programa en si sino que son situaciones que estava tomando como herradas.

1) despues de un call  se bebe terminar la seccion con un return o retlw nada de goto ya que la pila se carga con cada call que hagas y se esta no es basiada el programas se vuelve loco despues de no se si  8call.
2)yo incluia dentro de un retardo un goto y nunca terminaba con un return y como no hacia eso sino 3veces el programa no presentaba problemas y que despues de 9veces de hacer eso ahi venia el problema.

3) lo demas es saber como incluir una pregunta dentrto de un call sin alterar el stack.
como se observa en los ejemplos que hacer brunof.

4) gracias micro_Cadaver  por el espirutu colabarador y ademas el interes de ayudar es siempre grande  y seo es lo que admiro de los colegas del  foro.

5) el programa se hace mas elegante con una buena utlizacion de instrucciones de AND; XOR: IOR y ademas se economizan espacios y lineas.

5) saludos y gracias.
Título: Re: CALL vs RETURN
Publicado por: maunix en 24 de Octubre de 2006, 22:14:38
microcom me pone muy contento que hayas entendido el tema.

Son cosas que parecen simples pero no lo son tanto cuando uno comienza, cuesta acostumbrarse a esta forma de pensar así que bienvenido sea que lo hayas comprendido.   :)
Título: Re: CALL vs RETURN
Publicado por: BrunoF en 25 de Octubre de 2006, 00:09:22
buena caballero y yo que me encontraba 0.00001% de estas instrucciones y ejemplos que me estas indicando estan callendo en el punto.

ademas siempre tengo la costumbre de colocar una resistencia a tierra y preguntar por unos pero eso no es un inconveniente en esto..

bueno ahi biene la pregunta si yo pregunto por unos o sea coloco una resistencis a tierra y conecto el pulsador a vcc. entonces cogeria

clrf    mascara
movf   porta,0
andwf mascara,1
btfss   status,2
return
sigue el retardo

ahi se eliminaria le complemento de comf  porta ya que no seria necesario.


como el puerto esta a tierra y al hacer AND con mascara que tambien es 0
se me activa el bit 2 de status lo cual no hay ningun pulsador presionado y el progarama sigue su retardo normal hasta que se acabe.
siguen rotando los leds con 5seg de retardo y sigo preguntado.

al salir del retardo por un pulsador
btfsc   mascara,0
goto    primer
btfsc   mascara,1
goto    segundo
btfsc   mascara,2
goto    tercer
 
caballero digame como boy .

el retardo sigue si no pulso ningun pulsador ya aqui no se toma en cuenta el tiempo pulsado en el pulsador si no que se debe atender el pulsador inmediatamente sin esperar nada.

con el programa que usted me corrigio en el otro link que el problema era del direccines generales del pic 16f873A.

tengo un retardo de 5seg y como la pregunta de los pulsadores la tengo es fuera de retardo tengo que demorar un largo rato presionando culaquier pulsador para que sea atendido.

y con esta explicacion ya se como es atendido inmediatemente sin alterar el stack de la pila y reducindo el programa.

caballero si no es un  inconveniente de seguirle preguntando de esto ya que me quedan mas dudas.

gracias y saludos



No tengo problemas en responderte todas las preguntas que te surjan u ocurran. Sera un placer responderlas.

Con respecto a esto:


clrf    mascara
movf   porta,0
andwf mascara,1
btfss   status,2
return
sigue el retardo

No va a funcionar.
Fijate que tenes pones  a Mascara en todos ceros.
Entonces veamos que sucede que no funcionará:

clrf Mascara

Entonces Mascara = b'00000000'

movf PORTA,w     

Entonces W = b'XXXXXXXX'

andwf Mascara,1

la AND es una multiplicacion bit a bit:

Hagamosla:

Mascara = b'00000000'
W =          b'XXXXXXX'

Resultado: b'00000000'
Entonces Mascara = b'00000000'

Recorda que 0 * X = siempre 0. Ahi se hacen 8 multiplicaciones entre los bit analogos de Mascara y W.

Ese algoritmo tengas presionado o no los pulsadores, va a ejecutar el segundo entero de demora.
Mascara siempre valdra 0x00, por lo que tambien saldra de la subrutina valiendo 0x00.

Cuando salga valiendo 0x00, obviamente no va a ejecutar nunca ninguna rutina.

Entonces, veamos como hacer para que funcione con pulsadores como los tienes configurados tu( 0= no presionado, 1= presionado)

Ejemplo: si PORTA,0 es mantenido durante el segundo entero, deberia salir el bit Mascara,0 en alto para poder desviar el programa hacia primer.

Tengamos en cuenta un factor que tal vez no habias percatado:

Tenes conectados 4 pulsadores solamente en el puerto A. ¡Ojo! hay que tener en cuenta los otros 4 bits del puerto A tambien, ya que sino pueden "ensuciar" la variable Mascara, y que no pueda salir de la subrutina antes de tiempo si no hay pulsadores presionados.
Recorda que cuando lees un puerto como el Puerto A, esten configurados como entradas o salidas sus pines, te va a leer los valores de los pines igualmente.

Vamos a ver entonces...

Primero, deberiamos lograr descartar esos bits del puertoA que no estan conectados a pulsadores, o bien conectados a ellos pero que no nos interesan si se pulsan o no.

Para esto entonces podriamos optar por dos opciones. Definimos los bits a ignorar del puertoA como 0 y los que queremos revisar como 1 o viceversa.
El binario no nos deja muchas otras posibilidades, ¿eh?:D

Lo mas simple es definir los bits a revisar en alto, y el resto en bajo, entonces hacemos:

   movlw   b'00001111'   ;indiquemos con altos los bits a revisar del PUERTOA!(RA0,RA1,RA2,RA3)
   call   UNO_SEG


Sigamos. Entonces, la idea es esta. Todo bit que yo cargue alli con un alto, deberia salir alto transcurrido el segundo(o antes si se sueltan todos).

Entonces necesito solo 1 cosa. Una instruccion que me cambie el valor de ese bit de Mascara si se solto el pulsador antes de completarse el segundo de demora: Necesito que esa instruccion mantenga ese valor cambiado, independientemente de lo que pase luego dentro de la demora con el pulsador ese.

Entonces, si tengo un 1 inicialmente indicando que voy a revisar ese pulsador, necesito algo que me cambie el valor de ese bit si el pulsador deja de presionarse antes del segundo.

La funcion es otra vez, la AND.

Llevemoslo a la practica.

ingresa Mascara cargada con un bit en ALTO(1).

luego leemos el puertoA y lo guardamos en W.Hacemos una AND entre W y Mascara

1
AND
X

Da como resultado 1 si X= 1. Si X= 0 el resultado sera 0.
¿Por que? Para que una multiplicacion binaria de como resultado 1 ambos bits de las variables a comparar deben valer 1. Facil.
Entonces, si se suelta en algun momento el pulsador la AND hace esto:
1
AND
0

Da como resultado 0. Esto provoca que Mascara ahora tenga ese bit en BAJO.
NO HAY NADA QUE PUEDA HACER QUE ESE BIT DE MASCARA VUELVA A VALER UN ALTO NUEVAMENTE dentro de la subrutina. ¿Por que?
Porque ahora ese bit de Mascara vale cero, y al hacer todas las AND posteriores dentro del retardo pasara esto:

0
AND
X

Siempre devuelve 0.

¿Para que nos ha servido?

Nos ha servido para indicar que el pulsador se solto antes de tiempo. Hemos afectado a ese bit de Mascara de manera que no pueda volver a valer un ALTO.

¿Cómo saber cuando se han soltado todos los pulsadores a revisar?

Si te fijas, veras que la funcion AND puede poner bits en BAJO, pero jamas en ALTO si una de los dos bits a comparar esta en BAJO. Esta es la propiedad caracteristica de esta instruccion.

Entonces, significa que si Mascara = 0x00 querra decir que no hay pulsadores presionados, y haremos entonces que salga de la subrutina de demora antes de completar el segundo.


El código:

Código: ASM
  1. movlw   b'00001111'     ;definimos como 1 los bits a revisar del PUERTOA!(RA0,RA1,RA2,RA3)El resto en 0
  2.         call    UNO_SEG
  3.  
  4.         btfsc  Mascara,0        ;Pulsador RA0 mantenido durante 1 seg?
  5.         goto    prog1           ;Si. Saltar a prog1
  6.        
  7.         btfsc  Mascara,1        ;Pulsador RA1 mantenido durante 1 seg?
  8.         goto   prog2            ;Si. Saltar a prog2
  9.  
  10.         btfsc  Mascara,2        ;Pulsador RA2 mantenido durante 1 seg?
  11.         goto   prog3            ;Si. Saltar a prog3
  12.  
  13.         btfsc  Mascara,3        ;Pulsador RA3 mantenido durante 1 seg?
  14.         goto   prog3            ;Si. Saltar a prog3
  15.  
  16.         goto   siga
  17.  
  18. UNO_SEG  
  19.         movwf   Mascara         ;Volquemos los bits a revisar del PUERTOA en una variable
  20.         movlw     .14      
  21.         movwf     PDel0    
  22. PLoopx  movlw     .72    
  23.         movwf     PDel1  
  24. PLoopy  movlw     .247    
  25.         movwf     PDel2  
  26.  
  27. PLoopz  movf    PORTA,W         ;copiar el valor del puertoA en W      
  28.         andwf   Mascara,F       ;Inclusión de bits entre Mascara y el PUERTOA
  29.         btfsc   STATUS,Z        ;¿Mascara= 0?
  30.         return                  ;Si. Volver
  31.  
  32.         decfsz  PDel2, 1        ;No. continuar revisando
  33.         goto    PLoopz  
  34.         decfsz  PDel1,  1
  35.         goto    PLoopy  
  36.         decfsz  PDel0,  1
  37.         goto    PLoopx    
  38. PDelL1  goto    PDelLx        
  39. PDelLx  clrwdt            
  40.         return



Te recomiendo que si sabes usar el MPLAB SIM, simules esto(no lo he hecho yo) para comprender como funciona.
Sino, agarra papel y lapiz y simula el programa y fijate que Mascara no varia si un pulsador en PORTA se mantiene presionado, y lo que sucede en Mascara cuando se suelta.

Saludos
Título: Re: CALL vs RETURN
Publicado por: microcom en 25 de Octubre de 2006, 17:20:56
brunof la verdad me confundi con la and del programa que escribi apenas leo su comentario me doy cuenta de error y ademas no se que me pasó.

muy buena aplicacion de que si transcurriendo  el segundo yo suelto el puldador el programa se quedaria en donde esta y no se iría a otra parte.

bueno no si me entiendas esta pregunta.
mira que para que el programa se desvie para otra rutina debo esperar 1 seg.
 
¡si es para 5seg debe esperar 5seg.¡

si yo presiono algun pulsador transcurriendo esos 5seg y necesito que no me espere terminar esos 5seg sino que vuelva a preguntar  por los bits  de mascara para ver para que subrutina cojer.

quedarias asi solamete hay que cambiar
btfsc  status,2
return

por
btfss  status,2   ; esta seria la instruccion a colocar.
return

puesto que si no hay ningun pulsador  00001111 AND 00000000= 0  ; Z= 1 entonces se ejecutarian los 5seg y volveria con return al final
pero si presiono algun pulsador Z es  cero ya que  1 AND 1 haria  que el programa return y asi volveria a preguntar que bits de mascara esta activo. lo cual combiaria la rutina.


                movlw   b'00001111'   
   call   UNO_SEG    
                btfsc  Mascara,0   ;Pulsador RA0 mantenido durante 1 seg?    
                goto    prog1
   
   btfsc  Mascara,1   ;Pulsador RA1 mantenido durante 1 seg?
   goto   prog2      ;Si. Saltar a prog2

   btfsc  Mascara,2   ;Pulsador RA2 mantenido durante 1 seg?
   goto   prog3      ;Si. Saltar a prog3

   btfsc  Mascara,3   ;Pulsador RA3 mantenido durante 1 seg?
   goto   prog3      ;Si. Saltar a prog3

   goto   siga

UNO_SEG 
   movwf   Mascara      ;Volquemos los bits a revisar del PUERTOA en una variable
   movlw     .14       
   movwf     PDel0   
PLoopx   movlw     .72   
   movwf     PDel1   
PLoopy   movlw     .247     
   movwf     PDel2 

PLoopz   movf   PORTA,W      ;copiar el valor del puertoA en W   
   andwf   Mascara,F   ;Inclusión de bits entre Mascara y el PUERTOA
   btfss   STATUS,Z   ;¿Mascara= 0?
   return         ;Si. Volver

   decfsz   PDel2, 1     ;No. continuar revisando
   goto   PLoopz   
   decfsz   PDel1,  1
   goto   PLoopy   
   decfsz   PDel0,  1
   goto   PLoopx   
PDelL1   goto   PDelLx       
PDelLx   clrwdt             
   return


viejo brunoF yo creo que usted ha sido muy paciente con este tema y le doy las gracias por ello. yo creo que con esta ultima pregunta es la vencida.

le agradesco la colaboracion y estoy en deuda.

saludos y gracias .


Título: Re: CALL vs RETURN
Publicado por: MGLSOFT en 26 de Octubre de 2006, 16:31:19
Muchachos:
Pido perdon por no leer completo el hilo.
Lo que quiero decirles es que cuando hacen un GoTo dentro de un Call estan haciendo una llamada recursiva.
El PIC no admite recursividad. En ninguno de los lenguajes de programacion...

Para leer los pulsadores si no quieren utilizar las interrupciones del PortB lo mejor que pueden hacer es una temporizacion por interrupcion (igual van a utilizarlas), pueden hacerla cada 5 milisegundos y dentro de la interrupcion levantan el estado del port y hacen un and con la mascara de los pulsadores, segun cual este activo graban ese estado en un bit que usaran luego como bandera (flag) para ver que se pulso.

Cuando termina la interrupcion, que sera muy rapida su ejecucion, siguen con lo que estaban haciendo, teniendo en cuenta consultar los flags de cada interruptor o pulsador.
El antirrebote pueden hacerlo consultando el estado y comparando con el estado anterior o temporizando o ambos en conjunto.

La ventaja es que luego ya tienen un timer de uso general incluido, que les permite hacer diferentes temporizaciones, por ser multiplo directo de cualquier tiempo necesario.

Ejemplo:
Cuento 40 interrupciones y tengo 200 milisegundos (40x5=200)

Pierdanle el miedo a las interrupciones, una vez que las utilizen bien veran la programacion de otra manera !!! :-/ :-/
Título: Re: CALL vs RETURN
Publicado por: maunix en 26 de Octubre de 2006, 17:56:31
Lo que quiero decirles es que cuando hacen un GoTo dentro de un Call estan haciendo una llamada recursiva.
El PIC no admite recursividad. En ninguno de los lenguajes de programacion...

MGLSoft ¿podrías explicar mejor tu punto?  realmente no estoy de acuerdo con lo que dices.

Un goto, dentro de un call constituye un "bucle", o una "bifurcación", pero no recursividad.

Recursividad sería que hagamos un call y dentro de ese call, volvamos a llamar de nuevo a la misma subritina.

Ej:

Código: ASM
  1. call   MIRUTINA
  2.  
  3.  
  4. MIRUTINA:
  5.         movlw  .20
  6.         call     MIRUTINA

El ejemplo es burdo, pero eso en mi opinión eso sería recursividad.   No es imposible, y se podría aplicar en ensamblador, usando un stack por software y acotando la cantidad de calls anidados.


Saludos
Título: Re: CALL vs RETURN
Publicado por: microcom en 26 de Octubre de 2006, 18:11:58
tenia ganas de preguntar  pero me di la tarea de esperar que  opinan manos expertas en el  asunto .

Lo que quiero decirles es que cuando hacen un GoTo dentro de un Call estan haciendo una llamada recursiva.?
El PIC no admite recursividad. En ninguno de los lenguajes de programacion?

saludos y gracias
Título: Re: CALL vs RETURN
Publicado por: maunix en 26 de Octubre de 2006, 19:02:52
tenia ganas de preguntar  pero me di la tarea de esperar que  opinan manos expertas en el  asunto .

Lo que quiero decirles es que cuando hacen un GoTo dentro de un Call estan haciendo una llamada recursiva.?
El PIC no admite recursividad. En ninguno de los lenguajes de programacion?

saludos y gracias


microcom, no entiendo cuál es tu pregunta puntual.

Título: Re: CALL vs RETURN
Publicado por: BrunoF en 26 de Octubre de 2006, 22:07:20
Marcos, realmente no entendi lo que quisiste decir. Igualmente aca no hay recursividad alguna...

A ver si entendi microcom. No queres usar Interrupciones. Entonces, la idea es hacerlo dentro de un loop principal del programa.
Si o si debe hacerse un retardo de 1 segundo, excepto si se presiona un pulsador. SI esto sucede, debe salir de la subrutina y desviar el codigo hacia otro lado.

Aca va el codigo si esto es lo que queres hacer:


Código: ASM
  1. movlw   b'00001111'     ;indiquemos los bits a revisar del PUERTOA!(RA0,RA1,RA2,RA3)
  2.         call    UNO_SEG
  3.         movwf   Mascara         ;Volcar W en Mascara
  4.         movf    Mascara,F       ;Afectar flag Z
  5.         btfss   STATUS,Z        ;Se presiono algo?
  6.         call    Antirebote      ;Si. Demora.
  7.  
  8.         btfsc  Mascara,0        ;Pulsador RA0 presionado?
  9.         goto    prog1           ;Si. Saltar a prog1
  10.        
  11.         btfsc  Mascara,1        ;Pulsador RA1 presionado?
  12.         goto   prog2            ;Si. Saltar a prog2
  13.  
  14.         btfsc  Mascara,2        ;Pulsador RA2 presionado?
  15.         goto   prog3            ;Si. Saltar a prog3
  16.  
  17.         btfsc  Mascara,3        ;Pulsador RA3 presionado?
  18.         goto   prog3            ;Si. Saltar a prog3
  19.  
  20.         goto   siga
  21.  
  22. UNO_SEG  
  23.         movwf   Mascara         ;Volquemos los bits a revisar del PUERTOA en una variable
  24.         movlw     .14      
  25.         movwf     PDel0    
  26. PLoopx  movlw     .72    
  27.         movwf     PDel1  
  28. PLoopy  movlw     .247    
  29.         movwf     PDel2  
  30.  
  31. PLoopz  movf    PORTA,W         ;Copiar bits del registro PORTA y guardarlos en W
  32.         andwf   Mascara,W       ;Multiplicacion de los bits de ambos registros, GUARDAR RESULTADO EN W.
  33.         btfss   STATUS,Z        ;Revisar si no hay ningun pulsador presionado.
  34.         return                  ;Hay algo presionado. Volver con W indicando el pulsador/es presionado/s
  35.  
  36.         decfsz  PDel2, 1  
  37.         goto    PLoopz  
  38.         decfsz  PDel1,  1
  39.         goto    PLoopy  
  40.         decfsz  PDel0,  1
  41.         goto    PLoopx    
  42. PDelL1  goto    PDelLx        
  43. PDelLx  clrwdt            
  44.         retlw   .0              ;Indicar que nada ha sido presionado durante la demora


Saludos.
Título: Re: CALL vs RETURN
Publicado por: microcom en 27 de Octubre de 2006, 16:53:48
gracias BRUNOF;y demas colegas
por sacarme e dudas.

saludos ya entendi lo necesario para ejecutar los programas.

gracias por las atenciones prestadas y demas..............
 MAUNIX el problema ya está concluido.
gracias
saludos.





Título: Re: CALL vs RETURN
Publicado por: MGLSOFT en 31 de Octubre de 2006, 12:06:58
Marcos, realmente no entendi lo que quisiste decir. Igualmente aca no hay recursividad alguna...

BrunoF:
Tenes razon me exprese mal, quise decir que cabe la posibilidad que hicieses una llamada recursiva usando GoTo's dentro de un Call, esto es porque se debe tener muy en cuenta como se sale de un goto, especialmente si ese goto se refiere a una posicion de memoria anterior a la llamada del Call estarias entrando en una llamada recursiva al llegar al Call original...
No me hice entender bien... disculpas... :lol: :lol:

Una cosa debe quedar en claro, lo ideal para programar en assembler es que sean muy ordenados y comenten muy bien lo que estan haciendo (vean el ejemplo de BrunoF), ya que sino en el futuro ni ustedes mismos entenderan que quisieron hacer...
 Hagan identacion de los lazos como si programaran en un lenguaje de alto nivel, eso ayuda mucho a seguir un programa. :) :)
Título: Re: CALL vs RETURN
Publicado por: BrunoF en 31 de Octubre de 2006, 14:32:24
Ahhh perfecto. Ahora quedó claro.
Si, en ASM a veces se hace un poco dificil seguir el código. Especialmente cuando hay muchos goto que van y vienen.

La prolijidad y el seguimiento de ciertas pautas a la hora de programar son muy importantes, especialmente para futuras modificaciones propias o ajenas.

Muchas gracias por los halagos:D:D