TODOPIC

Microcontroladores PIC => Todo en microcontroladores PIC => Mensaje iniciado por: Mady en 24 de Abril de 2007, 08:24:09

Título: Subrutinas con parámetros
Publicado por: Mady en 24 de Abril de 2007, 08:24:09
Necesito usar una misma subruitna para escanear distintos puertos de entrada, pero claro, cada vez debo indicarle un puerto distinto. ¿Hay algun camino para hacer esto, sin tener que reescribir la ruitna para cada puerto?


Gracias
Título: Re: Subrutinas con parámetros
Publicado por: Nichita en 24 de Abril de 2007, 11:02:41
Lo que puedes hacer es que antes de llamar a tu subrutina cargas W o cualquier variable con un valor (que indique el puerto) y dentro de tu subrutina utilizas esa variable para direccionar que puerto es que vas acceder.

Saludos
Título: Re: Subrutinas con parámetros
Publicado por: Mady en 26 de Abril de 2007, 16:36:14
Gracias, intentaré ese camino
Título: Re: Subrutinas con parámetros
Publicado por: manuelroin24 en 26 de Abril de 2007, 18:44:56
Podrias intentar crear una MACRO para atacar de manera más fácil el cambio de puertos
Título: Re: Subrutinas con parámetros
Publicado por: Mady en 29 de Abril de 2007, 14:55:46
He usado el siguiente código, pensando que la directiva  undefine me permitiria reasignar el puerto antes de entrar en la subrutina. Sin embargo, al ejecutar, las dos llamadas a la subrutina se ejecutan con la segunda asignación hecha para MIRA y BIT.

Adjunto trozo del código:

      #define   BIT   PUERTAB,0
      #define   MIRA   PUERTAA,0
      
      call   led
      

      #undefine   BIT
      #undefine   MIRA

      #define   BIT   PUERTAB,1
      #define   MIRA   PUERTAA,1
      
      call   led

led      clrf   PUERTAB
      btfss   MIRA
      bsf   BIT
      return
      
END         ; Fin del programa
Título: Re: Subrutinas con parámetros
Publicado por: maunix en 29 de Abril de 2007, 20:05:37
Mady, creo que estas errando el camino.  Según entendí quieres una función genérica a la cual le pases como parámetro el número de puerto y pin por el cual sacar el dato.

Tu lo que has hecho, es sencillamente definir constantes que luego 'dejas de definir', con lo cual no has hecho una función, simplemente dijiste al ensamblador que una cadena de texto antes valia  PUERTAB,0 y luego  PUERTAB,1.  Eso no es algo que se interpreta/modifica durante el tiempo de ejecución, sino que se modifica durante el ensamblado de tu código, lo cual quiere decir que quedará "fijo" y no cambiará el puerto de salida a medida que tu lo desees sino que será algo fijo.

Déjame decirte que es una de las preguntas muy frecuentes que se hacen y no es una tarea simple.  Debes de alguna forma, indicar que haga una elección de puerto manualmente, ya que no se puede pasar el puerto en sí como parámetro.

Lo que te sugirió Nichita es lo que se hace gralmente, se pasa como parámero un número (0,1,2..) que corresponderá a PORTA, PORTB, PORTC.. y luego dentro de la subrutina se elige el número de puerto.  Paso a continuar se elige el número de pin.

Podrias intentar crear una MACRO para atacar de manera más fácil el cambio de puertos

Manuel, esta opción si bien es cómoda, en realidad copia el código una y otra vez y no es lo que , según entiendo, es lo que quiere Mady.


Título: Re: Subrutinas con parámetros
Publicado por: Mady en 01 de Mayo de 2007, 14:21:46
Lo que me dice Nichita, no sé muy bien si es algo similar a lo que se hace con RETLW para trabajar con un display de 7 segmentos, por ejemplo. ¿Es eso?

Gracias
Título: Re: Subrutinas con parámetros
Publicado por: maunix en 01 de Mayo de 2007, 17:47:18
Lo que me dice Nichita, no sé muy bien si es algo similar a lo que se hace con RETLW para trabajar con un display de 7 segmentos, por ejemplo. ¿Es eso?

Mmm, no se cómo has hecho al analogia pero no , no sería exactamente eso.

La subrutina debe recibir el parámetro en alguna variable.  Es común que el parámetro se mande en WREG y la rutina sabe "ah, WREG = 2" entonces el dato lo saco por PORTB.  Si WREG=1, lo sacará por PORTA.

Eso depende la lógica de tu programa.

Te sugiero que si recién empiezas con esto de los pics, no te la hagas tan complicada de entrada, es decir, si tienes que sacar datos por el PORTA, PORTB y PORTC.  haz 3 rutinas diferentes y listo.

Saludos
Título: Re: Subrutinas con parámetros
Publicado por: Nichita en 01 de Mayo de 2007, 18:20:06
A lo que me rereria era a esto:
creas una variable por ejm llamada PUERTO (que va tomar el valor del puerto que quieras acceder es decir 0x05 puerto A, 0x06 puerto B, etc. Entonces antes de llamar tu rutina asignas el valor apropiado a PUERTO. En tu subrutina utilizas esa variable como argumento de la instrucion btfss, btfsc, bcf o bsf segun lo que vayas hacer, quedaria mas o menos asi:

'PUERTO = 0x05 Indicamos que va trabajar con el puerto A
movlw 0x05
movwf PUERTO

call RUTINA 'llamas a tu rutina
..
..
end

RUTINA   'ejemplo
   
bcf PUERTO,1  'Pone en bajo RA1
bsf PUERTO,3  'pone en alto RA3
btfsc PUERTO,5 'testea el estado de RA5
..
return

Tb podrias crear otra variable para indicar el nro. de pin que vas acceder por ejm PIN.  Tu instruccion quedaria asi:

'PUERTO = 0x06 tomamos el puerto B
'PIN = 4

RUTINA
bcf PUERTO, PIN 'pone en bajo RB4
...
...
return

Espero haya aclarado tu duda
Saludos
Título: Re: Subrutinas con parámetros
Publicado por: maunix en 01 de Mayo de 2007, 20:08:05
Nichita, si PUERTO tomará valor durante el proceso de ensambaldo tu técnica funcionará.  Ahora si la variable PUERTO cambia durante la ejecución del programa, el programa no hará lo que tu esperas, ya que PUERTO será una dirección de memoria fija. 

No hay instrucciones en el assembler de los pic12F; 16F y 18F que permitan pasar el numero de puerto como parámetro.

Hacer lo siguiente

     movlw  0x05
     movwf   PUERTO
     bcf     PUERTO,5

     movlw  0x06
     movwf   PUERTO
     bcf     PUERTO,5


No significa que en el primer caso, se borrará PORTA<5> (direccion 0x05 en memoria) y en el segundo caso PORTB<5> (direccion 0x06 en memoria).

PUERTO tomará un valor al ensamblarse, el cual será 5, 6, 10, 20, lo que sea, y no cambiará.

Título: Re: Subrutinas con parámetros
Publicado por: Mady en 03 de Mayo de 2007, 14:22:04
He intentado probar el siguiente código, y la verdad es que el simulador no ejecuta lo esperado, y además me sale el siguiente aviso:
CORE-E0002: Stack under flow error occurred from instruction at 0x000011

   puerto   equ   0x20
   pin   equ   0x21         
   
      movlw   PUERTAB
      movwf   puerto
      movlw   3
      movwf   pin
      
      call led
   
led   
      bsf   puerto,pin
      return
      
END         ; Fin del programa

El aviso que da no se muy bien lo que significa. CReo que ya que soy novata, crearé varias subrutinas. Pero si consigo hacerlo os lo comentaré.

Muchas gracias
Título: Re: Subrutinas con parámetros
Publicado por: maunix en 03 de Mayo de 2007, 14:55:28
CORE-E0002: Stack under flow error occurred from instruction at 0x000011
Significa que has hecho un RETURN sin un previo call, por lo tanto te está diciendo que el STACK o PILA de retorno de subrutinas tuvo un sobrevaciamiento.

Me tomé la libertad de ponerle un número a cada línea así explico mejor tu problema.
Código: ASM
  1. 1.              movlw   PUERTAB
  2. 2.              movwf   puerto
  3. 3.              movlw   3
  4. 4.              movwf   pin
  5.                
  6. 5.              call led
  7.        
  8. led    
  9. 6.              bsf     puerto,pin
  10. 7.              return
Tu programa ejecutará de 1 a 5, en forma lineal.

Luego está el call, con lo cual ejecutará 6 y 7.  Al ejecutar 7 (return) , se vuelve a la instrucción próxima siguiente de donde se lo llamo.  Es decir, debajo de "call led", osea en 6.

Se ejecuta nuevamente 6, y luego 7, por lo cual hay un RETURN al cual no le corresponde ningún CALL.

Se solucionaría si luego de 5. haces un bucle infinito. algo así como esto:

Código: ASM
  1. 1.              movlw   PUERTAB
  2. 2.              movwf   puerto
  3. 3.              movlw   3
  4. 4.              movwf   pin
  5.                
  6. 5.              call led
  7. 5.a   nada:
  8.                 nop
  9. 5.b            goto nada
  10. led    
  11. 6.              bsf     puerto,pin
  12. 7.              return

Espero se haya entendido.  Saludos
Título: Re: Subrutinas con parámetros
Publicado por: Mady en 03 de Mayo de 2007, 16:25:08
Gracias MAunix, lo he entendido perfectamente.
Título: Re: Subrutinas con parámetros
Publicado por: Mady en 03 de Mayo de 2007, 16:36:02
He entendido que lo dice Nichita es lo siguiente:

   W      EQU   0   ; Cuando el destino es W, d = 0
   F      EQU   1   ; Cuando el destino es el registro f, d = 1
   PUERTAA   EQU   0x05   ; La Puerta A (datos) ocupa la direcci¢n 5 del    
                  ; banco 0 y el registro de configuraci¢n la       
                  ; direcci¢n 5 del banco 1

   PUERTAB EQU   0x06   ; La misma etiqueta para el registro de datos y el    
                  ; de configuraci¢n de la Puerta B
   ESTADO   EQU   0x03    ; El registro Estado ocupa direcci¢n 3 de los dos   
                  ; bancos
;**************************************************************************************
;*                COMIENZO DEL PROGRAMA                      *
;**************************************************************************************

   ORG    0      ; El programa comienza en la direcci¢n 0 (Vector Reset)
   goto   inicio   ; Se salta a la etiqueta “inicio”
   ORG   5      ; Se asigna la direcci¢n 5 a la siguiente instrucci¢n


inicio   bsf   ESTADO,5   ; Pone a 1 el bit 5 de Estado. Acceso al banco 1.
   clrf   PUERTAB      ; Se configuran como salidas las l¡neas de la Puerta B
   movlw   0xff      ; El registro W se carga con unos
   movwf   PUERTAA      ; Se configuran como entradas las l¡neas de la Puerta A
        bcf     ESTADO,5    ; Pone a 0 el bit 5 de Estado. Acceso al banco 0.

   puerto   equ      0x20
   pin   equ      0x21         
   
      movlw   PUERTAB
      movwf   puerto
      movlw   .3
      movwf   pin
      
      call led
nada:   nop
      goto   nada

   
led   
      bsf   puerto,pin
      return
      
   END         ; Fin del programa

Sin embargo, sigue sin salir, no se pone a 1 PUERTAB;3

ESpero algún dia aportar  tambien soluciones, de momento estoy aprendiendo mucho gracias a vosotros

Título: Re: Subrutinas con parámetros
Publicado por: dhmejia en 03 de Mayo de 2007, 18:39:03
Te falto leer bien lo que dice Maunix:

Nichita, si PUERTO tomará valor durante el proceso de ensambaldo tu técnica funcionará.  Ahora si la variable PUERTO cambia durante la ejecución del programa, el programa no hará lo que tu esperas, ya que PUERTO será una dirección de memoria fija. 

No hay instrucciones en el assembler de los pic12F; 16F y 18F que permitan pasar el numero de puerto como parámetro.

Hacer lo siguiente

     movlw  0x05
     movwf   PUERTO
     bcf     PUERTO,5

     movlw  0x06
     movwf   PUERTO
     bcf     PUERTO,5


No significa que en el primer caso, se borrará PORTA<5> (direccion 0x05 en memoria) y en el segundo caso PORTB<5> (direccion 0x06 en memoria).

PUERTO tomará un valor al ensamblarse, el cual será 5, 6, 10, 20, lo que sea, y no cambiará.

Hacerlo de esa forma no funciona,

saludos
Título: Re: Subrutinas con parámetros
Publicado por: dhmejia en 04 de Mayo de 2007, 14:36:02
Hay una opción que creo debe funcionar y es usando direccionamiento indirecto, aca un ejemplo prendiendo el bit cero del puerto B y el bit 1 del puerto a:

Código: ASM
  1. ;declarar las variables:
  2. ;bit
  3. ;RotaBit
  4. ;Banderas
  5.  
  6. #define EstadoBit       Banderas,0
  7. ;***************************
  8.         movlw   0x06           ;Puerto B
  9.         movwf   FSR
  10.         bsf        EstadoBit    ;Para prender
  11.         movlw   .1               ;bit 0
  12.         call       Led
  13.         movlw   0X05           ;Puerto A
  14.         movwf   FSR
  15.         bcf        EstadoBit    ;Para apagar
  16.         movlw   .2               ;bit 1
  17.         call       Led
  18.         ....
  19.         ....
  20.  
  21. Led      movwf       bit
  22.            clrf           RotaBit
  23.            bsf           STATUS,C
  24. Rota     rlf             RotaBit,f
  25.            decfsz       bit,f
  26.            goto          Rota
  27.            btfss          EstadoBit
  28.            goto          Apaga
  29. Prende  movfw        RotaBit
  30.            iorwf          INDF
  31.            return
  32. Apaga   comf          RotaBit,f
  33.            movfw        RotaBit
  34.            andwf        INDF
  35.            return

La dirección del puerto se carga en el FSR y el bit a prender o apagar en el registro 'bit', el problema es que en este caso los bits se cuentan desde uno y no desde cero (para el bit cero se debe cargar un 1... para el bit 7 se debe cargar un 8), si se desea prender o apagar el bit se pone en 1 o 0 el EstadoBit.

saludos
Título: Re: Subrutinas con parámetros
Publicado por: maunix en 04 de Mayo de 2007, 15:10:43
Te falto leer bien lo que dice Maunix:

Nichita, si PUERTO tomará valor durante el proceso de ensambaldo tu técnica funcionará.  Ahora si la variable PUERTO cambia durante la ejecución del programa, el programa no hará lo que tu esperas, ya que PUERTO será una dirección de memoria fija. 

No hay instrucciones en el assembler de los pic12F; 16F y 18F que permitan pasar el numero de puerto como parámetro.

Hacer lo siguiente

     movlw  0x05
     movwf   PUERTO
     bcf     PUERTO,5

     movlw  0x06
     movwf   PUERTO
     bcf     PUERTO,5


No significa que en el primer caso, se borrará PORTA<5> (direccion 0x05 en memoria) y en el segundo caso PORTB<5> (direccion 0x06 en memoria).

PUERTO tomará un valor al ensamblarse, el cual será 5, 6, 10, 20, lo que sea, y no cambiará.

Hacerlo de esa forma no funciona,

saludos

dhmejia... no entiendo tu aclaración... en mi post estoy claramente diciendo que eso así no funciona.

Título: Re: Subrutinas con parámetros
Publicado por: maunix en 04 de Mayo de 2007, 15:24:21
Mady, tu código así como está no funciona por lo que expliqué anteriormente.

No puedes pasar como parámetro un número de puerto (al menos no de esa forma) y menos un número de pin o bit.

Repasemos.


puerto = 0x20
pin = 0x21
PUERTAA = 0x05
PUERTAB = 0x06


He puesto como comentarios la explicación de qué hace el código.
Código: ASM
  1. movlw   PUERTAB             ; Cargas 0x06 en WREG
  2.       movwf   puerto              ; Pones 0x06 en la posición de memoria 0x20
  3.       movlw   .3                  ; Cargas 3 en WREG
  4.       movwf   pin                 ; Mueves 3 a la posición de memoria 0x21

Y esto, aún más erróneo
Código: ASM
  1. bsf   puerto,pin
Acá estas seteando el bit "pin" de la posición de memoria 0x20. el bit 0x21.  Como pin solo puede tomar valores de 0 a 7, es probable que el assember trunque el valor de 0x21 y te quede solo 0x01

Con lo cual estas haciendo

   bsf 0x20,0x01

osea encender el bit 1, del registro de memoria 0x20.


Te sugiero leas el set de instrucciones y cómo funcionan.  Definir constantes con EQU y usarlas como a uno le parezca no es lo que el PIC va a interpretar.

Recuerda que el pic hace caso a las instrucciones no a tus intenciones  :)

Título: Re: Subrutinas con parámetros
Publicado por: maunix en 04 de Mayo de 2007, 15:33:39
Hay una opción que creo debe funcionar y es usando direccionamiento indirecto, aca un ejemplo prendiendo el bit cero del puerto B y el bit 1 del puerto a:

...

La dirección del puerto se carga en el FSR y el bit a prender o apagar en el registro 'bit', el problema es que en este caso los bits se cuentan desde uno y no desde cero (para el bit cero se debe cargar un 1... para el bit 7 se debe cargar un 8), si se desea prender o apagar el bit se pone en 1 o 0 el EstadoBit.

Ahí estamos de acuerdo  :)

Con direccionamiento indirecto se puede pasar como parámetro el número de puerto más no el número de pin/bit el cual deberá ser calculado y luego aplicarse una OR (para set) o AND (para clear).

No le indiqué ese paso a Mady, no por omisión sino porque me parece que debe conocer otras cosas antes, ya que el direccionamiento indirecto cuesta manejarlo si no se manejan otros conceptos antes como por ej, distinguir entre las definición de puerto o de un registro.
Título: Re: Subrutinas con parámetros
Publicado por: dhmejia en 04 de Mayo de 2007, 18:16:17
dhmejia... no entiendo tu aclaración... en mi post estoy claramente diciendo que eso así no funciona.

Maunix, solo estaba confirmando lo que ya habías dicho porque Mady seguía intentando con el código de Nichita después de la explicación que habías dado del por que no funcionaba.

De pronto no fui claro, pero estaba reafirmando lo que ya habías dicho.

saludos.
Título: Re: Subrutinas con parámetros
Publicado por: maunix en 04 de Mayo de 2007, 18:53:27
dhmejia... no entiendo tu aclaración... en mi post estoy claramente diciendo que eso así no funciona.

Maunix, solo estaba confirmando lo que ya habías dicho porque Mady seguía intentando con el código de Nichita después de la explicación que habías dado del por que no funcionaba.

De pronto no fui claro, pero estaba reafirmando lo que ya habías dicho.

saludos.

Ok, asunto aclarado y sin rencores   :) :)
Título: Re: Subrutinas con parámetros
Publicado por: Mady en 05 de Mayo de 2007, 15:30:30
Realmente creo que lo del direccionamiento indirecto lo dejaré para más adelante. Aunque cojo la idea, creo que aún es pronto. GRacias igualmente por las aportaciones, espero usarlas en un futuro muy lejano.
Ah, ya me ha quedado claro porque no funcioba mi código.

Gracias
Título: Re: Subrutinas con parámetros
Publicado por: Nichita en 05 de Mayo de 2007, 19:41:49
Hola, maunix tienes razón las instrucciones bsf, btfss, etc. toman la dirección de la variable y no su contenido. Bueno entonces creo que lo mejor sería hacerlo con una macro como sugería manuelroin24.

Mady, aunque maunix decia que ésta se copia una y otra vez y te sugeria que hagas las rutinas que necesites para acceder a los puertos para no complicarte tanto, ya que recien empezabas con los PICs, es precisamente esto lo que hace la macro, se copia el codigo cuantas veces lo llames (es decir la cantidad de rutinas que necesites y con los valores del puerto al que vas acceder) pero lo hace de forma automatica y claro con ciertas ventajas, que nos otorga ésta poderosa herramienta del assembler, con respecto a las subrutinas.

Lo que he hecho es trasladar todo lo anterior a una macro y quedaría así:

#define PUERTOA 0x05
#define PUERTOB 0x06   ; segun los puertos que disponga tu PIC y a los que vayas a acceder
..
..
#define PUERTOE 0x09

mi_rutina macro puerto
                     
bcf puerto, 1    ;como se asigno el puerto A y pin 1 entonces: pone en bajo RA1       
bsf puerto, 3    ;pone en alto RA3       
btfsc puerto,5   ;testea el estado de RA5
...
...
endm

; en la rutina principal invocamos a la macro
main
    mi_rutina PUERTOA, 1  ;asignamos el puerto A y el pin 1
    ...
    ...
   goto main

Y de la misma manera para especificar que PIN vamos a acceder podemos crear la macro así:

#define PUERTOA 0x05
....
#define PIN0 0x00
#define PIN1 0x01
#define PIN2 0x02
#define PIN3 0x03
#define PIN4 0x04
#define PIN5 0x05
#define PIN6 0x06
#define PIN7 0x07


mi_rutina macro puerto, pin

  bcf puerto, pin ;pone en bajo el pin 4 del puerto B (segun lo asignado en la invocacion de la macro)

endm

main
    mi_rutina PUERTOB, PIN4 ;invocamos a la macro
    ...
   goto main

Otra forma tb sería con direccionamiento indirecto, pero para hacer que se pueda elegir tb el pin creo que se complicaria mas.

espero te sirva,

Saludos
Título: Re: Subrutinas con parámetros
Publicado por: maunix en 07 de Mayo de 2007, 08:23:16
Creo que luego de todo el post, lo que queda claro es que tal vez, por ser novata, le convenga escribir las instrucciones y listo.

Hacer uso de un macro que ejecute varias instrucciones sobre un puerto, solo nos ahorra escribir ese código una y otra vez, pero no nos permite lograr lo que era el pedido original, ya que sería MUY RARO que tengamos conectados en cada pin de cada puerto, exactamente lo mismo como para que se justifique usar un macro de esa forma.

Por eso, creo que es más práctico escribir directamente la instrucción y listo.

Saludos

 
Título: Re: Subrutinas con parámetros
Publicado por: Nichita en 07 de Mayo de 2007, 10:52:47
En realidad no se trata tampoco de una macro compleja es mas bien una bien simple y creo que es la mejor solución a lo que quería ya que hacer lo mismo sin utilizar una macro ahi si se hacía más complejo, pero en realidad esa complejidad dependería de que exactamente es lo que quiere hacer dentro de su subrutina, tal vez no necesita especificar el pin que va acceder, con lo cual todo quedaría solucionado con direccionamiento indirecto. También no es necesario que tengamos cada pin del puerto conectado de igual forma, se puede especificar mas parametros para la macro y asi acceder de forma independiente los puertos y pines, pero como decía es cuestión de saber que es lo que exactamente quiere hacer dentro de su subrutina, no les parece?.

Saludos