You are on page 1of 63

PRÁCTICA Nº1

Microcontrolador PIC16F84

Objetivo: Encender y apagar cada segundo los leds conectados al puerto B.


Esquema eléctrico:

Programa:
;------------------------------------------------------
;PROGRAMA PORTB.ASM
;Apagar y encender el puerto B cada segundo
;-------------------------------------------------------

list p = 16f84A ; identificar el micro usado.


Include "p16F84A.inc" ; archivo con los registros definidos.
org 00h ;posición de memoria de comienzo del reset ( 0000h )
goto inicio ;salto a posición de memoria donde comienza el programa.
org 10h ; posición de memoria donde comienza el programa ( 0010h ).
inicio ; etiqueta = dirección 0010h.

;-------------------------------------------
; Configurar el puerto B como salida
;--------------------------------------------
; Registro TRISB=00h para salidas.
bsf STATUS,5 ; pongo a uno el bit 5 del registro STATUS para entrar en el banco1.
movlw 00h ; cargo w con el dato 00h.
movwf TRISB ; cargo el registro TRISB con el w para hacer el puerto B como salida.
Bcf STATUS,5 ; pongo a cero el bit 5 del registro STATUS para entrar en el banco 0.

;----------------------------------
;PROGRAMA PRINCIPAL
;-----------------------------------
programa ; etiqueta de programa principal.
movlw 00h ; cargo w con el dato 00h
movwf PORTB ; cargo el registro PORTB con w apagando los leds.
call sg1 ; subrutina de retardo de 1 seg.
movlw 0ffh ; cargo w con el dato ffh.
movwf PORTB ; cargo el registro PORTB con w encendiendo los leds.
call sg1 ; subrutina del retardo de 1 seg.
goto programa ; salta al comienzo del programa.

;------------------------------------------------
;RETARDOS
;------------------------------------------------
;ffh=255 goto=2 useg. decfsz=1 useg.
;(255 x 2) + 255= 765 useg
;(765 x 765) + 255= 585480 useg.
;(585480 x 2) + 1= 1170961 useg.
sg1 ; etiqueta = subrutina del retardo de 1 seg.
movlw 0ffh ; cargo w con el dato ffh.
movwf 0ch ; cargo el registro 0ch con el w.
movwf 0dh ; cargo el registro 0dh con el w.
movlw 01h ; cargo w con el dato 01h.
movwf 0eh ; cargo el registro 0eh con w.

salto1 ; etiqueta del bucle de repetición.


decfsz 0ch,1; decremento el registro 0ch y salto si es cero depositando el resultado en 0ch
goto salto1 ; salto a la etiqueta salto1.
decfsz 0dh,1 ; decremento el registro 0dh y salto si es cero depositando el resultado en 0dh.
goto salto1 ; salto a salto1.
decfsz 0eh,1 ; decremento el registro 0eh y salto si es cero depositando el resultado en 0eh.
goto salto1 ; salto a salto1.
return ; regreso de subrutina.

end ; fin del programa


PRÁCTICA Nº 2
Microcontrolador PIC16F84A.

Objetivo: Hacer juegos de encendidos y apagados de leds conectados al puerto B. A la vez practicaremos con
las instrucciones: swapf f,d Rlf f,d Rrf f,d

La instrucción swapf f,d intercambia los 4 bits de mayor peso por los cuatros de menor peso y viceversa del
dato contenido en el registro usado. Ejemplo: swapf 0ch,1

Si tuviéramos en el registro 0ch el dato 0fh, al aplicar la instrucción el contenido se transformaría en f0h y lo
guardaríamos en 0ch por ser d= 1. Si fuese d= 0 lo guardaríamos en el acumulador w.

La instrucción rlf f,d desplaza el contenido del registro usado hacia la izquierda, introduciendo por el lugar del
bit de menor peso el valor del acarreo. El acarreo es a su vez cargado con el contenido del bit de más peso del
dato contenido en el registro usado. El contenido es almacenado en el registro si d= 1 y si no será guardado en
el acumulador w por ser d= 0. Ejemplo: rlf 0ch,1

Si el valor contenido en el registro 0ch es 01h y el acarreo es cero, al desplazarse hacia la izquierda el contenido
será 02h. El valor 02h se guardará en 0ch por ser d= 1.

La instrucción rrf f, d desplaza el contenido del registro usado hacia la derecha introduciendo el valor del
acarreo por el bit de más peso y cargándose el acarreo con el valor del bit de menor peso del registro. El valor
del dato se guardará en el registro si d= 1 o en el acumulador w, si d= 0.

Ejemplo: rrf 0ch,1


Si el contenido del registro 0ch fuese 00h y el acarreo valiese 1, el contenido del registro sería 80h, y se
guardaría en 0ch.

EL PROGRAMA SALTA A LA PRIMERA COMBINACION Y SE REPITEN TODAS


Esquema eléctrico:
Programa:
;--------------------------------------------------------
;PROGRAMA LED.ASM
;Apagar y encender el puerto B cada segundo
;--------------------------------------------------------
list p=16f84A
include "p16F84A.inc"
org 00h
reset
goto inicio
org 10h
inicio
;-------------------------------------------
;Configurar el puerto B como salida
;--------------------------------------------
;Registro TRISB=00h para salidas.
bsf STATUS,5 ;pongo a 1 el bit 5 del registro STATUS para entrar en el banco1.
movlw 00h ; cargo w con el dato 00h.
movwf TRISB ; cargo el registro TRISB con el w para hacer el puertoB como salida.
bcf STATUS,5 ; pongo a cero el bit 5 del registro STATUS para entrar en el banco 0.

;-----------------------------------
;PROGRAMA PRINCIPAL
;-----------------------------------
programa
movlw 00h ; cargo w con el dato 00h.
movwf PORTB ; cargo el registro PORTB con el w.
call sg1 ; subrutina de retardo de 1 seg.
call sg1
movlw 0fh ; cargo w con el dato 0fh.
movwf PORTB ; cargo el registro PORTB con el w.
call sg1
call sg1
swapf PORTB,1 ; aplico la instrucción al contenido del registro PORTB y lo
; deposito en el mismo ya que d= 1
call sg1
call sg1
movlw 0ffh ; cargo el w con el dato ffh.
movwf PORTB ; cargo PORTB con el w.
call sg1
call sg1
call rotacion ; subrutina de rotar un solo led de derecha a izquierda y
; viceversa ,una sola vez.
goto programa ; salto al comienzo del programa principal.
;-------------------------------------------------------------
;PROGRAMA DE ROTACION.
;-------------------------------------------------------------
rotacion
movlw 00h ; cargo w con el dato 00h.
movwf 10h ; cargo registro 10h con el w.
movlw 09h ; cargo w con el dato 09h.
movwf 11h ; cargo el registro 11h con w.
bsf STATUS,0 ; pongo a uno el bit 0 del STATUS ( bit 0 = C = acarreo )
der
decfsz 11h,1 ; decremento el registro 11h y salto si es cero y deposito el
; contenido en 11h ya que d=1
goto derecha ; salto a la etiqueta ( dirección ) llamada derecha.
movlw 08h ; cargo w con el dato 08h.
movwf 11h ; cargo el registro 11h con w.
bcf STATUS,0 ; pongo a cero el bit 0 de STATUS ( bit 0 = C = acarreo ).

izq
decfsz 11h,1 ; decremento el registro 11h y salto si vale cero depositando el
; contenido en el mismo ya d= 1.
goto izquierda ; salto a la etiqueta ( dirección ) llamada izquierda.
return; regreso de subrutina.
derecha
rrf 10h,0 ; roto a la derecha el contenido del registro 10h y lo almaceno en
; w ya que d=0
movwf 10h ; cargo el registro 10h con el w.
movwf PORTB ; cargo el registro PORTB con el w.
call sg1
goto der ; salto a etiqueta der.
izquierda
rlf 10h,0 ; roto a la izq. el contenido del registro 10h y lo almaceno en w
; ya que d=0
movwf 10h ; cargo 10h con el w.
movwf PORTB ; cargo PORTB con w.
call sg1
goto izq ; salto a etiqueta izq.
; RETARDOS
sg1
movlw 0ffh
movwf 0ch
movwf 0dh
movlw 01h
movwf 0eh
salto1
decfsz 0ch,1
goto salto1
decfsz 0dh,1
goto salto1
decfsz 0eh,1
goto salto1
return
end
PRACTICA Nº 3
Microcontrolador PIC16F84A.

Objetivo: Comprobar como funciona la interrupción externa, RB0/INT. Al actuar sobre el pin RB0/INT mediante
un pulsador provocaremos que el puerto A, al cual, hemos conectados unos leds, se apaguen y enciendan en un
bucle repetitivo.

¿Cómo se configuran los registros que intervienen en una interrupción externa?


1º paso: Como las interrupciones de este microcontrolador están vectorizadas en una sola posición de
memoria, hay que poner la dirección de la interrupción (04h), que es donde va a ir a buscar la instrucción de
salto (goto), que conducirá al microcontrolador al programa de tratamiento de la interrupción.

2º paso: Se configura el registro OPTION_REG y en concreto se eligirá el tipo de flanco: ascendente o


descendente. El bit 6 de este registro, llamado INTEDG, se cargará con 1 para elegir flanco ascendente y 0 para
flanco descendente. Yo he elegido flanco descendente.

3ºpaso: Se configura el registro relacionado con el software de la interrupción /INT.

El registro y los bits son:


INTCON: bit 7 (GIE)= Activación global de interrupciones = 1= permiso concedido.
bit 4 (INTE)= Activación de la interrupción externa = 1= activada.

¿Cómo sabremos si se ha producido una interrupción externa, /Int?


Toda interrupción, si está activada, al producirse provocará la activación de las llamadas banderas o bits, que al
ser examinados nos descubrirán si sea producido una interrupción. La bandera o bit de la interrupción /Int, está
en el registro INTCON, y es el bit 1, llamado INTF. Un 1 en él nos indica que se ha producido una interrupción.
Esta bandera hay que bajarla, o sea, ponerla a cero por software para saber si se ha producido una petición de
interrupción posterior.

Esquema eléctrico:
Programa:
;---------------------------------------------------------
;PROGRAMA inter.ASM
;Cómo funciona la interrupción externa /Int.
;---------------------------------------------------------
list p=16f84A
include "p16F84A.inc"
;---------------------------------------------------
;RESET
;---------------------------------------------------
org 0h
reset
goto inicio
;------------------------------
;INTERRUPCION
;------------------------------
org 04h
goto int
;--------------------------------
;PUNTERO DE INICIO
;--------------------------------
org 10h
inicio
;-----------------------------------------------------------
;Configurar el puerto A como salida.
;-----------------------------------------------------------
;Registro TRISB=00h para salidas.
bsf STATUS,RP0 ; banco1
movlw 00h
movwf TRISA ; puertoA como salida
bcf STATUS,RP0 ; banco0
;-----------------------
;PuertoA apagado.
;-----------------------
movlw 00h
movwf PORTA
;------------------------------------------------
;Configurar el registro OPTION_REG. Flanco de bajada.
;------------------------------------------------
;Registro OPTION_REG bit6=INTEDG= 0= flanco descendente
bsf STATUS,RP0 ; banco1
bcf OPTION_REG,INTEDG ; flanco descendente
bcf STATUS,RP0 ; banco0
;--------------------------------------------------------------------------------
;Configurar el registro INTCON. Habilitar permisos de interrupciones general y particular de
; /Int. Habilitar permiso de interrupción global.
bsf INTCON,GIE ; 1= activación permiso general.
;Habilitar permiso int.
bsf INTCON,INTE ; 1= activación permiso /int.
;---------------------------------------------------------------------
;Esperando la interrupción.
; Cuando pulse el botón provoco un flanco de bajada y salgo del bucle de espera. La bandera
; pasa a 1 y salto al programa de la interrupción y luego al programa principal, haciendo
;infinitos bucles. La /Int la uso como autorización (pulsar el botón) para ejecutar el
;programa principal.
;---------------------------------------------------------------------
espera
btfss INTCON,INTF ; salta si es uno
goto espera ; salto a "espera" hasta que la bandera sea 1.Cuando pulse el botón

; provoco la interrupción y salto a ejecutar la subrutina de interrupción "int". Luego


; ejecuto el programa principal.
;--------------------------------------------------
;PROGRAMA PRINCIPAL
;--------------------------------------------------
programa
movlw 00h ; apago puerto A.
movwf PORTA
call sg1
movlw 0ffh ; enciendo puerto A.
movwf PORTA
call sg1
goto programa
;------------------------------------------------------------------------------------------
;INTERRUPCION DE /Int.
;------------------------------------------------------------------------------------------
;Deshabilitar permiso de int. global y particular de /Int.
;Con deshabilitar una de los dos bastaría para no haber más interrupciones.

int
bcf INTCON,GIE ; 0 para no más interrupciones de ningún tipo.
bcf INTCON,INTE ; 0 para no más interrupción /Int.

; Poner a cero el flag de la /Int., necesario si hubiera más interrupciones de /Int. Este
; programa solo va haber una "unica" llamada a la /Int. y se ejecutará el programa principal
;indefinidamente deshabilitando para siempre la /Int.

bcf INTCON,INTF ; 0 por software.


retfie ; retorno de subrutina de interrupción.

;-------------------------------------------------------------------------
;Retardos.
;--------------------------------------------------------------------------
;0ch, 0dh y 0eh registros RAM del GPR
;----------------------------------------
sg1 ; 1005723 useg.
movlw 0c1h
movwf 0ch
movwf 0dh
movlw 01h
movwf 0eh
salto1
decfsz 0ch,1
goto salto1
decfsz 0dh,1
goto salto1
decfsz 0eh,1
goto salto1
return

sg500 ; 497025 useg.


movlw 0e6h ; e6h= 235
movwf 0ch
movwf 0dh
salto2 decfsz 0ch,1
goto salto2
decfsz 0dh,1
goto salto2
return

sg250 ; 251001 useg.


movlw 0a7h ; a7h= 167
movwf 0ch
movwf 0dh
salto3
decfsz 0ch,1
goto salto3
decfsz 0dh,1
goto salto3
return

sg125 ; 125316 useg.


movlw 76h ; 76h= 118
movwf 0ch
movwf 0dh
salto4
decfsz 0ch,1
goto salto4
decfsz 0dh,1
goto salto4
return
end
PRÁCTICA Nº 4
Microcontrolador PIC16F84A.

Objetivo: Hacer funcionar el contador y ver como al desbordarse el contador provoca una interrupción. El pin
nº6 es la entrada de un contador que cuenta de 00h a ffh. Al pasar de ffh a 00h provoca una interrupción y la
subida de una bandera o flag.

¿Cómo se configuran los registros que intervienen en los conteos?


1º paso: Configurar el hardware del contador.
Se configurará el registro OPTION_REG y en concreto los bits siguientes:
 El bit 4, llamado TOSE, nos da la elección de elegir el tipo de flanco: ascendente o descendente. Un
1=flanco descendente y un 0= flanco ascendente. Yo he elegido flanco descendente.
 El bit 5, llamado TOCS, nos da la opción de elegir el tipo de reloj. Un 1= pulsos introducidos por el pin nº 6
(T0cki) y un 0= pulsos de reloj interno de frecuencia un cuarto de la frecuencia del cristal usado.
En este caso será pulso exterior.
2º paso: Configurar el software.
Se configura el registro INTCON y en concreto los bits siguientes:
 El bit 7 (GIE) se pondrá a 1 para habilitar el permiso general de interrupciones.
 El bit 5 (T0IE) se cargará con 1 para habilitar el permiso particular de la interrupción por desbordamiento
del contador.
¿Cómo sabremos si se ha producido una interrupción debido al desbordamiento del contador?
 Esta interrupción tiene asociada una bandera o flag, el bit 2 (T0IF) del registro INTCON.
 Esta bandera hay que borrarla por software.

Esquema eléctrico:
Programa:
;----------------------------------------------
;PROGRAMA CONTADOR.ASM
;Probar el contador y su interrupción.
;----------------------------------------------

list p=16f84A
include "p16F84A.inc"
;------------------------------
;RESET
;------------------------------
org 00h
reset
goto inicio
;------------------------------
;INTERRUPCION
;------------------------------
org 04h
goto int
;------------------------------
;PUNTERO DE INICIO
;------------------------------
org 10h
inicio
;-----------------------------------------------------
;Configurar el puerto A como salida
;-----------------------------------------------------
;Registro TRISA= 00h para salidas.
bsf STATUS,RP0; banco1
movlw 00h;
movwf TRISA; puertoA como salida
bcf STATUS,RP0; banco0
;PuertoA apagado
movlw 00h
movwf PORTA
;------------------------------------------------------
;Configurar el contador TMR0
;------------------------------------------------------
;TMR0 = contador descendente cargado con el dato ffh.
;Registro OPTION_REG
;Contador= bit5=T0CS= 1= pulsos exteriores.
;Descentente= bit4=T0SE= 1
bsf STATUS,RP0; banco1
bsf OPTION_REG,T0SE
bsf OPTION_REG,T0CS
bcf STATUS,RP0; banco0
;Cargar el TMR0 con ffh.
movlw 0ffh
movwf TMR0; cargo TMR0 con el dato ffh
; para que desborde con un pulso del pulsador conectado a la
; entrada T0cki.
;---------------------------------------------
;Preparar interrupciones.
;---------------------------------------------
;Habilitar permiso de interrupción global.
bsf INTCON,GIE
;Habilitar permiso int. particular del TMR0.
bsf INTCON,T0IE
;Espera hasta rebosar el TMR0.
espera
btfss INTCON,T0IF; salta si es 1. Al pulsar hago
; que el contador se desborde al pasar de ffh a 00h. La bandera se
; pone a 1 y salto a la interrupción y luego al programa principal.
; El puerto A se encenderá y apagará en un bucle indefinido.
goto espera
;-----------------------------------
;PROGRAMA PRINCIPAL
;-----------------------------------
programa
movlw 00h
movwf PORTA; apago el puertoA
call sg1
movlw 0ffh; enciendo el puertoA
movwf PORTA
call sg1
goto programa
;-------------------------------------------
;INTERRUPCION DEL TMR0
;-------------------------------------------
int
;Deshabiltar permiso de int. global
bcf INTCON,GIE
;Deshabilitar permiso de int. del contador
bcf INTCON,T0IE
;Poner a cero el flag
bcf INTCON,T0IF
retfie; retorno subrutina de interrupción.
;------------------------------------------------------------------
;Retardos.
;------------------------------------------------------------------
;c1h=193 goto=2 useg. decfsz=1 useg.( skip if 0 ).
;(193 x 2) + 193 = 579 useg
;(579 x 579) = 335241 useg.
;(335241 x 3) = 1005723 useg.
;0ch, 0dh y 0eh registros RAM del GPR
;----------------------------------------------------
sg1; 1005723 useg.
movlw 0c1h
movwf 0ch
movwf 0dh
movlw 01h
movwf 0eh
salto1
decfsz 0ch,1
goto salto1
decfsz 0dh,1
goto salto1
decfsz 0eh,1
goto salto1
return
;-------------------------
sg500; 497025 useg.
movlw 0e6h; e6h= 235
movwf 0ch
movwf 0dh
salto2
decfsz 0ch,1
goto salto2
decfsz 0dh,1
goto salto2
return
;--------------------------
sg250; 251001 useg.
movlw 0a7h; a7h= 167
movwf 0ch
movwf 0dh
salto3
decfsz 0ch,1
goto salto3
decfsz 0dh,1
goto salto3
return
;------------------------------------------------
sg125; 125316 useg.
movlw 76h; 76h= 118
movwf 0ch
movwf 0dh
salto4
decfsz 0ch,1
goto salto4
decfsz 0dh,1
goto salto4
return
end
PRÁCTICA Nº 5
Microcontrolador PIC16F84A

Objetivo: Encender y apagar cada segundo un led conectado al puerto RA2. Se usará el timer0 para hacer la
temporización.

Esquema eléctrico:

Programa:
;-----------------------------------------------
;PROGRAMA TIMER0.ASM
;Temporizador con el timer0
;haciendo on-off un led seg. alternos.
;-----------------------------------------------
list p=16F84A
include "p16F84A.inc"

;------------------
;RESET
;------------------
org 00h
reset
goto inicio

;---------------------------
INTERRUPCIONES
;---------------------------
org 04h
goto int

;-------------------------------
;Comienzo del programa
;-------------------------------
org 10h
inicio
;-----------------------------------------------
;Configurar el puertoA como entrada
;excepto el PA2 que será salida.
;-----------------------------------------------
;1= entradas, 0= salidas
;PA3,4= 1; PA2= 0; PA1,0= 1
;Registro TRISA= ---1 1011b= 1bh

bsf STATUS,RP0; banco1


movlw 1bh
movwf TRISA
bcf STATUS,RP0

;apagar led

bcf PORTA,2; poner 0 en la puerta 2.

;------------------------------------------
;Configurar el TMR0 (contador).
;------------------------------------------

bsf STATUS,RP0; banco1


movlw 87h; Divido la frecuencia entre 256 po-
; niendo PS0,PS1 y PS2= 1; PSA= 0
; asigno el divisor de frecuencia a
; TMR0; T0SE= 0 flanco ascendente;
; T0CS= 0 pulsos de reloj interno de
; f= fosc./4; INTEDG:= 0 flanco des-
; cendente (no usada la /int);
; /RBP0= 1 desactivadas (no usadas las
; resistencias pull-up puerta B).
movwf OPTION_REG

bcf STATUS,RP0; banco0

;--------------------------------------
;Configurar las interrupciones
;--------------------------------------

bsf INTCON,GIE; activo permiso interrupción general.


bsf INTCON,T0IE; activo interrupción del TMR0.

;--------------------------------------
;Configurar registros generales.
;--------------------------------------

movlw 64h; 64h= 100 decimal


movwf 0eh

;--------------------------------------
;Programa principal
;--------------------------------------
programa

bsf PORTA,2; poner 1 en el PA2, enciendo el led.


call cuenta1; retardo 1 sg.
bcf PORTA,2; poner 0 en el PA2, apago el led.
call cuenta1
goto programa; salto a programa

;---------------------------------------------
;Subrutina de temporizar 1 segundo.
;---------------------------------------------
;Frecuencia del cristal es 4Mhz.
;La señal de entrada al TMR0 es fosc./4, o sea, 1Mhz (T= 1 useg.).
;El divisor de frecuencia divide por 256, con lo que la señal de 1 Mhz se
;transforma en una de 3906,25 Hz (T= 0,256 mseg.)
;1seg= 1000 mseg.
;0,256 mseg x 3900= 998,4 mseg
;El TMR0 va a contar desde 216 a 255 que son 39 impulsos de 0,256 mseg.
;y esto lo va hacer 100 veces, o sea, las 3900 veces que necesito.

cuenta1
bsf INTCON,T0IE; activo int. timer0.
bcf INTCON,T0IF; poner a cero el flag del timer0.
movlw 0d8h; d8h= 216 decimal
movwf TMR0; 255 - 216 = 39.

cuenta

btfss INTCON,T0IF; salta si es 1. Espero la interrupción por


goto cuenta; desbordamiento.
decfsz 0eh,1; decrementa 0eh y salta si es cero.
goto cuenta1
movlw 64h; 64h= 100
movwf 0eh
return

;---------------------------------------
;Tratamiento de la interrupción.
;---------------------------------------

int
bcf INTCON,T0IE; desactivación de la int. del timer0.
bcf INTCON,T0IF; borro el flag
retfie; retorno subrutina interrupción.

end
PRACTICA Nº6
Construcción de una alarma compuesta de dos sensores y un elemento sonoro, un buzzer

Objetivo de la práctica:
1º: Usar las instrucciones de manejo de bits:

BCF f,b : pon a cero un bit determinado de un registro.


Ejemplo: bcf STATUS,C (pon a cero el bit acarreo (C)del registro de estado, STATUS).

BSF f,b : pon a uno un bit determinado de un registro.


Ejemplo: bsf PORTB,0 (pon a uno el bit nº 0 del registro PORTB, es decir, RB0 estará a uno).

2º : Usar las instrucciones de salto condicional de bits:

BTFSC f,b : comprueba que el bit “x” está cero y salta.


Ejemplo: btfsc STATUS,Z ( salta si el resultado es igual a cero).

BTFSS f,b : comprueba que el bit “x” está a uno y salta.


Ejemplo: btfss PORTB,6 ( si RB6 está a uno salta).

3º : Usar las instrucciones de salto condicional de registros:

DECFSZ f,d: decrementa el registro f y si vale cero salta.


Ejemplo: decfsz 10h,0 (decrementa el contenido del registro 10h, lo guardo en W (d=0) y si vale cero salta)

INCFSZ f,d : incrementa el registro f y si vale cero salta.


Ejemplo: incfsz 0fh,1 (incrementa el contenido del registro 0fh, lo guardo en el propio registro 0Fh (d=1) y si
vale cero salta.

Descripción de los componentes que intervendrán en el sistema:

1º: Dos sensores de detección, que serán simulados con los pulsadores.

2º: El PIC que ejecutará el programa de funcionamiento de la alarma con las siguientes directrices:
a: Una vez conectada la alimentación nos debe dar tiempo suficiente a abandonar el local, 1 minuto de retardo.
b: Comprobar cuatro veces que los detectores están activos a intervalos de un cuarto de minuto.
c: Una vez activada totalmente hacer sonar una señal sonora durante dos minutos.

3º: Esta señal sonora será producida por una chicharra (buzzer).

Descripción del circuito eléctrico de el buzzer.


El buzzer está controlado por transistor NPN que al serle conectados cinco voltios a través de la resistencia de
base se satura y el buzzer entones es conectada a cero voltios, sonando por lo tanto.

Descripción de las funciones de los pines del puerto B para configurarlo para la alarma.

1. RB0 y RB1 serán conexionado a los pulsadores (anteponiendo lo circuitos disparadores).

2. RB7 será conexionado a la base del transistor que controla la alarma.

Descripción del montaje pulsador-red RC-circuito disparador:

Consiste en descargar una red RC a través del pulsador y la resistencia de 47 ohmios. Al conectar la
alimentación el condensador de 100 nF se carga a través de la resistencia de 10K ohmios.

En las entradas de los circuitos disparadores (pines 1-2 o 8-9) atendremos +5voltios con lo que a las salidas
(pines 3 y 10) del circuito disparador habrá cero voltios.

Si le conectásemos otro circuito (entradas pines 5-6 y 12-13) disparador a las salidas anteriores invertiríamos
esos cero voltios a cinco voltios en las salidas, pines 4 y 11.

El diodo conectado en paralelo con la resistencia de 10k sirve para descargar el condensador cuando se
desconecte la fuente de alimentación y así no dañar al PIC.

Usamos como inversores las puertas NAND de dos entradas aunque valdría cualquier otro inversor, pero eso sí,
con entradas de disparador ya que sino ante cualquier rebote de los pulsadores, ruido o interferencia que
llegase a las entradas no conseguiríamos un solo pulso sino varios pulsos al activar el pulsador.
Descripción de los pasos a seguir para hacer el programa:

1º. Pondremos a uno los bit 0 y 1 del TRISB para hacer dos entradas en el puerto B. Pondremos a cero los bit 7
del TRISB para hacer una salida en el puerto B.

2º. Con las instrucciones de salto condicional de bits detectaremos como están las entradas y se actuará sobre
la alarma sonora.

Habrá que realizar varias temporizaciones: una de 60 segundos y otra de 15 segundos.

Programa :
;-----------------------------------------------------------------------
;SEXTO PROGRAMA:
;Alarma con dos sensores y señal sonora.
;-----------------------------------------------------------------------
;PIC 16F84A/ 4 MHz/
;Bits de configuración para el programador:
;CP(protección de la memoria de código):....................No
;PWRTE(activación del temporizador "Power-up"):....No
;WDTE(activación del "perro guardián"):.....................No
;FOSC1-FOSC0(tipo de oscilador):...............................Xtal
;-------------------------------------------------------------------------
;PROGRAMA
LIST p=16f84A
INCLUDE "p16f84A.inc"

ORG 00h
goto inicio
inicio
ORG 10h

;Configurar el puerto B como salida RB7 y como entradas RB0 y RB1.

call banco1
bsf TRISB,0
bsf TRISB,1
bcf TRISB,7
call banco0

programa
call buzzer2 ; Subrutina para hacer sonar dos veces el buzzer
call sg60 ; retardo de 60 segundos.

programa1
movlw 04h ; muevo el nº 04h al W.
movwf 11h ; muevo W al registro 11h
call buzzer1 ; subrutina de hacer sonar el buzzer una vez

comprueba1
btfsc PORTB,0 ; compruebo si el sensor 0 está activo o no
goto cuatro1 ; salto incondicional a la etiqueta “cuatro1” para
;comprobar 4 veces si está activado el sensor 0 conectado a RB0

bcf PORTB,7 ; pongo a cero RB7, o sea, apago el buzzer


;si no está activado el sensor 0
comprueba2
btfsc PORTB,1 ; compruebo si el sensor 1 está activo o no
goto cuatro2 ; salto incondicional a la etiqueta “cuatro2”
;para comprobar 4 veces si está activado el
;sensor 1 conectado a RB1

bcf PORTB,7 ; pongo a cero RB7, o sea, apago el buzzer


;si no está activado el sensor 1
movlw 04h ;cargo con el nº 04h el W
movwf 11h ;cargo el registro 11h con W
goto comprueba1 ; salto incondicional a la etiqueta “comprueba1”

cuatro1
call buzzer1 ;suena una vez el buzzer
call sg15 ; retardo de 15 segundos
decfsz 11h,1 ; decrementa el registro 11h y si vale cero salta
goto comprueba1 ; salto incondicional
call buzzer120 ; suena el buzzer durante 120 segundos
goto programa1 ; salto incondicional

cuatro2
call buzzer1
call sg15
decfsz 11h,1
goto comprueba2
call buzzer120
goto programa1
;----------------------------------------------
;Subrutinas de cambios de bancos.
;----------------------------------------------
banco0
bcf STATUS,RP0
return
banco1
bsf STATUS,RP0
return

;---------------------------------------------
;Subrutinas de el buzzer (buzzer)
;---------------------------------------------
buzzer1
bsf PORTB,7
call sg1
bcf PORTB,7
return

buzzer2

bsf PORTB,7
call sg1
bcf PORTB,7
call sg1
bsf PORTB,7
call sg1
bcf PORTB,7
return

buzzer120
bsf PORTB,7
call sg60
call sg60
bcf PORTB,7
return

;---------------------------------
;Subrutinas de retardos.
;---------------------------------
sg1
call banco0
movlw 0ffh
movwf 0ch
movlw 0ffh
movwf 0dh
movlw 05h
movwf 0eh
repite
decfsz 0ch,1
goto repite

decfsz 0dh,1
goto repite

decfsz 0eh,1
goto repite
return

;Retardo de 15 segundos.
;Decrementaremos un registro, 0fh, cargado
;con el nº 0fh (15) hasta llegar a cero.

sg15
movlw 0fh
movwf 0fh
otra
call sg1
decfsz 0fh,1
goto otra
return

;Retardo de 60 segundos.Incrementaremos un registro, 10h, cargado con el nº C3h hasta llegar


;a 00h (60 veces)

sg60
movlw 0c3h
movwf 10h
otravez
call sg1
incfsz 10h,1
goto otravez
return
END
PRÁCTICA Nº 7
Proyecto: Regulador lumínico mediante el control de la fase.

¿En qué consiste una regulación por control de la fase?


La corriente eléctrica que usamos en la vida diaria es una señal alterna senoidal como la de la figura:

Al pasar esta corriente eléctrica por la lámpara haremos que se ilumine al 100 %. Si nos las ingeniamos para
que la señal aplicada a la lámpara se recorte como se ve en la figura siguiente, obtendremos valores de
iluminación entre un 0% y un 100%.

¿Cómo conseguimos esos recortes en la señal?


1º: Necesitamos una señal de referencia que esté situada en los cero voltios de la señal senoidal.
Si a la salida del transformador de toma intermedia colocamos un rectificador de onda completa (dos diodos
1N4148) obtenemos una señal de igual nombre. Esta señal la atenuamos con un potenciómetro de 47K y la
introducimos en un circuito disparador para transformarla en una señal cuadrada positiva de +5voltios de
amplitud.
2º: Con los flancos de bajada de esos impulsos situados alrededor de los cero voltios activaremos la interrupción
externa INT y subiremos la bandera INTF. A partir de ese instante programaremos pulsos de tiempo variable
que nunca llegarán a tener más duración más allá del siguiente impulso de referencia y que una vez agotado
daremos un impulso pequeño de disparo del Triac.

Fuente de alimentación y circuitos para obtener la señal de referencia de T= 10 mseg.


Circuito de botones UP y DOWN.

Circuito microcontrolador PIC 16F84A.


Circuito de control del Triac.

;Proyecto: regulador de luz.


; Control de la intensidad lumínica de la lámpara mediante
; el sistema de recorte o graduador de fase. Cada 10 mseg.
; tenemos el paso de la señal rectificada en doble onda por
; cero. A partir de hay introducimos temporizaciones que al
; acabar nos indicará el instante para disparar el triac,
; siempre antes de que llegue otro impulso de paso por cero.
;
; Condiciones de funcionamiento según se empiece a pulsar el
; botón UP o DOWN:
; * Al conectarse el montaje la lámpara está apagada.
; * Si toco el botón UP se enciende lámpara al 100% y con dicho
; botón puedo bajar la intensidad de luz hasta llegar al 0%.
; Con el botón DOWN a partir de ese 0% puedo ir incrementando
; la intensidad de la luz hasta el 100%.
; * Si una vez conectado el montaje (lámpara apagada) tocó el
; botón DOWN la luz irá aumentado progresivamente de 0% al
100%.
; Al llegar al 100% con el botón UP puedo ir disminuyendo la
; intensidad de luz hasta llegar al 0%
;----------------------------------------------------------------------------------
;PIC 16F84A/ 4 MHz/
;Bits de configuración para el programador:
;CP(protección de la memoria de código):..............................No
;PWRTE(activación del temporizador "Power-up"):..............No
;WDTE(activación del "perro guardián"):...............................No
;FOSC1-FOSC0(tipo de oscilador):........................................Xtal
;-----------------------------------------------------------------------------------
;PROGRAMA
LIST p=16f84A
INCLUDE "p16f84A.inc"

ORG 00h
goto inicio
inicio
ORG 10h

;Configurar el puerto B (RB4 salida).


call banco1
bcf TRISB,4 ;El Puerto RB4 como salida
call banco0
bcf PORTB,4 ;pongo a cero el Puerto RB4

;Configurar la INT.
call banco1
bcf OPTION_REG,INTEDG ;flanco de bajada de la INT
call banco0

programa
movlw 00h
movwf 20h

progra1
btfss INTCON,INTF
goto progra1
bcf INTCON,INTF
call varia
call disparo
call up
call down
goto progra1

;--------------------------------------------------
;Subrutinas de los botones UP-DOWN.
;---------------------------------------------------
up
btfss PORTB,2 ;testeo el puerto RB2 y si vale uno salto
goto saltu1
incf 20h,1 ;incremento el registro 20h
bcf STATUS,C ;corrección para no llegar a FFh, solo llego hasta F1h
movlw 0fh
addwf 20h,0
btfss STATUS,C
goto saltu1
movlw 0f1h
movwf 20h
saltu1
return
down
btfss PORTB,3 ;testeo el puerto RB3 y si vale uno salto
goto saltu3
decf 20h,1 ;decremento el registro 20h
bcf STATUS,C ;corrección para no llegar a 00h, sólo llego hasta 0Fh
movlw 0f1h
addwf 20h,0
btfss STATUS,C
goto saltu2
return
saltu2
movlw 0fh
movwf 20h
saltu3
return

;------------------------------------
;Disparo del triac: 225 useg.
;------------------------------------
;Pulso de disparo de 225 microsegundos necesarios para activar el triac

disparo
bsf PORTB,4
call usg225
bcf PORTB,4
return
usg225
movlw 4bh
movwf 30h
sal4
decfsz 30h,1
goto sal4
return

;-----------------------------------------------
;Retardo variable después de la INT.
;-----------------------------------------------
;El tiempo entre que se activa la bandera INTF es de 10mseg (10.000 microsegundos)
;Si un registro (21h) lo cargo con un valor comprendido entre 01h y FFh y lo voy
;decrementando hasta llegar a cero con un retardo fijo de unos 25 microsegundos entre medias
;puedo conseguir unos pocos microsegundos o los 10.000 microsegundos.

varia
movf 20h,0
movwf 21h
salte
call usg25
decfsz 21h,1
goto salte
return
usg25
movlw 08h
movwf 31h
sal5
decfsz 31h,1
goto sal5
return
;------------------------------------------
;Subrutinas de cambios de bancos.
;------------------------------------------
banco0
bcf STATUS,RP0
return
banco1
bsf STATUS,RP0
return

END
PRÁCTICA Nº 8
La instrucción RETLW.

Es una instrucción de regreso de subrutina que carga en el acumulador, W, un número. Realizaremos un


contador (TMR0) de eventos (del 0h al fh) simulado por un pulsador y teniendo como elemento de visualización
un display de siete segmentos. Como el microcontrolador sólo cuenta en hexadecimal tendremos que decodificar
el nº hexadecimal a siete segmentos. Esto lo haremos creando una tabla con la instrucción “retlw”.

Tabla de decodificación hexadecimal-7 segmentos.


;-----------------------------------------------------------------------------
;PROGRAMA COMPROBADO:
;Manejo de la instrucción RETLW
;Realizaremos un contador de eventos
;con TMR0 (de 00h a 0Fh).
;-----------------------------------------------------------------------------
;PIC 16F84A/ 4 MHz/
;Bits de configuración para el programador:
;CP(protección de la memoria de código):..............................No
;PWRTE(activación del temporizador "Power-up"):..............No
;WDTE(activación del "perro guardián"):...............................No
;FOSC1-FOSC0(tipo de oscilador):.........................................Xtal
;-------------------------------------------------------------------------------
;PROGRAMA
LIST p=16f84A
INCLUDE "p16f84A.inc"

ORG 00h
goto inicio
ORG 10h
tabla
movf TMR0,0
andlw 0fh
addwf PCL,1
retlw 3fh
retlw 06h
retlw 5bh
retlw 4fh
retlw 66h
retlw 6dh
retlw 7dh
retlw 07h
retlw 7fh
retlw 67h
retlw 77h
retlw 7ch
retlw 39h
retlw 5eh
retlw 79h
retlw 71h

inicio

;Configurar el puerto B salida


call banco1
movlw 00h
movwf TRISB
call banco0
movlw 00h
movwf PORTB

;Configurar el TMR0.
call banco1
bsf OPTION_REG,T0SE
bsf OPTION_REG,T0CS
call banco0
clrf TMR0

programa
call tabla
movwf PORTB
goto programa

;------------------------------------------
;Subrutinas de cambios de bancos.
;------------------------------------------
banco0
bcf STATUS,RP0
return
banco1
bsf STATUS,RP0
return

END
PRÁCTICA Nº 9
Conexión de una pantalla LCD de 1 línea y 16 caracteres.

Descripción de los pines de conexión de la LCD (basada en el HD44780).

Descripción del lugar que ocupa cada carácter en la pantalla y la dirección de la posición de memoria en la LCD.
Descripción del carácter colocado y la dirección que ocupa en la memoria de la LCD.

Tabla de código de los caracteres.


Descripción de las conexiones al PIC 16F84A.

Instrucciones de manejo de la LCD.

CODIGO Tiempo
Instrucción. Descripción de
RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 ejecución
Borra la
pantalla y
retorna el
Borrar Pantalla 0 0 0 0 0 0 0 0 0 1 1.64 mS.
cursor a la
dirección 0 (
Home )
Retorna el
cursor al
Cursor Home 0 0 0 0 0 0 0 0 1 * 1.64 mS.
inicio (
Dirección o)
Donde
I/D=0
Decremente
la posición
del cursor,
I/D=1
incrementa
Modo de
la posición
entrada de 0 0 0 0 0 0 0 1 I/D S 40 uS.
del cursor,.
caracteres
S=0 El texto
de la
pantalla no
se desplaza,
S=1 El texto
de la
pantalla se
desplaza en
el momento
que se
escribe un
carácter
Donde D=0
Pantalla
apagada,
D=1 Pantalla
encendida,
C=0 Cursor
apagado,
Apagado y C=1 Cursor
encendido de 0 0 0 0 0 0 1 D C B encendido, 40 uS..
la pantalla. B=0
Intermitencia
del cursor
apagado,
B=1
Intermitencia
del cursor
encendido.
Desplazamiento
0 0 0 0 0 1 S/C R/L * * 40 uS.
cursor y display
Funtion Set 0 0 0 0 1 DL N F * * 40 uS.
Dirección
0 0 0 1 ACG 40 uS.
CG RAM
Dirección
0 0 1 ADD 40 uS.
DD RAM
Leer busy flag
y 0 1 BF AC 1 uS.
dirección
Escribir dato en
1 0 Escribir el Dato 40 uS.
CG o DD RAM
Leer dato en
1 1 Leer el Dato 40 uS.
CG or DD RAM
NOMENCLATURAS
Nomenclatura Valor = 1 Valor = 0
I/D=1 Incrementa el Cursor I/D=0 Decrementa el Cursor en
I/D
en una posición una posición.
D D=1 Pantalla Encendida D=0 Pantalla Apagada.
C C=1 Cursor Encendido. C=0 Cursor Apagado.
B=1 Intermitencia del cursor B=0 Intermitencia del cursor
B
encendida. apagado
S/C S/C=1 Mover todo el texto. S/C=0 Mover el cursor.
R/L=1 Mover todo el texto a R/L=1 Mover todo el texto a la
R/L
la izquierda. derecha.
DL DL=1 Bus de datos de 8 Bits. DL=0 Bus de datos de 4 Bits.
S=1 Desplazamiento del S=0 No desplazamiento del
S
texto. texto
BF=1 Operación Interna en BF=0 No puede aceptar
BF
progreso. instrucción
F=1 Matriz para el carácter F=0 Matriz del carácter de 5 x 7
F
de 5 X 10 dots Dost
N N=1 Activación de dos lineas. N=0 Activación de 1 linea

Códigos hexadecimales de las instrucciones usadas.

INSTRUCCIÓN Hexadecimal
Función set (DL=1, 8-bit interface; N=0, 1 line; F=0, 5*7 Pixels) 30
Modo entrada (I/D=1; S=0) 06
Display ON-OFF (Control: D=0; C=0; B=0) Display apagado 08

Display ON-OFF (Control: D=1; C=0; B=0) Display encendido 0C

Cursor Home 02
Desplazamiento cursor y display ( S/C=0; R/L=1,derecha) 14
Borrar pantalla 01

;------------------------------------------------------------------------------
;PROGRAMA COMPROBADO:
;Manejo de una LCD.
;Escribir el mensaje: PIC 16F84A, v.00
;------------------------------------------------------------------------------
;PIC 16F84A/ 4 MHz/
;Bits de configuración para el programador:
;CP(protección de la memoria de código):..............................No
;PWRTE(activación del temporizador "Power-up"):..............No
;WDTE(activación del "perro guardián"):...............................No
;FOSC1-FOSC0(tipo de oscilador):........................................Xtal
;------------------------------------------------------------------------------
;PROGRAMA
LIST p=16f84A
INCLUDE "p16f84A.inc"
ORG 00h
goto inicio
ORG 10h
inicio
;Configurar los puertos A y B.
call pabconfig
;Configuración inicial de la LCD.
call lconfigI
;Configuración de trabajo de la LCD.
call lconfigW
programa
call lcdPIC
progra
goto progra

;----------------------------------------
;Subrutina para poner un texto.
;---------------------------------------

;P I C _ 1 6 F 8 4 A , _ v . 0 0
lcdPIC
call pabconfig; subrutina de configurar Puerto A y B para la LCD.
call lclear; borrar pantalla
call lhome; dirección 00h de la pantalla

movlw 00h; dirección de comienzo del mensaje en la 1ª línea


call wdir; carga dirección 00h en la pantalla

movlw 50h; P carga 50h = P (ASCII)


call wdato; escribir el símbolo P en la pantalla (dirección 00h)
movlw 49h; I
call wdato
movlw 43h; C
call wdato
movlw 20h
call wdato
movlw 31h; 1
call wdato
movlw 36h; 6
call wdato
movlw 46h; F
call wdato
movlw 38h; 8
call wdato
movlw 34h; 4
call wdato
movlw 41h; A
call wdato
movlw 2ch; ,
call wdato
movlw 20h
call wdato
movlw 76h; v
call wdato
movlw 2eh; .
call wdato
movlw 30h; 0
call wdato
movlw 30h; 0
call wdato
call pabI0O; subrutina de hacer los pines entradas excepto RA0= E
;(habilitación de la pantalla)= 0, deshabilitada.
return

;-------------------------------------------
;-------------------------------------------
;Subrutinas de la pantalla LCD.
;-------------------------------------------
;--------------------------------------
;Subrutina de configuración del puerto A y B.
;-------------------------------------
pabconfig
call pacontrol
call pbbusO
return
;---------------------------------------------
;Subrutina de configuración inicial de la pantalla LCD.
;---------------------------------------------
lconfigI
call mseg20
call l8xx
call mseg6
call l8xx
call useg150
call l8xx
call l817
call ldisplay0xx
call lclear
call lmode10
return
;-------------------------------------------
;Subrutina de configuración de la
;LCD para comenzar a trabajar.
;-------------------------------------------
lconfigW
call ldisplay10x
call lcursorder
return
;-----------------------------------------------------
;Puerto A 3,4= entradas, 0,1 y 2 = salidas
;y las pongo a cero.
;-----------------------------------------------------
pacontrol
call banco1
bcf TRISA,0
bcf TRISA,1
bcf TRISA,2
call banco0
bcf PORTA,0
bcf PORTA,1
bcf PORTA,2
return
;------------------------------
;Puerto B= salidas y las pongo a cero.
;------------------------------
pbbusO
call banco1
movlw 00h
movwf TRISB
call banco0
movlw 00h
movwf PORTB
return
;----------------------------------------------------
;Puerto B y RA2,1 = entradas y la RA0 se queda como salida a cero para inhabilitar la LCD.
;---------------------------------------------------
pabI0O
call banco1
movlw 0ffh
movwf TRISB
bsf TRISA,1
bsf TRISA,2
call banco0
return

;----------------------------------------
;Pulso de habilitación del LCD.
;----------------------------------------
;Flanco de subida
lE1
nop
bcf PORTA,0
nop
bsf PORTA,0
return
;Flanco de bajada
lE2
nop
bcf PORTA,0
nop
return
;------------------
;Escribir dato.
;------------------
lwd
bsf PORTA,2
bcf PORTA,1
call lE1
return
;---------------------------
;Escribir instrucción.
;--------------------------
lwi
bcf PORTA,2
bcf PORTA,1
call lE1
return
;-----------------------------
;Escribir instrucciones.
;-----------------------------
;De 20h a puerto B.
;----------------------------
w20pb
movf 20h,0
movwf PORTB
return
;--------------------------------------------------
;Escribir instrucción de "No operación".
;--------------------------------------------------
lnop
movlw 00h
call winst
return
winst
movwf 20h
call lwi
call w20pb
call lE2
call useg45
return

;----------------------------------------------------
;Escribir inst. de limpiar display y
;poner a cero el contador de direcciones.
;----------------------------------------------------
lclear
movlw 01h
call winstt
return
winstt
movwf 20h
call lwi
call w20pb
call lE2
call mseg2
return
;---------------------------------------
;Escribir inst. de cursor a casa.
;--------------------------------------
lhome
movlw 02h
call winstt
return

;------------------------------------------
;Escribir inst. de modo de entrada.
;------------------------------------------
;-----------------------------------------------------------------
;El cursor se mueve incremental (I/D= 1)
;y el display no se desplaza automáticamente (S= 0).
;-----------------------------------------------------------------
lmode10
movlw 06h
call winst
return

;------------------------------------------------
;Escribir inst. del control del display.
;------------------------------------------------
;------------------------------------------------------
;Display on, D= 1; Cursor off, C= 0; B= x.
;------------------------------------------------------
ldisplay10x
movlw 0ch
call winst
return
;-----------------------------------------
;Display off, D= 0; C= x; B= x.
;-----------------------------------------
ldisplay0xx
movlw 08h
call winst
return
;----------------------------------------------------
;Desplazar display o mover cursor (S/C) y
;especificar dirección (R/L).
;----------------------------------------------------
;---------------------------------------------------
;Desplazar display y no cursor (S/C=1) a
;la derecha (R/L=1).
;---------------------------------------------------
ldisplayder
movlw 1ch
call winst
return
;------------------------------------------------
;Mover cursor y no display (S/C=0) a
;la derecha (R/L=1).
;------------------------------------------------
lcursorder
movlw 14h
call winst
return
;---------------------------------------------------------------
;Función Set.
;Configurar la pantalla: bus de 4 o 8 bits (DL),
;1 o 2 líneas (N) y nº de puntos (5x10 o 5x7) (F).
;---------------------------------------------------------------
l8xx
call lwi
movlw 30h
movwf 20h
call w20pb
call lE2
call useg45
return
l817
movlw 30h
call winst
return
;--------------------------------------------------
;Subrutina para colocar datos seguidos
;-------------------------------------------------
wdato
movwf 20h
call lwd
call w20pb
call lE2
call useg45
return
;----------------------------------------------------
;Subrutina para colocar datos en cualquier
;posición de la pantalla: DDRAM dirección.
;----------------------------------------------------
wdir
addlw 80h
movwf 20h
call lwi
call w20pb
call lE2
call useg45
return

;------------------------------
;Retardos para la LCD.
;------------------------------
;---------------------------
;Retardo de 2 mseg.
;--------------------------
mseg2
call banco0
movlw 0ffh
movwf 30h
movlw 03h
movwf 31h
salto5s
decfsz 30h,1
goto salto5s
decfsz 31h,1
goto salto5s
return
;--------------------------
;Retardo de 6 mseg.
;--------------------------
mseg6
call banco0
movlw 0ffh
movwf 30h
movlw 08h
movwf 31h
salto41s
decfsz 30h,1
goto salto41s
decfsz 31h,1
goto salto41s
return
;---------------------------
;Retardo de 20 mseg.
;---------------------------
mseg20
call banco0
movlw 0ffh
movwf 30h
movlw 1ah
movwf 31h
salto4s
decfsz 30h,1
goto salto4s
decfsz 31h,1
goto salto4s
return

;---------------------------
;Retardo de 45 useg.
;---------------------------
useg45
call banco0
movlw 0fh
movwf 30h
salto6s
decfsz 30h,1
goto salto6s
return

;------------------------------
;Retardo de 150 useg.
;------------------------------
useg150
call banco0
movlw 32h
movwf 30h
salto61s
decfsz 30h,1
goto salto61s
return
;------------------------------------------
;Subrutinas de cambios de bancos.
;------------------------------------------
banco0
bcf STATUS,RP0
return
banco1
bsf STATUS,RP0
return

END
PRÁCTICA nº 10
Conexión de un teclado.

Teclado estático: formado por dos decodificadores decimales. Al unir los dos decodificadores con unas puertas
OR y añadirles un buffer tres estados obtenemos un dispositivo capacitado para ser conectado al puerto B y que
no tendrá problemas de choque de buses al ser controlado por un pin específico del PIC, habilitar del teclado sin
cortocircuitarse con el bus de una LCD conectada al puerto B, por ejemplo.

Buffer tres estados, 74HC245. El terminal RA3 controlará la salida de datos al bus de datos que también es
usado por la LCD.
Poniendo RA3 a cero los datos saldrán hacia el puerto B del PIC. Hemos construido un teclado hexadecimal ( 00
a 0fh). Hemos necesitado cuatro integrados CMOS, unas cuantas resistencias y pulsadores sueltos; si queremos
disminuir el número de integrados, de conexiones de pulsadores y de componentes, etc, hay un integrado
llamado 74C922 que nos facilita las conexiones. También podemos usar un teclado ya encapsulado.
El teclado encapsulado usado tiene las siguientes conexiones y dibujado los números así:
Si observamos los números de las teclas en el dibujo del integrado y los números del teclado, vemos que no
coinciden, por lo tanto en el software habrá que hacer corresponder los números de las teclas del 74C922 con
las del teclado.

Vamos haber que transformaciones hay que hacer para poder ver en la pantalla LCD la tecla que pulses.

Las teclas pulsadas en el 74c922 son las siguientes:


Por los terminales RB0, RB1, RB2 y RB3 entrarán esas combinaciones pero por RB4,RB5,RB6 y RB7 entrará
cualquier combinación que neutralizaremos haciendo una operación AND con 0Fh. Ahora tendremos las
siguientes combinaciones:

Usaremos la instrucción RETLW para hacer una correspondencia entre esas combinaciones y las necesarias para
ser visualizadas en la pantalla LCD y correspondan a las dibujadas en el teclado encapsulado. Las combinaciones
de correspondencia son:
En ASCII el 30h es nuestro 0 decimal, el 39h es el 9, 3ch es < y 3eh es >. En la práctica anterior visualizamos
un mensaje:

En la posición de memoria 0Fh de la LCD visualizaremos la tecla pulsada.

PIC 16F84A, v.0

TECLA PULSADA
;------------------------------------------------------------------------------
;PROGRAMA COMPROBADO:
;Manejo de un teclado (74C922) y una LCD.
;Escribir un mensaje y ver la tecla que pulso en el teclado.
;------------------------------------------------------------------------------
;PIC 16F84A/ 4 MHz/
;Bits de configuración para el programador:
;CP(protección de la memoria de código):..............................No
;PWRTE(activación del temporizador "Power-up"):..............No
;WDTE(activación del "perro guardián"):...............................No
;FOSC1-FOSC0(tipo de oscilador):........................................Xtal
;------------------------------------------------------------------------------
;PROGRAMA
LIST p=16f84A
INCLUDE "p16f84A.inc"
ORG 00h
goto inicio
ORG 10h
inicio
;Configurar los puertos A y B.
call pa3saluno; desactivo el teclado, RA3=1
call pabconfig
;Configuración inicial de la LCD.
call lconfigI
;Configuración de trabajo de la LCD.
call lconfigW
programa
call lcdPIC
progra
call pa3cero; activo el teclado con RA3=0 y hago PB entradas
call binasc; convierto el código binario en ASCII
movwf 40h; cargo 40h con W
call vertecla; veo la tecla pulsada
call pa3saluno; desactivo el teclado, RA3=1

goto progra

;--------------------------------------
;Leer el Puerto B: RB0,RB1,RB2 y RB3.
;y transformarlo en ASCII.
; 0-31, 1-32, 2-33
; 4-34, 5-35, 6-36
; 8-37, 9-38, A-39
; C-3c, D-30, E-3e
; En las combinaciones 3,7,B y F
; pondré el símbolo ffh.
;--------------------------------------
binasc
movf PORTB,0; leo el puerto PB y lo llevo a W
andlw 0fh; pongo a cero los bits altos y lo dejo en el W
addwf PCL,1; sumo al contador de programa bajo lo que tenía el acumulador
retlw 31h; regreso de subrutina con el W cargado con ASCII.
retlw 32h
retlw 33h
retlw 0ffh
retlw 34h
retlw 35h
retlw 36h
retlw 0ffh
retlw 37h
retlw 38h
retlw 39h
retlw 0ffh
retlw 3ch
retlw 30h
retlw 3eh
retlw 0ffh

;-----------------------------------
;Subrutina de ver la tecla pulsada.
;-----------------------------------
vertecla
call pabconfig; subrutina de configurar Puerto A y B para la LCD.
movlw 0fh; dirección de visión de la tecla pulsada
call wdir; carga dirección 0fh en la pantalla
movf 40h,0; cargo el dato en ASCII presente en 40h en W
call wdato; escribir el símbolo en la pantalla (dirección 0fh)
call pabI0O; subrutina de hacer los pines entradas excepto
;RA0= E (habilitación de la pantalla)= 0, deshabilitada.
return

;----------------------------------------
;Subrutina para poner un texto.
;---------------------------------------

;P I C _ 1 6 F 8 4 A , _ v . 0 0

lcdPIC
call pabconfig; subrutina de configurar Puerto A y B para la LCD.
call lclear; borrar pantalla
call lhome; dirección 00h de la pantalla

movlw 00h; dirección de comienzo del mensaje en la 1ª línea


call wdir; carga dirección 00h en la pantalla

movlw 50h; P carga 50h = P (ASCII)


call wdato; escribir el símbolo P en la pantalla (dirección 00h)
movlw 49h; I
call wdato
movlw 43h; C
call wdato
movlw 20h
call wdato
movlw 31h; 1
call wdato
movlw 36h; 6
call wdato
movlw 46h; F
call wdato
movlw 38h; 8
call wdato
movlw 34h; 4
call wdato
movlw 41h; A
call wdato
movlw 2ch; ,
call wdato
movlw 20h
call wdato
movlw 76h; v
call wdato
movlw 2eh; .
call wdato
movlw 30h; 0
call wdato
movlw 30h; 0
call wdato

call pabI0O; subrutina de hacer los pines entradas excepto


; RA0= E (habilitación de la pantalla)= 0, deshabilitada.
return

;-------------------------------------------
;-------------------------------------------
;Subrutinas de la pantalla LCD.
;-------------------------------------------
;--------------------------------------
;Subrutina de configuración del puerto A y B.
;-------------------------------------
pabconfig
call pacontrol
call pbbusO
return

;---------------------------------------------
;Subrutina de configuración inicial
;de la pantalla lCD.
;---------------------------------------------
lconfigI
call mseg20
call l8xx
call mseg6
call l8xx
call useg150
call l8xx

call l817
call ldisplay0xx
call lclear
call lmode10
return
;-------------------------------------------
;Subrutina de configuración de la
;LCD para comenzar a trabajar.
;-------------------------------------------
lconfigW
call ldisplay10x
call lcursorder
return
;-----------------------------------------------------
;Puerto A 3,4= entradas, 0,1 y 2 = salidas
;y las pongo a cero.
;-----------------------------------------------------
pacontrol
call banco1
bcf TRISA,0
bcf TRISA,1
bcf TRISA,2
call banco0
bcf PORTA,0
bcf PORTA,1
bcf PORTA,2
return

;---------------------------
;PA3 como salida y a uno:
;inhabilito teclado
;---------------------------
pa3saluno
call banco1
bcf TRISA,3
call banco0
bsf PORTA,3
return
;--------------------------------
;PA3 a cero: activo teclado
;y PB entrada.
;--------------------------------
pa3cero
call banco1
movlw 0ffh
movwf TRISB
call banco0
bcf PORTA,3
return
;------------------------------
;Puerto B= salidas
;y las pongo a cero.
;------------------------------
pbbusO
call banco1
movlw 00h
movwf TRISB
call banco0
movlw 00h
movwf PORTB
return

;----------------------------------------------------
;Puerto B y RA2,1 = entradas y
;la RA0 se queda como salida a cero para
;inhabilitar la LCD.
;---------------------------------------------------
pabI0O
call banco1
movlw 0ffh
movwf TRISB
bsf TRISA,1
bsf TRISA,2
call banco0
return

;----------------------------------------
;Pulso de habilitación del LCD.
;----------------------------------------
;Flanco de subida
lE1
nop
bcf PORTA,0
nop
bsf PORTA,0
return

;Flanco de bajada
lE2
nop
bcf PORTA,0
nop
return
;------------------
;Escribir dato.
;------------------
lwd
bsf PORTA,2
bcf PORTA,1
call lE1
return
;---------------------------
;Escribir instrucción.
;--------------------------
lwi
bcf PORTA,2
bcf PORTA,1
call lE1
return
;-----------------------------
;Escribir instrucciones. De 20h a puerto B.
;----------------------------
w20pb
movf 20h,0
movwf PORTB
return
;--------------------------------------------------
;Escribir instrucción de "No operación".
;--------------------------------------------------
lnop
movlw 00h
call winst
return
winst
movwf 20h
call lwi
call w20pb
call lE2
call useg45
return
;----------------------------------------------------
;Escribir inst. de limpiar display y poner a cero el contador de direcciones.
;----------------------------------------------------
lclear
movlw 01h
call winstt
return
winstt
movwf 20h
call lwi
call w20pb
call lE2
call mseg2
return
;---------------------------------------
;Escribir inst. de cursor a casa.
;--------------------------------------
lhome
movlw 02h
call winstt
return
;------------------------------------------
;Escribir inst. de modo de entrada.
;------------------------------------------
;-----------------------------------------------------------------
;El cursor se mueve incremental (I/D= 1) y el display no se desplaza automáticamente (S= 0).
;-----------------------------------------------------------------
lmode10
movlw 06h
call winst
return

;------------------------------------------------
;Escribir inst. del control del display.
;------------------------------------------------
;------------------------------------------------------
;Display on, D= 1; Cursor off, C= 0; B= x.
;------------------------------------------------------
ldisplay10x
movlw 0ch
call winst
return

;-----------------------------------------
;Display off, D= 0; C= x; B= x.
;-----------------------------------------
ldisplay0xx
movlw 08h
call winst
return
;----------------------------------------------------
;Desplazar display o mover cursor (S/C) y especificar dirección (R/L).
;----------------------------------------------------
;---------------------------------------------------
;Desplazar display y no cursor (S/C=1) a la derecha (R/L=1).
;---------------------------------------------------
ldisplayder
movlw 1ch
call winst
return
;------------------------------------------------
;Mover cursor y no dispaly (S/C=0) a la derecha (R/L=1).
;------------------------------------------------
lcursorder
movlw 14h
call winst
return
;---------------------------------------------------------------
;Función Set.
;Configurar la pantalla: bus de 4 o 8 bits (DL),
;1 o 2 líneas (N) y nº de puntos (5x10 o 5x7) (F).
;---------------------------------------------------------------
l8xx
call lwi
movlw 30h
movwf 20h
call w20pb
call lE2
call useg45
return
l817
movlw 30h
call winst
return
;--------------------------------------------------
;Subrutina para colocar datos seguidos
;-------------------------------------------------
wdato
movwf 20h
call lwd
call w20pb
call lE2
call useg45
return
;----------------------------------------------------
;Subrutina para colocar datos en cualquier
;posición de la pantalla: DDRAM address.
;----------------------------------------------------
wdir
addlw 80h
movwf 20h
call lwi
call w20pb
call lE2
call useg45
return

;------------------------------
;Retardos para la LCD.
;------------------------------
;---------------------------
;Retardo de 2 mseg.
;--------------------------
mseg2
call banco0
movlw 0ffh
movwf 30h
movlw 03h
movwf 31h
salto5s
decfsz 30h,1
goto salto5s
decfsz 31h,1
goto salto5s
return

;--------------------------
;Retardo de 6 mseg.
;--------------------------
mseg6
call banco0
movlw 0ffh
movwf 30h
movlw 08h
movwf 31h
salto41s
decfsz 30h,1
goto salto41s
decfsz 31h,1
goto salto41s
return

;---------------------------
;Retardo de 20 mseg.
;---------------------------
mseg20
call banco0
movlw 0ffh
movwf 30h
movlw 1ah
movwf 31h
salto4s
decfsz 30h,1
goto salto4s
decfsz 31h,1
goto salto4s
return

;---------------------------
;Retardo de 45 useg.
;---------------------------
useg45
call banco0
movlw 0fh
movwf 30h
salto6s
decfsz 30h,1
goto salto6s
return

;------------------------------
;Retardo de 150 useg.
;------------------------------
useg150
call banco0
movlw 32h
movwf 30h
salto61s
decfsz 30h,1
goto salto61s
return
;--------------------
;Retardo de 1 seg.
;--------------------
sg1
call banco0
movlw 0c2h
movwf 10h
movwf 11h
movlw 04h
movwf 12h
sal1
decfsz 10h,1
goto sal1
goto recarga1
sal2
decfsz 11h,1
goto sal1
goto recarga2
sal3
decfsz 12h,1
goto sal1
return
recarga1
movlw 0c2h
movwf 10h
goto sal2
recarga2
movlw 0c2h
movwf 11h
goto sal3
;------------------
;Retardo de 5 seg.
;------------------
sg5
call sg1
call sg1
call sg1
call sg1
call sg1
return

;------------------------------------------
;Subrutinas de cambios de bancos.
;------------------------------------------
banco0
bcf STATUS,RP0
return
banco1
bsf STATUS,RP0
return

END
PRÁCTICA nº 11
Hacer funcionar en ambos sentidos un motor paso a paso unipolar mediante dos pulsadores.

Motor unipolar paso a paso tiene la siguiente configuración:

Dispone de cuatro bobinas puenteadas, o puenteadas dos a dos (puentealas tú) o ninguna puenteada (
puentealas las cuatro). El problema es saber la secuencia de activación del motor. O buscas el motor en la red o
lo haces experimentando.

Experimentando:
1. Leer la tensión y ohmios en el motor para saber la intensidad que consume, aplica la ley de Ohm.
2. Para un experimento inicial busca un motor con bastantes ohmios, cientos de ohmios. Usa tensiones
entre 5 y 12 voltios, si no pone tensión en el motor.
3. En las impresoras de inyección los puedes encontrar.
4. Simplemente dando tensión manualmente averigua la secuencia hacia la derecha y por tanto, hacia la
izquierda.
5. Elegir un integrado o transistores que conmuten bien las bobinas y poner diodos de recirculación a cada
bobina.
El motor que usaré es de un impresora de tinta con las características siguientes:
MARCA: NMB PM42S-048-ML06 (MINEBEA).
No pone voltaje, ohmios ni corriente. Búscalo en la red o experimenta.Dispone en su conector una disposición
bastante aclaratoria:
Midiendo entre rojo y marrón o negro, da unos 90 ohmios. Igual entre rojo y naranja o amarillo.

La secuencia para paso completo es la siguiente:

NEGRO MARRÓN NARANJA AMARILLO

1 + +
2 + +
3 + +
4 + +

Si le damos pesos y le adjudicamos un pin en el PIC, en el puerto B:

RA3 RA2 RA1 RA0

8 4 2 1

Los valores hexadecimales a sacar por el puerto B, haciendo los bits altos igual a cero:
1 0Ah
2 09h
3 05h
4 06h

El buffer ULN 2803 invierte por lo tanto los valores serán: F5h, F6h, FAh y F9h. Sólo nos queda elegir un
integrado que disipe esa corriente que consume el motor. Elijo el ULN 2803, capaz de aguantar cada transistor
en colector abierto hasta 500 mA
; ;------------------------------------------------------------------------------
;PROGRAMA COMPROBADO:
;Manejo de un motor paso a paso unipolar.
;Según pulsador, giro a derechas o a izquierdas.
;------------------------------------------------------------------------------
;PIC 16F84A/ 4 MHz/
;Bits de configuración para el programador:
;CP(protección de la memoria de código):..............................No
;PWRTE(activación del temporizador "Power-up"):..............No
;WDTE(activación del "perro guardián"):...............................No
;FOSC1-FOSC0(tipo de oscilador):........................................Xtal
;------------------------------------------------------------------------------
;PROGRAMA

LIST p=16f84A
INCLUDE "p16f84A.inc"
ORG 00h
goto inicio
ORG 10h
inicio
;Configurar el Puerto B como salida.
;ponerlo a cero
call banco1
movlw 00h
movwf TRISB
call banco0
movlw 00h
movwf PORTB

;Configurar el Puerto A como entrada.


call banco1
movlw 0ffh
movwf TRISA
call banco0

;Configurar registro de subrutinas de giro.

clrf 31h; registro 31h hace de puntero de la tabla

;Programa principal.

derecha
btfss PORTA,0
goto izquierda
call der
goto derecha
izquierda
btfss PORTA,1
goto derecha
call izq
goto izquierda

;----------------------------------
;Subrutinas de giro a derecha e
;izquierda del motor.
;----------------------------------
izq
incf 31h,1; incremento puntero
movlw 0fh; elimino bits altos
andwf 31h,1; AND de 31h con valor 0Fh
movf 31h,0; guardo en W
call tabgiro; tabla de los valores de secuencia del motor
movwf PORTB ; envio al puerto B

call msg1; retardo de 1 milisegundo


return

der
decf 31h,1; decremento el puntero
movlw 0fh
andwf 31h,1
movf 31h,0
call tabgiro
movwf PORTB
call msg1
return

tabgiro
addwf PCL,1
retlw 0f9h
retlw 0fah
retlw 0f6h
retlw 0f5h

retlw 0f9h
retlw 0fah
retlw 0f6h
retlw 0f5h

retlw 0f9h
retlw 0fah
retlw 0f6h
retlw 0f5h

retlw 0f9h
retlw 0fah
retlw 0f6h
retlw 0f5h
;-------------------------
;SUBRUTINAS DE TIEMPOS.
;-------------------------
;0c1h=193 goto= 2 useg
;decfsz= 1 useg o 2 useg si el PC es modificicado o
;la condición es verdadera
;(decfsz= 1 useg) + (goto= 2 useg)= 3 useg.
; 3 x 193 = 579
; 579 x 579 = 335241 useg.
; 335241 x 3 = 1005723 useg.

sg1
call banco0
movlw 0c1h
movwf 10h
movwf 11h

movlw 03h
movwf 12h

salto1
decfsz 10h,1
goto salto1
goto recarga1

salto2

decfsz 11h,1
goto salto1
goto recarga2

salto3

decfsz 12h,1
goto salto1

return

recarga1

movlw 0c1h
movwf 10h
goto salto2

recarga2
movlw 0c1h
movwf 11h
goto salto3

;----------------
;1 milisegundo.
;----------------
msg1

call banco0
movlw 0ffh
movwf 10h
movlw 40h
movwf 11h

sal
decfsz 10h,1
goto sal

call sal1
decfsz 11h,1
goto sal
return

sal1
movlw 0ffh
movwf 10h
return

;----------------
;10 milisegundo.
;----------------
msg10
call banco0
movlw 0ffh
movwf 10h
movlw 80h
movwf 11h
sal2
decfsz 10h,1
goto sal2
call sal3
decfsz 11h,1
goto sal2
return

sal3
movlw 0ffh
movwf 10h
return
;-----------------------------------
;SUBRUTINAS DE CAMBIO DE BANCOS.
;-----------------------------------
banco0
bcf STATUS,IRP
bcf STATUS,RP1
bcf STATUS,RP0
return
banco1
bcf STATUS,IRP
bcf STATUS,RP1
bsf STATUS,RP0
return
banco2
bsf STATUS,IRP
bsf STATUS,RP1
bcf STATUS,RP0
return
banco3
bsf STATUS,IRP
bsf STATUS,RP1
bsf STATUS,RP0
return

END

You might also like