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
- 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
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.
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
- 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
- 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:
|
- ALGORITMO
- 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
- 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
- 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
- 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
- ALGORITMO
- 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
- 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
- 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













