uControl
Febrero 24, 2017, 06:47:30 *
Bienvenido(a), Visitante. Por favor, ingresa o regístrate.
¿Perdiste tu email de activación?

Ingresar con nombre de usuario, contraseña y duración de la sesión
 
   Inicio   Ayuda Buscar Ingresar Registrarse  
Páginas: 1 [2]   Ir Abajo
  Imprimir  
Autor Tema: Rutinas para compartir.  (Leído 22504 veces)
0 Usuarios y 1 Visitante están viendo este tema.
Leon Pic
Moderator
dsPIC
***
Desconectado Desconectado

Sexo: Masculino
Mensajes: 5693


Cumulonimbus


WWW
« Respuesta #15 : Septiembre 14, 2010, 10:48:42 »

Hola Pardillete. Bienvenido al foro,

Muchas gracias por tu aporte. La verdad que es muy práctico.
En línea

Jesús dijo, yo soy el CAMINO, la VERDAD y la VIDA, nadie llega al PADRE si no es por mi.
sander
PIC10F
*
Desconectado Desconectado

Mensajes: 28


« Respuesta #16 : Septiembre 14, 2010, 08:16:43 »

Saludos al foro!

Os pongo una pequeña aportación. A veces tenemos que intercambiar el valor de dos variables. Aparentemente habría que utilizar una variable intermedia, algo así como:

Código:
movf    Var_1,w             ; Carga el valor de la primera variable
movwf   Var_Aux             ; Lo copia en el auxiliar
movf    Var_2,w             ; Carga el valor de la segunda variable
movwf   Var_1               ; Lo copia en la primera
movf    Var_Aux,w           ; Recupera el valor de la primera almacenado en la variable auxiliar
movwf   Var_2               ; Lo copia en la segunda

Bueno pues hay una manera más sencilla y elegante que no requiere variable auxiliar y ocupa menos código.

Código:
movf     Var_1,w            ; Carga el valor de la primera variable
xorwf    Var_2,w            ; Hace un XOR sobre el acumulador con la segunda
xorwf    Var_1,f            ; Hace un XOR sobre la primera
xorwf    Var_2,f            ; Hace un XOR sobre la segunda y ¡¡ Ya está !!

No os parece elegante?


Saludos Pardillete realmente es una gran rutina , muy interesante esa forma de hacerlo.
En línea
Pardillete
PIC10F
*
Desconectado Desconectado

Mensajes: 3


« Respuesta #17 : Septiembre 29, 2010, 06:51:00 »

Saludos al Foro!

Todos nos hemos visto alguna vez en la necesidad de mantener el valor del acumulador W durante un retardo determinado.
Nos hubiera gustado disponer de las instrucciones PUSH y POP o de unas subrutinas de retardo que no nos cambiaran el valor de W.
Pues aquí hay unas subrutinas de retardo que no cambian el valor de W (Y no utilzan ninguna variable de almacenamiento).
Tan solo requieren dos variables, que en el código he llamado Cont_0 y Cont_1.
Los valores son exactos para una frecuencia de 4MHz. Si no se requiere tanta precisión se pueden simplificar muchísimo.
Es muy entretenido jugar con el MPLAB SIM con distintas frecuencias hasta ajustar el tiempo exacto.

Retardo de 1 milisegundo
Código:
;------------------------------------------------------------
; Subrutina de 1 ms exacta (Para 4 MHz)
; Utiliza solo el Cont_0
;------------------------------------------------------------
Ret_1ms
CLRF Cont_0 ; Contador 00000000 = 0
BSF Cont_0,7 ; Contador 10000000 = 128
BSF Cont_0,6 ; Contador 11000000 = 192
BSF Cont_0,2 ; Contador 11000100 = 196
BSF Cont_0,1 ; Contador 11000101 = 197

Ret_1ms_0
GOTO $+1 ; 2 ciclos en una sola instrucción
DECFSZ Cont_0 ; Decrementa el Contador
GOTO Ret_1ms_0 ; Bucle de retardo
GOTO $+1 ; Ajuste de 2 ciclos
RETURN ; Vuelve

Retardo de 10 milisegundos exactos. No utiliza llamadas a otras subrutinas por lo que no gastamos niveles de anidamiento
Código:
;------------------------------------------------------------
; Subrutina de 10 ms exacta (Para 4 MHz)
; Utiliza el Cont_0 y el Cont_1
;------------------------------------------------------------
Ret_10ms
CLRF Cont_1 ; Borra el Cont_1
BSF Cont_1,4 ; Cont_1 = 16

Ret_10ms_0
CLRF Cont_0 ; Borra el Cont_0
DECF Cont_0 ; Cont_0 = 11111111 = 255
BCF Cont_0,7 ; Cont_0 = 01111111 = 127
BCF Cont_0,2 ; Cont_0 = 01111011 = 123

Ret_10ms_1
GOTO $+1 ; Ajuste de 2 ciclos en una instrucción
DECFSZ Cont_0 ; Decrementa el Cont_0
GOTO Ret_10ms_1 ; Bucle de reardo interior

DECFSZ Cont_1 ; Decrementa el Cont_1
GOTO Ret_10ms_0 ; Bucle de reardo exterior

; Aquí llegamos con Cont_0 a cero (Y tambien Cont_1 pero no lo usamos)

BSF Cont_0,4 ; Cont_0 = 00010000 = 16
BSF Cont_0,1 ; Cont_0 = 00010010 = 18
BSF Cont_0,0 ; Cont_0 = 00010011 = 19

Ret_10ms_2
DECFSZ Cont_0 ; Decrementa el Cont_0
GOTO Ret_10ms_2 ; Bucle de ajuste final

RETURN ; Vuelve

Retardo de 100 milisegundos exactos. No utiliza llamadas a otras subrutinas por lo que no gastamos niveles de anidamiento
Código:
;------------------------------------------------------------
; Subrutina de 100 ms exacta (Para 4 MHz)
; Utiliza el Cont_0 y el Cont_1
;------------------------------------------------------------
Ret_100ms
CLRF Cont_1 ; Borra el Cont_1
DECF Cont_1 ; Cont_1 = 11111111 = 255
BCF Cont_1,7 ; Cont_1 = 01111111 = 127
BCF Cont_1,0 ; Cont_1 = 01111110 = 126

Ret_100ms_0
CLRF Cont_0 ; Borra el Cont_0
DECF Cont_0 ; Cont_0 = 11111111 = 255
BCF Cont_0,6 ; Cont_0 = 10111111 = 191
BCF Cont_0,5 ; Cont_0 = 10011111 = 159
BCF Cont_0,1 ; Cont_0 = 10011101 = 157

Ret_100ms_1
GOTO $+1 ; Ajuste de 2 ciclos en 1 instrucción
DECFSZ Cont_0 ; Decrementa el Cont_0
GOTO Ret_100ms_1 ; Bucle de retardo interior

NOP ; Ajuste de 1 ciclo
DECFSZ Cont_1 ; Decrementa el Cont_1
GOTO Ret_100ms_0 ; Bucle de Retardo exterior

; Aquí llegamos con Cont_0 a cero (Y tambien Cont_1 pero no lo usamos)

BSF Cont_0,4 ; Cont_0 = 00010000 = 16
BSF Cont_0,2 ; Cont_0 = 00010100 = 20
BSF Cont_0,1 ; Cont_0 = 00010110 = 22
BSF Cont_0,0 ; Cont_0 = 00010111 = 23

Ret_100ms_2
DECFSZ Cont_0 ; Decrementa el Cont_0
GOTO Ret_100ms_2 ; Cierra el Bucle de ajuste

GOTO $+1 ; Nos faltan 3 ciclos
NOP ; Para dejarlo exacto
RETURN ; Y terminar

Espero que le resulten útiles a alguien. Saludos!
En línea
Leon Pic
Moderator
dsPIC
***
Desconectado Desconectado

Sexo: Masculino
Mensajes: 5693


Cumulonimbus


WWW
« Respuesta #18 : Septiembre 29, 2010, 07:22:34 »

Gracias por las rutinas.
En línea

Jesús dijo, yo soy el CAMINO, la VERDAD y la VIDA, nadie llega al PADRE si no es por mi.
Pardillete
PIC10F
*
Desconectado Desconectado

Mensajes: 3


« Respuesta #19 : Octubre 03, 2010, 01:10:51 »

Saludos al Foro !

Muchas veces nos encontramos con la necesidad de bifurcar a distintas partes de un programa en función de una variable que "numera" los distintos casos.
Cuando trabajamos con todo el código en una única página de programa no hay ningún problema, estamos ante el típico código parecido a éste:
Suponemos que la variable NumCaso la tenemos cargada con el nº de caso al que queremos bifurcar.

Código:
Ejemplo_Tabla_Sencilla
    MOVF    NumCaso,W               ; Cargamos el nº de caso
    ADDLW   Tabla_Saltos+1          ; Se lo suma a la posición de la Tabla + 1

Tabla_Saltos
    MOVWF   PCL                     ; Salta al caso correspondiente
    GOTO    Caso_0                  ; Caso 0
    GOTO    Caso_1                  ; Caso 1
    GOTO    Caso_2                  ; Caso 2
    GOTO    Caso_3                  ; Caso 3
    GOTO    Caso_4                  ; Caso 4
    GOTO    Caso_5                  ; Caso 5
    ; Y así los que hagan falta

La cosa comienza a complicarse si la Tabla de Saltos la tenemos en distinta página que el código desde el que la llamamos.
Por ejemplo supongamos el código siguiente donde el código inicial está en la página 0 y la Tabla en la página 12:

Código:
Ejemplo_Tabla_Complicada            ; NO FUNCIONARA
    MOVF    NumCaso,W               ; Cargamos el nº de caso
    ADDLW   Tabla_Saltos+1          ; Se lo suma a la posición de la Tabla + 1
    GOTO    Tabla_Saltos            ; Salta a la Tabla

ORG 0x1200
Tabla_Saltos
    MOVWF   PCL                     ; Salta al caso correspondiente
    GOTO    Caso_0                  ; Caso 0
    GOTO    Caso_1                  ; Caso 1
    GOTO    Caso_2                  ; Caso 2
    GOTO    Caso_3                  ; Caso 3
    GOTO    Caso_4                  ; Caso 4
    GOTO    Caso_5                  ; Caso 5
    ; Y así los que hagan falta

Este código NO FUNCIONARÁ como creemos, por el problema que existe cuando trabajamos entre páginas diferentes de memoria. La solución es ésta:

Código:
Solucion_Tabla_Complicada
    MOVLW   HIGH(Tabla_Saltos)      ; Prepara la Página de la Tabla
    MOVWF   PCLATH                  ; En el PCLATH
    MOVF    NumCaso,W               ; Cargamos el nº de caso
    ADDLW   Tabla_Saltos+1          ; Se lo suma a la posición + 1
    GOTO    Tabla_Saltos            ; Salta a la Tabla

ORG 0x1200
Tabla_Saltos
    MOVWF   PCL                     ; Salta al caso correspondiente
    GOTO    Caso_0                  ; Caso 0
    GOTO    Caso_1                  ; Caso 1
    GOTO    Caso_2                  ; Caso 2
    GOTO    Caso_3                  ; Caso 3
    GOTO    Caso_4                  ; Caso 4
    GOTO    Caso_5                  ; Caso 5
    ; Y así los que hagan falta

Este código funciona bien si las direcciones Caso_0, Caso_1, etc están en la misma página que la Tabla_Saltos. Pero ¿qué ocurre si estas etiquetas están en diferentes páginas?
Podemos estar tentados de sustituir las instrucciones GOTO por las pseudoinstrucciones LGOTO que sí que bifurcarán bien pero el problema es que LGOTO no es una instrucción sino ¡Tres!.
Por lo tanto el salto no nos funcionará bien a no ser que lo ajustemos. Aquí está el código final:

Código:
;En cualquier página de memoria
    MOVLW   HIGH(Tabla_Saltos)      ; Prepara la Página de la Tabla
    MOVWF   PCLATH                  ; En el PCLATH
    CLRC                            ; Borramos el Carry por si acaso
    RLF     NumCaso,W               ; Cargamos el nº de caso x 2
    ADDWF   NumCaso,W               ; Cargamos el nº de caso x 3
    ADDLW   Tabla_Saltos+1          ; Se lo suma a la posición + 1
    GOTO    Tabla_Saltos            ; Salta a la Tabla

ORG 0x0400
Caso_4                  ; Caso 4
    NOP

ORG 0x500
Caso_5                  ; Caso 5
    NOP

ORG 0x600
Caso_0                  ; Caso 0
    NOP

ORG 0x700
Caso_1                  ; Caso 1
    NOP

ORG 0x800
Caso_2                  ; Caso 2
    NOP

ORG 0x900
Caso_3                  ; Caso 3
    NOP


ORG 0x1200
Tabla_Saltos
    MOVWF   PCL                     ; Salta al caso correspondiente
    LGOTO   Caso_0                  ; Caso 0
    LGOTO   Caso_1                  ; Caso 1
    LGOTO   Caso_2                  ; Caso 2
    LGOTO   Caso_3                  ; Caso 3
    LGOTO   Caso_4                  ; Caso 4
    LGOTO   Caso_5                  ; Caso 5
    ; Y así las que necesitemos

De esta manera nos da igual dónde estén la Tabla de saltos y las etiquetas de destino.

Saludos!
« Última modificación: Octubre 04, 2010, 03:07:34 por Pardillete » En línea
DML
PIC10F
*
Desconectado Desconectado

Sexo: Masculino
Mensajes: 30


« Respuesta #20 : Septiembre 08, 2015, 09:16:21 »

Bueno, aquí les dejo tres rutinas que tenias guardas y puede servirles a alguien. (Probadas)  Wink
  • Rutina de multiplicación de 16 bits x 16 bits, resultado de 32 bits.
  • Rutina de división de 24 bits / 16 bits, resultado de 24 bits.
  • Rutina de conversión Binario 16 bits a BCD.


Gracias Suky!!! me sirvio un montón la Rutina de conversión Binario 16 bits a BCD, por casualidad no tendras una rutina de conversión Binario 24 bits (tres bytes) a BCD
Trate de decifrar que es lo que hace tu rutina para modificarla a 24 bits pero no pude entenderla.

Gracias de antemano
Diego
En línea
DML
PIC10F
*
Desconectado Desconectado

Sexo: Masculino
Mensajes: 30


« Respuesta #21 : Septiembre 14, 2015, 04:31:35 »

Bueno, aquí les dejo tres rutinas que tenias guardas y puede servirles a alguien. (Probadas)  Wink
  • Rutina de multiplicación de 16 bits x 16 bits, resultado de 32 bits.
  • Rutina de división de 24 bits / 16 bits, resultado de 24 bits.
  • Rutina de conversión Binario 16 bits a BCD.


Gracias Suky!!! me sirvio un montón la Rutina de conversión Binario 16 bits a BCD, por casualidad no tendras una rutina de conversión Binario 24 bits (tres bytes) a BCD
Trate de decifrar que es lo que hace tu rutina para modificarla a 24 bits pero no pude entenderla.

Gracias de antemano
Diego

encontré un metodo y lo comparto...
si solo se desea el numero cargado en los registros DIGITO (no en ASCII para salir directamente por display)
comentar la linea
Código:
GOTO BCD_ASCII
Ah y poner un
Código:
RETLW 0
despues...

Código:
;****************************************************************************
;
; CREAR NUMERO BCD DESDE 3 BYTES
;
;****************************************************************************

BIN24_BCD8
BCF STATUS, C
MOVLW .24 ;24 Bits
MOVWF COUNTBCD ;Cargo contador...
CLRF R0 ;Borro registros...
CLRF R1
CLRF R2
CLRF R3
Loop24:
RLF NumL, 1
RLF NumM, 1
RLF NumH, 1
RLF R3, 1
RLF R2, 1
RLF R1, 1
RLF R0, 1
DECFSZ COUNTBCD, 1
GOTO A_Dec
GOTO BCD_ASCII
A_Dec
MOVLW R3
MOVWF FSR
CALL A_BCD
MOVLW R2
MOVWF FSR
CALL A_BCD
MOVLW R1
MOVWF FSR
CALL A_BCD
MOVLW R0
MOVWF FSR
CALL A_BCD
GOTO Loop24
A_BCD
MOVF INDF, 1
MOVLW 0x03
ADDWF INDF, w
MOVWF TEMP_BCD
BTFSC TEMP_BCD, 3
MOVWF INDF
MOVLW 0x30
ADDWF INDF, w
MOVWF TEMP_BCD
BTFSC TEMP_BCD, 7
MOVWF INDF
RETLW 0
BCD_ASCII
SWAPF R0, w
ANDLW 0x0F
ADDLW 0x30
MOVWF DIGITO1
MOVFW R0
ANDLW 0x0F
ADDLW 0x30
MOVWF DIGITO2
SWAPF R1, w
ANDLW 0x0F
ADDLW 0x30
MOVWF DIGITO3
MOVFW R1
ANDLW 0x0F
ADDLW 0x30
MOVWF DIGITO4
SWAPF R2, w
ANDLW 0x0F
ADDLW 0x30
MOVWF DIGITO5
MOVFW R2
ANDLW 0x0F
ADDLW 0x30
MOVWF DIGITO6
SWAPF R3, w
ANDLW 0x0F
ADDLW 0x30
MOVWF DIGITO7
MOVFW R3
ANDLW 0x0F
ADDLW 0x30
MOVWF DIGITO8
RETLW 0
« Última modificación: Septiembre 14, 2015, 04:34:50 por DML » En línea
Páginas: 1 [2]   Ir Arriba
  Imprimir  
 
Ir a:  

Impulsado por MySQL Impulsado por PHP Powered by SMF 1.1.21 | SMF © 2011, Simple Machines
SMFAds for Free Forums
XHTML 1.0 válido! CSS válido!
Página creada en 0.128 segundos con 25 consultas. (Pretty URLs adds 0.008s, 2q)
loggkey