Si Ud. no quiere armar el entrenador completo (que sirve para un sinf n de aplicaciones que se ense an en el Curso: Todo Sobre PICs , que est en ven- ta en varios pa ses de Am rica a trav s de la red de distribuidores de Editorial Quark y Centro Ja-
pon s - vea en Inter- net la direcci n: www.webelectroni- ca.com.ar) le propo- nemos que arme s - lo lo imprescindible para encender los leds seg n el circuito de la figura 3; un cir- cuito tan simple que no requiere plaque- ta, puede armarse ti- po ara a sobre la mesa de trabajo, Fig. 2 Fig. 2 Fig. 3 Fig. 3
porque no es algo para mostrar sino para aprender. Observe que los leds est n conectados directamente al puerto B predispuesto como de salida por el pro- grama. En efecto, el puerto de salida admite perfectamente los 3mAque toma cada led al conectarlos con resistores en serie de 1k5. Como nica precauci n para el armado debe utilizar un z calo de 18 patas para el PIC. Las conexiones de X1, C1 y C2 deben ser lo m s cortas posibles. Si usted repara TV y video- grabadores seguramente tendr cristales de 3,58MHz (de PALN o NTSC o in- clusive de PALM). Puede utilizarlos sin mayor inconveniente pero recuerde que los tiempos calculados estar n afectados de un coeficiente igual a 3,58/4.
Nuestro programa va a hacer uso de lo que se llama una subrutina. Una su- brutina es como un segundo programa anexo al principal. El programa principal va a la subrutina a trav s de una instrucci n "CALL" que no hab amos emplea- do hasta ahora.
Esta instrucci n salta del paso del programa donde se encuentra, a la su- brutina y cuando se ejecuta por completo vuelve al mismo punto del programa en donde se hab a producido el salto.
Una subrutina debe estar siempre dirigida a una etiqueta para que el salto se realice con un destino bien determinado. Por lo general, las subrutinas se es- criben a continuaci n del programa principal, pero esto es simplemente una costumbre, bien podr an ubicarse en otro lugar como el principio. Recuerde que todo comienza cuando se pulsa reset o cuando se enciende el equipo y, en ese momento, se ejecuta lo indicado con la etiqueta reset y se salta al rengl n si- guiente. Cuando termina una subrutina, se debe colocar una referencia "RE- TURN", que significa retornar al siguiente rengl n del programa principal don- de est la invocaci n a la subrutina.
Otra instrucci n nueva que no hab amos utilizado es "decfsz" que siempre va acompa ada de un n mero hexadecimal. Esta instrucci n se utiliza para programar retardos. Por ejemplo, si su paso del programa fuera:
CONST equ 06
decfsz CONST
En el encabezado se declara que la variable CONST estar en la direcci n 06 luego, al ejecutarse la instrucci n el contenido de la variable CONST se ha decrementado en una unidad.
Esto parece m s una complicaci n sin sentido, pero no es as ; en un pro- grama bien estructurado los cambios se realizan en el encabezado y, adem s, muchas veces es necesario cambiar solidariamente varios operandos y el m - todo propuesto lo logra f cilmente.
una subrutina (generalmente la cierra). Se trata de "retlw" que debe ir acompa- ado de un literal (n mero hexadecimal). Esta operaci n carga el registro w con el literal que lo acompa a y retorna al programa principal todo en un solo ren- gl n. Su funcionamiento se apreciar mejor cuando veamos el programa de aplicaci n pero es equivalente a:
movlw 0x12 ; cargo a W con el n mero 12h
return
Aesta altura Ud. debe recordar unas cuantas sentencias y todav a faltan unas cuantas m s (recuerde todo lo visto en el cap tulo 2). Como ayuda para que no deba estudiar todas las sentencias de memoria le decimos que lo me- jor es relacionarlas con palabras comunes del idioma ingl s. Por ejemplo "equ" proviene de "equal" que significa igual. En la figura 4 le damos una tabla con m s ayudas.
Para dise ar un programa usted debe tener en claro la funci n del proyec- to. En nuestro caso queremos que al encender la fuente el led conectado a RB0 se encienda y apague con un tiempo que pueda modificarse f cilmente para al- terar el programa. Al apretar el pulsador de reset se debe apagar el led y al sol- tarlo se encender luego de un retardo y continuar alternando per odos de en- cendido y apagado.
Fig. 4 Fig. 4
El programa completo lo vamos a dividir en dos partes: un programa princi- pal y una subrutina que llamamos retardar . Los hacemos as porque casi to- dos los programas incluyen retardo y el dise o de esa subrutina lo podemos emplear posteriormente y nos ahorraremos trabajo.
Un programa debe estar estructurado en forma clara, se deben diferenciar claramente los distintos sectores y esto se hace no s lo para que sea agrada- ble a la vista, sino para facilitar los futuros cambios.
La primera secci n es el t tulo y la declaraci n de qu PIC se va a utilizar. La segunda es el encabezado en donde se le da nombre a los literales (n me- ros hexadecimales) m s importantes. La tercera es el programa principal y la cuarta las subrutinas:
;=========================================================== ; Secuenciador de encendido de un led
list p=16C84 ;micro PIC16C84
;===========================================================
portb equ 06 ;el puerto b se ubica en la dirección de
;memoria RAM06
reg1 equ 0c ;asignación de los registros donde se cargan los
reg2 equ 0d ;diferentes literales
reg3 equ 0e ;
grueso equ 40 ;al literal 40 lo llamamos grueso
medio equ 40 ;al literal 40 lo llamamos medio
fino equ 50 ;al literal 50 lo llamamos fino
;===========================================================
reset org 0 ;un reset envía a la posición 00 de la memoria
;de programa.
Goto comienzo ;reenvío al comienzo del programa
;===========================================================
Analicemos el encabezado, las primeras l neas hasta la etiqueta portb ya las conocemos del programa anterior (aqu empleamos portb en lugar de ptob). Luego tenemos tres sentencias que le dan nombre reg1, reg2 y reg3 a tres re- gistros de uso general, ubicados en las posiciones de memoria RAM destina- das a los registros. Recuerde que las primeras 12 posiciones de memoria has- ta 0B est n ocupadas por registros fijos. Apartir de 0C se ubican los registros de prop sitos generales de los cuales usaremos 3, a saber: 0C, 0D y 0E (que son los registros que hemos denominado reg1, reg2 y reg3).
En esos registros volcamos inicialmente los literales 30, 40 y 50 que nom- bramos como grueso , medio y fino . Esto se realiza en las tres ltimas sen- tencias del encabezado que son aquellas que Ud. debe variar si desea que el
ritmo de encendido se haga m s lento o m s r pido. Desde luego que estas tres sentencias no son imprescindibles pero si no se usan, luego habr a que buscar dentro de la subrutina para cambiar los literales. Trabajando de esta ma- nera es m s f cil introducir cambios porque los hacemos desde el encabezado. La secci n principal del programa es muy similar a la utilizada en el primer programa para encender permanentemente un led:
reset org 0 ;un reset envía el programa a la posición 0
goto comenzar ;se envía el control al comienzo
comenzar movlw 00 ;se carga w con 00
tris ptob ;se programa el puerto b como salida
ppal movlw 01 ;se carga w con 01
movwf ptob ;se descarga w en el puerto b para
;encender el led conectado RB0
call demora ;se mantiene el led encendido por
;un intervalo de tiempo
movlw 00 ;se carga w con 00
movwf ptob ;se descarga w en el puerto b para
;apagar el led de RB0
call demora ;se mantiene el led apagado por
;un intervalo de tiempo
goto ppal ;continua el programa en el principio
;hasta realizar un reset
Siempre se comienza a analizar el programa observando qu ocurre al rea- lizar un reset. En este caso, vemos que todo comienza en la posici n 00 de la memoria de programa. En la siguiente posici n se env a el control del progra- ma a la posici n comenzar , en donde se predispone el puerto b para operar como salida. Luego, comienza el programa principal en el etiqueta ppal, en don- de se carga el registro w con el n mero hexadecimal 01. Cuando este n mero se descarga en el puerto b se enciende el led conectado en RB0.
Ahora se env a el control a la subrutina demora porque pretendemos que el led quede encendido algo menos de un segundo. Cuando se cumpla ese tiempo volver el control desde demora continuando por la carga de w con el hexadecimal 00. Al descargar w en el punto b se produce el apagado de led conectado en RB0.
Nuevamente el control pasa a la subrutina demora, en donde se queda por algo menos de 1 segundo antes de volver al programa principal. Cuando vuel- ve es enviado de inmediato al comienzo de ppal con un nuevo encendido de RB0 y as permanentemente hasta que se opere el reset.
Es el turno de platicar sobre la subrutina demora. Esta subrutina es m s complicada que el programa principal. Lo que ocurre es que la dise amos pa-
ra uso general, ya que la vamos a aplicar en una infinidad de programas. En principio, la demora la vamos a poder variar con tres n meros hexadecimales que fueron definidos en el encabezamiento como grueso , medio y fino por- que operan de ese modo sobre el retardo final:
demora movlw grueso ;recarga w con el número hexadecimal
;“grueso” es decir, con 30
movwf reg1 ;se vuelca “grueso” en el registro
;reg 1
dem3 movlw medio ;se carga w con el número hexadecimal
;“medio” es decir con 40
movwf reg2 ;se vuelca "medio" en el registro
;reg2.
dem2 movlw fino ;se carga w con el número hexadecimal "fino"
;es decir con 50.
movwf reg3 ;se vuelca "fino" en el registro reg3.
dem1 decfsz reg3 ;se decrementa el registro reg3 en una unidad
;y si el resultado es cero se salta a la siguiente ;instrucción, si no se sigue decrementando.
goto dem1 ;retorno a la frecuencia etiqueta dem1.
decfsz reg2 ;idem con reg2.
goto dem2 ;retorno a la etiqueta dem2.
decfsz reg3 ;idem con reg1.
goto dem1 ;retorno a la etiqueta dem3.
retlw 0 ;se carga w con 0 y se retorna al programa
;principal end
La subrutina comienza cargando los registros de uso general con los n me- ros hexadecimales declarados en el encabezado. Luego que los tres registros especiales est n cargados con los hexadecimales 30, 40 y 50 se comienza a decrementar el registro 3 de a una unidad; mientras el registro tenga un n me- ro mayor o igual a 1 se contin a este proceso, pero al llegar a cero se salta a la siguiente sentencia que justamente es un "goto". Es como si el control retor- nara y fuera a dem1 tantas veces como lo indica el n mero hexadecimal carga- do en el registro 1. Luego la subrutina pasa a la siguiente sentencia que co- mienza a decrementar el n mero cargado en reg2, s lo que el "goto" es a la eti- queta dem2 que es anterior a la dem1, es decir, que se vuelve a pasar por "dem1" a hacer todo el primer decremento del n mero guardado en "reg3" y re- ci n despu s se hace el siguiente decremento en el registro "reg2". Cuando "reg2" llega a cero se produce el primer decremento de "reg3" y para que se produzca el segundo tienen que decrementarse a cero "reg2". En una palabra, que la subrutina da much simas vueltas sobre "dem 1", muchas sobre "dem2"
y pocas sobre "dem3". Finalmente cuando "reg3" llega a cero, se pasa retlw que reenv a el control al programa principal justo en la sentencia que invoc a la subrutina pero antes de retornar lleva el registro w a cero. El programa ter- mina en "end" que no puede considerarse como una sentencia, ya que no rea- liza ninguna tarea; sin embargo, su existencia es imprescindible para que el programador de PICs d por terminada su tarea. Cuando no se coloca el pro- grama ensamblador emite un mensaje de error.
Tenga en cuenta que le estamos ense ando a programar , es decir, a utili- zar las instrucciones del set del PIC. Si Ud. es programador, estos ejemplos le van a parecer muy torpes, dado que el experto sabe c mo utilizar rutinas que permitan hacer lo mismo con menos esfuerzo de programaci n. Ud. est apren- diendo como cuando comenz a sumar y en aquella oportunidad seguramente le costaba entender que 1 + 1 es igual a dos, aunque hoy le parezca un ejem- plo muy burdo.
Volviendo a nuestro programa, sabemos que la subrutina "demora" tiene una cierta duraci n. Con un m nimo conocimiento de matem ticas podemos calcular ese retardo en funci n de los n meros hexadecimales que hallamos elegido.
Tomemos primero el "loop" (rulo) m s interno de la subrutina; mientras no se cumpla que "reg 3" = 0 se consume un ciclo de instrucci n por vuelta (gen ri- camente podemos decir que todas las sentencias consumen un ciclo salvo las de salto como la "goto" que consume dos).
N mero de ciclos "reg 3" = 3 x "grueso" = 3 x 80 (ya que 50 Hex = 80 decimal) = 240 ciclos de instrucci n
Para calcular la demora de los dos loops siguientes es conveniente realizar un diagrama de los mismos tal como el mostrado en la figura 5.
Ahora vemos que el loop intermedio dura 2 + 1 + 1 + 1 = 5 ciclos de instruc- ci n a los cuales se les suman los 240 ciclos del loop m s interno. En total se- r an 5 + 240 = 245. Pero este loop es recorrido hasta que el hexadecimal 40 (equivalente al decimal 64) se anule:
n mero de ciclos "reg 2" = 245 x medio = 245 x 64
= 15.860 ciclos de instrucci n.
El loop m s externo dura 2 + 1 + 1 + 1 = 5 ciclos de instrucci n a los cuales se les suman los 15.860.
Pero este loop es recorrido hasta que el hexadecimal 40 (equivalente al de- cimal 64) se anule:
n mero de ciclos "reg 1" = 15.860 x fino = 15.860 x 64
= 1.015.040 ciclos de instrucci n.
Nos quedar an 1 + 1 ciclos al comien- zo de la subrutina y 2 ciclos al final para llegar a un valor de 1.015.044 ciclos de instrucci n.
La duraci n de un ciclo de instrucci n depende del cristal utilizado. Si usamos un cristal de 4MHz cada ciclo de instruc- ci n dura 1 s y tendr amos una demora de 1,015 seg.
El led estar a encendido casi un se- gundo y apagado otro tanto.
El funcionamiento del programa princi- pal y la subrutina de demora pueden re- presentarse en un diagrama de flujo co- mo el mostrado en la figura 6 para el pro- grama principal.
Fig. 5 Fig. 5
Fig. 6 Fig. 6