Herramientas personales

Ensamblador/PROGRAMACIÓN EN ENSAMBLADOR

De Linexedu

Tabla de contenidos

Introducción

En el presente tema se verán los conceptos básicos de programación. Los ejemplos podrán simularse con gpsim a partir de las soluciones en formato texto dadas o con KTechLab a partir de los ficheros que se indicarán al final de cada apartado.

Estructura general

En general, la estructura de un programa en ensamblador será la siguiente:

  • Descripción: aunque no es necesario, conviene hacer, como comentario, una descripción del programa, añadiendo además otros datos como el nombre del autor, fecha, licencia, etc.
  • Directivas: donde se indicará principalmente el tipo de PIC a utilizar y el sistema de numeración.
  • Etiquetas: mediante el comando EQU se pueden sustituir los valores numéricos de los distintos registros y variables por cadenas de texto con el fin de facilitar la comprensión del programa. De este modo es más fácil identificar, por ejemplo, al puerto A como PORTA que como 0x05. Para este propósito los compiladores suelen disponer de ficheros, como el pic16cxx.inc, que contiene las etiquetas de todos los registros y bits más utilizados e la familia de microprocesadores 16CXX. Mediante el comando INCLUDE se puede añadir al programa este tipo de fichero con lo que el programador se despreocupa de tener que escribir las etiquetas en cuestión. Otros compiladores ya reconocen las etiquetas los registros y bits más utilizados y no es necesario utilizar el comando INCLUDE.
  • Rutina de inicio: aunque no se utilice el vector de interrupción, es costumbre hacer que el programa comience en la posición en la dirección 5, saltando de este modo la 4 que es donde se encuentra el mencionado vector.
  • Programa principal: líneas con el código del programa principal.
  • Subrutinas: líneas de código de los subprogramas.
  • Final: todo programa terminará con el comando end.

Aunque para el funcionamiento del sistema no es necesario, es muy aconsejable añadir comentarios en los programas para facilitar su lectura e interpretación. En ensamblador todo comentario va precedido de un punto y coma (;). A continuación se ofrece un ejemplo en el que puede observarse todos los apartados anteriores. No se preocupe por lo que no entienda, se trata únicamente de que observe su estructura.

;****************************************************** 
;Autor: José Luis Gálvez                                                               
;Fecha: 03-06-2008                                    
;Título: dado electrónico a leds.                 
;Descripción: cada vez que se actúa sobre el pulsador 
; conectado en RA0 se obtiene un valor  del dado.
;Ficheros KTechLab: dado-01.asm y dado-01.circuit
;Licencia GPL                                         
;****************************************************** 

;*********************DIRECTIVAS********************* 

        LIST    P=16C84   ; Modelo de PIC a utilizar 
        RADIX   HEX       ; Empleo del sistema hexadecimal 

;********************ETIQUETAS*********************** 

W	EQU 0x00        ; Registro de destino W : d=0 
F 	EQU 0x01        ; Registro de destino F : d=1 
Z	EQU 0x02        ; Bit 2 del registro ESTADO 
PC	EQU 0x02        ; El registro PC ocupa la dirección 2 de los dos bancos 

ESTADO   EQU 0x03       ; El registro ESTADO ocupa la dirección 3 
                        ; de los dos bancos 
PUERTOA  EQU 0x05       ; El PUERTOA ocupa la dirección 5 del banco 0 y 
                        ; su registro de configuración la 5 del banco 1 
PUERTOB  EQU 0x06       ; El PUERTOB ocupa la dirección 6 del banco 0 y su 
                        ; registro de configuración la dirección 6 del banco 1 
 
;*****************RUTINA DE INICIO******************** 
	ORG 	0 		; El programa comienza en la dirección 0 
	goto	INICIO 	        ; Salto a la dirección 5 para sobrepasar 
				; el vector de interrupción 
	ORG	5 		; Dirección 5 
 
;****************PROGRAMA PRINCIPAL******************* 

INICIO  bsf     ESTADO,5        ; Selección del banco 1 
        movlw   b'00000001'     ; Se configura RA0 como entrada 
        movwf   PUERTOA 	 
        clrf    PUERTOB         ; Se configura el puerto B como salida 
        bcf     ESTADO,5        ; Selección del banco 0 

BUCLE   call RANDOM 
        movwf   PUERTOB         ; W ==> PB y se muestra el resultado por los leds 

        goto BUCLE 

;********************SUBRUTINA*********************** 

;GENERACIÓN DEL NÚMERO ALEATORIO 

RANDOM 
        btfsc   PUERTOA,0	; Si RA0=0 se ha pulsado salta el goto 
        goto    RANDOM 
UNO 
        movlw 0x08		; Valor para mostrar 1 
        btfss   PUERTOA,0	; Si RA0=1, se ha soltado y salta el goto 
        goto    DOS 
        return 
DOS 
        movlw 0x21		; Valor para mostrar 2 
        btfss   PUERTOA,0	; Si RA0=1, se ha soltado y salta el goto 
        goto    TRES 
        return 

TRES 
        movlw 0x29		; Valor para mostrar 3 
        btfss   PUERTOA,0	; Si RA0=1, se ha soltado y salta el goto 
        goto    CUATRO 
        return 

CUATRO 
        movlw 0x63		; Valor para mostrar 4 
        btfss   PUERTOA,0	; Si RA0=1, se ha soltado y salta el goto 
        goto    CINCO 
        return 

CINCO 
        movlw 0x6B		; Valor para mostrar 5 
        btfss   PUERTOA,0	; Si RA0=1, se ha soltado y salta el goto 
        goto    SEIS 
        return 

SEIS 
        movlw 0x77		; Valor para mostrar 6 
        btfss   PUERTOA,0	; Si RA0=1, se ha soltado y salta el goto 
        goto    UNO 
        return 
end 

Ficheros KTechLab: dado-01.asm - dado-01.circuit

Estructuras básicas de programación

Mediante una serie de ejemplos básicos se verán las distintas estructuras de programación (si las desconoce puede estudiarlas en el apartado 4 del siguiente documento). Los ejemplos servirán para iniciarse en la elaboración y ejecución de programas en ensamblador, por lo que, en general, no tendrán una aplicación práctica. Lea atentamente cada enunciado, razone la solución dada, algoritmo y programa ensamblador, y compruebe el funcionamiento con el simulador indicado.

Secuencial

ENUNCIADO
Se desea sumar aritmética y lógicamente los valores 3AH y 77H y guardar los resultados en las posiciones 20H y 21H de la memoria de datos.
ALGORITMO

Imagen:algoritmo-01.png

PROGRAMA EN ENSAMBLADOR
;****************************************************** 
;Autor: José Luis Gálvez                                                               
;Fecha: 07-08-2008                                    
;Título: Suma aritmética y lógica de dos datos.                 
;Descripción: las sumas aritmética y lógica de 3AH y 77H 
;se guardan en las posiciones 20H y 21H de la memoria de 
;datos.
;Fichero gpsim: suma.asm
;Licencia GPL                                         
;****************************************************** 

;*********************DIRECTIVAS***********************

        LIST    P=16C84   ; Modelo de PIC a utilizar 
        RADIX   HEX       ; Empleo del sistema hexadecimal 

;********************ETIQUETAS*************************

SUM_ARIT   EQU 0x20   ; Se asocia SUM_ARIT a la dirección 20H
SUM_LOG    EQU 0x21   ; Se asocia SUM_LOG a la dirección 21H
 
;*****************RUTINA DE INICIO******************** 
	ORG 	0 		; El programa comienza en la dirección 0 
	goto	INICIO 	        ; Salto a la dirección 5 para sobrepasar 
				; el vector de interrupción 
	ORG	5 		; Dirección 5 
 
;****************PROGRAMA PRINCIPAL******************* 

INICIO  movlw  0x3A       ; 3AH ==> W
        addlw  0x77       ; 77H + W ==> W
        movwf  SUM_ARIT   ; W ==> SUM_ARIT
        movlw  0x3A       ; 3AH ==> W
        iorlw  0x77       ; 77H OR W ==> W
        movwf  SUM_LOG    ; W ==> SUM_LOG
 
end 

Fichero gpsim: suma.asm

Alternativa

Cuando se desea comparar en ensamblador dos valores, A y B, se debe tener en cuenta los siguientes puntos:

1. Se restan ambos valores (A-B).

2. Se estudian los estados de los bits Z y C del registro de estado:

Si Z = 1 entonces A es igual a B (A=B).
Si Z = 0 entonces A es distinto de B, en este caso:
Si C = 1 entonces A es mayor que B (A>B).
Si C = 0 entonces A es menor que B (A<B).

De acuerdo con ello, en las siguientes tablas se indican los algoritmos y el código en ensamblador a escribir.

Estudio para comprobar igualdad: A = B
AlgoritmoEnsamblador
Imagen:algoritmo-A.png
Con X=0

movf B,W
subwf A,W
btfsc STATUS,Z
goto A_igual_B
..................;Código para A ≠ B

Con X=1

movf B,W
subwf A,W
btfss STATUS,Z
goto A_distinto_B
..................;Código para A = B
Estudio para comparar: A > B / A < B
AlgoritmoEnsamblador
Imagen:algoritmo-B.png
Con X=0

......
btfsc STATUS,C
goto A_mayor_B
..................;Código para A < B

Con X=1

......
btfss STATUS,C
goto A_menor_B
..................;Código para A > B

Seguidamente se estudiarán las estructuras alternativas simple, doble y múltiple a partir de sendos jemplos.

Simple

ENUNCIADO
Diseñe un programa que ponga a cero la posición de memoria 0DH sólo en el caso de que su contenido sea igual a FFH.
ALGORITMO

Imagen:algoritmo-02.png

PROGRAMA EN ENSAMBLADOR
;****************************************************** 
;Autor: José Luis Gálvez                                                               
;Fecha: 08-08-2008                                    
;Título: Borrado del dato FFH en (0DH)
;Descripción: Si (0AH)=FFH se pondrá a 00H y en caso
;contrario se dejará el dato.
;Fichero gpsim: borradoffh.asm
;Licencia GPL                                         
;****************************************************** 

;*********************DIRECTIVAS********************* 

        LIST    P=16C84   ; Modelo de PIC a utilizar 
        RADIX   HEX       ; Empleo del sistema hexadecimal 

;********************ETIQUETAS*********************** 

W         EQU 0x00      ; Registro de destino W : d=0 
F         EQU 0x01      ; Registro de destino F : d=1 
Z         EQU 0x02      ; Posición del bit Z en el registro de estado
ESTADO    EQU 0x03      ; El registro ESTADO ocupa la dirección 3 
                        ; de los dos bancos 
DATO      EQU 0x0D      ; Se asigna a DATO el valor 0x0D
 
;*****************RUTINA DE INICIO******************** 
	ORG 	0 		; El programa comienza en la dirección 0 
	goto	INICIO 	        ; Salto a la dirección 5 para sobrepasar 
				; el vector de interrupción 
	ORG	5 		; Dirección 5 
 
;****************PROGRAMA PRINCIPAL******************* 

INICIO  movf    DATO,W     ;(0DH) ==> W
        sublw   0xFF       ;FFH - W ==> W
        btfsc   ESTADO,Z   ;Si Z=0 salta la siguiente línea
        clrf    DATO       ;00H ==> (0DH)
        nop
end 

Doble

ENUNCIADO
Si el valor presente en la dirección 10H es menor o igual a BBH deberá ser sustituido por FFH y si es mayor por 11H.
ALGORITMO

Imagen:algoritmo-03.png

PROGRAMA EN ENSAMBLADOR
;***********************************************************
;Autor: José Luis Gálvez                                                               
;Fecha: 08-08-2008                                    
;Título: Asignación según valor
;Descripción: Si (10H)<=BBH se pondrá a FFH y en caso
;contrario se dejará a 11H.
;Fichero gpsim: comparabbh.asm
;Licencia GPL                                         
;*********************************************************** 

;***********************DIRECTIVAS**************************

        LIST    P=16C84   ; Modelo de PIC a utilizar 
        RADIX   HEX       ; Empleo del sistema hexadecimal 

;***********************ETIQUETAS***************************

W         EQU 0x00      ; Registro de destino W : d=0 
F         EQU 0x01      ; Registro de destino F : d=1 
C         EQU 0x00      ; Posición del bit C en el registro de estado
ESTADO    EQU 0x03      ; El registro ESTADO ocupa la dirección 3 
                        ; de los dos bancos 
DATO      EQU 0x10      ; Se asigna a DATO el valor 0x10
 
;********************RUTINA DE INICIO************************
	ORG 	0 		; El programa comienza en la dirección 0 
	goto	INICIO 	        ; Salto a la dirección 5 para sobrepasar 
				; el vector de interrupción 
	ORG	5 		; Dirección 5 
 
;********************PROGRAMA PRINCIPAL**********************

INICIO    movf    DATO,W     ;(10H) ==> W
          sublw   0xBB       ;BBH - W ==> W
          btfss   ESTADO,C   ;Si C=1 (10H)<=BBH y se salta la siguiente línea
          goto    ES_MAYOR   ;Si C=0 (10H)>BBH y se ejecuta este salto
          movlw   0xFF       ;0xFF ==> W
          movwf   DATO       ;W ==> (10H)
          goto    FIN        ;Salto a FIN
ES_MAYOR
          movlw   0x11       ;0x11 ==> W
          movwf   DATO       ;W ==> (10H)  
FIN       nop

end 

Múltiple

ENUNCIADO
Se dispone de dos datos A y B sitos en las posiciones 15H y 16H respectivamente. En función de sus valores se desea guardar en 17H la suma aritmética, la suma lógica o el producto lógico, de acuerdo con el siguiente criterio:
A = B: A + B
A < B: A OR B
A > B: A AND B
ALGORITMO

Imagen:algoritmo-04.png

PROGRAMA EN ENSAMBLADOR
;***********************************************************
;Autor: José Luis Gálvez                                                               
;Fecha: 18-08-2008                                    
;Título: Asignación según valor
;Descripción: Se dispone de dos datos A y B sitos en las 
;posiciones 15H y 16H respectivamente. En función de sus 
;valores se desea guardar en 17H la suma aritmética, la suma 
;lógica o el producto lógico, de acuerdo con el siguiente 
;criterio:
;    A = B: A + B 
;    A < B: A OR B 
;    A > B: A AND B 
;Fichero gpsim: compara2.asm
;Licencia GPL                                         
;*********************************************************** 

;***********************DIRECTIVAS**************************

        LIST    P=16C84   ; Modelo de PIC a utilizar 
        RADIX   HEX       ; Empleo del sistema hexadecimal 

;***********************ETIQUETAS***************************
W          EQU 0x00      ; Registro de destino W : d=0 
C          EQU 0x00      ; Posición del bit C en el registro de estado
Z          EQU 0x02      ; Posición del bit Z en el registro de estado
ESTADO     EQU 0x03      ; El registro ESTADO ocupa la dirección 3 

Dato_A     EQU 0x15      ; Asignaciones
Dato_B     EQU 0x16
Resultado  EQU 0x17
 
;********************RUTINA DE INICIO************************
	ORG 	0 		; El programa comienza en la dirección 0 
	goto	INICIO 	        ; Salto a la dirección 5 para sobrepasar 
				; el vector de interrupción 
	ORG	5 		; Dirección 5 
 
;********************PROGRAMA PRINCIPAL**********************

INICIO    movf    Dato_B,W   ;Dato_B ==> W
          subwf   Dato_A,W   ;Dato_A - W ==> W
          btfsc   ESTADO,Z   ;¿Dato_A = Dato_B? (Salta una línea si Z = 0)
          goto    A_igual_B  ;Sí
          btfsc   ESTADO,C   ;No; ¿Dato_A < Dato_B? (Resultado negativo si C = 0)
          goto    A_mayor_B  ;Sí

A_menor_B movf    Dato_B,W   ;Dato_B ==> W
          iorwf   Dato_A,W   ;Dato_A OR Dato_B ==> W
          movwf   Resultado  ;W ==> Resultado
          goto    FIN

A_igual_B movf    Dato_B,W   ;Dato_B ==> W
          addwf   Dato_A,W   ;Dato_A + Dato_B ==> W
          movwf   Resultado  ;W ==> Resultado
          goto    FIN

A_mayor_B movf    Dato_B,W   ;Dato_B ==> W
          andwf   Dato_A,W   ;Dato_A AND Dato_B ==> W
          movwf   Resultado  ;W ==> Resultado

FIN       nop

end 

Repetitiva

ENUNCIADO
Se desea escribir desde la dirección 20H a la 2FH de la memoria de datos el valor AAH.
SOLUCIÓN 1
Mediante la instrucción btfss f,b
ALGORITMO

Imagen:algoritmo-05.png

PROGRAMA EN ENSAMBLADOR
;***********************************************************
;Autor: José Luis Gálvez                                                               
;Fecha: 19-08-2008                                    
;Título: Asignación según valor
;Descripción: se escribe desde la dirección 20H a la 2FH de la 
;memoria de datos el valor AAH.
;Fichero gpsim: llenaram.asm
;Licencia GPL                                         
;*********************************************************** 

;***********************DIRECTIVAS**************************

        LIST    P=16C84   ; Modelo de PIC a utilizar 
        RADIX   HEX       ; Empleo del sistema hexadecimal 

;***********************ETIQUETAS***************************
W          EQU 0x00      ; Registro de destino W : d=0 
F          EQU 0x01      ; Registro de destino F : d=1  
INDF       EQU 0x00      ; El registro INDF ocupa la dirección 0.
FSR        EQU 0x04      ; El registro FSR ocupa la dirección 4.
 
;********************RUTINA DE INICIO************************
	ORG 	0 		; El programa comienza en la dirección 0 
	goto	INICIO 	        ; Salto a la dirección 5 para sobrepasar 
				; el vector de interrupción 
	ORG	5 		; Dirección 5 
 
;********************PROGRAMA PRINCIPAL**********************

INICIO    movlw   0x20       ;20H ==> W (Valor inicial del índice)
          movwf   FSR        ;W ==> FSR 

          movlw   0xAA       ;AAH ==> W (Valor A GRABAR)
REPETIR   movwf   INDF       ;W ==> INDF 
          incf    FSR,F      ;FSR + 1 ==> FSR 
          btfss   FSR,4      ;Si el bit 4 es 1 entonces FSR = 30H
          goto	  REPETIR    
          nop
end 
SOLUCIÓN 2
Mediante la instrucción decfsz f,d
ALGORITMO

Imagen:algoritmo-06.png

PROGRAMA EN ENSAMBLADOR
;***********************************************************
;Autor: José Luis Gálvez                                                               
;Fecha: 21-08-2008                                    
;Título: Asignación según valor
;Descripción: se escribe desde la dirección 20H a la 2FH de la 
;memoria de datos el valor AAH.
;Fichero gpsim: llenaram2.asm
;Licencia GPL                                         
;*********************************************************** 

;***********************DIRECTIVAS**************************

        LIST    P=16C84   ; Modelo de PIC a utilizar 
        RADIX   HEX       ; Empleo del sistema hexadecimal 

;***********************ETIQUETAS***************************
W          EQU 0x00      ; Registro de destino W : d=0 
F          EQU 0x01      ; Registro de destino F : d=1  
INDF       EQU 0x00      ; El registro INDF ocupa la dirección 0.
FSR        EQU 0x04      ; El registro FSR ocupa la dirección 4.
CONTADOR   EQU 0x0C      ; Registro para almacenar el número de
                         ; posiciones a escribir.
 
;********************RUTINA DE INICIO************************
	ORG 	0 		; El programa comienza en la dirección 0 
	goto	INICIO 	        ; Salto a la dirección 5 para sobrepasar 
				; el vector de interrupción 
	ORG	5 		; Dirección 5 
 
;********************PROGRAMA PRINCIPAL**********************

INICIO    movlw   0x20       ;20H ==> W (Valor inicial del índice)
          movwf   FSR        ;W ==> FSR 
          movlw   0x10       ;20H ==> W (Número de posiciones a escribir)
          movwf   CONTADOR   ;W ==> CONTADOR

          movlw   0xAA       ;AAH ==> W (Valor A GRABAR)
REPETIR   movwf   INDF       ;W ==> INDF 
          incf    FSR,F      ;FSR + 1 ==> FSR 
          decfsz  CONTADOR,F ;CONTADOR - 1 ==> CONTADOR y salta si es 0
	  goto	  REPETIR    
          nop
end 

Los puertos

Como ya sabemos, el microcontrolador se comunica con el mundo exterior a través de los puertos. El siguiente ejemplo mostará como han de configurarse en modo entrada o salida según las necesidades.

ENUNCIADO
Se desea visualizar el valor presente en el cuarteto bajo del puerto A, RA0-RA3, por los LED's conectados al cuarteto bajo del puerto B, RB0-RB3,
ALGORITMO

Imagen:algoritmo-07.png

PROGRAMA EN ENSAMBLADOR
;****************************************************** 
;Autor: José Luis Gálvez                                                               
;Fecha: 24-08-2008                                    
;Título: Los puertos.
;Descripción: visualiza el valor presente en el cuarteto bajo del 
;puerto A, RA0-RA3, por los LED's conectados al cuarteto bajo del 
;puerto B, RB0-RB3
;Ficheros KTechLab: pa-to-pb.asm y pa-to-pb.circuit
;Licencia GPL                                         
;****************************************************** 

;*********************DIRECTIVAS********************* 

        LIST    P=16C84   ; Modelo de PIC a utilizar 
        RADIX   HEX       ; Empleo del sistema hexadecimal 

;********************ETIQUETAS*********************** 

W	EQU 0x00        ; Registro de destino W : d=0 

ESTADO   EQU 0x03       ; El registro ESTADO ocupa la dirección 3 
                        ; de los dos bancos 
PUERTOA  EQU 0x05       ; El PUERTOA ocupa la dirección 5 del banco 0 y 
                        ; su registro de configuración, TRISA, la 5 del banco 1 
PUERTOB  EQU 0x06       ; El PUERTOB ocupa la dirección 6 del banco 0 y su 
                        ; registro de configuración, TRISB, la dirección 6 del banco 1 
 
;*****************RUTINA DE INICIO******************** 
	ORG 	0 		; El programa comienza en la dirección 0 
	goto	INICIO 	        ; Salto a la dirección 5 para sobrepasar 
				; el vector de interrupción 
	ORG	5 		; Dirección 5 
 
;***********CONFIGURACIÓN DE LOS PUERTOS***************
INICIO  bsf     ESTADO,5        ; Selección del banco 1: 1 ==> IRP0
        movlw   b'00001111'     ; Se configura RA0-RA3 como entrada 
        movwf   PUERTOA 	 
        clrf    PUERTOB         ; Se configura el puerto B como salida 
        bcf     ESTADO,5        ; Selección del banco 0: 0 ==> IRP0

;****************PROGRAMA PRINCIPAL******************* 
BUCLE   movf   PUERTOA,W        ; PA ==> W
        movwf  PUERTOB          ; W ==> PB y se muestra el resultado por los leds 

        goto BUCLE 

end
Ficheros KTechLab: pa-to-pb.asm - pa-to-pb.circuit

Tablas

El siguiente ejemplo le mostrará la utilidad de una tabla en ciertos programas.

ENUNCIADO
Se desea que un visualizador de siete segmentos conectado al puerto B según se muestra en el circuito siguiente, indique el valor BCD natural presente en el cuarteto bajo del puerto A.
CIRCUITO

Imagen:BCD-7segmentos.png

ALGORITMO

Imagen:algoritmo-08.png

PROGRAMA EN ENSAMBLADOR
;******************************************************
;Autor: José Luis Gálvez                              *
;Fecha: 25-08-2008                                    *
;Título: Convertidor BCD a 7 segmentos.               *
;Descripción: muestra el valor BCD en RA0-RA3 por el  *
; visualizador de 7 segmentos.                        *
;Ficheros KTechLab: dado-02.asm y dado-02.circuit     *
;Licencia GPL                                         *
;******************************************************

;*********************DIRECTIVAS*********************

        LIST    P=16C84         ; Modelo de PIC a utilizar
        RADIX   HEX		; Empleo del sistema hexadecimal

;********************ETIQUETAS***********************

W	EQU 0x00	; Registro de destino W : d=0
F 	EQU 0x01	; Registro de destino F : d=1
Z	EQU 0x02	; Bit 2 del registro ESTADO
PC	EQU 0x02	; El registro PC ocupa la dirección 2 de los dos bancos
ESTADO  EQU 0x03	; El registro ESTADO ocupa la dirección 3 de los dos
			; bancos
PUERTOA EQU 0x05 	; El PUERTOA ocupa la dirección 5 del banco 0 y
			;su registro de configuración la 5 del banco 1
PUERTOB EQU 0x06 	; El PUERTOB ocupa la dirección 6 del banco 0 y su
			; registro de configuración la dirección 6 del banco 1
 
;*****************RUTINA DE INICIO********************
	ORG 	0 		; El programa comienza en la dirección 0 
	goto	INICIO 		; Salto a la dirección 5 para sobrepasar 
				; el vector de interrupción
	ORG	5 		; Dirección 5 

;***********CONFIGURACIÓN DE LOS PUERTOS***************

INICIO  bsf     ESTADO,5 	; Selección del banco 1
        movlw   0xFF            ; Se configura puerto A como entrada
        movwf   PUERTOA 	
        clrf    PUERTOB 	; Se configura puerto B como salida
        bcf     ESTADO,5 	; Selección del banco 0

;****************PROGRAMA PRINCIPAL*******************

BUCLE   movf    PUERTOA,W       ; PUERTOA ==> W
        call    TABLA
        movwf   PUERTOB         ; W ==> PB y se muestra el resultado por los leds

        goto    BUCLE

;********************SUBRUTINA***********************

TABLA   addwf	PC,F       ; W+PC==>PC con esto el PC apunta a la direccin de la
                           ; tabla que se corresponde con el valor a
                           ; visualizar en el dado.
        retlw	0x3F	   ; Valor 0
        retlw	0x06       ; Valor 1.
        retlw	0x5B       ; Valor 2
        retlw	0x4F       ; Valor 3
        retlw	0x66       ; Valor 4
        retlw	0x6D       ; Valor 5
        retlw	0x7C       ; Valor 6
        retlw	0x07       ; Valor 7
        retlw	0x7F       ; Valor 8
        retlw	0x67       ; Valor 9
        retlw	0x79       ; Valor A
        retlw	0x79       ; Valor B
        retlw	0x79       ; Valor C
        retlw	0x79       ; Valor D
        retlw	0x79       ; Valor E
        retlw	0x79       ; Valor F
end

Ficheros KTechLab: BCD-7segmentos.asm - BCD-7segmentos.circuit

Si ha seguido y entendido cada uno de los puntos anteriores, debería estar en condiciones de comprender el programa ejemplo que se puso en el apartado de estructura general. Lea el código detenidamente e intente razonarlo, compruebe con KTechLab o gpsim su funcionamiento, e intente obtener su diagrama de flujo. A continuación vea la solución y compruebe si su diagrama y razonamiento coinciden con los suyos.

A continuación se ofrece el mismo programa pero utilizando una tabla, simplificándose de este modo el código.

ALGORITMO

Imagen:algoritmo-10.png

PROGRAMA EN ENSAMBLADOR
;******************************************************
;Autor: José Luis Gálvez                              *
;Fecha: 24-08-2008                                    *
;Título: dado electrónico a leds.                     *
;Descripción: cada vez que se actúa sobre el pulsador *
; conectado en RA0 se obtiene un valor  del dado.     *
;Ficheros KTechLab: dado-02.asm y dado-02.circuit     *
;Licencia GPL                                         *
;******************************************************

;*********************DIRECTIVAS*********************

        LIST    P=16C84         ; Modelo de PIC a utilizar
        RADIX   HEX		; Empleo del sistema hexadecimal

;********************ETIQUETAS***********************

W	EQU 0x00	; Registro de destino W : d=0
F 	EQU 0x01	; Registro de destino F : d=1
Z	EQU 0x02	; Bit 2 del registro ESTADO
PC	EQU 0x02	; El registro PC ocupa la dirección 2 de los dos bancos
ESTADO  EQU 0x03	; El registro ESTADO ocupa la dirección 3 de los dos
			; bancos
PUERTOA EQU 0x05 	; El PUERTOA ocupa la dirección 5 del banco 0 y
			;su registro de configuración la 5 del banco 1
PUERTOB EQU 0x06 	; El PUERTOB ocupa la dirección 6 del banco 0 y su
			; registro de configuración la dirección 6 del banco 1
ALEATOR  EQU 0x0C	; Registro auxiliar para guardar los números aleatorios
 
;*****************RUTINA DE INICIO********************
	ORG 	0 		; El programa comienza en la dirección 0 
	goto	INICIO 		; Salto a la dirección 5 para sobrepasar 
				; el vector de interrupción
	ORG	5 		; Dirección 5

;***********CONFIGURACIÓN DE LOS PUERTOS***************


INICIO  bsf     ESTADO,5 	; Selección del banco 1
        movlw   b'00000001' 	; Se configura RA0 como entrada
        movwf   PUERTOA 	
        clrf    PUERTOB 	; Se configura puerto B como salida
        bcf     ESTADO,5 	; Selección del banco 0

;****************PROGRAMA PRINCIPAL*******************

        clrf    ALEATOR         ; Valor inicial: ALEATOR=0

BUCLE   call    RANDOM
        movwf   PUERTOB         ; W ==> PB y se muestra el resultado por los leds

        goto    BUCLE

;********************SUBRUTINAS***********************

;GENERACIÓN DEL NÚMERO ALEATORIO ENTRE 1 Y 6

RANDOM
        incf    ALEATOR,F  ; ALEATOR + 1 ==> ALEATOR
        movlw   0x07       ; 07H ==> W
        subwf   ALEATOR,W  ; ALEATOR -  W ==> W
        btfsc   ESTADO,Z   ; Si Z=0 salta la siguiente línea
        call    INICIALIZA ; Salto a subrrutina
        btfsc   PUERTOA,0  ; Si RA0=0 se ha pulsado y salta el goto
        goto    RANDOM

;RUTINA DE VISUALIZACIÓN
        movf   ALEATOR,W   ; ALEATOR ==> W
        addwf	PC,F       ; W+PC==>PC con esto el PC apunta a la direccin de la
                           ; tabla que se corresponde con el valor a
                           ; visualizar en el dado.
        retlw	0x00	   ; Este primer desplazamiento nunca se va a dar, ya 

                           ; que ALEATOR sólo contendrá de 1 a 6
        retlw	0x08       ; Valor 1.
        retlw	0x21       ; Valor 2
        retlw	0x29       ; Valor 3
        retlw	0x63       ; Valor 4
        retlw	0x6B       ; Valor 5
        retlw	0x77       ; Valor 6

INICIALIZA                 ;inicializa ALEATOR A 1.

        movlw   0x01       ; 01H ==> W
        movwf   ALEATOR    ; W ==> ALEATOR
        return
end

Temporizaciones y retardos

Temporizaciones

Para realizar temporizaciones se emplea el registro TMR0, en el cual habrá que cargar el valor adecuado. Las temporizaciones suelen realizarse mediante bucles de retardo o mediante el registro de interrupciones. Par facilitar las temporizaciones y evitar los cálculos, existen ficheros que contienen ya programados una serie de retardos (1 ms, 10 ms, etc.) que pueden ser utilizados por el programa principal. En este punto se explicará no obstante como realizar los cálculos para una temporización dada.

La fórmula para calcular el tiempo de la temporización es la siguiente:

T = 4·TOSC·(255-VTMR0)·Rd

donde:

  • TOSC: período del ciclo de reloj de trabajo del PIC.
  • VTMR0: valor a cargar en el registro TMR0.
  • Rd: Rango seleccionado en el divisor (bits PS2-PS1-PS0 del registro OPTION).

Según esta fórmula, la máxima temporización para una frecuencia de trabajo típica de 4 MHz se conseguirá con VTMR0 = 0 y Rd = 256:

T = 4·250 ns·255·256 = 65,28 ms

Para obtener temporizaciones más altas se realizan bucles de repetición.

A la hora de programar una temporización se deberán determinar los valores a cargar en TMR0, VTMR0, y el del rango de programación del divisor, Rd. Veamos como hallar dichos valores mediante un ejemplo. Supongamos que para un sistema de 4 MHz se desea una temporización de 1,2 segundos. Como es muy superior a la temporización máxima antes calculada, deberemos seleccionar un valor más pequeño, a ser posible múltiplo de 1,2, y repetir la veces que sea necesario.

Comencemos despejando VTMR0:

VTMR0 = 255 - T/(4·TOSC·Rd) = 255 - T·106/Rd

Los valores de T y Rd que pertenecen al minuendo son las incógnitas a determinar. El minuendo ideal, además de ser inferior a 255, debería darnos un valor entero junto con un valor de T que fuera un múltiplo de 1,2 y sabiendo que Rd ha de ser un valor del tipo 2n con n entero en el intervalo [1,8]. Esto no siempre es posible, y habrá que conformarse con un valor aproximado. La ecuación se resuelve por tanteo. En nuestro caso una posible solución es 1,2 ms para T y 16 para Rd:

VTMR0 = 255 - 1,2·10-3·106/16 = 255 - 75 = 180

Esta temporización calculada deberá repetirse 1.000 veces para obtener los 1,2 segundos deseados. El siguiente ejemplo aclarára la programación.

ENUNCIADO
Se desea que un LED conectado a RA0 funcione en modo intermitente con tiempos de encendido y apagado idénticos de 1,2 segundos.
ALGORITMO

Imagen:algoritmo-11.png

PROGRAMA EN ENSAMBLADOR
;****************************************************** 
;Autor: José Luis Gálvez                                                               
;Fecha: 02-09-2008                                    
;Título: Intermitente
;Descripción: el LED conectado en RA0 funciona en modo 
;intermitente con tiempos de encendido y apagado idénticos
; de 1,2 segundos. 
;Ficheros KTechLab: intermitente.asm e intentermitente.circuit
;Licencia GPL                                         
;****************************************************** 

;*********************DIRECTIVAS********************* 

        LIST    P=16C84   ; Modelo de PIC a utilizar 
        RADIX   HEX       ; Empleo del sistema hexadecimal 

;********************ETIQUETAS*********************** 

W	    EQU 0x00       ; Registro de destino W : d=0 
F	    EQU 0x01       ; Registro de destino F : d=1 

TMR0        EQU 0x01       ; El registro TMR0 ocupa la dirección 1 del banco 0

OPTION_REG  EQU 0x01       ; El registro OPTION ocupa la dirección 1 del banco 1

ESTADO      EQU 0x03       ; El registro ESTADO ocupa la dirección 3 
                           ; de los dos bancos 
PUERTOA     EQU 0x05       ; El PUERTOA ocupa la dirección 5 del banco 0 y 
                           ; su registro de configuración, TRISA, la 5 del banco 1  
INTCON      EQU 0x0B       ; El registro INTCON ocupa la dirección 11 
TOIF        EQU 0x02       ; TOIF es el bit 2 del registro INTCON 

CONTADOR1   EQU 0x0C       ; Variable para el contador 1. 
CONTADOR2   EQU 0x0D       ; Variable para el contador 2.

;*****************RUTINA DE INICIO******************** 
	ORG 	0       ; El programa comienza en la dirección 0 
	goto	INICIO  ; Salto a la dirección 5 para sobrepasar 
                        ; el vector de interrupción 
	ORG	5       ; Dirección 5 
 
;***********CONFIGURACIÓN DE LOS PUERTOS***************
INICIO  bsf     ESTADO,5        ; Selección del banco 1: 1 ==> IRP0
        movlw   b'11111110'     ; Se configura RA0 como salida
        movwf   PUERTOA
        movlw   b'11000011'     ; Se configura el rango del divisor a 16 (Rd=16) y se
                                ; selecciona la procedencia de los impulsos de reloj
        movwf   OPTION_REG
        bcf     ESTADO,5        ; Selección del banco 0: O ==> IRP0

;****************PROGRAMA PRINCIPAL******************* 

BUCLE   movlw   0x01            ; 01H ==> W
        movwf   PUERTOA         ; 1 ==> RA0
        call    RETARDO         ; Salto a subrutina
        movlw   0x00            ; 00H ==> W
        movwf   PUERTOA         ; 0 ==> RA0
        call    RETARDO         ; Salto a subrutina
        goto BUCLE 

;****************SUBRUTINA DE RETARDO******************* 
RETARDO movlw   d'10'            ; 10 ==> W
        movwf   CONTADOR1        ; Valor inicial de CONTADOR1
Bucle0  call    RET_120ms        ;Salto a subrutina de 120 ms
        decfsz  CONTADOR1,F      ;CONTADOR1-1 → CONTADOR1 y salta si es 0
        goto    Bucle0
        return 

RET_120ms
        movlw   d'100'           ; 100 ==> W
        movwf   CONTADOR2        ; Valor inicial de CONTADOR1
Bucle1  clrf    INTCON           ; Se impiden las interrupciones (GIE=0)
        movlw   d'180'           ; 180 ==> W
        movwf   TMR0             ; Valor para 1,2 ms con Rd=16

Bucle2  btfss   INTCON,TOIF     ; ¿TOIF=1? (¿TMR0=0?)
        goto    Bucle2           ; No: esperar.
        decfsz  CONTADOR2,F      ;CONTADOR2-1 → CONTADOR2 y salta si es 0
        goto    Bucle1
        return
end
Ficheros KTechLab: intermitente12.asm - intermitente12.circuit

Retardos

Cuando no sea necesaria mucha precisión se pueden utilizar los retardos.Para ello debemos saber que en los PIC todas las instrucciones tardan en ejecutarse un ciclo máquina, excepto los saltos que tardan dos. El tiempo de un ciclo máquina es igual a cuatro veces el período de oscilación. Por ejemplo, para una frecuencia de 4 MHz, cada ciclo máquina tarda un microsegundo. De acuerdo con ello se pueden realizar una rutina de retardo a partir de un bucle o de bucles anidados. Observe la siguiente rutina.

RETARDO
  movlw k            ;1
  movwf CONTADOR     ;1
BUCLE
  decfsz CONTADOR,F  ;(k-1)+2
  goto BUCLE         ;2(k-1)
return

A la derecha de cada instrucción se indica el número de ciclos máquina. La instrucción decfsz tarda (k-1)+2, porque se decrementará k-1 veces la constante k y en el último decremento hará un salto, que como sabemos son dos ciclos. La instrucción goto se ejecuta en 2 ciclos y se ejecutará k-1 veces, por lo que su valor es 2(k-1). Sumando todos los ciclos nos da 3k+1. Si se desea un retardo de por ejemplo 25 µs, y suponiendo que cada ciclo máquina es de 1 µs, el valor de la constante k deberá ser 8.

Mediante bucles anidados como el siguiente, pueden aumentarse los tiempos de retardo.

RETARDO
  movlw k              ;1
  movwf CONTADOR_1     ;1
BUCLE_1
  movlw m              ;1
  movwf CONTADOR_2     ;1
BUCLE_2
  decfsz CONTADOR_2,F  ;(m-1)+2
  goto BUCLE_2         ;2(m-1)
  decfsz CONTADOR_1,F  ;(k-1)+2
  goto BUCLE_1         ;2(k-1)
return

En este caso el BUCLE_2 está anidado en BUCLE_1, por lo que se repetirá k veces. A continuación se indica el cálculo total de ciclos:

1+1+(1+1)(k-1)+ k[(m-1)+2+2(m-1)]+(k-1)+2+2(k-1) = k(3m+2)-1

El valor máximo se alcanza con k=m=255, lo que nos daría, par un ciclo máquina de 1 µs, un total de 195.584 µs, aproximadamente 0,2 s. Obviamente para retardos mayores se pueden seguir anidando bucles.

Contajes

Cuando se desea contar impulsos externos se utiliza como entrada de los mismos el terminal RA4/TOCK1 y se configura adecuadamente el registro OPTION, esto es, se pone a uno el bit TOCS y PS2, PS1 y PS0 con los valores según la división deseada.

ENUNCIADO
Se desea mostrar por el puerto B la mitad de los impulsos dados por en RA4/TOCK1.
PROGRAMA EN ENSAMBLADOR
;****************************************************** 
;Autor: José Luis Gálvez                                                               
;Fecha: 30-09-2008                                    
;Título: Contador de impulsos externos
;Descripción: por el puerto B se muestra el valor de TMR0
;que es incrementado por cada dos impulsos en RA4/TOCK1
;Ficheros KTechLab: impulsos.asm e impulsos.circuit
;Licencia GPL                                         
;****************************************************** 

;*********************DIRECTIVAS********************* 

        LIST    P=16C84   ; Modelo de PIC a utilizar 
        RADIX   HEX       ; Empleo del sistema hexadecimal 

;********************ETIQUETAS*********************** 

W	    EQU 0x00       ; Registro de destino W : d=0 

TMR0        EQU 0x01       ; El registro TMR0 ocupa la dirección 1 del banco 0

OPTION_REG  EQU 0x01       ; El registro OPTION ocupa la dirección 1 del banco 1

ESTADO      EQU 0x03       ; El registro ESTADO ocupa la dirección 3 
                           ; de los dos bancos 
PUERTOA     EQU 0x05       ; El PUERTOA ocupa la dirección 5 del banco 0 y 
                           ; su registro de configuración, TRISA, la 5 del banco 1  
PUERTOB     EQU 0x06       ; El PUERTOb ocupa la dirección 6 del banco 0 y 
                           ; su registro de configuración, TRISB, la 6 del banco 1  

;*****************RUTINA DE INICIO******************** 
	ORG 	0       ; El programa comienza en la dirección 0 
	goto	INICIO  ; Salto a la dirección 5 para sobrepasar 
                        ; el vector de interrupción 
	ORG	5       ; Dirección 5 
 
;***********CONFIGURACIÓN DE LOS PUERTOS***************
INICIO  bsf     ESTADO,5        ; Selección del banco 1: 1 ==> IRP0
        movlw   b'11111111'     ; Se configura el puerto A como entrada
        movwf   PUERTOA
        movlw   b'00000000'     ; Se configura el puerto B como salida
        movwf   PUERTOb

        movlw   b'11100000'     ; Se selecciona la procedencia externa de 
                                ; los impulsos con una división de 1:2
        movwf   OPTION_REG
        bcf     ESTADO,5        ; Selección del banco 0: O ==> IRP0

;****************PROGRAMA PRINCIPAL******************* 

BUCLE   movf   TMR0,W           ; TMR0 ==> W
        movwf  PUERTOB          ; W ==> PB y se muestra el resultado por los leds 

        goto BUCLE 

end
Ficheros KTechLab: impulsos.asm - impulsos.circuit



ÍNDICE