Haz una pregunta
  Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos
Foros Registrarse ¿Olvidaste tu contraseña?

Temas similares

13/12/2014 #161

Avatar de JoaquinFerrero

Hay otra forma de hacerlo: diciendo al enlazador que omita ese mensaje.

Pon esto al principio:

Código PHP:
     errorlevel  -302                        Turn off banking message 
Eso sí... con eso te estás comprometiendo a que vas a llevar un control férreo de en qué banco estás trabajando en cada momento.

Más información en el manual del ensamblador del PIC.
13/12/2014 #162


No soy vidente pero le atine, estabas usando un solo registro para el mismo proposito, en este caso el TMR1.

El compañero Daniel Meza ya te dio la respuesta a tu problema y el compañero JoaquinFerrero ya te dijo como eliminar los "warning".

Solo como sugerencia, nunca utilices los registros de uso especial del PIC como registros cualquiera de la RAM, a menos que no los vayas a utilizar para nada y que tu proceso requiera una cantidad de RAM que ya sobrepasaste y que solo tocando esos registros puedas solucionar ese problema.

Los registros de uso especial pueden verse afectados por el uso de otros registros especiales y cuando menos te lo esperas te crean un "problema" que no contemplas. En este caso no tienes habilitado el TMR1 ni estas utilizando interrupciones ni cosa por el estilo, asi que no hay problema. Lo recomendable es usar la RAM a partir de la direccion donde inician los registros de proposito general (para este PIC, la 20h para el Banco 0).

Ademas, en un futuro podrias necesitar ese registro y tendrias que modificar tu programa, mejor declara tu bloque de variables:

Código:
	CBLOCK	0x20
	CONTADOR			;EN LUGAR DE PONER	"MOVWF	.15"	PUEDES PONER	"MOVWF	CONTADOR"
	ENDC
18/01/2015 #163

Avatar de dragon33

Tengo una duda, a ver si los expertos en ensambler me ayudan. Imaginaos, cargo un registro con el número 25 y ese número deseo sacarlo de la siguiente forma por el PORTB, el 5 sacarlo por un nibble que puede ser desde RB0 a RB3, y el 2 por otro nibble desde RB4 a RB7 ¿Como lo haría?. Lo que pretendo es poder sacar cualquier número entre 0 a 99 y poder visualizarlo por dos displays de 7 segmentos.
18/01/2015 #164

Avatar de fdesergio

dragon33 dijo: Ver Mensaje
Tengo una duda, a ver si los expertos en ensambler me ayudan. Imaginaos, cargo un registro con el número 25 y ese número deseo sacarlo de la siguiente forma por el PORTB, el 5 sacarlo por un nibble que puede ser desde RB0 a RB3, y el 2 por otro nibble desde RB4 a RB7 ¿Como lo haría?. Lo que pretendo es poder sacar cualquier número entre 0 a 99 y poder visualizarlo por dos displays de 7 segmentos.
Si no hay problema con codigo extenso puedes usar una tabla, cargas el valor en W, llamas la tabla, retornas con el codigo en W y pasas al PORTB, asi de facil, chaooooo
18/01/2015 #165

Avatar de JoaquinFerrero

Lo primero que debes hacer es transformar el número en binario a BCD. Por estos foros hay algunos hilos que lo explican.

Hay dos formas básicas:
  • Hacemos un bucle por el que necesitamos sacar el número de decenas restando 10 al valor original. Si es menor que 10, entonces lo que quedan son las unidades. Cuando tenemos los dos valores, componemos el nuevo valor en BCD haciendo una rotación del valor de las decenas en el nibble alto, y luego haciendo un OR con el valor de las unidades
  • La otra forma es un poco más de matemáticas, pero más breve que la anterior. Consiste primero en saber cuántas decenas hay. Eso lo podemos sacar haciendo lo mismo que antes, con restas sucesivas. Una vez que lo sabemos, multiplicamos ese valor por 6, y el resultado se lo sumamos al valor original. Eso nos da el valor original ya transformado a BCD. Naturalmente, esta es la solución literal, pero en la práctica se usan trucos, como por ejemplo: cada vez que sumamos una decena más, lo que hacemos en realidad es sumar 6 a un sumador aparte. De esa manera, al mismo tiempo que hacemos la división de las decenas, estamos haciendo la multiplicación por 6 de las decenas. Solo quedaría hacer la suma del valor original con ese multiplicando.
18/09/2015 #166


Leyendo el foro, observé que la mayoría de ustedes no comenta su código, y como es un tema para principiantes, deben de hacerlo para que todo mundo los siga sin dificultad.

También observé que cuando quieren mostrar un dato binario en un display multiplexado, tienen varias dudas de cómo hacerlo.

Si pueden leer inglés, les recomiendo éste sitio:
http://www.islavici.ro/cursuriold/co...ook/0_Uvod.htm
Tiene la versión on-line del libro gratis "PIC microcontrollers, for beginners too"

Si no, aquí les dejo el macro corregido y programa de prueba como aparece en ese libro. (No lo he simulado)
Si alguien quiere simularlo y comentar su resultado, sería muy bueno.
Código PHP:
Ejemplo de uso de macro

        PROCESSOR    P16F84
        
#include    "p16f84.inc"
        
_CONFIG        _CP_OFF _WDT_OFF _PWRTE_ON _XT_OSC

Macro para extraer info para mostrar en el Display
Dig1 MSD (centenasDig2decenas  Dig3LSB (unidades)
par0 variable a ser mostrada LSB 8-bits (0-255)

digibyte macro par0
    local Loop_C
    local Loop_D
    local Pozitiv
    
    clrf    Dig1        
Limpiamos contadores que contienen lo
    clrf    Dig2        
que se va a mostrar en el display
    clrf    Dig3        
En este caso 3 digitos (0 a 255)

Pozitiv
    movf    par0
,w        Guarda el número a ser separado
    movwf    Digtemp        
en forma temporal
;
Convierte a BCD
La técnica consiste en dividir el parámetro entre una mascara
;   (100,10,1). para obtener asi el digito en decimal.
Se implementa la división subtrayendo al parametro la
;    mascara contando cuantas veces lo hemos hechohasta que el
;    resultado de la resta sea menor a la mascara
como empesamos con el contador en 1 debemos substraer 1 antes de
salirPara tener en el contador con el resultado correcto
;
Empesamos con las centenas 
    movlw    .100        
mascara para las centenas
Loop_C
    incf    Dig1
,f      Centenas Centenas 1
    subwf    Digtemp
,f   Parametro Parametro .100
    btfsc    STATUS
,C    Si es menor a zero (c=0salta 1 linea
    
goto    Loop_C        Si no regresa hasta que ocurra
    decf    Dig1
,f        Resta 1 alcontador antes de salir
                        
Digtemp contiene el cosiente de la division
Seguimos con las decenas
    movlw    .10         
Ajustamos la mascara para decenas
Loop_D
    incf    Dig2
,f        Decenas Decenas 1
    subwf    Digtemp
,f
    btfsc    STATUS
,C
    
goto    Loop_D
    decf    Dig2
,f      Dig2 contiene las Decenas y
                        
Digtemp contiene ahora las unidades
y finalizamos con las unidades
    movf    Digitemp
,w    Mueve las unidades a su contador
    movwf    Dig3
    endm
        
        org    0x00
        
goto    main        Inicio del programa
        
        org    0x04
        
goto    ISR            Inicio del vextor de interrupción
        
        Cblock 0x0C
        Dig1                
Centenas del numero binario D
        Dig2                
Decenas  del numero binario D
        Dig3                
Unidades del numero binario D
        Digtemp             
auxiliar en conversion bin-.Dec
        D                    
numero a desplegar
        One                    
auxiliar para el multiplexado del Display
        W_temp                
copia de W en interrupciones
        endc
        
Main
;    banksel    TRISA
        bsf STATUS
,5        ;se pone un 1 en el bit 5 del status para
                            
;   elegir el banco 1
         movlw    
b'11111100'    RA0 RA1 son salida para multiplexado
        movwf    TRISA
        clrf    TRISB        
Puerto B son las salidas de los segmentos
        movlw    
b'10000100'    Prescaler 32-> TMR0 incrementa cada 32ms
        movwf    OPTION_REG    
;   Asumimos que se usa un cristal de 4 MHz4
;        banksel    PORTA
        bcf STATUS
,5  n     cambiamos al banco 0 poniendo un 0 en el
                            
;   bit 5 del Status
        movf PORTA
,0nn      leemos el puerto A y cargamos en W
        movlw    
,96            TMR0 inicia en 96
                            
de manera que una interrupcion ocurre
                            
cada (255-97)* 32 ms 5.088 ms
        movwf    TMR0
        movlw    
b'10100000'    Habilita interrupcion del timer 0
        novwf    INTCON
        
        movlw    .21            
Despliega el numero 21
        movwf    D
        clrf    One
        clrf    PORTA        
Apaga ambos digitos al inicio
Loop
        
goto Loop        Loop principal -> salimos con una interrupcion
        
ISR                            
Rutina de interrupcion
        movwf    W_temp        
Salva W
        movlw    .96            
Inicializa TMR0 para que tenga la siguiente
        movwf    TMR0        
interrupcion en aprox 5ms
        bcf        INTCON
T0IF ;Limpia bandera de Overflow del TMR0
                            
para ser capaz de reaccionar a la siguiente
                            
interupcion
        bcf        PORTA
0    Digito en A0apagado
        bcf        PORTA
1    Digito en A1encendido
        movf    One
f        Ajusta banderas
        btfsc    STATUS
,Z    Cual display debe prenderse?
        goto     
Msd_on
Lsd_on                        
Si el MSD estaba anteriormente ON
        bcf        One
,0        indica que LSD esta ON
        movlw    High Bcdto7seg 
Antes de usar el macro tenemos que ir
                            
a la tabla de conversionPCLATH
        movwf    PCLATH        
W debe sr inizializado con la direccion
                            
mas alta de la tabla
                            
para prever errores de direccionamiento
        digibyte    D        
llama a la macro para separar digitos de D
        movf    Dig3
w        Unidades
        call    Bcdto7seg    
llama la tabla de conversion para 7-seg
                            
para displays que son catodo común
                            
regresa W con el codigo correspondiente
        movwf    PORTB        
y prepara los segmentos
        bsf        PORTA
1    Enciende el Digito de las Unidades
                            
por 5mshasta que la siguiente
                            
interrución ocurra
        movf    W_temp
,w    Recupera W alvalor que tenia antes de
                            
entrar a la rutina de interrupción.
        
retie
        
Msd_On
        bsf        One
0        Indica que el MSD esta encendido
        movlw    High Bcdto7seg 
Antes de usar el macro tenemos que ir
                            
a la tabla de conversionPCLATH
        movwf    PCLATH        
W debe sr inizializado con la direccion
                            
mas alta de la tabla
                            
para prever errores de direccionamiento
        digibyte    D        
llama a la macro para separar digitos de D
        movf    Dig2
w        Unidades
        call    Bcdto7seg    
llama la tabla de conversion para 7-seg
                            
para displays que son catodo común
                            
regresa W con el codigo correspondiente
        movwf    PORTB        
y prepara los segmentos
        bsf        PORTA
0    Enciende el Digito de las Decenas
                            
por 5mshasta que la siguiente
                            
interrución ocurra
        movf    W_temp
,w    Recupera W alvalor que tenia antes de
                            
entrar a la rutina de interrupción.
        
retie
    
    org    0x300                
Inicio de la tabla de conversion
                            
puesta al inicio de la tercer banco de RAM4
                            
Otras paginas son posibles pero la tabla
                            
;debe estar en una sola pagina (bancode RAM

Bcdto7seg                    
Tabla de conversion para 7-seg
        addwf    PCL
,f        Ajusta W al valor de tabla offset
        dt        0x3f
0x060x5b0x4f0x660x6d0x7d0x070x7f0x6f
;        retlw    0x3f        número 0
;        retlw    0x06        número 1
;        retlw    0x5b        número 2
;        retlw    0x4f        número 3
;        retlw    0x66        número 4
;        retlw    0x6d        número 5
;        retlw    0x7d        número 6
;        retlw    0x07        número 7
;        retlw    0x7f        número 8
;        retlw    0x6f        número 9 
Archivos Adjuntos
Tipo de Archivo: txt macro.txt (5,9 KB (Kilobytes), 15 visitas)
19/09/2015 #167


Les dejo una traducción e interpretación del codigo de conversión de un número de 16-bits a BCD
Este código se puede usar en cualquier PIC, y esta publicado en la nota de aplicación de microchip
AN526 PIC16C5X KPIC16CXXX Math Utility Routines.
Espero que les sea útil.

Código:
LIST P = 16C54, n = 66
;
;********************************************************************
;  Programa para convertir un número Binario de 16-Bit a BCD
; Esta rutina convierte un número binario de 16-Bit a un  número
; BCD  de 5 Digitos. Esta rutina es útil puesto que los PIC16C55 & ;
;  PIC16C57 tienen dos puertos de 8-bit y uno de 4-bit (RA) 
; para mostrar el resultado de los 5 digitos BCD)
;
; El número binario de 16-bit es colocado en variables RAM
;  H_byte & L_byte, con el byte más significativo en H_byte.
; El número BCD de 5-digitos es regresado en R0, R1 & R2 
;  con R0 conteniendo el MSD en su nibble alto (el mas a la derecha) 
; Usa la técnica Shift - Add 3
;
; Performance :
; Program Memory : 35
; Clock Cycles : 885
;
;
; Program: B16TOBCD.ASM
; Revision Date:
; 1-13-97 Compatibility with MPASMWIN 1.40
;
;*******************************************************************;
;
		Cuenta equ 16		; Contador para número de bits
		temp   equ 17
;
		H_byte equ 10
		L_byte equ 11
		R0     equ 12 		; RAM Assignments
		R1     equ 13
		R2     equ 14
;
	include “p16c5x.inc”
	LIST
;P16C5X.INC Standard Header File, Ver. 3.30 Microchip Technology, Inc.
    LIST
;
B2_BCD
		bcf STATUS,0 	        ; carry bit = 0
		movlw .16		; Cuenta=16  bits
		movwf Cuenta
		clrf R0			; Limpia Registros
		clrf R1
		clrf R2
loop16
		rlf L_byte, F      ; Shift a la izquierda un bit del dato en 
		rlf H_byte, F	;   los registros del resultado
		rlf R2, F
		rlf R1, F
		rlf R0, F
;
		decfsz Cuenta, F ; Terminamos todos los16 bits
		goto adjDEC         ;  No: Continua procesando
		RETLW 0               ; Si:  Regresa con W = 0
;
adjDEC				  ; Despues de cada shift left
					  ; Debemos checar cada nibble del Registro
		movlw R2		  ;  no sea mayor a 7 y si es así hay que
                                          ; sumarle 3
		movwf FSR	  ;  empesamos con R2
		call adjBCD			
;
		movlw R1		  ; y seguimos con R1
		movwf FSR			
		call adjBCD
;
		movlw R0		 ; y al último con R0
		movwf FSR
		call adjBCD
;
		goto loop16
;
adjBCD
		; 
		movlw 3			; Suma 3 a LSB
		addwf 0, W		; y sumamos al registro
		movwf temp		;
		btfsc temp, 3		; test if LSB > 7
							;  Si :  LSD = LSD + 3 
		movwf 0				;  No :  no alteramos LSD
		movlw 30			; Suma 30 al MSB
		addwf 0, W		;
		movwf temp
		btfsc temp, 7 		; test if MSB > 7
							;  Si  :  MSD = MSD + 3 
		movwf 0				;  No : no alteramos MSD
		RETLW 0
;
;********************************************************************
; Test Program
;*********************************************************************
main
		movlw 0FF		; número binario a convertir = FFFF
		movwf H_byte	        ; 
		movwf L_byte
		call B2_BCD 	        ; Despues de la conversion del número
						; a BCD obtenemos
; 						;      R0,R1,R2 = 06,55,35
;
self
		goto self
;
		org 1FF			; Reset vector
		goto main
		
		END
Archivos Adjuntos
Tipo de Archivo: txt 16-Bit Binary To BCD Conversion Routine.txt (2,9 KB (Kilobytes), 5 visitas)
20/09/2015 #168


Disculpen por el error en la macro para descomponer un numero binario de 8-bits usando division entre 10
aqui esta el codigo correcto

Código:
; Macro para extraer info para mostrar en el Display
; Dig1 = Centenas, Dig2= Decenas  Dig3= LSB (unidades)
; par0 = variable 8-bits a ser convertida a BCD  (0-255)

digibyte macro par0
	local ExitC			; Declaramos las etiquetas internas
	local ExitD
	
	clrf	Dig1		; Limpiamos contadores que contien
	clrf	Dig2		;    en decimal lo que se va a mostrar en
	clrf	Dig3		;     el display

; Convierte a BCD
; La técnica consiste en dividir el parámetro entre una mascara
;   (100,10). para obtener así el digito en decimal.
; Se implementa la división - subtrayendo al parametro la
;    mascara y contando cuantas veces lo hemos hecho, hasta que el
;    resultado de la resta sea menor a la mascara. 
; como empesamos con el contador en 1 debemos substraer 1 antes de
; salir y sumar la mascara al parametro. Para tener en el contador
; con el resultado correcto
;
	movf	par1,w		; Guarda el número a ser
	movwf	Digtemp	;    separado en registro de conversión
;
; Empesamos con las Centenas
;
	movlw	.100        ; mascara para las centenas
ExitC
	incf	Dig1, f		; Centenas = Centenas + 1
	subwf	Digtemp, f	; Parametro = Parametro - .100
	btfsc	STATUS, C	; Si es menor a zero (c=0) salta 1 linea
	goto	ExitC		; Si no regresa hasta que ocurra
	addwf	Digtemp, f	; Agrega 100 ya que restamos de más 
	decf	Dig1, f		;    y Resta 1 al contador antes de salir
	                    ; Digtemp contiene del número a procesar
						;    solo las Decenas y Unidades
; Seguimos con las decenas
;
	movlw	.10			; Ajustamos la mascara para decenas
ExitD
	incf	Dig2, f		; Decenas = Decenas + 1
	subwf	Digtemp, f
	btfsc	STATUS, C
	goto	ExitD
	addwf	Digtemp, f	; Agrega 10 ya que restamos de más 
	decf	Dig2, f		;    y Resta 1 al contador antes de salir
	                    ; Digtemp contiene del número a procesar
						;    solo las Unidades
; y finalizamos con las unidades
	movf	Digitemp,w	; Mueve las unidades a su contador
	movwf	Dig3
	endm
01/10/2015 #169


Cambiando un poco, Supongan que deseamos colocar 4 datos, en el ejemplo números, en 4 localidades de memoria RAM consecutivas, en el ejemplo empesamos en 10h. Facil verdad...? un ejemplo de clase o tarea. Les dejo aqui 3 formas diferentes de hacerlo. Fuerza bruta si son números, uso de pseudo-instruccion, y el importante direccionamiento indirecto.

Código:
;****************************************************
;                                                                    *
;    Filename:	    Dir_Indexado.asm                 *
;    Date:          Septiembre 29,2015                *
;    File Version:  1.0                                       *
;                                                                    *
;    Author:	    David Sanchez                      *
;    Company:       David Sanchez                     *
;                                                                    * 
;                                                                    *
;****************************************************
;    Descripción :                                              *
; Prueba de movimiento de Datos usando          *
;   diferentes metodos de direccionamiento        *
;   direccionamiento indexado                            *
;       Dirección = Reg4(FSR) + Reg0 (INDF)      *
;       Contenido de Dirección  en W0                 *
;                                                                     *
;   Para ello se coloca los números 1,2,3 & 4     *
;   En localidades continuas de RAM                 *
;   iniciando en 0x010h                                      *
;                                                                     *
;                                                                     *
;*****************************************************

	list      p=16c54             ; directiva para definir el procesador
	#include <p16c5x.inc>         ; definición  de las variables specificas
                                 ; del procesador 

	__CONFIG   _CP_OFF & _WDT_OFF & _RC_OSC

; '__CONFIG'  Esta directiva es useda para implantar una palabra  de configuración en el archivo  *.asm
; Las etiquetas que siguen la directiva estan localizadas en el archivo que describe el procesador *.inc 
;
;***** DEFINICION DE CONSTANTES
Zero	    EQU	0	    ; zero
;
;***** DEFINICION DE VARIABLES RAM
temp	    EQU 0x07        ; 
Prueba	    EQU	0x10        ; Seis localidades seguidas
;    
;***** Macros
; INCW Incrementa W
INCW MACRO
    MOVWF   temp	; Salva W
    INCF    temp, w	; temp = temp + 1
    ENDM
;   
;       Shift PORTA to the left 
;	SLCPA   MACRO
;	MOVLW   1
;	BCF     STATUS, C       ; Clear carry
;	RLF     (PORTA),F       ; Rotate left
;        ENDM        
   
;*****
	ORG     0x000

start	                    ; Inicio del Programa
	CALL CLR_REG	    ; Limpia registros
		
	; Fuerza bruta ... ponemos 1 en 0x10, 2 en 0x11. 3 en 0x12, & 4 en 0x13
	INCF	Prueba         ; 1 en 0x10
	INCF	Prueba +1      ; 1 en 0x11
	INCF	Prueba +2      ; 1 en 0x12
	INCF	Prueba +3      ; 1 en 0x13
	
	INCF	Prueba +1      ; 2 en 0x11
	INCF	Prueba +2      ; 2 en 0x12
	INCF	Prueba +3      ; 2 en 0x13
	
	INCF	Prueba +2      ; 3 en 0x12
	INCF	Prueba +3      ; 3 en 0x13

	INCF	Prueba +3      ; 4 en 0x13
	; aqui terminamos Fuerza bruta
    ;	     ... 10 localidades de Memoria del Programa
	;            ...  0 localidades de RAM
	;            .  10 cyclos de ejecución.
	; Si queremos escribir oto dato a la siguiente localidad
	;    usa 5 más localidades de memoria del program x dato
        ;       o sea "n" localidades de mas por cada dato adicional
	;                  donde "n" es el número de datos
;
	; Exploremos otra forma:
	CALL CLR_REG	    ; Limpia registros
	
	; alternativa 1 de fuerza bruta   usa Pseudo instrucción INCW
	; Una Pseudo instrucción es una instrucción que no es parte de
	;        grupo de instrucciones que vienen en la Hoja de datos.
    ;        Se declaran como macros.	
	MOVLW	1
	MOVWF	Prueba      ;      coloca 1 en 0x10
	INCW		         ; W=2
	MOVWF	Prueba+1    ;      coloca 2 en 0x11
	INCW		         ; W=3
	MOVWF	Prueba+2    ;      coloca 3 en 0x12
	INCW		         ; W=4
	MOVWF	Prueba+3    ;      coloca 4 en 0x13
;
	; INCW no existe asi que tiene que ser implementada
	; por un macro o sustutida por 
	; MOVWF temp
	; INCF  temp ,w
;
	; aqui terminamos  alternativa 1
    ;	... 11 localidades de Memoria del Programa
	;       ...  1 localidades de RAM
	;     ...  11 cyclos de ejecución.
	; Si queremos escribir oto dato a la siguiente localidad
	;    usa solo 2 más localidades de memoria del program x dato
;  Aparentemente Fuerza bruta es más rápida y ocupa menos Memoria,
;    pero solo para pocos movimientos de datos ....si movemos más datos
;    ... alternativa 1 es más eficiente
;
	CALL CLR_REG	    ; Limpia registros
;
	; Alternativa Direccionamiento Indexado
	MOVLW	Prueba	    ; Base = 10h
	MOVWF	FSR         ; FSR = 111 1 0000
	MOVLW	1
	MOVWF	INDF        ; Write W en base         1 en 0x10
	INCF	FSR	    ; Base = base + 1		    ; W = 01h
	INCW		    ;   W = 02h
	MOVWF	INDF	    ;   Write 02 en base+1    2 en 0x11
	INCF	FSR	    ; Base = base + 2
	INCW		    ;   W = 03h
	MOVWF	INDF	    ;   Write 03 en base+2    3 en 0x12
	INCF	FSR	    ; Base = base + 3
	INCW		    ;   W = 04h
	MOVWF	INDF	    ;   Write 04 en base+3    4 en 0x13
;
	;aqui terminamos  Direccionamiento indexado
    ;	... 13 localidades de Memoria del Programa
	;       ...  0 localidades de RAM
	;     ...  13 cyclos de ejecución.
	; Si queremos escribir oto dato a la siguiente localidad
	;    usa solo 3 mas localidades de memoria del programa x dato
	;
;    Aparentemente Alternativa 1 es más rápida pero usa 1 preciosa
;      localidad de Memoria RAM
;  Asi que ha usar el direccionamiento indexado.

; SUBRUTINAS
;
CLR_REG	; Limpia Registros Prueba
	CLRW		   
	MOVWF	temp	    ; temp = 0
	MOVWF	Prueba	    ; Prueba = 0
	MOVWF	Prueba +1   ; Prueba +1 = 0
	MOVWF	Prueba +2   ; Prueba +2 = 0
	MOVWF	Prueba +3   ; Prueba +3 = 0
	RETLW	0	    ;  Regresa con w=0
;
; TABLAS

; ***** Reset
	ORG     0x1FF       ; processor reset vector
	goto    start

	END
Archivos Adjuntos
Tipo de Archivo: txt Dir_Indexado.asm.txt (5,6 KB (Kilobytes), 2 visitas)
14/10/2015 #170


Hola a todos,
Necesitaba una rutina para el PIC16x54 que me hiciera la conversión de binario (16-bits) a BCD. Hay muchas en el web pero para PICs más caros y poderosos que usan la instrucción SUBLW ... que el 16x54 carece. Asi que cambie un poco su implementación. Les dejo aqui la rutina en Ensamblador probada en MPLAB X. y espero sus comentarios.

Código:
;****************************************************
;                                                   *
;    Filename:	    ShiftAdd3.asm                   *
;    Date:          Octubre 14,2015                 *
;    File Version:  1.0                             *
;                                                   *
;    Author:	    David Sanchez                   *
;    Company:       David Sanchez                   *
;                                                   * 
;                                                   *
;****************************************************
;    Implementado para el PIC16x54                  *
; Toma un número binario de 16-bit y lo convierte en *
; 5 digitos BCD almacenados en forma consecutiva    *
;  MSB en la localidad más baja                     * 
;****************************************************

	list      p=16c54            ; directiva para definir el procesador
	#include <p16c5x.inc>        ; definición  de las variables specificas
                                 ; del procesador 

	__CONFIG   _CP_OFF & _WDT_OFF & _RC_OSC
;
;***** DEFINICION DE CONSTANTES
;
;***** DEFINICION DE VARIABLES RAM
temp      EQU 0x07   ; variable de trabajo
binH      EQU 0x08   ;número binario a convertir - high byte
binL      EQU 0x09   ;número binario a convertir - low byte
PackBCD_x_4      EQU 0x10   ;resultado en packed BCD - digitos altos
PackBCD_3_2      EQU 0x12   ;resultado en packed BCD - digitos de enmedio
PackBCD_1_0      EQU 0x14   ;resultado en packed BCD - digitos bajos
counter   EQU 0x0A   ;High nible of PackBCD_x_4  - variable de trabajo
BCD_1     EQU 0x13   ;UnPackBCD
BCD_3     EQU 0x11   ;UnPackBCD
;
;***** Macros
;
; Programa principal 
;*****
	ORG     0x000
;
start
; Escribimos valor que deseamos convertir 3AF3=15091  
    movlw   0xF3
    movwf   binL
    movlw   0x3A
    movwf   binH
	    
; Inicia la converción Binario a BCD con el algorithmo shift-Add3     
  ; Limpia los registros BCD     
     clrf   PackBCD_1_0     
     clrf   PackBCD_3_2     
     clrf   PackBCD_x_4
     clrf   BCD_1
     clrf   BCD_3
  
     ; loop por 15 rotaciones con la corrección "add 3"     
     movlw    .15     
     movwf    counter    
     ; convierte binario  (16 bits) a BCD packed     
Bin2Bcd_Loop     
     bcf        STATUS, C     ; preparamos carry flag para RLF   
     ; Rotamos todos a la izquierda     
     rlf        binL, F     
     rlf        binH, F     
     rlf        PackBCD_1_0, F     
     rlf        PackBCD_3_2, F     
     rlf        PackBCD_x_4, F     
     ; Prueba los digitos BCD que tengan un valor binario >= 5     
     ;  - Si son >=5 add3     
Test_Digit_0
     movlw   0x04
     movwf   temp
     movlw   0x0f     
     andwf   PackBCD_1_0, W
;     sublw    0x04
     subwf   temp, w 
      ;
     btfsc   STATUS, C
     goto    Test_Digit_1      ; digito 0 < 5
     ; Add3 a digito 0
     movlw   0x03
     addwf   PackBCD_1_0, F    ;  Nunca hay un acarreo de digitos
Test_Digit_1
     movlw   0x40
     movwf   temp
     movlw   0xf0
     andwf   PackBCD_1_0, W
     ; sublw   0x40
     subwf   temp, w
     btfsc   STATUS, C
     goto    Test_Digit_2      ; digito 1 < 5
     ; Add3 a digito 1
     movlw   0x30
     addwf   PackBCD_1_0, F
Test_Digit_2
     movlw   0x04
     movwf   temp
     movlw   0x0f
     andwf   PackBCD_3_2, W
     ;sublw   0x04
     subwf   temp, w
     btfsc   STATUS, C
     goto    Test_Digit_3      ; digito 2 < 5
     ; Add3 a digito 2
     movlw   0x03
     addwf   PackBCD_3_2, F    ; Nunca hay un acarreo de digitos
Test_Digit_3
     movlw   0x40
     movwf   temp
     movlw   0xf0     
     andwf   PackBCD_3_2, W
     ;sublw   0x40
     subwf   temp, w
     btfsc   STATUS, C
     goto    Test_Digit_4     ; digito 3 < 5
     ; Add3 a digito 3
     movlw   0x30
     addwf   PackBCD_3_2, F
Test_Digit_4
     movlw   0x40
     movwf   temp
     movlw   0x0f
     andwf   PackBCD_x_4, W
     ;sublw   0x40
     subwf   temp, w
     btfsc   STATUS, C
     goto    Test_Digits_End   ; digito 4 < 5
     ; Add3 a digito 4
     movlw   0x03
     addwf   PackBCD_x_4, F    ; Nunca hay un acarreo de digitos
Test_Digits_End
     decfsz  counter, F
     goto    Bin2Bcd_Loop
     ; Ultima rotación (16th) sin adiciones correctivas
     bcf     STATUS, C        ; preparamos carry flag para RLF
     ; Rotamos todos a la izquierda
     rlf     binL, F
     rlf     binH, F
     rlf     PackBCD_1_0, F
     rlf     PackBCD_3_2, F
     rlf     PackBCD_x_4, F
     ; la converción ha terminado
     movlw    0x0f                ; limpiamos los nibble no usados
     andwf    PackBCD_x_4, F
 ;
 ; * Ahora ya tenemos los 5 digitos BCD pero agrupados
 ; *  Si es necesario procedemos a desagruparlos
 ;
 ; Unpack los digitos BCD
     swapf   PackBCD_1_0, W        ; extrae digito 1
     andlw   0x0f
     movwf   BCD_1
     swapf   PackBCD_3_2, W        ; extrae digito 3
     andlw   0x0f
     movwf   BCD_3
     ; limpia los high nibles en BCD_0 y BCD_2
     movlw   0x0f
     andwf   PackBCD_1_0, F
     andwf   PackBCD_3_2, F
 ;
halt_loop     
     nop     
     goto    halt_loop         
 	
; ***** Reset
	ORG     0x1FF       ; processor reset vector
	goto    start

	END
Archivos Adjuntos
Tipo de Archivo: txt ShiftAdd3 para 16-bit.asm.txt (5,3 KB (Kilobytes), 2 visitas)
25/10/2015 #171


Leyendo "MANUAL DE MICROCONTROLADORES PIC" que consegui en la web, como no trae otra referencia mas alla del titulo no puedo darle el reconocimiento que se merece el author, me encontre con esta muy eficiente rutina de Shift-Add3 para la conversion de números binarios a BCD. Ya la probe y trabaja muy bien y usa solo 47 localidades de la memoria del programa. Usa direccionamiento indirecto en una forma muy eficiente.

Aqui les dejo la rutina con mis comentarios añadidos
Código:
;****************************************************
;                                                   *
;    Filename:	    ShiftAdd3.asm                   *
;    Date:          Octubre 24,2015                 *
;    File Version:  1.1                             *
;                                                   *
;    Author:	    David Sanchez                   *
;    Company:       David Sanchez                   *
;                                                   * 
;                                                   *
;****************************************************
;                                                   *
;  Convierte número binario 16-bits a 5 digitos BCD *
;     Usando la técnica de Desplaza-Suma3           *
;****************************************************

	list      p=16c54             ; directiva para definir el procesador
	#include <p16c5x.inc>         ; definición  de las variables especificas
                                      ; del procesador 

	__CONFIG   _CP_OFF & _WDT_OFF & _RC_OSC
;
;***** DEFINICION DE CONSTANTES
;
#DEFINE ZERO  STATUS,2   ; Bit de zero
#Define Carry STATUS,0   ; Bit de carry
;
;***** DEFINICION DE VARIABLES RAM
temp      EQU 0x07   ; variable de trabajo
binH      EQU 0x08   ;número binario a convertir - high byte
binL      EQU 0x09   ;número binario a convertir - low byte
counter   EQU 0x0A   ; contador de número de bits (shifts) procesados
BCD_x_5   EQU 0x0B   ;resultado en packed BCD - digitos altos
BCD_4     EQU 0x0C   ;UnPackBCD - digito 4
BCD_4_3   EQU 0x0D   ;resultado en packed BCD - digitos de enmedio
BCD_2     EQU 0x0E   ;UnPackBCD - digito 2
BCD_2_1   EQU 0x0F   ;resultado en packed BCD - digitos bajos

; Programa principal 
; ***** Reset
	ORG     0x1FF       ; processor reset vector
	goto    start

	ORG     0x000
;
Main
  goto start

;
; --- subrutina B2_BCD
; Inicia la converción Binario a BCD con el algorithmo Desplaza-Suma3     
   ; loop por 15 rotaciones con la corrección "Suma 3"     

B2_BCD
    bcf Carry       ;Prepara carry a zero
    movlw .16       ; número de bits = 16
    movwf counter 
    clrf BCD_x_5    ; limpia registros
    clrf BCD_4_3    ; donde almacenamos
    clrf BCD_2_1    ; la conversión
    clrf BCD_2
    clrf BCD_4
    
    ;
Loop16
    rlf binL      ; desplaza todos los registros
    rlf binH      ; una vez a la izquierda
    rlf BCD_2_1   ; aqui el orden es importante
    rlf BCD_4_3   ; por el ajuste del bit Carry
    rlf BCD_x_5
;
    decfsz counter  ; Hemos terminado la conversion?
    goto adjDEC     ;    No:  asi que continua procesando
    retlw 0         ;    Si: ya terminamos asi que salte de la rutina
;
adjDEC
    movlw BCD_2_1   ; apunta a los digitos de menor peso
    movwf FSR      
    call adjBCD     ; y ajustalos
;
    movlw BCD_4_3   ; ahora los siguientes dos digitos 
    movwf FSR
    call adjBCD     ; y ajustalos
;
    movlw BCD_x_5   ; por último los 2 de mayor peso
    movwf FSR
    call adjBCD     ; y ajustalos
;
    goto Loop16
;
adjBCD
    movlw 3         ; Suma 3 al Low-nibble
    addwf 0,W       ;  w = reg_x_y + 3
    movwf temp      ;  y prueba el Low-nibble
    btfsc temp,3    ;   si es mayor a 7
    movwf 0         ;     Si: necesitamos ajustar el high-nibble 
	            ;        vuelve a leer reg_x_y  y
    movlw 30        ;     No: Suma 3 al High-nibble
    addwf 0,W       ;  w = reg_x_y + 30
    movwf temp      ;  y prueba el High-nibble
    btfsc temp,7    ; si es mayor a 7
    movwf 0         ;    Si: Suma 3 a reg_x_y
    retlw 0         ;    No: terminamos los ajustes asi que Regresa con w=0


start
; Escribimos valor que deseamos convertir 3AF3=15091  
    movlw   0xF3
    movwf   binL
    movlw   0x3A
    movwf   binH
    call    B2_BCD
   
     ; la converción ha terminado     
     movlw    0x0f                ; Ajusta a zero el High-nibble     
     andwf    BCD_x_5, F      ;  ya que no lo usamos
 ; * Ahora ya tenemos los 5 digitos BCD pero agrupados     
 ; *  Si es necesario procedemos a desagrurarlos     
 
 ; Unpack los digitos BCD     
     swapf   BCD_2_1, W        ; extrae digito 2     
     andlw   0x0f     
     movwf   BCD_2     
     swapf   BCD_4_3, W        ; extrae digito 4     
     andlw   0x0f     
     movwf   BCD_4     
     ; limpia los high nibles en BCD_2_1 y BCD_4_3     
     movlw   0x0f     
     andwf   BCD_2_1, F     
     andwf   BCD_4_3, F
 
     
	END
Archivos Adjuntos
Tipo de Archivo: txt Improved ShiftAdd3 para 16-bit.asm.txt (4,4 KB (Kilobytes), 4 visitas)
09/01/2017 #172

Avatar de elelectronico2012

Lenguaje ensamblador para PIC desde 0
Hola a todos los amigos del foro soy nuevo en el foro y vengo a dejar mi primera aportación
es un material para programar y aprenderse las 35 instrucciones del PIC16F84A con ejemplos prácticos y explicados uno a uno ya se que hay mucha información acerca de esto pero nunca esta demás tener algo extra

También les recomiendo el libro ¨ "Microcontrolador PIC16F84 Desarrollo de proyectos"
espero que le sea de ayuda a los que incursionan en este maravilloso mundo de los PIC un saludo al usuario META My respect for you
Archivos Adjuntos
Tipo de Archivo: rar Tutorial_Programación_de_PICs_en_Ensamblador.rar (118,1 KB (Kilobytes), 25 visitas)
Respuesta
¿Tienes una mejor respuesta a este tema? ¿Quieres hacerle una pregunta a nuestra comunidad y sus expertos? Registrate

Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO ©2011, Crawlability, Inc.