Вы находитесь на странице: 1из 24

Aprendiendo a programar PICs en BASIC

Introduccin

Aprende BASIC!
Esta guia o tutorial esta dedicada al lenguaje de programacin PIC BASIC incluido en el PIC
SIMULATOR IDE, y puede ser til para aquellos que estn aprendiendo a utilizar otros dialectos de
BASIC de microcontroladores, como PIC BASIC PRO (PBP) o PROTON, ya que se parecen
mucho.
NOTA: Este artculo forma parte de la Revista uControlNumero 1, Numero 2 y Numero 3.

Tabla de contenidos
[esconder]
1 Introduccin
2 Variables
2.1 Tipos
2.2 DIM
3 RESERVE
4 Puertos
5 Punteros
6 SYMBOL
7 GOTO
8 Operaciones Lgicas y
Matemticas
9 Mi primer programa:
Un LED parpadeando
10 Mi segundo
programa: Usando un
pulsador
11 IF - THEN - ELSE ENDIF
11.1 CASO 1
11.2 CASO 2
11.3 CASO 3
12 FOR - TO - STEP NEXT
13 WHILE - WEND
14 LOOKUP
15 SHIFTLEFT y
SHIFTRIGHT
16 Displays LCD
16.1 LCD
alfanumricos
17 Temas relacionados
18 Revista uControl
19 Autor

Variables
Vamos a comenzar a ver algo de la programacin en el BASIC incluido en el entorno PIC
SIMULATOR IDE, al que en adelante nos referiremos como "BASIC", a secas.
La programacin seria prcticamente imposible sin el uso de variables. Podemos hacernos una
imagen mental de las variables consistente en una caja en la que podemos guardar algo. Esa caja es
una de las muchas que disponemos, y tiene en su frente pegada una etiqueta con su nombre. Estas
cajas tienen ciertas particularidades, que hace que solo se puedan guardar en ellas determinados
tipos de objetos.

En esta analoga, cada caja es una variable, su contenido es el valor que adopta, y la etiqueta es el
nombre de la variable. Como su nombre lo indica, y como veremos mas adelante, el contenido de
una variable puede ser modificado a lo largo del programa.

Tipos
En BASIC tenemos distintos tipos de variables, segn el dato que puedan almacenar:
Bit (un bit de longitud, almacena 0 o 1 nicamente)
Byte (un byte de longitud, almacena nmeros enteros entre 0 y 255)
Word (dos bytes de longitud, almacena nmeros enteros entre 0 y 65,535)
Long (cuatro bytes de longitud, almacena nmeros enteros entre 0 y 4,294,967,295)

El tipo "Long" solo esta disponible mediante un modulo opcional al PIC SIMULATOR IDE. A
diferencia de otros BASIC, la declaracin de variables puede ser hecha en cualquier parte del
programa, y todas son consideradas globales, es decir, su valor es accesible desde todas las
subrutinas y zonas del programa. El numero de variables esta lgicamente limitado al monto de
memoria RAM disponible en cada microcontrolador.

DIM
Las variables deben ser declaradas antes de utilizarlas, mediante la instruccin DIM, como se
muestra en los siguientes ejemplos:
DIM
DIM
DIM
DIM

A
B
X
Y

AS
AS
AS
AS

BIT
BYTE
WORD
LONG

Tambin es posible utilizar vectores, que son una matriz de dimensiones 1xN . Por ejemplo, la
sentencia siguiente:
DIM A(10) AS BYTE

declara un vector (al que nos referiremos algunas veces como "array") de diez elementos del tipo
BYTE, que sern accedidos mediante el uso de subndice (entre parntesis) del 0 al 9.
Las variables tipo Word, como vimos, estn compuestas por dos bytes. el primero de ellos es
llamado byte "alto" y el otro "bajo", dado que el primero contiene los 8 bits mas significativos. En
BASIC podemos acceder individualmente a cada uno de los bytes que componen un Word mediante
las extensiones ".HB" (High byte, o byte alto) y ".LB" (Low Byte o byte bajo) . Veamos un
ejemplo:
DIM A AS BYTE
DIM B AS WORD
A = B.HB
A = B.LB 'Esto es lo mismo que A = B
B.HB = A
B.LB = A
B = A 'Esto tambin borra el byte alto de la variable B

Los bits individuales de cada variable pueden ser accedidos individualmente tambin, simplemente
poniendo como extensin ".n" donde "n" es el numero de bit (1,2, 3, etc. )
DIM A AS BYTE
DIM B AS BIT

B = A.1
B = A.7
A.0 = A.5

RESERVE
La sentencia RESERVE le permite al programador reservar un numero de posiciones de la RAM
para su uso en rutinas en assembler o para el In-Circuit Debugger de MPLAB. Simplemente, si
queremos reservar 20 bytes de RAM, escribimos:
RESERVE 20

Puertos
Todos los registros del microcontrolador esta disponibles para usar en los programas BASIC, como
si se tratase de variables del tipo BYTE con el nombre del registro utilizado en las datasheet
(PORTA, PORTB, TRISA, etc.). Por supuesto, se puede acceder a bits individuales de los registros
con la tcnica vista prrafos atrs. Algunos ejemplos:
TRISA.1 = 0
TRISB = 0
PORTA.1 = 1
PORTB = 255
STATUS.RP0 = 1
INTCON.INTF = 0

Existe una "forma corta" de acceder a los bits individuales de cada port, simplemente usando las
variables BASIC tipo byte RA, RB, RC, RD, RE o bien las tipo bit RA0, RA1, RA2, ..., RE6, RE7
RA = 0xFF
RB0 = 1

Punteros
En BASIC tambin podemos usar punteros. En realidad, cualquier variable definida como tipo
BYTE o WORD pude ser usada como un putero de memoria, usndola como argumento de la
funcin POINTER. El valor contenido por la variable debe tener un valor comprendido entre 0 y
511. Ejemplos:
DIM X AS WORD
DIM Y AS BYTE
X = 0x3F
Y = POINTER(X)
Y = Y + 0x55
X = X - 1
POINTER(X) = Y
Y = 0xAA
X = X - 1
POINTER(X) = Y

SYMBOL
Una forma de escribir programas que nos resulten mucho mas fciles de entender es el uso de
nombres simblicos, o SYMBOL. Un "symbol" es una cadena que contiene cdigo, asignado a un
nombre. Al momento de compilar, PIC BASIC hace la "bsqueda y reemplazo" de nuestros
smbolos y luego genera el cdigo ASM y el HEX. Supongamos que tenemos un LED conectado al
bit cero del puerto B. Mediante SYMBOL podemos hacer:
SYMBOL LED1 = PORTB.0

Luego, si queremos encender el LED, en lugar de


PORTB.0 = 1

podemos hacer
LED1 = 1

que es mucho mas claro y fcil de leer. Por supuesto, el cdigo que aparece a la derecha del igual no
puede contener instrucciones o comandos.
Las constantes (valores que usamos en nuestro programa, y que, por ejemplo, asignamos a las
variables) pueden ser escritas en decimal (directamente el valor), en hexadecimal (anteponiendo
"0x" o posponiendo "H" al valor) o en binario (anteponiendo "%" al valor). Por ejemplo:
DIM
DIM
A =
B =
B =

A AS BIT
B AS BYTE
TRUE
0x55
%01010101

Por supuesto, se pueden asignar nombres a las constantes, usando la instruccin CONST:
DIM A AS WORD
CONST PI = 314
A = PI

Hay tres instrucciones para el manejo individual de bits, que si bien no hacen nada que no se puede
resolver con otras instrucciones o smbolos, ayudan mucho en la lectura del cdigo. Se tratan de
HIGH, LOW y TOGGLE, que ponen el bit en alto, bajo o lo invierten, respectivamente. Importante:
Si el bit implicado como argumento de una de estas instrucciones es un bit de un PORT, el mismo
bit en el TRIS correspondiente es puesto en cero, y dicho pin queda configurado como salida.
Algunos ejemplos:
HIGH PORTB.0
LOW ADCON0.ADON
TOGGLE OPTION_REG.INTEDG

GOTO
Esta es una de las instrucciones ms polemicas que se encuentra en todos los dialectos BASIC.
GOTO significa literalmente "IR A", y sirve justamente para eso: desviar el flujo del programa a
otro punto.
Para usar GOTO, es necesario poner una etiqueta en el lugar al que queremos "saltar". Las etiquetas

son simplemente nombres terminados en ":", tal como se ve a continuacin:


...
...
calculos:
...
...
...
...
...
GOTO calculos
...
...

En el ejemplo anterior, el programa se ejecutar hasta encontrar la instruccin "GOTO calculos",


que hara que se ejecuten nuevamente las instrucciones siguientes a la etiqueta "calculos:". Cabe
aclarar que las etiquetas no son un cdigo ejecutable, es decir, no realizan ninguna accin, solo son
un "marcador" del lugar al que se puede saltar con GOTO.

Operaciones Lgicas y Matemticas


PIC SIMULATOR IDE dispone de cinco operaciones matemticas bsicas, disponibles para las
variables tipo Byte y Word. Estas son la suma (operador +), la sustraccin (operador -), el producto
(operador *), el cociente (operador /) y el mdulo (operador MOD) .Por supuesto, el compilador es
capaz de combinarlas para obtener operaciones matemticas mas complejas.
DIM
DIM
DIM
A =
B =
X =
X =

A AS WORD
B AS WORD
X AS WORD
123
A * 234
2
(12345 - B * X) / (A + B)

Es posible calcular races cuadradas (aunque el resultado debe ser entero) con la funcin SQR:
DIM A AS WORD
A = 3600
A = SQR(A)

Para las variables de tipo Bit existen siete operaciones lgicas disponibles. Solo es posible efectuar
una operacin lgica por instruccin (aunque es muy posible que prximas versiones permitan mas
flexibilidad. Este al tanto de las novedades!). Estas operaciones tambin estn disponibles para
variables tipo Word o Byte. Veamos algunos ejemplos:
DIM
DIM
DIM
X =
X =
X =
X =
X =
X =
X =

A AS BIT
B AS BIT
X AS BIT
NOT A
A AND B
A OR B
A XOR B
A NAND B
A NOR B
A NXOR B

DIM A
DIM B
A = A
PORTB

AS WORD
AS WORD
OR B
= PORTC AND %11110000

Mi primer programa: Un LED parpadeando


Luego de estos captulos de introduccin, puramente tericos, vamos a encarar nuestro primer
programa. A diferencia de un programa de ordenador, donde uno escribe el programa, lo compila, lo
ejecuta y ya, en el mundo de los microcontroladores hay que, previamente, definir el tipo de
microcontrolador que se va a utilizar, cual va a ser su frecuencia de clock, como va a ser el circuito
en que se va a utilizar el mismo, etc.
Para estas practicas, utilizaremos un PIC16F628A, uno de los mas difundidos y que mas o menos
viene a reemplazar al viejo y popular PIC16F84A, ya obsoleto. El diagrama circuital que
utilizaremos para las primeras practicas es el siguiente:

Si bien se supone que quien esta leyendo este tutorial tiene una buena idea sobre electrnica y
microcontroladores (si no, puede leer el resto de uControl), igualmente vamos a hacer una muy
breve descripcin del circuito.

En primer lugar, vamos a aprovechar el oscilador interno del PIC16F628Ay nos evitaremos el xtal y
condensadores asociados. El puerto B del micro (pines 6 al 13) esta conectado a 8 LEDs mediante 8
resistencias de 220ohms, que tienen como funcin limitar la corriente que circula por los LEDS.
Estos sern nuestras "salidas". Los pines 17 y 18, correspondientes al PORTA.0 y PORTA.1 estn
conectados a sendos pulsadores, que al ser presionados conducen 5V (un "1") al pin respectivo.
Cuando estn en reposo, las resistencias R1 y R2 se encargan de mantener el pin en "0". Por ultimo,
el pin 1 (PORTA.2) comanda un parlante mediante un transistor, para hacer alguna prueba con
sonidos.
El circuito debe alimentarse con 5v bien filtrados y regulados.
Volviendo a nuestro programa, vamos a escribir el "hola mundo" de los microcontroladores:
encender un LED.
El primer paso es, desde el men "Opciones" -> "Select Microcontroller", elegir el PIC16F628A.

Luego, debemos configurar los bits correspondientes:

Lo destacable por ahora de esta configuracin es que estamos dejando la memoria (FLASH y
EEPROM) sin proteccin, que el pin RESET se va a comportar como I/O y que usaremos como
oscilador el oscilador interno INTRC.
Una vez hecho esto, arrancamos el edito de BASIC (presionando CTRL-C, por ejemplo), y
escribimos el siguiente cdigo:
AllDigital
TRISA = %11111111
TRISB = %00000000
loop:
PORTB.0 = 1
WaitMs 500
PORTB.0 = 0
WaitMs 500
Goto loop

Vamos a analizarlo lnea por lnea para entender su funcionamiento:


La lnea 001 utiliza la sentencia AllDigital para convertir todos los pines del micro en pines de E/S.
Esto equivale a deshabilitar los comparadores, conversores A/D y todos los mdulos que pudiese
tener nuestro microcontrolador. No es la nica manera de hacer esto, pero si la mas sencilla desde el
punto de vista del programador BASIC.

Las lneas 003 y 004 convierten todos los pines del puerto A en entradas ( TRISA = %11111111 ) y
los del puerto B en salidas ( TRISB = %00000000 ). El "%" indica que el numero que viene a
continuacin esta en binario. Se podra haber escrito, por ejemplo TRISB = 0 y hubiera sido lo
mismo. Personalmente me gusta esta manera, ya que "veo" el estado de cada pin. Por supuesto, es
valido activar como entrada algunos pines, y como salidas otros, haciendo algo parecido a TRISB =
%11000111.
En la lnea 006 encontramos una "etiqueta" ( loop: ). Esta no hace nada, solo sirve como referencia
para enviar el flujo del programa a esa lnea desde otro lugar, mediante la sentencia "Goto".
La lnea 007 pone en "1" el pin correspondiente a PORTB.0, de manera que en el pin 6 del
microcontrolador habr 5V. Esta tensin har que circule una corriente a travs de la resistencia
limitadora y el LED1, haciendo que este se encienda, ya que el ctodo se encuentra conectado a 0V.
En 008 tenemos la sentencia WaitMs 500 . WaitMs se encarga de hacer una pausa en milisegundos.
La duracin de la pausa esta dada por el numero que sigue a la instruccin, en este caso 500
milisegundos, o medio segundo.
Luego, en 009, otra vez se vuelve a poner en 0 el pin 6, mediante PORTB.0 = 0 , lo que provoca que
ese pin se ponga a 0V, y no haya mas circulacin de corriente a travs de la resistencia y del LED,
con lo que este se apaga.
En 010 se hace nuevamente una pausa de medio segundo, y por ultimo, la lnea Goto Loop hace que
el programa contine en la lnea 006 (que es donde esta la etiqueta Loop).
El programa se repite indefinidamente, encendiendo el LED medio segundo, apagndolo otro medio
segundo.
Si presionamos F9 o vamos al men que vemos a continuacin:

PIC SIMULATOR IDE compilara el programa, y cargara el HEX resultante en el simulador.


Aparecer el cuadro de dialogo siguiente, en donde se nos informa entre otras cosas que no han
ocurrido errores, el tamao del programa (69 words), y la ruta a donde se ubicaron los archivos
generados.

Si volvemos a la ventana principal del PIC SIMULATOR IDE, y desde "Tools" -> "Microcontroller
View" abrimos la vista del microntrolador, al darle "Start" a la simulacin tendremos algo parecido
a lo que sigue:

En la captura se puede apreciar que el pin 6, correspondiente a RB0 esta en "ON". Si esperamos lo
suficiente, veremos como pasa a "OFF", y mas tarde vuelve a "ON", etc. Si queremos esperar
menos tiempo, y esto lo debemos tomar como una regla general al correr simulaciones, podemos
disminuir el tiempo indicado en las instrucciones "WaitMS" a valores iguales a 1, de esta manera la
simulacin ser mucho mas gil. Por supuesto, al momento de llevar el HEX a nuestro
microcontrolador en el circuito "real", debemos cambiar a los tiempos originales y volver a
compilar. Caso contrario, el LED permanecera encendido solo una milsima de segundo, luego
apagado el mismo tiempo, etc., por lo que nuestro ojo lo percibira como encendido a medias,
incapaz de discriminar su verdadero estado.
Se podra haber utilizado la instruccin SYMBOL para hacer mas claro el programa. En el siguiente
ejemplo, hemos hecho algunos cambio y obtenido un programa que hace exactamente lo mismo que
el anterior, pero que resulta mas claro de entender, ya que se aproxima algo mas al "lenguaje
natural":

Mi segundo programa: Usando un pulsador


En la segunda practica del lenguaje BASIC veremos como leer una entrada del PIC. Utilizaremos el
mismo esquema que vimos antes, y el programa que mostramos a continuacin:
AllDigital
TRISA = %11111111
TRISB = %00000000
loop:
PORTB.0 = PORTA.0
Goto loop

Como resulta evidente a simple vista, el programa ejemplo2.bas es muy similar al ejemplo1.bas que
vimos en el capitulo anterior. Las diferencias estn dentro del bucle. La instruccin PORTB.0 =
PORTA.0 hace que el valor del bit 0 del PORTB tome el valor del bit 0 del PORTA. Que ambos bits
sean el cero es solo una coincidencia, se podran haber elegido otros valores.
Al ejecutarse el programa, cada vez que se accione el pulsador conectado a PORTA.0, ese pin se
pondr a estado alto, ya que la corriente circulara desde +V al pin 17 del PIC por medio del
pulsador. Ese "estado alto" se interpreta dentro del PIC como un "1", y es el valor que se le asigna a
PORTB.0 , con lo que el tambin pasara a estado alto. Eso provocara que el led conectado en ese
pin se ilumine.
Cuando soltamos el pulsador, PORTA.0 vuelve a estado bajo, ya que se pone a masa a travs de la
resistencia de 10K, y PORTB.0 har lo propio, apagando el LED.
Nuestro sencillo (sencillsimo!) programa todo lo que hace es "copiar" en el LED el estado del
pulsador.

Si presionamos F9 o vamos al men que vemos a continuacin

PIC SIMULATOR IDE compilara el programa, y cargara el HEX resultante en el simulador.


Aparecer el cuadro de dialogo que nos informa que no han ocurrido errores y que el tamao del
programa esta vez es de 20 words.
Si volvemos a la ventana principal del PIC SIMULATOR IDE, y desde "Tools" -> "Microcontroller
View" abrimos la vista del microntrolador, al darle "Start" a la simulacin tendremos algo parecido
a lo que sigue:

El pin 6, correspondiente a RB0 esta en "OFF" por que el pulsador del pin 17 (RA0) esta en OFF. Si
con el mouse hacemos un click sobre la "T" que esta al lado del pin 17, la vista del
microcontrolador pasara al estado que muestra la imagen siguiente:

Recordemos que el botn "T" significa "cambio" (Toggle) por lo que el estado del pin 17
permanecer en alto hasta que lo pulsemos otra vez, y el estado del microcontrolador volver a ser
el inicial. Como en cualquier curso, conviene realizar estas practicas, que aunque puedan parecer
muy sencillas nos ayudaran a conocer las herramientas disponibles y "tomar confianza" al
programa. Tambin es interesante el realizar cambios en el programa BASIC, recompilar y analizar
los resultados.

IF - THEN - ELSE - ENDIF


En cualquier programa medianamente complejo que queramos realizar, seguramente necesitaremos
en algn punto tomar alguna decisin basndonos en el estado de una entrada o en el valor de una
variable. PIC BASIC incorpora instrucciones que nos permiten este tipo de comportamiento,
siendo la mas sencilla y frecuentemente utilizada la sentencia IF - THEN - ELSE - ENDIF.
Existen varias formas de utilizar esta instruccin. Comenzaremos con los casos mas sencillos y a lo
largo de este capitulo iremos agregando complejidad hasta ver todas las posibilidades.

CASO 1
El caso mas simple es el siguiente:
IF condicin THEN instruccin

"IF" significa "SI....", y "THEN" significa "LUEGO" o "ENTONCES". El caso anterior puede
leerse como "SI se cumple la condicin, entonces ejecuto la instruccin"
La "condicin" es una expresin lgica que puede ser verdadera o falsa. En caso de ser verdadera, la
instruccin a continuacin del THEN ser ejecutada. En caso de la condicin sea falsa, el programa
seguir su ejecucin con la instruccin siguiente al "IF - THEN".
Veamos un ejemplo. Supongamos el siguiente programa:
ALLDIGITAL 'Voy a usar todos los pines como E/S.
TRISA = %11111111 'Todo el PORTA como entradas
DIM A AS BYTE 'Declaro la variable "A" como BYTE
DIM TOTAL AS BYTE 'Declaro la variable "TOTAL" como BYTE
'
TOTAL = 10 'Le asigno el valor 10 a la variable "TOTAL"
A = 2 'Le asigno el valor 2 a la variable "A"
'
IF PORTA.4 = 1 THEN A = 4
'
TOTAL = TOTAL + A 'Sumo a "TOTAL" el valor de "A"

Cundo comienza el programa, se declaran dos variables tipo BYTE (que pueden almacenar valores
entre 0 y 255), y a TOTAL se le asigna el valor "0" y a "A" el valor "2". Hasta aqu, no hay nada
que no hayamos visto antes.
La lnea siguiente realiza la siguiente tarea: evala si la condicin PORTA.4 = 1 es cierta. En caso
de que efectivamente el valor presente en el bit 4 del PORTA sea "1", se ejecuta la instruccin a
continuacin del THEN, la variable "A" toma el valor "4", y se pasa a la instruccin de abajo. Si
PORTA es igual a "0", se pasa a la instruccin siguiente sin mas.
El valor final de la variable "TOTAL" depende entonces de cual sea el estado de PORTA.4 al
momento de hacer la evaluacin. Si es igual a "1", "TOTAL" tendr un valor de 14 (10 + 4). Si
PORTA.4 = 0, "TOTAL" tendr un valor de 12 (10 + 2).
Veamos algunos ejemplos validos de este caso:
IF A = B THEN PORTA.0 = 1
IF B > A THEN A = B

IF B = 5 THEN A = 0
IF (A = 0) OR (B = 5) THEN C = 2
IF PORTA.0 THEN PORTB.3 = 0

En el ultimo ejemplo la condicin PORTA.0 equivale a PORTA.0 = 1.

CASO 2
Muchas veces, luego de evaluar la condicin necesitamos ejecutar mas de una instruccin. En los
ejemplos vistos en el CASO 1 siempre se ejecutaba una sola instruccin cuando la condicin era
cierta. La manera de ejecutar mltiples sentencias dentro de una estructura IF-THEN implica
emplear el ENDIF:
IF condicin THEN
instruccin 1
instruccin 2
...
instruccin n
ENDIF

No varia prcticamente nada respecto del primer caso, solo que esta vez se van a ejecutar todas las
instrucciones que se encuentren entre el THEN y el ENDIF cada vez que condicin sea verdadera.
Veamos un ejemplo. Supongamos el siguiente programa:
DIM A AS BYTE 'Declaro la variable "A" como BYTE
DIM B AS BYTE 'Declaro la variable "B" como BYTE
DIM C AS BYTE 'Declaro la variable "C" como BYTE
DIM D AS BYTE 'Declaro la variable "D" como BYTE
DIM TOTAL AS BYTE 'Declaro la variable "TOTAL" como BYTE
'
TOTAL = 0 'Le asigno el valor 0 a la variable "TOTAL"
A = 2 'Le asigno el valor 2 a la variable "A"
B = 5 'Le asigno el valor 5 a la variable "B"
C = 1 'Le asigno el valor 1 a la variable "C"
D = 0 'Le asigno el valor 0 a la variable "D"
'
IF A = 2 THEN
A = B + (C * D)
TOTAL = A * B
ENDIF

El ejemplo anterior, la condicin A = 2 es verdadera (puesto que ese es el valor que le asignamos a
"A" mas arriba), por lo que las dos instrucciones dentro del THEN-ENDIF se ejecutaran. Esto hace
que TOTAL tome el valor de 10 (hagan las cuentitas!). Si "A" hubiese tenido otro valor, esas dos
sentencias no se ejecutaran y TOTAL seguira valiendo "0" al terminar el programa.

CASO 3
Hay veces que de acuerdo a la condicin, queremos ejecutar un grupo u otro de instrucciones. Para
eso, utilizamos el ELSE:
IF condicin THEN

instruccinv
instruccinv
...
instruccinv
ELSE
instruccinf
instruccinf
...
instruccinf
ENDIF

1
2
n
1
2
n

Es decir, si la condicin es verdadera, se ejecutan las sentencias entre THEN y ELSE. Y si la


condicin es falsa, las que estn entre ELSE y ENDIF. "ELSE" puede ser traducido como "en otro
caso" o "si no...".
Veamos un ejemplo. Supongamos el siguiente programa:
ALLDIGITAL 'Voy a usar todos los pines como E/S.
'
TRISA = %11111111 'Todo el PORTA como entradas
DIM A AS BYTE 'Declaro la variable "A" como BYTE
DIM TOTAL AS BYTE 'Declaro la variable "TOTAL" como BYTE
'
TOTAL = 10 'Le asigno el valor 10 a la variable "TOTAL"
A = 2 'Le asigno el valor 2 a la variable "A"
'
IF PORTA.4 = 1 THEN
A = 4
TOTAL = TOTAL + 5
ELSE
A = 0
TOTAL = TOTAL + 15
ENDIF

El ejemplo anterior, la condicin PORTA.4 = 1 determina que bloque de instrucciones se ejecutan.


Si es verdadera, A = 4 y TOTAL = TOTAL + 5 son usadas. Caso contrario se ejecutan A = 0 y
TOTAL = TOTAL + 15. Luego, independientemente de cual haya sido el caso, el programa sigue
con la sentencia que se encuentre a continuacin del ENDIF.
Por ultimo, tenemos que saber que es posible "anidar" instrucciones IF-THEN-ELSE-ENDIF, con
lo que se pueden tomar decisiones verdaderamente complejas. Por supuesto, tenemos que ser cautos
en el uso de esta caracterstica ya que debido a limitaciones en el tamao de la pila y cantidad de
memoria disponible del PIC podemos ocasionar un desborde y el programa colapsara. Este seria un
ejemplo de un anidamiento:
IF PORTB.1 = 1 THEN
IF A = 2 THEN
A = B + (C * D)
TOTAL = A * B
ELSE
A = 0
ENDIF
ELSE
A = 19
ENDIF

Las sentencias en color negro corresponden a una estructura IF-THEN-ELSE-ENDIF y las que
estn en verde a la otra, que se encuentra dentro ("anidada" en) de la primera.

FOR - TO - STEP - NEXT


As como la toma de decisiones que vimos en el capitulo anterior esta presente en casi todos
nuestros programas, las estructuras que permiten repetir un grupo de instrucciones un numero
determinado de veces tambin son indispensables. En PIC SIMULATOR IDE hay dos de ellas.
Veremos en este capitulo la primera, FOR - TO - STEP - NEXT.
Esta estructura necesita una variable (tipo Byte o Word) para funcionar. En cada iteracin del bucle,
la variable va cambiando su valor. Cuando el valor de la variable alcanza o supera el valor
prefijado, el bucle termina. La forma del bucle es la siguiente:
FOR variable = valor_inicial TO valor_final STEP paso
instruccion1
instruccion2
...
instruccionn
NEXT variable

Veamos un ejemplo concreto. Supongamos que queremos sumar los nmeros del 1 al 100. El
programa quedara como sigue:
DIM A AS BYTE
'Declaro la variable "A" como BYTE
DIM TOTAL AS WORD
'Declaro la variable "TOTAL" como WORD
'
TOTAL = 0
'Asigno "0" a la variable "TOTAL".
'
FOR A = 1 TO 100 STEP 1 '"A" va de 1 a 100 de 1 en 1
TOTAL = TOTAL + A
'Sumo "A" al valor de "TOTAL".
NEXT A
'fin del bucle.

Hemos declarado la variable A como BYTE, ya que su valor va a mantenerse en el rango 0..255.
Para TOTAL utilizamos una variable tipo WORD, ya que la suma va a superar el valor mximo de
un BYTE. (Recordemos que WORD permite valores en el rango 0..65535)
El bucle se ejecuta 100 veces, la primera de ellas A vale 1, la segunda 2, la tercera 3, hasta la ultima
en la que vale 100. Ese incremento (1 por ves) esta dado por el valor a continuacin del STEP. En
los casos como este en que STEP vale 1, puede omitirse, como veremos en ejemplos posteriores.
TOTAL comienza valiendo 0 (se le asigna ese valor fuera del bucle) y en cada iteracin se le suma
el valor que tenga A en ese momento. De esa manera, TOTAL va tomando los valores 1, 3, 6, 10, ....
5050.
Tanto valor_inicial como valor_final y paso pueden ser variables. El siguiente trozo de cdigo hace
lo mismo que el anterior, pero usa variables:
DIM A AS BYTE
DIM INICIO AS BYTE
DIM FINAL AS BYTE
DIM PASO AS BYTE
DIM TOTAL AS WORD
'
INICIO = 1
FINAL = 100
PASO = 1
TOTAL = 0
'
FOR A = INICIO TO FINAL
TOTAL = TOTAL + A
NEXT A

'Declaro
'Declaro
'Declaro
'Declaro
'Declaro
'Asigno
'Asigno
'Asigno
'Asigno

la
la
la
la
la

variable
variable
variable
variable
variable

"1" a
"100"
"1" a
"0" a

"A" como BYTE


"INICIO" como BYTE
"FINAL" como BYTE
"PASO" como BYTE
"TOTAL" como WORD

la variable "INICIO".
a la variable "FINAL".
la variable "PASO".
la variable "TOTAL".

STEP PASO '"A" va de 1 a 100 de 1 en 1


'Sumo "A" al valor de "TOTAL".
'fin del bucle.

Y el mismo ejemplo, sin usar STEP:


DIM A AS BYTE
DIM TOTAL AS WORD
'
TOTAL = 0
'
FOR A = 1 TO 100
TOTAL = TOTAL + A
NEXT A

'Declaro la variable "A" como BYTE


'Declaro la variable "TOTAL" como WORD
'Asigno "0" a la variable "TOTAL".
'"A" va de 1 a 100 de 1 en 1
'Sumo "A" al valor de "TOTAL".
'fin del bucle.

Hay casos en que es necesario que el valor de la variable de control del bucle se decremente en
lugar de ir aumentando. En ese caso, se puede usar un valor negativo para STEP. El siguiente
ejemplo cuenta desde 50 hasta 20, de 5 en 5:
DIM A AS BYTE
'Declaro la variable "A" como BYTE
'
FOR A = 50 TO 20 STEP -5 '"A" va de 50 a 20 de 5 en 5
instruccion1
instruccion2
...
instruccionn
NEXT A
'fin del bucle.

De la misma manera que ocurra con IF-THEN-ELSE-ENDIF, pueden anidarse diferentes bucles
FOR-TO-STEP-NEXT , uno dentro de otro:
FOR variable1 = valor_inicial1 TO valor_final1 STEP paso1
FOR variable2 = valor_inicial2 TO valor_final2 STEP paso2
instruccion1
instruccion2
...
instruccionn
NEXT variable2
NEXT variable1

La nica condicin es que un bucle este completamente dentro del otro. El siguiente anidamiento
dara un error en el compilador:
FOR variable1 = valor_inicial1 TO valor_final1 STEP paso1
FOR variable2 = valor_inicial2 TO valor_final2 STEP paso2
instruccion1
instruccion2
...
instruccionn
NEXT variable1
NEXT variable2

Para terminar, veamos el siguiente cdigo:


AllDigital
TRISB = 0
Dim a As Byte
For a = 0 To 15
PORTB = a
Next a

Si se lo corre en el PIC SIMULATOR IDE, puede verse como los primeros 4 bits del PORTB

cuentan en binario de 0 a 15.

WHILE - WEND
La segunda estructura de control que proporciona PIC BASIC es WHILE - WEND. Su propsito es
el mismo que la que vimos en el capitulo anterior, y su estructura es la siguiente:
WHILE condicin
instruccion1
instruccion2
...
instruccionn
WEND

Mientras que la condicin sea verdadera, el grupo de instrucciones dentro del cuerpo del WHILEWEND se ejecuta. Las caractersticas de la condicin son las mismas que vimos en el capitulo 10
para IF-THEN-ELSE-ENDIF.
Por supuesto, si no somos cuidadosos al momento de elegir la condicin, puede darse el caso de que
el numero de repeticiones del bucle sea infinito, y nunca salgamos de el. De hecho, esta
circunstancia se aprovecha en algunos programas para repetir indefinidamente un grupo de
instrucciones. Tambin hay que tener presente que si la condicin no es cierta al momento de
ejecutar la primera vez el WHILE, el flujo del programa pasara directamente a la instruccin
posterior al WEND y las instrucciones dentro del bucle no se ejecutaran ninguna vez.
No hay mucho mas para decir de WHILE-WEND , solo analizar algunos ejemplos:
Ejemplo 1: El siguiente es un bucle infinito. Como dentro del cuerpo del WHILE-WEND no se
cambia el valor de la variable A, esta siempre vale "0" y la condicin del WHILE nunca es falsa,
por lo que se repite eternamente:
DIM A AS BYTE
A = 0
...
WHILE A = 0
instruccion1
instruccion2
...
instruccionn
WEND
...

Ejemplo 2: Las instrucciones dentro del siguiente WHILE-WEND no se ejecutan nunca, dado que
la condicion siempre es falsa:
DIM A AS BYTE
A = 0
...
WHILE A > 0
instruccion1
instruccion2
...
instruccionn
WEND
...

Ejemplo 3: Las instrucciones dentro del siguiente WHILE-WEND se ejecutan 10 veces, y al

terminar la variable B contiene la suma de los nmeros del 0 al 10 naturales:


DIM A AS BYTE
DIM A AS BYTE
A = 0
B = 0
'
WHILE A < 10
A = A + 1 'Incremento la variable A
B = B + A 'Sumo a B el valor de la variable A
WEND

Cuando A = 10, se suma su valor a A, y al llegar al WEND el control del programa se transfiere al
WHILE, donde se evala la condicin A < 10, se determina que es falsa, y el programa pasa el
control a la lnea que exista despus del WEND.

LOOKUP
La funcin LOOKUP puede ser utilizada para seleccionar un Byte desde una lista de constantes del
mismo tipo, de acuerdo al valor de un ndice (tambin de tipo Byte). El resultado de la seleccin se
almacena (como no!) tambin en una variable tipo byte.
La forma de la funcin LOOKUP es la siguiente:
variable = LOOKUP(byte0, byte1, ..., byteN), indice

Veamos un ejemplo sencillo:


DIM indice AS BYTE
DIM variable AS BYTE
indice = 3
variable = LOOKUP(25, 35, 55, 70, 85, 100), indice
...

variable tendr el valor "70" (decimal) al ejecutar este cdigo. El primer elemento de la lista,
recordemos, corresponde al valor "0" de indice.
Si bien la lista puede contener un mximo de 255 elementos, que es el mximo direccionable por
una variable indice de tipo byte, hay que asegurarse que el microcontrolador que estamos
empleando tenga memoria suficiente para albergarla.
El segundo ejemplo, extrado de la propia ayuda del PIC SIMULATOR IDE, nos muestra como
manejar un display LED de siete segmentos conectado al puerto B:
Dim digito As Byte
Dim mascara As Byte
'Comienzo el bucle principal
loop:
TRISB = %00000000
For digito = 0 To 9
mascara = LookUp(0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f,
0x6f), digito
PORTB = mascara
WaitUs 10 'esta demora debe ser mayor si no es una simulacin!
Next digito
Goto loop

Este es el aspecto que muestra el simulador cuando ejecutamos el programa anterior. Debemos
asegurarnos de que uno de los dgitos LED este configurado como conectado al puerto PORTB, tal
como se ve en la imagen:

Si algunas o todas las constantes de la lista son valores ASCII, se puede hacer mas corta y legible la
misma utilizando como parte de ella una cadena de caracteres, como se ve a continuacin.
MASK = LOOKUP("ABCDEFGHIJK"), INDEX

"A" seria el valor que tendra MASK cuando INDEX vale "0", y "K" cuando INDEX tenga el valor
"10".
Por ultimo, en caso de que el valor de INDEX sea mayor a la cantidad de argumentos de la lista, el
valor de la variable (en este ejemplo MASK) no cambia.

SHIFTLEFT y SHIFTRIGHT
SHIFTLEFT y SHIFTRIGHT son funciones a nivel bit que pueden ser utilizadas para "correr" el
contenido de variable a la izquierda o a la derecha. Cada uno de los bits que componen la variable
se desplazan una posicin (a la izquierda o a la derecha, de acuerdo a que funcin utilicemos). Esto
tiene dos consecuencias. En primer lugar, el bit de mas a la izquierda (SHIFTLEFT) o derecha
(SHIFTRIGHT) se pierde. Y el espacio creado en el otro extremo se completa con un "0".
SHIFTLEFT

SHIFTRIGHT
El siguiente ejemplo muestra como utilizar estas funciones en un programa:
TRISB = 0x00
PORTB = %00000011
goleft:
WaitUs 5 'esta demora debe ser
PORTB = ShiftLeft(PORTB, 1)
If PORTB = %11000000 Then Goto
Goto goleft
goright:
WaitUs 5 'esta demora debe ser
PORTB = ShiftRight(PORTB, 1)
If PORTB = %00000011 Then Goto
Goto goright

mayor si no es una simulacin!


goright
mayor si no es una simulacin!
goleft

Lo que hace el programa es muy sencillo: enciende los dos primeros bits del PORTB, espera un
tiempo, los desplaza hacia la izquierda, si esos bits llegaron al extremo de la variable tipo byte que
es el PORTB, se invierte el sentido del desplazamiento.

Displays LCD
LCD alfanumricos
A grandes rasgos, y a pesar de la simplicidad que brinda el disponer de un mismo integrado
especializado en casi todos los modelos de displays, la escritura en estos es relativamente compleja,
dado que se deben respetar protocolos de inicializacin, tiempos entre envo de datos, etc., lo que
hace bastante tediosa su programacin en assembler.
Pero PIC BASIC dispone de un juego de instrucciones especiales para manejar displays en modo
8 bits y en modo 4 bits que nos evitan toda esa complejidad.
El manejo de los LCD se hace mediante el uso de sentencias DEFINE, que le dicen al
compilador a que pines del microcontrolador hemos conectado cada uno de los pines del LCD. La
forma de la instruccin DEFINE es la siguiente:
DEFINE parametro = valor

Donde parametro es el nombre del parmetro al que le queremos asignar el valor. Los
parmetros disponibles para el manejo de LCD alfanumricos son los siguientes:

LCD_BITS: Define el nmero de bits de la interfaz de datos. Se pueden asignar valores de 4


u 8, siendo 4 el valor por defecto.

LCD_DREG: Define a que puerto del PIC tenemos conectado el port de datos del LCD. Los
valores permitidos son PORTA, PORTB, PORTC, etc. Por defecto se asume PORTB.

LCD_DBIT: Define cual es el primer pin del puerto que usamos para enviar los datos al
LCD cuando seleccionamos un bus de 4 bits. Solo puede ser el 0 (para los pines el 0, 1, 2 y
3) o 4 (para usar los pines 4, 5, 6 y 7). Por defecto se asume 4, y esta instruccin se ignora
para LCD_BITS = 8.

LCD_RSREG: Define a que puerto del PIC tenemos conectado el pin RS del LCD. Los
valores permitidos son PORTA, PORTB, PORTC, etc. Por defecto se asume PORTB.

LCD_RSBIT: Define a que pin del puerto tenemos conectado el pin RS del LCD. Por
defecto se asume 3.

LCD_EREG: Define a que puerto del PIC tenemos conectado el pin E del LCD. Los
valores permitidos son PORTA, PORTB, PORTC, etc. Por defecto se asume PORTB.

LCD_EBIT: Define a que pin del puerto tenemos conectado el pin E del LCD. Por defecto
se asume 2.

LCD_RWREG: Define a que puerto del PIC tenemos conectado el pin RW del LCD. Los
valores permitidos son 0, PORTA, PORTB, PORTC, etc. Por defecto se asume 0, que
significa no usamos el pin RW.

LCD_RWBIT: Define a que pin del puerto tenemos conectado el pin RW del LCD. Por
defecto se asume 0, que significa no usamos el pin RW.

LCD_COMMANDUS: Define cuantos microsegundos demora la escritura de un comando


en el display. Por defecto, este valor es de 5000. La mayora de los LCD funcionan bien con
un valor de 2000, lo que hace ms rpidos nuestros programas.

LCD_DATAUS: Define cuantos microsegundos demora la escritura de un dato en el LCD.


Por defecto, este valor es de 100.

LCD_INITMS: Define cuantos microsegundos demora la inicializacin e la electrnica del


LCD. Por defecto, este valor es de 100.

Luego, tenemos una serie de instrucciones que manejan el envo de comandos e instrucciones al
display:
LCDINIT debe utilizarse antes de enviar cualquier comando o dato al LCD. La forma de esta
instruccin es al siguiente:
LCDINIT n

Donde n es el tipo de cursor que queremos que muestre el display. 0 significa que el cursor
estar oculto, 1 significa que el cursor parpadeara, 2 nos mostrara un cursor subrayado, y 3
un cursor subrayado y parpadeando.
LCDCMDOUT es la instruccin que enva comandos al LCD. Se emplea de la siguiente manera:
LCDCMDOUT comando

Donde comando es alguno de los siguientes:

LcdClear: Borra el contenido del LCD.


LcdHome: Lleva el cursor a la primera posicin del primer rengln del LCD.
LcdLine2Home: Lleva el cursor a la primera posicin del segundo rengln del LCD.
LcdLeft: Mueve el cursor una posicin a la izquierda.
LcdRight: Mueve el cursor una posicin a la derecha.
LcdShiftLeft: Desplaza el contenido del LCD una posicin a la izquierda.
LcdShiftRight: Desplaza el contenido del LCD una posicin a la derecha.
LcdLine1Clear: Borra la primera lnea del LCD.
LcdLine2Clear: Borra la segunda lnea del LCD.
LcdLine1Pos(x): Coloca el cursor en la posicin x del primer rengln del LCD. X
puede tener cualquier valor entre 1 y 40
LcdLine2Pos(x): Coloca el cursor en la posicin x del segundo rengln del LCD. X
puede tener cualquier valor entre 1 y 40

LCDOUT enva datos al display. Si son caracteres, simplemente los ponemos entre comillas a
continuacin del comando. Si se trata de mostrar el contenido de una variable, se escribe la variable
(precedida por #) a continuacin del comando. Si se necesitan imprimir varias variables, se
pueden separar por comas.
A continuacin, un par de ejemplos de cmo se utilizan todas estas instrucciones. El primero se
encarga de mostrar un texto parpadeando en la primera lnea del display. Intenten deducir como est
conectado el LCD al PIC mirando las instrucciones DEFINE del principio del programa.
DEFINE
DEFINE
DEFINE
DEFINE
DEFINE
DEFINE

LCD_BITS = 8
LCD_DREG = PORTB
LCD_DBIT = 0
LCD_RSREG = PORTD
LCD_RSBIT = 1
LCD_EREG = PORTD

DEFINE LCD_EBIT = 3
DEFINE LCD_RWREG = PORTD
DEFINE LCD_RWBIT = 2
'
LCDINIT 0 inicializo el LCD sin cursor.
'
loop:
LCDOUT "www.uControl.com" Muestra el texto
WAITMS 1000 Espero un segundo
LCDCMDOUT LcdClear Borro el display
WAITMS 1000 Espero un segundo
GOTO loop Vuelvo a loop: para repetir indefinidamente.

El segundo ejemplo muestra como imprimir el contenido de una variable (A) en el LCD.
Concretamente, se muestra un texto en el primer rengln, mientras que en el segundo se cuentan los
nmeros del 65535 al 0 en el segundo.
DEFINE LCD_BITS = 8
DEFINE LCD_DREG = PORTB
DEFINE LCD_DBIT = 0
DEFINE LCD_RSREG = PORTD
DEFINE LCD_RSBIT = 1
DEFINE LCD_EREG = PORTD
DEFINE LCD_EBIT = 3
DEFINE LCD_RWREG = PORTD
DEFINE LCD_RWBIT = 2
'
DIM A AS WORD
A = 65535
'
LCDINIT 3 Cursor parpadeando
WAITMS 1000
'
loop:
LCDOUT "Estoy contando! Texto del primer rengln
LCDCMDOUT LcdLine2Home Paso al Segundo rengln
LCDOUT #A Muestro el valor de A
A = A - 1
WAITMS 250
LCDCMDOUT LcdClear Limpio del display
GOTO loop